diff --git a/UsbSerialExamples/src/com/hoho/android/usbserial/examples/DemoActivity.java b/UsbSerialExamples/src/com/hoho/android/usbserial/examples/DemoActivity.java index c69415a..92caaf4 100644 --- a/UsbSerialExamples/src/com/hoho/android/usbserial/examples/DemoActivity.java +++ b/UsbSerialExamples/src/com/hoho/android/usbserial/examples/DemoActivity.java @@ -110,7 +110,7 @@ public class DemoActivity extends Activity { @Override protected void onResume() { super.onResume(); - mSerialDevice = UsbSerialProber.acquire(mUsbManager); + mSerialDevice = UsbSerialProber.findFirstDevice(mUsbManager); Log.d(TAG, "Resumed, mSerialDevice=" + mSerialDevice); if (mSerialDevice == null) { mTitleTextView.setText("No serial device."); diff --git a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialProber.java b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialProber.java index 9527a6f..fdad88a 100644 --- a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialProber.java +++ b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialProber.java @@ -20,15 +20,28 @@ package com.hoho.android.usbserial.driver; -import java.util.Map; - import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbDeviceConnection; import android.hardware.usb.UsbManager; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + /** - * Helper class to assist in detecting and building {@link UsbSerialDriver} - * instances from available hardware. + * Helper class which finds compatible {@link UsbDevice}s and creates + * {@link UsbSerialDriver} instances. + * + *

+ * You don't need a Prober to use the rest of the library: it is perfectly + * acceptable to instantiate driver instances manually. The Prober simply + * provides convenience functions. + * + *

+ * For most drivers, the corresponding {@link #probe(UsbManager, UsbDevice)} + * method will either return an empty list (device unknown / unsupported) or a + * singleton list. However, multi-port drivers may return multiple instances. * * @author mike wakerly (opensource@hoho.com) */ @@ -43,102 +56,160 @@ public enum UsbSerialProber { */ FTDI_SERIAL { @Override - public UsbSerialDriver getDevice(final UsbManager manager, final UsbDevice usbDevice) { + public List probe(final UsbManager manager, final UsbDevice usbDevice) { if (!testIfSupported(usbDevice, FtdiSerialDriver.getSupportedDevices())) { - return null; + return Collections.emptyList(); } final UsbDeviceConnection connection = manager.openDevice(usbDevice); if (connection == null) { - return null; + return Collections.emptyList(); } - return new FtdiSerialDriver(usbDevice, connection); + final UsbSerialDriver driver = new FtdiSerialDriver(usbDevice, connection); + return Collections.singletonList(driver); } }, CDC_ACM_SERIAL { @Override - public UsbSerialDriver getDevice(UsbManager manager, UsbDevice usbDevice) { + public List probe(UsbManager manager, UsbDevice usbDevice) { if (!testIfSupported(usbDevice, CdcAcmSerialDriver.getSupportedDevices())) { - return null; + return Collections.emptyList(); } final UsbDeviceConnection connection = manager.openDevice(usbDevice); if (connection == null) { - return null; + return Collections.emptyList(); } - return new CdcAcmSerialDriver(usbDevice, connection); + final UsbSerialDriver driver = new CdcAcmSerialDriver(usbDevice, connection); + return Collections.singletonList(driver); } }, - + SILAB_SERIAL { @Override - public UsbSerialDriver getDevice(final UsbManager manager, final UsbDevice usbDevice) { + public List probe(final UsbManager manager, final UsbDevice usbDevice) { if (!testIfSupported(usbDevice, Cp2102SerialDriver.getSupportedDevices())) { - return null; + return Collections.emptyList(); } final UsbDeviceConnection connection = manager.openDevice(usbDevice); if (connection == null) { - return null; + return Collections.emptyList(); } - return new Cp2102SerialDriver(usbDevice, connection); + final UsbSerialDriver driver = new Cp2102SerialDriver(usbDevice, connection); + return Collections.singletonList(driver); } }; /** - * Builds a new {@link UsbSerialDriver} instance from the raw device, or - * returns null if it could not be built (for example, if the - * probe failed). + * Tests the supplied {@link UsbDevice} for compatibility with this enum + * member, returning one or more driver instances if compatible. * * @param manager the {@link UsbManager} to use * @param usbDevice the raw {@link UsbDevice} to use - * @return the first available {@link UsbSerialDriver}, or {@code null} if - * no devices could be acquired + * @return zero or more {@link UsbSerialDriver}, depending on compatibility + * (never {@code null}). */ - public abstract UsbSerialDriver getDevice(final UsbManager manager, final UsbDevice usbDevice); + protected abstract List probe(final UsbManager manager, final UsbDevice usbDevice); /** - * Acquires and returns the first available serial device among all - * available {@link UsbDevice}s, or returns {@code null} if no device could - * be acquired. + * Creates and returns a new {@link UsbSerialDriver} instance for the first + * compatible {@link UsbDevice} found on the bus. If none are found, + * returns {@code null}. * - * @param usbManager the {@link UsbManager} to use + *

+ * The order of devices is undefined, therefore if there are multiple + * devices on the bus, the chosen device may not be predictable (clients + * should use {@link #findAllDevices(UsbManager)} instead). + * + * @param usbManager the {@link UsbManager} to use. * @return the first available {@link UsbSerialDriver}, or {@code null} if - * no devices could be acquired + * none are available. */ - public static UsbSerialDriver acquire(final UsbManager usbManager) { + public static UsbSerialDriver findFirstDevice(final UsbManager usbManager) { for (final UsbDevice usbDevice : usbManager.getDeviceList().values()) { - final UsbSerialDriver probedDevice = acquire(usbManager, usbDevice); - if (probedDevice != null) { - return probedDevice; + for (final UsbSerialProber prober : values()) { + final List probedDevices = prober.probe(usbManager, usbDevice); + if (!probedDevices.isEmpty()) { + return probedDevices.get(0); + } } } return null; } /** - * Builds and returns a new {@link UsbSerialDriver} from the given - * {@link UsbDevice}, or returns {@code null} if no drivers supported this - * device. + * Creates a new {@link UsbSerialDriver} instance for all compatible + * {@link UsbDevice}s found on the bus. If no compatible devices are found, + * the list will be empty. * - * @param usbManager the {@link UsbManager} to use - * @param usbDevice the {@link UsbDevice} to use - * @return a new {@link UsbSerialDriver}, or {@code null} if no devices - * could be acquired + * @param usbManager + * @return */ - public static UsbSerialDriver acquire(final UsbManager usbManager, final UsbDevice usbDevice) { + public static List findAllDevices(final UsbManager usbManager) { + final List result = new ArrayList(); + + // For each UsbDevice, call probe() for each prober. + for (final UsbDevice usbDevice : usbManager.getDeviceList().values()) { + result.addAll(probeSingleDevice(usbManager, usbDevice)); + } + return result; + } + + /** + * Special method for testing a specific device for driver support, + * returning any compatible driver(s). + * + *

+ * Clients should ordinarily use {@link #findAllDevices(UsbManager)}, which + * operates against the entire bus of devices. This method is useful when + * testing against only a single target is desired. + * + * @param usbManager the {@link UsbManager} to use. + * @param usbDevice the device to test against. + * @return a list containing zero or more {@link UsbSerialDriver} instances. + */ + public static List probeSingleDevice(final UsbManager usbManager, + UsbDevice usbDevice) { + final List result = new ArrayList(); for (final UsbSerialProber prober : values()) { - final UsbSerialDriver probedDevice = prober.getDevice(usbManager, usbDevice); - if (probedDevice != null) { - return probedDevice; - } + final List probedDevices = prober.probe(usbManager, usbDevice); + result.addAll(probedDevices); + } + return result; + } + + /** + * Deprecated; Use {@link #findFirstDevice(UsbManager)}. + * + * @param usbManager + * @return + */ + @Deprecated + public static UsbSerialDriver acquire(final UsbManager usbManager) { + return findFirstDevice(usbManager); + } + + /** + * Deprecated; use {@link #probeSingleDevice(UsbManager, UsbDevice)}. + * + * @param usbManager + * @param usbDevice + * @return + */ + @Deprecated + public static UsbSerialDriver acquire(final UsbManager usbManager, final UsbDevice usbDevice) { + final List probedDevices = probeSingleDevice(usbManager, usbDevice); + if (!probedDevices.isEmpty()) { + return probedDevices.get(0); } return null; } /** - * Returns {@code true} if the given device is found in the vendor/product map. + * Returns {@code true} if the given device is found in the driver's + * vendor/product map. * * @param usbDevice the device to test - * @param supportedDevices map of vendor ids to product id(s) + * @param supportedDevices map of vendor IDs to product ID(s) * @return {@code true} if supported */ private static boolean testIfSupported(final UsbDevice usbDevice,