1
0
mirror of https://github.com/mik3y/usb-serial-for-android.git synced 2026-08-11 16:32:53 +00:00

support multi-port CDC devices

This commit is contained in:
kai-morich
2020-01-08 17:11:08 +01:00
parent ce97a3408b
commit bbed92eafb
12 changed files with 2375 additions and 51 deletions
@@ -164,6 +164,11 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
context = InstrumentationRegistry.getContext();
usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(usbManager);
if(availableDrivers.isEmpty()) {
ProbeTable customTable = new ProbeTable();
customTable.addProduct(0x2342, 0x8036, CdcAcmSerialDriver.class); // arduino multiport cdc witch custom VID
availableDrivers = new UsbSerialProber(customTable).findAllDrivers(usbManager);
}
assertEquals("no USB device found", 1, availableDrivers.size());
usbSerialDriver = availableDrivers.get(0);
if(test_device_driver != null) {
@@ -29,7 +29,7 @@ import android.hardware.usb.UsbInterface;
import android.util.Log;
import java.io.IOException;
import java.util.Collections;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -47,11 +47,26 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
private final String TAG = CdcAcmSerialDriver.class.getSimpleName();
private final UsbDevice mDevice;
private final UsbSerialPort mPort;
private final List<UsbSerialPort> mPorts;
public CdcAcmSerialDriver(UsbDevice device) {
mDevice = device;
mPort = new CdcAcmSerialPort(device, 0);
mPorts = new ArrayList<>();
int controlInterfaceCount = 0;
int dataInterfaceCount = 0;
for( int i = 0; i < device.getInterfaceCount(); i++) {
if(device.getInterface(i).getInterfaceClass() == UsbConstants.USB_CLASS_COMM)
controlInterfaceCount++;
if(device.getInterface(i).getInterfaceClass() == UsbConstants.USB_CLASS_CDC_DATA)
dataInterfaceCount++;
}
for( int port = 0; port < Math.min(controlInterfaceCount, dataInterfaceCount); port++) {
mPorts.add(new CdcAcmSerialPort(mDevice, port));
}
if(mPorts.size() == 0) {
mPorts.add(new CdcAcmSerialPort(mDevice, -1));
}
}
@Override
@@ -61,7 +76,7 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
@Override
public List<UsbSerialPort> getPorts() {
return Collections.singletonList(mPort);
return mPorts;
}
class CdcAcmSerialPort extends CommonUsbSerialPort {
@@ -95,7 +110,7 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
@Override
public void openInt(UsbDeviceConnection connection) throws IOException {
if (1 == mDevice.getInterfaceCount()) {
if (mPortNumber == -1) {
Log.d(TAG,"device might be castrated ACM device, trying single interface logic");
openSingleInterface();
} else {
@@ -105,77 +120,51 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
}
private void openSingleInterface() throws IOException {
// the following code is inspired by the cdc-acm driver
// in the linux kernel
// the following code is inspired by the cdc-acm driver in the linux kernel
mControlIndex = 0;
mControlInterface = mDevice.getInterface(0);
Log.d(TAG, "Control iface=" + mControlInterface);
mDataInterface = mDevice.getInterface(0);
Log.d(TAG, "data iface=" + mDataInterface);
if (!mConnection.claimInterface(mControlInterface, true)) {
throw new IOException("Could not claim shared control/data interface");
}
int endCount = mControlInterface.getEndpointCount();
if (endCount < 3) {
Log.d(TAG,"not enough endpoints - need 3. count=" + mControlInterface.getEndpointCount());
throw new IOException("Insufficient number of endpoints (" + mControlInterface.getEndpointCount() + ")");
}
// Analyse endpoints for their properties
mControlEndpoint = null;
mReadEndpoint = null;
mWriteEndpoint = null;
for (int i = 0; i < endCount; ++i) {
for (int i = 0; i < mControlInterface.getEndpointCount(); ++i) {
UsbEndpoint ep = mControlInterface.getEndpoint(i);
if ((ep.getDirection() == UsbConstants.USB_DIR_IN) &&
(ep.getType() == UsbConstants.USB_ENDPOINT_XFER_INT)) {
Log.d(TAG,"Found controlling endpoint");
if ((ep.getDirection() == UsbConstants.USB_DIR_IN) && (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_INT)) {
mControlEndpoint = ep;
} else if ((ep.getDirection() == UsbConstants.USB_DIR_IN) &&
(ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)) {
Log.d(TAG,"Found reading endpoint");
} else if ((ep.getDirection() == UsbConstants.USB_DIR_IN) && (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)) {
mReadEndpoint = ep;
} else if ((ep.getDirection() == UsbConstants.USB_DIR_OUT) &&
(ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)) {
Log.d(TAG,"Found writing endpoint");
} else if ((ep.getDirection() == UsbConstants.USB_DIR_OUT) && (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)) {
mWriteEndpoint = ep;
}
if ((mControlEndpoint != null) &&
(mReadEndpoint != null) &&
(mWriteEndpoint != null)) {
Log.d(TAG,"Found all required endpoints");
break;
}
}
if ((mControlEndpoint == null) ||
(mReadEndpoint == null) ||
(mWriteEndpoint == null)) {
Log.d(TAG,"Could not establish all endpoints");
throw new IOException("Could not establish all endpoints");
if (mControlEndpoint == null) {
throw new IOException("No control endpoint");
}
}
private void openInterface() throws IOException {
Log.d(TAG, "claiming interfaces, count=" + mDevice.getInterfaceCount());
int controlInterfaceCount = 0;
int dataInterfaceCount = 0;
mControlInterface = null;
mDataInterface = null;
for (int i = 0; i < mDevice.getInterfaceCount(); i++) {
UsbInterface usbInterface = mDevice.getInterface(i);
if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_COMM) {
mControlIndex = i;
mControlInterface = usbInterface;
if(controlInterfaceCount == mPortNumber) {
mControlIndex = i;
mControlInterface = usbInterface;
}
controlInterfaceCount++;
}
if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_CDC_DATA) {
mDataInterface = usbInterface;
if(dataInterfaceCount == mPortNumber) {
mDataInterface = usbInterface;
}
dataInterfaceCount++;
}
}
@@ -202,8 +191,6 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
throw new IOException("Could not claim data interface");
}
mReadEndpoint = null;
mWriteEndpoint = null;
for (int i = 0; i < mDataInterface.getEndpointCount(); i++) {
UsbEndpoint ep = mDataInterface.getEndpoint(i);
if (ep.getDirection() == UsbConstants.USB_DIR_IN && ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)