mirror of
https://github.com/mik3y/usb-serial-for-android
synced 2025-06-08 00:16:13 +00:00
probe CDC devices by USB interface types instead of fixed VID+PID
- no more custom prober required for standard CDC devices - legacy (singleInterface) CDC devices still have to be added by VID+PID - for autostart VID+PID still have to be added to device_filter.xml
This commit is contained in:
parent
85f64aff96
commit
5db45548ba
13
README.md
13
README.md
@ -124,22 +124,23 @@ new device or for one using a custom VID/PID pair.
|
|||||||
UsbSerialProber is a class to help you find and instantiate compatible
|
UsbSerialProber is a class to help you find and instantiate compatible
|
||||||
UsbSerialDrivers from the tree of connected UsbDevices. Normally, you will use
|
UsbSerialDrivers from the tree of connected UsbDevices. Normally, you will use
|
||||||
the default prober returned by ``UsbSerialProber.getDefaultProber()``, which
|
the default prober returned by ``UsbSerialProber.getDefaultProber()``, which
|
||||||
uses the built-in list of well-known VIDs and PIDs that are supported by our
|
uses USB interface types and the built-in list of well-known VIDs and PIDs that
|
||||||
drivers.
|
are supported by our drivers.
|
||||||
|
|
||||||
To use your own set of rules, create and use a custom prober:
|
To use your own set of rules, create and use a custom prober:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
// Probe for our custom CDC devices, which use VID 0x1234
|
// Probe for our custom FTDI device, which use VID 0x1234 and PID 0x0001 and 0x0002.
|
||||||
// and PIDS 0x0001 and 0x0002.
|
|
||||||
ProbeTable customTable = new ProbeTable();
|
ProbeTable customTable = new ProbeTable();
|
||||||
customTable.addProduct(0x1234, 0x0001, CdcAcmSerialDriver.class);
|
customTable.addProduct(0x1234, 0x0001, FtdiSerialDriver.class);
|
||||||
customTable.addProduct(0x1234, 0x0002, CdcAcmSerialDriver.class);
|
customTable.addProduct(0x1234, 0x0002, FtdiSerialDriver.class);
|
||||||
|
|
||||||
UsbSerialProber prober = new UsbSerialProber(customTable);
|
UsbSerialProber prober = new UsbSerialProber(customTable);
|
||||||
List<UsbSerialDriver> drivers = prober.findAllDrivers(usbManager);
|
List<UsbSerialDriver> drivers = prober.findAllDrivers(usbManager);
|
||||||
// ...
|
// ...
|
||||||
```
|
```
|
||||||
|
*Note*: as of v3.5.0 this library detects CDC devices by USB interface types instead of fixed VID+PID,
|
||||||
|
so custom probers are typically not required any more for CDC devices.
|
||||||
|
|
||||||
Of course, nothing requires you to use UsbSerialProber at all: you can
|
Of course, nothing requires you to use UsbSerialProber at all: you can
|
||||||
instantiate driver classes directly if you know what you're doing; just supply
|
instantiate driver classes directly if you know what you're doing; just supply
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.hoho.android.usbserial.examples;
|
package com.hoho.android.usbserial.examples;
|
||||||
|
|
||||||
import com.hoho.android.usbserial.driver.CdcAcmSerialDriver;
|
import com.hoho.android.usbserial.driver.FtdiSerialDriver;
|
||||||
import com.hoho.android.usbserial.driver.ProbeTable;
|
import com.hoho.android.usbserial.driver.ProbeTable;
|
||||||
import com.hoho.android.usbserial.driver.UsbSerialProber;
|
import com.hoho.android.usbserial.driver.UsbSerialProber;
|
||||||
|
|
||||||
@ -14,7 +14,8 @@ class CustomProber {
|
|||||||
|
|
||||||
static UsbSerialProber getCustomProber() {
|
static UsbSerialProber getCustomProber() {
|
||||||
ProbeTable customTable = new ProbeTable();
|
ProbeTable customTable = new ProbeTable();
|
||||||
customTable.addProduct(0x16d0, 0x087e, CdcAcmSerialDriver.class); // e.g. Digispark CDC
|
customTable.addProduct(0x1234, 0x0001, FtdiSerialDriver.class); // e.g. device with custom VID+PID
|
||||||
|
customTable.addProduct(0x1234, 0x0002, FtdiSerialDriver.class); // e.g. device with custom VID+PID
|
||||||
return new UsbSerialProber(customTable);
|
return new UsbSerialProber(customTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,21 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
|
|||||||
public CdcAcmSerialDriver(UsbDevice device) {
|
public CdcAcmSerialDriver(UsbDevice device) {
|
||||||
mDevice = device;
|
mDevice = device;
|
||||||
mPorts = new ArrayList<>();
|
mPorts = new ArrayList<>();
|
||||||
|
int ports = countPorts(device);
|
||||||
|
for (int port = 0; port < ports; port++) {
|
||||||
|
mPorts.add(new CdcAcmSerialPort(mDevice, port));
|
||||||
|
}
|
||||||
|
if (mPorts.size() == 0) {
|
||||||
|
mPorts.add(new CdcAcmSerialPort(mDevice, -1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unused"})
|
||||||
|
public static boolean probe(UsbDevice device) {
|
||||||
|
return countPorts(device) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int countPorts(UsbDevice device) {
|
||||||
int controlInterfaceCount = 0;
|
int controlInterfaceCount = 0;
|
||||||
int dataInterfaceCount = 0;
|
int dataInterfaceCount = 0;
|
||||||
for (int i = 0; i < device.getInterfaceCount(); i++) {
|
for (int i = 0; i < device.getInterfaceCount(); i++) {
|
||||||
@ -46,12 +60,7 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
|
|||||||
if (device.getInterface(i).getInterfaceClass() == UsbConstants.USB_CLASS_CDC_DATA)
|
if (device.getInterface(i).getInterfaceClass() == UsbConstants.USB_CLASS_CDC_DATA)
|
||||||
dataInterfaceCount++;
|
dataInterfaceCount++;
|
||||||
}
|
}
|
||||||
for( int port = 0; port < Math.min(controlInterfaceCount, dataInterfaceCount); port++) {
|
return Math.min(controlInterfaceCount, dataInterfaceCount);
|
||||||
mPorts.add(new CdcAcmSerialPort(mDevice, port));
|
|
||||||
}
|
|
||||||
if(mPorts.size() == 0) {
|
|
||||||
mPorts.add(new CdcAcmSerialPort(mDevice, -1));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -297,51 +306,9 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unused"})
|
||||||
public static Map<Integer, int[]> getSupportedDevices() {
|
public static Map<Integer, int[]> getSupportedDevices() {
|
||||||
final Map<Integer, int[]> supportedDevices = new LinkedHashMap<>();
|
return new LinkedHashMap<>();
|
||||||
supportedDevices.put(UsbId.VENDOR_ARDUINO,
|
|
||||||
new int[] {
|
|
||||||
UsbId.ARDUINO_UNO,
|
|
||||||
UsbId.ARDUINO_UNO_R3,
|
|
||||||
UsbId.ARDUINO_MEGA_2560,
|
|
||||||
UsbId.ARDUINO_MEGA_2560_R3,
|
|
||||||
UsbId.ARDUINO_SERIAL_ADAPTER,
|
|
||||||
UsbId.ARDUINO_SERIAL_ADAPTER_R3,
|
|
||||||
UsbId.ARDUINO_MEGA_ADK,
|
|
||||||
UsbId.ARDUINO_MEGA_ADK_R3,
|
|
||||||
UsbId.ARDUINO_LEONARDO,
|
|
||||||
UsbId.ARDUINO_MICRO,
|
|
||||||
});
|
|
||||||
supportedDevices.put(UsbId.VENDOR_VAN_OOIJEN_TECH,
|
|
||||||
new int[] {
|
|
||||||
UsbId.VAN_OOIJEN_TECH_TEENSYDUINO_SERIAL,
|
|
||||||
});
|
|
||||||
supportedDevices.put(UsbId.VENDOR_ATMEL,
|
|
||||||
new int[] {
|
|
||||||
UsbId.ATMEL_LUFA_CDC_DEMO_APP,
|
|
||||||
});
|
|
||||||
supportedDevices.put(UsbId.VENDOR_LEAFLABS,
|
|
||||||
new int[] {
|
|
||||||
UsbId.LEAFLABS_MAPLE,
|
|
||||||
});
|
|
||||||
supportedDevices.put(UsbId.VENDOR_ARM,
|
|
||||||
new int[] {
|
|
||||||
UsbId.ARM_MBED,
|
|
||||||
});
|
|
||||||
supportedDevices.put(UsbId.VENDOR_ST,
|
|
||||||
new int[] {
|
|
||||||
UsbId.ST_CDC,
|
|
||||||
});
|
|
||||||
supportedDevices.put(UsbId.VENDOR_RASPBERRY_PI,
|
|
||||||
new int[] {
|
|
||||||
UsbId.RASPBERRY_PI_PICO_MICROPYTHON,
|
|
||||||
UsbId.RASPBERRY_PI_PICO_SDK,
|
|
||||||
});
|
|
||||||
supportedDevices.put(UsbId.VENDOR_QINHENG,
|
|
||||||
new int[] {
|
|
||||||
UsbId.QINHENG_CH9102F,
|
|
||||||
});
|
|
||||||
return supportedDevices;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -374,6 +374,7 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unused"})
|
||||||
public static Map<Integer, int[]> getSupportedDevices() {
|
public static Map<Integer, int[]> getSupportedDevices() {
|
||||||
final Map<Integer, int[]> supportedDevices = new LinkedHashMap<>();
|
final Map<Integer, int[]> supportedDevices = new LinkedHashMap<>();
|
||||||
supportedDevices.put(UsbId.VENDOR_QINHENG, new int[]{
|
supportedDevices.put(UsbId.VENDOR_QINHENG, new int[]{
|
||||||
|
@ -320,6 +320,7 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unused"})
|
||||||
public static Map<Integer, int[]> getSupportedDevices() {
|
public static Map<Integer, int[]> getSupportedDevices() {
|
||||||
final Map<Integer, int[]> supportedDevices = new LinkedHashMap<>();
|
final Map<Integer, int[]> supportedDevices = new LinkedHashMap<>();
|
||||||
supportedDevices.put(UsbId.VENDOR_SILABS,
|
supportedDevices.put(UsbId.VENDOR_SILABS,
|
||||||
|
@ -414,6 +414,7 @@ public class FtdiSerialDriver implements UsbSerialDriver {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unused"})
|
||||||
public static Map<Integer, int[]> getSupportedDevices() {
|
public static Map<Integer, int[]> getSupportedDevices() {
|
||||||
final Map<Integer, int[]> supportedDevices = new LinkedHashMap<>();
|
final Map<Integer, int[]> supportedDevices = new LinkedHashMap<>();
|
||||||
supportedDevices.put(UsbId.VENDOR_FTDI,
|
supportedDevices.put(UsbId.VENDOR_FTDI,
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
package com.hoho.android.usbserial.driver;
|
package com.hoho.android.usbserial.driver;
|
||||||
|
|
||||||
|
import android.hardware.usb.UsbDevice;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
@ -14,14 +15,14 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps (vendor id, product id) pairs to the corresponding serial driver.
|
* Maps (vendor id, product id) pairs to the corresponding serial driver,
|
||||||
*
|
* or invoke 'probe' method to check actual USB devices for matching interfaces.
|
||||||
* @author mike wakerly (opensource@hoho.com)
|
|
||||||
*/
|
*/
|
||||||
public class ProbeTable {
|
public class ProbeTable {
|
||||||
|
|
||||||
private final Map<Pair<Integer, Integer>, Class<? extends UsbSerialDriver>> mProbeTable =
|
private final Map<Pair<Integer, Integer>, Class<? extends UsbSerialDriver>> mVidPidProbeTable =
|
||||||
new LinkedHashMap<>();
|
new LinkedHashMap<>();
|
||||||
|
private final Map<Method, Class<? extends UsbSerialDriver>> mMethodProbeTable = new LinkedHashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds or updates a (vendor, product) pair in the table.
|
* Adds or updates a (vendor, product) pair in the table.
|
||||||
@ -33,7 +34,7 @@ public class ProbeTable {
|
|||||||
*/
|
*/
|
||||||
public ProbeTable addProduct(int vendorId, int productId,
|
public ProbeTable addProduct(int vendorId, int productId,
|
||||||
Class<? extends UsbSerialDriver> driverClass) {
|
Class<? extends UsbSerialDriver> driverClass) {
|
||||||
mProbeTable.put(Pair.create(vendorId, productId), driverClass);
|
mVidPidProbeTable.put(Pair.create(vendorId, productId), driverClass);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,12 +42,11 @@ public class ProbeTable {
|
|||||||
* Internal method to add all supported products from
|
* Internal method to add all supported products from
|
||||||
* {@code getSupportedProducts} static method.
|
* {@code getSupportedProducts} static method.
|
||||||
*
|
*
|
||||||
* @param driverClass
|
* @param driverClass to be added
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
ProbeTable addDriver(Class<? extends UsbSerialDriver> driverClass) {
|
void addDriver(Class<? extends UsbSerialDriver> driverClass) {
|
||||||
final Method method;
|
Method method;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
method = driverClass.getMethod("getSupportedDevices");
|
method = driverClass.getMethod("getSupportedDevices");
|
||||||
@ -68,20 +68,35 @@ public class ProbeTable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
try {
|
||||||
|
method = driverClass.getMethod("probe", UsbDevice.class);
|
||||||
|
mMethodProbeTable.put(method, driverClass);
|
||||||
|
} catch (SecurityException | NoSuchMethodException ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the driver for the given (vendor, product) pair, or {@code null}
|
* Returns the driver for the given USB device, or {@code null} if no match.
|
||||||
* if no match.
|
|
||||||
*
|
*
|
||||||
* @param vendorId the USB vendor id
|
* @param usbDevice the USB device to be probed
|
||||||
* @param productId the USB product id
|
|
||||||
* @return the driver class matching this pair, or {@code null}
|
* @return the driver class matching this pair, or {@code null}
|
||||||
*/
|
*/
|
||||||
public Class<? extends UsbSerialDriver> findDriver(int vendorId, int productId) {
|
public Class<? extends UsbSerialDriver> findDriver(final UsbDevice usbDevice) {
|
||||||
final Pair<Integer, Integer> pair = Pair.create(vendorId, productId);
|
final Pair<Integer, Integer> pair = Pair.create(usbDevice.getVendorId(), usbDevice.getProductId());
|
||||||
return mProbeTable.get(pair);
|
Class<? extends UsbSerialDriver> driverClass = mVidPidProbeTable.get(pair);
|
||||||
|
if (driverClass != null)
|
||||||
|
return driverClass;
|
||||||
|
for (Map.Entry<Method, Class<? extends UsbSerialDriver>> entry : mMethodProbeTable.entrySet()) {
|
||||||
|
try {
|
||||||
|
Method method = entry.getKey();
|
||||||
|
Object o = method.invoke(null, usbDevice);
|
||||||
|
if((boolean)o)
|
||||||
|
return entry.getValue();
|
||||||
|
} catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -566,6 +566,7 @@ public class ProlificSerialDriver implements UsbSerialDriver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unused"})
|
||||||
public static Map<Integer, int[]> getSupportedDevices() {
|
public static Map<Integer, int[]> getSupportedDevices() {
|
||||||
final Map<Integer, int[]> supportedDevices = new LinkedHashMap<>();
|
final Map<Integer, int[]> supportedDevices = new LinkedHashMap<>();
|
||||||
supportedDevices.put(UsbId.VENDOR_PROLIFIC,
|
supportedDevices.put(UsbId.VENDOR_PROLIFIC,
|
||||||
|
@ -23,27 +23,6 @@ public final class UsbId {
|
|||||||
public static final int FTDI_FT232H = 0x6014;
|
public static final int FTDI_FT232H = 0x6014;
|
||||||
public static final int FTDI_FT231X = 0x6015; // same ID for FT230X, FT231X, FT234XD
|
public static final int FTDI_FT231X = 0x6015; // same ID for FT230X, FT231X, FT234XD
|
||||||
|
|
||||||
public static final int VENDOR_ATMEL = 0x03EB;
|
|
||||||
public static final int ATMEL_LUFA_CDC_DEMO_APP = 0x2044;
|
|
||||||
|
|
||||||
public static final int VENDOR_ARDUINO = 0x2341;
|
|
||||||
public static final int ARDUINO_UNO = 0x0001;
|
|
||||||
public static final int ARDUINO_MEGA_2560 = 0x0010;
|
|
||||||
public static final int ARDUINO_SERIAL_ADAPTER = 0x003b;
|
|
||||||
public static final int ARDUINO_MEGA_ADK = 0x003f;
|
|
||||||
public static final int ARDUINO_MEGA_2560_R3 = 0x0042;
|
|
||||||
public static final int ARDUINO_UNO_R3 = 0x0043;
|
|
||||||
public static final int ARDUINO_MEGA_ADK_R3 = 0x0044;
|
|
||||||
public static final int ARDUINO_SERIAL_ADAPTER_R3 = 0x0044;
|
|
||||||
public static final int ARDUINO_LEONARDO = 0x8036;
|
|
||||||
public static final int ARDUINO_MICRO = 0x8037;
|
|
||||||
|
|
||||||
public static final int VENDOR_VAN_OOIJEN_TECH = 0x16c0;
|
|
||||||
public static final int VAN_OOIJEN_TECH_TEENSYDUINO_SERIAL = 0x0483;
|
|
||||||
|
|
||||||
public static final int VENDOR_LEAFLABS = 0x1eaf;
|
|
||||||
public static final int LEAFLABS_MAPLE = 0x0004;
|
|
||||||
|
|
||||||
public static final int VENDOR_SILABS = 0x10c4;
|
public static final int VENDOR_SILABS = 0x10c4;
|
||||||
public static final int SILABS_CP2102 = 0xea60; // same ID for CP2101, CP2103, CP2104, CP2109
|
public static final int SILABS_CP2102 = 0xea60; // same ID for CP2101, CP2103, CP2104, CP2109
|
||||||
public static final int SILABS_CP2105 = 0xea70;
|
public static final int SILABS_CP2105 = 0xea70;
|
||||||
@ -61,18 +40,7 @@ public final class UsbId {
|
|||||||
public static final int VENDOR_QINHENG = 0x1a86;
|
public static final int VENDOR_QINHENG = 0x1a86;
|
||||||
public static final int QINHENG_CH340 = 0x7523;
|
public static final int QINHENG_CH340 = 0x7523;
|
||||||
public static final int QINHENG_CH341A = 0x5523;
|
public static final int QINHENG_CH341A = 0x5523;
|
||||||
public static final int QINHENG_CH9102F = 0x55D4;
|
|
||||||
|
|
||||||
// at www.linux-usb.org/usb.ids listed for NXP/LPC1768, but all processors supported by ARM mbed DAPLink firmware report these ids
|
|
||||||
public static final int VENDOR_ARM = 0x0d28;
|
|
||||||
public static final int ARM_MBED = 0x0204;
|
|
||||||
|
|
||||||
public static final int VENDOR_ST = 0x0483;
|
|
||||||
public static final int ST_CDC = 0x5740;
|
|
||||||
|
|
||||||
public static final int VENDOR_RASPBERRY_PI = 0x2e8a;
|
|
||||||
public static final int RASPBERRY_PI_PICO_MICROPYTHON = 0x0005;
|
|
||||||
public static final int RASPBERRY_PI_PICO_SDK = 0x000a;
|
|
||||||
|
|
||||||
private UsbId() {
|
private UsbId() {
|
||||||
throw new IllegalAccessError("Non-instantiable class");
|
throw new IllegalAccessError("Non-instantiable class");
|
||||||
|
@ -10,12 +10,17 @@ import android.hardware.usb.UsbDevice;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author mike wakerly (opensource@hoho.com)
|
|
||||||
*/
|
|
||||||
public interface UsbSerialDriver {
|
public interface UsbSerialDriver {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Additional interface properties. Invoked thru reflection.
|
||||||
|
*
|
||||||
|
UsbSerialDriver(UsbDevice device); // constructor with device
|
||||||
|
static Map<Integer, int[]> getSupportedDevices();
|
||||||
|
static boolean probe(UsbDevice device); // optional
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the raw {@link UsbDevice} backing this port.
|
* Returns the raw {@link UsbDevice} backing this port.
|
||||||
*
|
*
|
||||||
|
@ -69,11 +69,7 @@ public class UsbSerialProber {
|
|||||||
* {@code null} if none available.
|
* {@code null} if none available.
|
||||||
*/
|
*/
|
||||||
public UsbSerialDriver probeDevice(final UsbDevice usbDevice) {
|
public UsbSerialDriver probeDevice(final UsbDevice usbDevice) {
|
||||||
final int vendorId = usbDevice.getVendorId();
|
final Class<? extends UsbSerialDriver> driverClass = mProbeTable.findDriver(usbDevice);
|
||||||
final int productId = usbDevice.getProductId();
|
|
||||||
|
|
||||||
final Class<? extends UsbSerialDriver> driverClass =
|
|
||||||
mProbeTable.findDriver(vendorId, productId);
|
|
||||||
if (driverClass != null) {
|
if (driverClass != null) {
|
||||||
final UsbSerialDriver driver;
|
final UsbSerialDriver driver;
|
||||||
try {
|
try {
|
||||||
|
85
usbSerialForAndroid/src/test/java/android/util/Pair.java
Normal file
85
usbSerialForAndroid/src/test/java/android/util/Pair.java
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.util;
|
||||||
|
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Container to ease passing around a tuple of two objects. This object provides a sensible
|
||||||
|
* implementation of equals(), returning true if equals() is true on each of the contained
|
||||||
|
* objects.
|
||||||
|
*/
|
||||||
|
public class Pair<F, S> {
|
||||||
|
public final F first;
|
||||||
|
public final S second;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for a Pair.
|
||||||
|
*
|
||||||
|
* @param first the first object in the Pair
|
||||||
|
* @param second the second object in the pair
|
||||||
|
*/
|
||||||
|
public Pair(F first, S second) {
|
||||||
|
this.first = first;
|
||||||
|
this.second = second;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the two objects for equality by delegating to their respective
|
||||||
|
* {@link Object#equals(Object)} methods.
|
||||||
|
*
|
||||||
|
* @param o the {@link Pair} to which this one is to be checked for equality
|
||||||
|
* @return true if the underlying objects of the Pair are both considered
|
||||||
|
* equal
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(@Nullable Object o) {
|
||||||
|
if (!(o instanceof Pair)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Pair<?, ?> p = (Pair<?, ?>) o;
|
||||||
|
return Objects.equals(p.first, first) && Objects.equals(p.second, second);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute a hash code using the hash codes of the underlying objects
|
||||||
|
*
|
||||||
|
* @return a hashcode of the Pair
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Pair{" + String.valueOf(first) + " " + String.valueOf(second) + "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience method for creating an appropriately typed pair.
|
||||||
|
* @param a the first object in the Pair
|
||||||
|
* @param b the second object in the pair
|
||||||
|
* @return a Pair that is templatized with the types of a and b
|
||||||
|
*/
|
||||||
|
public static <A, B> Pair <A, B> create(A a, B b) {
|
||||||
|
return new Pair<A, B>(a, b);
|
||||||
|
}
|
||||||
|
}
|
@ -53,6 +53,10 @@ public class CdcAcmSerialDriverTest {
|
|||||||
port.openInt();
|
port.openInt();
|
||||||
assertEquals(readEndpoint, port.mReadEndpoint);
|
assertEquals(readEndpoint, port.mReadEndpoint);
|
||||||
assertEquals(writeEndpoint, port.mWriteEndpoint);
|
assertEquals(writeEndpoint, port.mWriteEndpoint);
|
||||||
|
|
||||||
|
ProbeTable probeTable = UsbSerialProber.getDefaultProbeTable();
|
||||||
|
Class<? extends UsbSerialDriver> probeDriver = probeTable.findDriver(usbDevice);
|
||||||
|
assertEquals(driver.getClass(), probeDriver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -84,6 +88,10 @@ public class CdcAcmSerialDriverTest {
|
|||||||
port.openInt();
|
port.openInt();
|
||||||
assertEquals(readEndpoint, port.mReadEndpoint);
|
assertEquals(readEndpoint, port.mReadEndpoint);
|
||||||
assertEquals(writeEndpoint, port.mWriteEndpoint);
|
assertEquals(writeEndpoint, port.mWriteEndpoint);
|
||||||
|
|
||||||
|
ProbeTable probeTable = UsbSerialProber.getDefaultProbeTable();
|
||||||
|
Class<? extends UsbSerialDriver> probeDriver = probeTable.findDriver(usbDevice);
|
||||||
|
assertNull(probeDriver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
x
Reference in New Issue
Block a user