private void sendOUTandIN(
      byte testType,
      boolean SyncOrAsync,
      UsbPipe inPipe,
      UsbPipe outPipe,
      List listOfINIrps,
      List listOfOUTIrps) {
    try {
      if (endpointType == UsbConst.ENDPOINT_TYPE_ISOCHRONOUS) {
        // For isochronous, a list of IN IRPs must be async submitted as the IN for
        // the byte[], IRP, and IRP List tests.  Only the OUT, will be submitted
        // as a byte[], IRP, IRPList and in both synchronous and asynchronous modes.
        try {
          printDebug("About to async Submit IN IRP List for ISOCHRONOUS");
          inPipe.asyncSubmit(listOfINIrps);
          printDebug("Return from async Submit IN IRP List for ISOCHRONOUS");
        } catch (Exception uE) {
          System.out.println("Exception on async submit.  Submission failed." + uE.getMessage());
          Assert.fail("Exception on async submit.  Submission failed." + uE.getMessage());
        }
      }

      if (SyncOrAsync == SYNC_SUBMIT) {
        printDebug("About to sync Submit OUT IRP");
        // for single IRP, send the first IRP in the IRP list
        outPipe.syncSubmit((UsbIrp) listOfOUTIrps.get(0));
        printDebug("Return from sync Submit OUT IRP");
      } else {
        printDebug("About to async Submit OUT IRP");
        // for single IRP, send the first IRP in the IRP list
        outPipe.asyncSubmit((UsbIrp) listOfOUTIrps.get(0));
        printDebug("Return from async Submit OUT IRP");
        // wait for IRP to be complete; wait a max of 5000 ms
        ((UsbIrp) listOfOUTIrps.get(0)).waitUntilComplete(5000);
      }

      // all IRPs should be complete when sync submit returns
      for (int i = 0; i < (listOfOUTIrps.size()); i++) {
        Assert.assertTrue(
            "isComplete() not true for IRP after syncSubmit returned",
            ((UsbIrp) listOfOUTIrps.get(i)).isComplete());
        Assert.assertFalse(
            "isUsbException() is true for IRP after syncSubmit returned",
            ((UsbIrp) listOfOUTIrps.get(i)).isUsbException());
      }

      // isochronous IN IRP List was already submitted (see above)
      if (endpointType != UsbConst.ENDPOINT_TYPE_ISOCHRONOUS) {

        if (SyncOrAsync == SYNC_SUBMIT) {
          printDebug("About to sync Submit IN IRP");
          // for single IRP, send the first IRP in the IRP list
          inPipe.syncSubmit((UsbIrp) listOfINIrps.get(0));
          printDebug("Return from sync Submit IN IRP");
        } else {
          printDebug("About to async Submit IN IRP");
          // for single IRP, send the first IRP in the IRP list
          inPipe.asyncSubmit((UsbIrp) listOfINIrps.get(0));
          printDebug("Return from async Submit IN IRP");
          // wait for IRP to be complete; wait a max of 5000 ms
          ((UsbIrp) listOfINIrps.get(0)).waitUntilComplete(5000);
          printDebug("Finished waiting on async in irp--timeout");
          ((UsbIrp) listOfINIrps.get(0)).waitUntilComplete();
          printDebug("Finished waiting on async in irp");
        }
      }

      // all IRPs should be complete when sync submit returns
      for (int i = 0; i < (listOfINIrps.size()); i++) {
        Assert.assertTrue(
            "isComplete() not true for IRP after syncSubmit returned",
            ((UsbIrp) listOfINIrps.get(i)).isComplete());
        // Assert.assertFalse("isUsbException() is true for IRP after syncSubmit returned",
        //                   ((UsbIrp)listOfINIrps.get(i)).isUsbException());
      }

    } catch (UsbException uE) {

      // exceptions are expected in this test
    } catch (UsbDisconnectedException uDE) // @P1A
    { // @P1A
      Assert.fail("A connected device should't throw the UsbDisconnectedException!"); // @P1A
    } // @P1A

    try {
      /*
       * After all IRPs are complete, wait for all device events.
       * Wait for device event before leaving submit routine.
       * 400 * 5 ms = 2000 ms = 2 seconds max wait for the last event
       * before error.
       * This should be an adequate wait because we don't get here until
       * all of the submits are complete
       */
      // first wait for all OUT events
      for (int i = 0; i < 400; i++) {

        if (outPipeEvents.size() == listOfOUTIrps.size()) {
          // System.out.println("Data event took less than " + ((i+1) * 20 ) +" milliseconds");
          break;
        }

        Thread.sleep(5); // wait 5 ms before checkin for event
      }

      // now wait for all IN events
      for (int i = 0; i < 400; i++) {
        if (inPipeEvents.size() == listOfINIrps.size()) {
          // System.out.println("Data event took less than " + ((i+1) * 20 ) +" milliseconds");
          break;
        }

        Thread.sleep(5); // wait 5 ms before checkin for event
      }

    } catch (InterruptedException e) {
      Assert.fail("Sleep was interrupted");

    } finally {

      Assert.assertEquals(
          "Did not receive all expected IN pipe events after sleep.",
          listOfINIrps.size(),
          inPipeEvents.size());

      Assert.assertEquals(
          "Did not receive all expected OUT pipe event after sleep.",
          listOfOUTIrps.size(),
          outPipeEvents.size());
    }
  };