package javax.usb.tck; /** * Copyright (c) 2004, International Business Machines Corporation. * All Rights Reserved. * * This software is provided and licensed under the terms and conditions * of the Common Public License: * http://oss.software.ibm.com/developerworks/opensource/license-cpl.html */ /* * Change Activity: See below. * * FLAG REASON RELEASE DATE WHO DESCRIPTION * ---- -------- -------- ------ ------- ------------------------------------ * 0000 nnnnnnn yymmdd Initial Development * $P1 tck.rel1 040804 raulortz Support for UsbDisconnectedException * $P2 tck.rel1 040916 raulortz Redesign TCK to create base and optional * tests. Separate setConfig, setInterface * and isochronous transfers as optionals. */ import java.util.List; import javax.usb.*; import javax.usb.event.*; import javax.usb.util.StandardRequest; import org.junit.runner.RunWith; import de.ailis.usb4java.TCKRunner; import junit.framework.TestCase; /** * Hot Plug Test *

* This test verifies that devices can be attached and detached at runtime * (hot plugging) and checks that proper UsbServices events are generated. * @author Charles Jaeger */ @SuppressWarnings("all") @RunWith(TCKRunner.class) public class HotPlugTest extends TestCase { /* * Assumed event flow on a renumeration of the Cypress board is... * DeviceListener.DataEvent - response from syncSubmit of IRP * DeviceListener.DetachedEvent - device is offlined * ServiceListener.DetachedEvent - service is offlined * ServiceListener.AttachedEvent - service is online * * Assumed device under test is a Cypress board with the BulkInt * image running. */ public void setUp() { try { usbServices = UsbHostManager.getUsbServices(); } catch ( java.lang.SecurityException se ) { fail("SecurityException was not expected: " + se); } catch ( UsbException ue ) { fail("UsbException was not expected: " + ue); } // traverse the topology tree to locate the test device usbDevice = FindProgrammableDevice.getInstance().getProgrammableDevice(); assertTrue("USB Device was not configured", usbDevice.isConfigured()); // add a listener to receive events when the host has changes // (e.g. device is unplugged or is plugged in) usbServices.addUsbServicesListener(servicesListener); // add a listener to detect when the device is detached. usbDevice.addUsbDeviceListener(deviceListener); // init for each test -> numSubmits = 0; numDeviceDataEvents = 0; numDeviceDetachEvents = 0; numDeviceErrorEvents = 0; lastUsbDeviceDataEvent = null; lastUsbDeviceErrorEvent = null; lastUsbDeviceDetachedEvent = null; numServicesAttachEvents = 0; numServicesDetachEvents = 0; lastServicesAttachEvent = null; lastServicesDetachEvent = null; // <- } public void tearDown() { if ( debug ) { /* Print out some debug info */ System.out.println("numSubmits = " + numSubmits); System.out.println("numDataEvents = " + numDeviceDataEvents); System.out.println("numExceptionEvents = " + numDeviceErrorEvents); System.out.println("numDetachEvents = " + numDeviceDetachEvents); System.out.println( "numServicesAttachEvents = " + numServicesAttachEvents); System.out.println( "numServicesDetachEvents = " + numServicesDetachEvents); } usbDevice.removeUsbDeviceListener(deviceListener); usbServices.removeUsbServicesListener(servicesListener); } /** * Tests that the setUp() passes all assertions. */ public void testSetUp() { // was setup successful in init of members? assertNotNull("UsbDevice required for test not found", usbDevice); assertNotNull( "UsbHostManager returned null instead of usbServices object", usbServices); // test the numXXX members assertEquals("Devices detached should be 0", numDeviceDetachEvents, 0); assertEquals( "Device commands issued should be 0", numDeviceDataEvents, 0); assertEquals("Device error count should be 0", numDeviceErrorEvents, 0); assertEquals( "Services detached should be 0", numServicesDetachEvents, 0); assertEquals( "Services attached should be 0", numServicesAttachEvents, 0); assertEquals("Board commands should be 0", numSubmits, 0); // test the lastXXX members assertNull(lastUsbDeviceDataEvent); assertNull(lastUsbDeviceErrorEvent); assertNull(lastUsbDeviceDetachedEvent); assertNull(lastServicesAttachEvent); assertNull(lastServicesDetachEvent); // assertNotNull("usbDevice should already exist.", usbDevice); } public void testUsbServicesEvent() { UsbServicesEvent event = new UsbServicesEvent(usbServices, usbDevice); assertNotNull("UsbServicesEvent constructor failed.", event); //test methods of the UsbServicesEvent assertNotNull( "UsbServicesEvent.getUsbServices() returned null", event.getUsbServices()); assertNotNull( "UsbServicesEvent.getUsbDevice() returned null", event.getUsbDevice()); } /** * Test the method that will send the reset command to the Cypress board. */ public void testSimulateHotPlug() { // send reset command to the Cypress board simulateHotPlug(); // verify that all expected events were captured assertNotNull( "Did not receive a DeviceListener DataEvent after submitting IRP.", lastUsbDeviceDataEvent); assertNotNull( "Did not receive a DeviceListener DetachedEvent (indicating reset not issued).", lastUsbDeviceDetachedEvent); assertNotNull( "Did not receive a ServicesListener acknowledging detach.", lastServicesDetachEvent); assertNotNull( "Did not receive a ServicesListener acknowledging attach.", lastServicesAttachEvent); // Were the number of returned events correct? assertEquals( "The device should detach once during the run", numDeviceDetachEvents, 1); assertEquals("Only 1 command is sent", numDeviceDataEvents, 1); assertEquals("No errors should occur", numDeviceErrorEvents, 0); assertEquals( "The service should detach once during the run", numServicesDetachEvents, 1); assertEquals( "The service attached once during the run", numServicesAttachEvents, 1); } /** * Verify that proper exceptions are thrown (w/o failure) * for all other IO calls to a disconnected device */ public void testExceptionsOnDisconnectedDevice() { //local variable boolean isOK = false; // make sure the board is online assertNotNull("The Cypress board is not online", usbDevice); // flush any events from the listeners. // ... automatically done by the setUp() process // reset the board try { submitRenumerateIrp(); } catch ( Exception e ) { e.printStackTrace(); fail("Resetting the board should not issue any exceptions."); } // verify that the correct exceptions are returned for this offline device. if ( null == lastServicesDetachEvent ) { if ( debug ) { System.out.println( "-> public void testExceptionsOnDisconnectedDevice()"); System.out.println(" -> submitRenumerateIrp()"); } // UsbException try { submitRenumerateIrp(); fail("UsbException expected"); } catch ( UsbException e ) { isOK = true; if ( debug ) System.out.println("UsbException thrown" + e); } catch ( Exception e ) { e.printStackTrace(); fail("An Exception other than UsbException was detected."); } isOK = false; // IllegalArgumentException - If the UsbControlIrp is not valid. try { submitBadIrp(); fail("IllegalArgumentException was expected."); } catch ( IllegalArgumentException e ) { // System.out.println("good"); isOK = true; if ( debug ) System.out.println("IllegalArgumentException thrown"); } catch ( Exception e ) { e.printStackTrace(); fail("Exception other than IllegalArgumentException was detected"); } } else { fail("Can't proceed because the service got up and running quickly."); } if ( null != lastServicesDetachEvent ) { fail("The service may have attached during test, so results are inconclusive."); } // make sure board is up before leaving. isOK = false; try { waitForServiceAttachedEvent(20000); isOK = true; } catch ( InterruptedException e ) { e.printStackTrace(); fail("Timed out before all events were seen."); } finally { if ( !isOK ) fail("UsbDevice was not detected as going online"); } } /** * Verify proper events are generated after disconnecting. */ public void testDisconnectEvents() { // make sure the board is online assertNotNull("The Cypress board is not online", usbDevice); // reset the board try { submitRenumerateIrp(); } catch ( UsbException e ) { e.printStackTrace(); fail("Resetting the board should not issue any exceptions."); } // make sure all the disconnect events from the listeners fire try { // the total time to wait for the wanted disconnect events to occur waitForServiceDetachedEvent(20000); // Disconnect events follow // in the expected sequential order... assertNotNull( "The device did not detach within time", lastUsbDeviceDetachedEvent); assertNotNull( "The service did not detach within time", lastServicesDetachEvent); assertEquals( "1 Device detach events expected", numDeviceDetachEvents, 1); assertEquals( "1 Service detach events expected", numServicesDetachEvents, 1); assertEquals("0 Device errors expected", numDeviceErrorEvents, 0); // make sure board is up before leaving. waitForServiceAttachedEvent(5000); } catch ( InterruptedException e ) { e.printStackTrace(); fail("Timed out before all events were seen."); } } /** * Verify proper events are generated after hot plugging. */ public void testPlugInEvents() { // make sure the board is online assertNotNull("usbDevice should already be online.", usbDevice); try { // the setUp() flushes any events from the listeners // reset the board submitRenumerateIrp(); // wait til the board comes back up waitForServiceAttachedEvent(20000); // verify that all the events from the listeners fire assertNotNull( "Did not receive a DeviceListener DataEvent after submitting IRP.", lastUsbDeviceDataEvent); assertNotNull( "Did not receive a DeviceListener DetachedEvent (indicating reset not issued).", lastUsbDeviceDetachedEvent); assertNotNull( "Did not receive a ServicesListener acknowledging detach.", lastServicesDetachEvent); assertNotNull( "Did not receive a ServicesListener acknowledging attach.", lastServicesAttachEvent); // Were the number of returned events correct? assertEquals( "The device should detach once during the run", numDeviceDetachEvents, 1); assertEquals("Only 1 command is sent", numDeviceDataEvents, 1); assertEquals("No errors should occur", numDeviceErrorEvents, 0); assertEquals( "The service should detach once during the run", numServicesDetachEvents, 1); assertEquals( "The service attached once during the run", numServicesAttachEvents, 1); } catch ( InterruptedException e ) { e.printStackTrace(); fail("Sleep was interrupted"); } catch ( UsbException uE ) { /* The exception should indicate the reason for the failure. * For this example, we'll just stop trying. */ fail("DCP submission failed. " + uE.toString()); } } /** * Run a disconnect, reconnect cycle and then verify that 10 transfers will * succeed without data error. */ public void testNoErrorsOnDataTransfers() { // the setUp() flushes any events from the listeners // make sure the board is online assertNotNull("usbDevice should already be online.", usbDevice); assertTrue("usbDevice is not configured.", usbDevice.isConfigured()); //set up the board's: endpoints, pipes, etc .. Board theBoard = new Board(usbDevice); // test: while online, data can be sent without error... try { theBoard.sendData(); } catch ( Exception e ) { e.printStackTrace(); fail("Exception not expected."); } // tested: while online, data can be sent without error... // While transferring data through input and output endpoints // (loop bulk data), unplug the device. // (Vendor request to Cypress Board to renumerate will simulate unplug.) try { theBoard.testAsyncInFailure(); } catch ( InterruptedException ie ) { fail("Timed out while waiting for the device detach event."); } catch ( Exception e ) { e.printStackTrace(); fail("Resetting the board should not issue any exceptions."); } // tested: when offline, abort all submissions try { waitForServiceAttachedEvent(20000); } catch ( InterruptedException ie ) { fail("Timed out while waiting for the device detach event."); } // test: when online again, send data without error // wait for the device to come back up try { waitForServiceAttachedEvent(10000); setUp(); theBoard = new Board(usbDevice); theBoard.sendData(); theBoard.tearDown(); } catch ( InterruptedException ie ) { fail("Timed out waiting for service attach event."); } catch ( Exception e ) { fail("Exception not expected."); } // tested: when online again, send data without error } /** * Tell the Cypress board to initiate its reset and binary upload method. * in order to simulate human involved device detach and attach action. * Returns successfully once device service is attached; otherwise * a fails method is asserted. */ private void simulateHotPlug() { /* This will block until the submission is complete. * Note that submissions (except interrupt and bulk in-direction) * will not block indefinitely, they will complete or fail within * a finite amount of time. See MouseDriver.HidMouseRunnable for more details. */ try { submitRenumerateIrp(); waitForDeviceDataOrErrorEvent(2000); waitForDeviceDetachedEvent(5000); waitForServiceDetachedEvent(2000); waitForServiceAttachedEvent(10000); } catch ( InterruptedException e ) { e.printStackTrace(); fail("Sleep was interrupted"); } catch ( UsbException uE ) { /* The exception should indicate the reason for the failure. * For this example, we'll just stop trying. */ fail("DCP submission failed. " + uE.toString()); } } /** * Generates the Renumerate command for the cypress board as a UsbControlIrp * @return the UsbControlIrp ready for use */ private UsbControlIrp getRenumerateIrp() { byte sentbmRequestType = UsbConst.REQUESTTYPE_DIRECTION_OUT | UsbConst.REQUESTTYPE_TYPE_VENDOR | UsbConst.REQUESTTYPE_RECIPIENT_DEVICE; short sentwIndex = 0; //first isochronous IN endpoint // An IRP UsbControlIrp usbControlIrp = usbDevice.createUsbControlIrp( sentbmRequestType, VENDOR_REQUEST_RENUMERATE, VENDOR_REQUEST_DATA_OUT, sentwIndex); //set variable parts of Irp byte[] sentData = new byte[0]; usbControlIrp.setData(sentData); usbControlIrp.setAcceptShortPacket(true); return usbControlIrp; } /** * Generates an IRP that will cause the IllegalArgumentException * on syncSubmit to the Cypress board * @return the UsbControlIrp ready for use private UsbControlIrp getBadIrp() { UsbControlIrp badIrp = getRenumerateIrp(); //set Irp data to cause IllegalArgumentException on syncSubmit return badIrp; } */ /** * Sends a reset and binary upload call to the Cypress board. * @throws UsbException */ private void submitRenumerateIrp() throws UsbException { try { UsbControlIrp usbControlIrp = getRenumerateIrp(); assertNotNull("usbControlIrp should not be null", usbControlIrp); usbDevice.syncSubmit(usbControlIrp); numSubmits++; } catch ( IllegalArgumentException e ) { e.printStackTrace(); fail("IllegalArgumentException was not expected."); } } /** * Sends an invalid UsbControlIrp to the Cypress board. * @throws IllegalArgumentException */ private void submitBadIrp() throws IllegalArgumentException { // An IRP UsbControlIrp usbControlIrp = getRenumerateIrp(); assertNotNull("usbControlIrp should not be null", usbControlIrp); //set Irp data to cause IllegalArgumentException on syncSubmit usbControlIrp.setData(null); try { usbDevice.syncSubmit(usbControlIrp); } catch ( UsbDisconnectedException uDE ) // @P1C { // @P1A fail ("A connected device should't throw the UsbDisconnectedException!"); // @P1A } catch ( UsbException e ) // @P1A { e.printStackTrace(); fail("UsbException not expected."); } numSubmits++; } /** * Wait for deviceListener deviceData or deviceError event before continuing. * @param timeout minimum number of milliseconds before timeout is issued (suggested minimum: 2000) * @throws InterruptedException raised if timeout occurs */ private void waitForDeviceDataOrErrorEvent(int timeout) throws InterruptedException { // up to 2 sec min timeout on submission for ( int i = 0; i < (timeout / 20); i++ ) { if ( (lastUsbDeviceDataEvent != null) || (lastUsbDeviceErrorEvent != null) ) { if ( debug ) System.out.println( "waitForDeviceDataOrErrorEvent took less than " + ((i + 1) * 20) + " milliseconds"); break; } Thread.sleep(20); //wait 20 ms before checkin for event } } /** * Wait for deviceListener deviceDetached event before continuing * @param timeout minimum number of milliseconds before timeout is issued (suggested minimum: 5000) * @throws InterruptedException raised if timeout occurs */ private void waitForDeviceDetachedEvent(int timeout) throws InterruptedException { for ( int i = 0; i < (timeout / 20); i++ ) { if ( lastUsbDeviceDetachedEvent != null ) { if ( debug ) System.out.println( "waitForDeviceDetachedEvent took less than " + ((i + 1) * 20) + " milliseconds"); break; } Thread.sleep(20); //wait 20 ms before checkin for event } if ( lastUsbDeviceDetachedEvent == null ) { throw new InterruptedException( "DeviceDetachedEvent not found within " + timeout + " ms"); } } /** * Wait for servicesListener deviceDetached event before continuing * @param timeout minimum number of milliseconds before timeout is issued (suggested minimum: 2000) * @throws InterruptedException raised if timeout occurs */ private void waitForServiceDetachedEvent(int timeout) throws InterruptedException { for ( int i = 0; i < (timeout / 20); i++ ) { if ( lastServicesDetachEvent != null ) { if ( debug ) System.out.println( "waitForServiceDetachedEvent took less than " + ((i + 1) * 20) + " milliseconds"); break; } Thread.sleep(20); //wait 20 ms before checkin for event } } /** * Wait for servicesListener deviceAttached event before continuing * @param timeout minimum number of milliseconds before timeout is issued (suggested minimum: 5000) * @throws InterruptedException raised if timeout occurs */ private void waitForServiceAttachedEvent(int timeout) throws InterruptedException { for ( int i = 0; i < (timeout / 20); i++ ) { if ( (null != lastServicesAttachEvent) && (usbDevice.isConfigured() ) ) { if ( debug ) System.out.println( "waitForServiceAttachedEvent took less than " + ((i + 1) * 20) + " milliseconds"); break; } Thread.sleep(20); //wait 20 ms before checkin for event } } private class Board { // attributes private UsbInterface iface; private UsbPipe inPipe; private UsbPipe outPipe; private boolean hasRenumerated = false; private boolean hasSubmittedAsyncIn = false; // Concrete instance of a UsbPipeListener interface private UsbPipeListener inPipeListener = new UsbPipeListener() { public void dataEventOccurred(UsbPipeDataEvent updE) { } public void errorEventOccurred(UsbPipeErrorEvent upeE) { if ( hasRenumerated && hasSubmittedAsyncIn ) // ok { } else //err { upeE.getUsbException().printStackTrace(); fail ("No in pipe errors are expected at this point."); } } }; private UsbPipeListener outPipeListener = new UsbPipeListener() { public void dataEventOccurred(UsbPipeDataEvent updE) { } public void errorEventOccurred(UsbPipeErrorEvent upeE) { fail("No out pipe errors should occur during this test."); } }; // default no arg ctor not allowed private Board() { } //ctor public Board(UsbDevice usbDevice) { config(usbDevice); } /** * set up endpoints, pipes, etc .. */ private void config(UsbDevice usbDevice) { try { // set the endpoints List endpoints = null; /** * select alternate setting for the programmable board (AS0 or AS1) * @param usbDevice The UsbDevice obj */ if ( usbDevice.isConfigured() ) { iface = usbDevice.getUsbConfiguration((byte) 1).getUsbInterface((byte) 0); iface.claim(); // @P2D4 iface = iface.getActiveSetting(); if ( debug ) System.out.println("Select Alternate Setting 1"); endpoints = iface.getUsbEndpoints(); UsbEndpoint inEndpoint8 = findEndpoint( endpoints, UsbConst.REQUESTTYPE_DIRECTION_IN, UsbConst.ENDPOINT_TYPE_BULK, 8); UsbEndpoint outEndpoint8 = findEndpoint( endpoints, UsbConst.REQUESTTYPE_DIRECTION_OUT, UsbConst.ENDPOINT_TYPE_BULK, 8); inPipe = inEndpoint8.getUsbPipe(); outPipe = outEndpoint8.getUsbPipe(); inPipe.addUsbPipeListener(inPipeListener); outPipe.addUsbPipeListener(outPipeListener); inPipe.open(); outPipe.open(); } else { fail("device is not configured!"); } } catch ( UsbClaimException uce ) { fail("UsbClaimException: " + uce); } catch ( UsbDisconnectedException uDE ) // @P1A { // @P1A fail ("A connected device should't throw the UsbDisconnectedException!"); // @P1A } catch ( UsbException ue ) { fail("UsbException: " + ue); } catch ( UsbNotActiveException unae ) { unae.printStackTrace(); fail("UsbNotActiveException: " + unae); } } public void testAsyncInFailure() throws Exception { int dataSize = 8; byte[] inData = new byte[dataSize]; UsbIrp irp = inPipe.createUsbIrp(); irp.setData(inData); inPipe.asyncSubmit(irp); hasSubmittedAsyncIn = true; hasRenumerated = true; submitRenumerateIrp(); waitForServiceAttachedEvent(20000); } public void tearDown() { try { inPipe.abortAllSubmissions(); outPipe.abortAllSubmissions(); inPipe.close(); outPipe.close(); inPipe.removeUsbPipeListener(inPipeListener); outPipe.removeUsbPipeListener(outPipeListener); if ( null != iface ) { if ( debug ) System.out.println("releasing interface!!!!"); iface.release(); if ( debug ) System.out.println("released interface!!!!"); } } catch ( UsbClaimException uce ) { fail("UsbClaimException: " + uce); } catch ( UsbDisconnectedException uDE ) // @P1C { // @P1A fail ("A connected device should't throw the UsbDisconnectedException!"); // @P1A } catch ( UsbException ue ) { fail("UsbException: " + ue); } catch ( UsbNotActiveException unae ) { fail("UsbNotActiveException: " + unae); } } /** * Performs bulk data transfer for 10 datum. * @exception */ public void sendData() throws Exception { for ( int tries = 0; tries < 10; tries++ ) { try { sendDatum(); } catch ( Exception e ) { fail("The following exception was caught"); e.printStackTrace(); throw e; } } } /** * Will throw an exception if a buffer it sends is different than the one it receives. */ private void sendDatum() throws Exception { byte txType = TRANSFORM_TYPE_PASSTHROUGH; int dataSize = 8; byte[] inData = new byte[dataSize]; TransmitBuffer txBuffer = new TransmitBuffer(txType, dataSize); try // @P1A { // @P1A outPipe.syncSubmit(txBuffer.getOutBuffer()); // @P1C inPipe.syncSubmit(inData); // @P1C } catch ( UsbDisconnectedException uDE ) // @P1C { // @P1A fail ("A connected device should't throw the UsbDisconnectedException!"); // @P1A } // @P1A if ( txBuffer.compareBuffers(inData) ) { // it's all good, display the data if ( debug ) { System.out.print("Received data was: "); for ( int i = 0; i < dataSize; i++ ) System.out.print(inData[i] + ","); System.out.println(); } } else { throw new Exception("received inData from pipe was != outData."); } } /** * find endpoint that match the requirement * @param totalEndpoints The List of End Points * @param inDirection The direction ( 81 = in, 00 = out) * @param inType The endpoint type ( 3 - interrupt, 2 - bulk) * @param inSize The endpoint size (8 or 64 bytes for this programmable board) */ private UsbEndpoint findEndpoint( List totalEndpoints, int inDirection, int inType, int inSize) { boolean found = false; for ( int j = 0; j < totalEndpoints.size(); j++ ) { UsbEndpoint ep = (UsbEndpoint) totalEndpoints.get(j); int direction = ep.getDirection(); int type = ep.getType(); int maxPackageSize = ep.getUsbEndpointDescriptor().wMaxPacketSize(); int endpointAddress = ep.getUsbEndpointDescriptor().bEndpointAddress(); if ( (byte) (inDirection & 0x80) == (byte) direction && inType == type && inSize == maxPackageSize ) { return ep; } } if ( debug ) System.out.println("End point NOT FOUND!!!"); return null; } } private final UsbServicesListener servicesListener = new UsbServicesListener() { public void usbDeviceAttached(UsbServicesEvent use) { if ( debug ) System.out.println("UsbServicesListener.usbDeviceAttached()"); numServicesAttachEvents++; assertNotNull(use); lastServicesAttachEvent = use; assertNotNull( "Device was attached: ", lastServicesAttachEvent.toString()); } public void usbDeviceDetached(UsbServicesEvent use) { if ( debug ) System.out.println("UsbServicesListener.usbDeviceDetached()"); numServicesDetachEvents++; assertNotNull(use); lastServicesDetachEvent = use; assertNotNull( "Device was detached: ", lastServicesDetachEvent.toString()); //testing attributes of the UsbServicesEvent assertNotNull( "UsbServicesEvent.getUsbServices() returned null", use.getUsbServices()); assertNotNull( "UsbServicesEvent.getUsbDevice() returned null", use.getUsbDevice()); } }; private final UsbDeviceListener deviceListener = new UsbDeviceListener() { public void dataEventOccurred(UsbDeviceDataEvent uddE) { numDeviceDataEvents++; // fail("Test that we get a data event"); // assertEquals(0,numDataEvents); assertNotNull(uddE); lastUsbDeviceDataEvent = uddE; if ( debug ) System.out.println( "UsbDeviceListener.dataEventOccurred(). uddE = " + uddE + "numDataEvents = " + numDeviceDataEvents); } public void errorEventOccurred(UsbDeviceErrorEvent udeE) { numDeviceErrorEvents++; assertNotNull(udeE); lastUsbDeviceErrorEvent = udeE; if ( debug ) System.out.println( "UsbDeviceListener.errorEventOccurred(). uddE = " + udeE + "numExceptionEvents = " + numDeviceErrorEvents); assertNotNull( "Should not have null UsbException on UsbDeviceErrorEvent.", udeE.getUsbException()); } public void usbDeviceDetached(UsbDeviceEvent udE) { numDeviceDetachEvents++; assertNotNull(udE); lastUsbDeviceDetachedEvent = udE; if ( debug ) System.out.println( "UsbDeviceListener.usbDeviceDetached(). object = " + udE + "numDeviceDetachEvents = " + numDeviceDetachEvents); assertNotNull( "Should not have null UsbDevice on usbDeviceEvent.", udE.getUsbDevice()); } }; // for debugging private boolean debug = false; // instances of USB classes private UsbDevice usbDevice; private UsbHostManager usbHostManager; private UsbServices usbServices; private UsbDeviceDataEvent lastUsbDeviceDataEvent; private UsbDeviceErrorEvent lastUsbDeviceErrorEvent; private UsbDeviceEvent lastUsbDeviceDetachedEvent; private UsbServicesEvent lastServicesDetachEvent, lastServicesAttachEvent; private static int numSubmits = 0; private static int numDeviceDataEvents = 0; private static int numDeviceErrorEvents = 0; private static int numDeviceDetachEvents = 0; private static int numServicesAttachEvents = 0; private static int numServicesDetachEvents = 0; private static final short VENDOR_REQUEST_DATA_OUT = 0x00; private static final byte VENDOR_REQUEST_RENUMERATE = (byte) 0xA8; private static final byte TRANSFORM_TYPE_PASSTHROUGH = (byte) 0x01; private static final byte[] manufacturerString = {(byte) 26, //length of descriptor (byte) UsbConst.DESCRIPTOR_TYPE_STRING, (byte) 'M', (byte) 0x00, (byte) 'a', (byte) 0x00, (byte) 'n', (byte) 0x00, (byte) 'u', (byte) 0x00, (byte) 'f', (byte) 0x00, (byte) 'a', (byte) 0x00, (byte) 'c', (byte) 0x00, (byte) 't', (byte) 0x00, (byte) 'u', (byte) 0x00, (byte) 'r', (byte) 0x00, (byte) 'e', (byte) 0x00, (byte) 'r', (byte) 0x00}; }