From 61b272b8b6e087f0bc9b065eef1e7baf66412fa7 Mon Sep 17 00:00:00 2001
From: Kai Morich
Date: Thu, 10 May 2018 20:28:26 +0200
Subject: [PATCH] support ft_232h, cp210_ multiport devices
harmonize claimInterface() error handling
cancel read() on close()
---
.idea/.name | 1 -
.idea/compiler.xml | 21 ------
.idea/copyright/profiles_settings.xml | 3 -
.idea/misc.xml | 25 ++-----
build.gradle | 2 +-
usbSerialExamples/build.gradle | 4 +-
usbSerialForAndroid/build.gradle | 6 +-
.../hoho/android/usbserial/DeviceTest.java | 73 ++++++++++++++-----
.../usbserial/driver/Ch34xSerialDriver.java | 20 +++--
.../usbserial/driver/Cp21xxSerialDriver.java | 61 +++++++++++-----
.../usbserial/driver/FtdiSerialDriver.java | 65 +++++++++--------
.../hoho/android/usbserial/driver/UsbId.java | 3 +
12 files changed, 161 insertions(+), 123 deletions(-)
delete mode 100644 .idea/.name
delete mode 100644 .idea/compiler.xml
delete mode 100644 .idea/copyright/profiles_settings.xml
diff --git a/.idea/.name b/.idea/.name
deleted file mode 100644
index 88cdcce..0000000
--- a/.idea/.name
+++ /dev/null
@@ -1 +0,0 @@
-usb-serial-for-android
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
deleted file mode 100644
index 1f2af51..0000000
--- a/.idea/compiler.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
deleted file mode 100644
index e7bedf3..0000000
--- a/.idea/copyright/profiles_settings.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 13c4629..c0f68ed 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -5,11 +5,12 @@
@@ -24,26 +25,10 @@
-
+
-
-
-
-
- 1.8
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 089111f..df159ef 100644
--- a/build.gradle
+++ b/build.gradle
@@ -6,7 +6,7 @@ buildscript {
google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.1.1'
+ classpath 'com.android.tools.build:gradle:3.1.2'
}
}
diff --git a/usbSerialExamples/build.gradle b/usbSerialExamples/build.gradle
index 9fff8b3..cde7b10 100644
--- a/usbSerialExamples/build.gradle
+++ b/usbSerialExamples/build.gradle
@@ -1,12 +1,12 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 26
+ compileSdkVersion 27
buildToolsVersion '27.0.3'
defaultConfig {
minSdkVersion 14
- targetSdkVersion 26
+ targetSdkVersion 27
testInstrumentationRunner "android.test.InstrumentationTestRunner"
}
diff --git a/usbSerialForAndroid/build.gradle b/usbSerialForAndroid/build.gradle
index db097a5..d335842 100644
--- a/usbSerialForAndroid/build.gradle
+++ b/usbSerialForAndroid/build.gradle
@@ -3,12 +3,12 @@ apply plugin: 'maven'
apply plugin: 'signing'
android {
- compileSdkVersion 26
+ compileSdkVersion 27
buildToolsVersion '27.0.3'
defaultConfig {
minSdkVersion 14
- targetSdkVersion 26
+ targetSdkVersion 27
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
@@ -23,7 +23,7 @@ android {
dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support:support-annotations:27.1.1'
- androidTestImplementation 'com.android.support.test:runner:1.0.1'
+ androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'commons-net:commons-net:3.6'
androidTestImplementation 'org.apache.commons:commons-lang3:3.7'
}
diff --git a/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/DeviceTest.java b/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/DeviceTest.java
index 3b7abf9..e20ab5e 100644
--- a/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/DeviceTest.java
+++ b/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/DeviceTest.java
@@ -79,10 +79,12 @@ import static org.junit.Assert.fail;
@RunWith(AndroidJUnit4.class)
public class DeviceTest implements SerialInputOutputManager.Listener {
+ // configuration:
private final static String rfc2217_server_host = "192.168.0.100";
private final static int rfc2217_server_port = 2217;
private final static boolean rfc2217_server_nonstandard_baudrates = false; // false on Windows, Raspi
private final static boolean rfc2217_server_parity_mark_space = false; // false on Raspi
+ private final static int test_device_port = 0;
private final static int TELNET_READ_WAIT = 500;
private final static int USB_READ_WAIT = 500;
@@ -110,6 +112,7 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
private static OutputStream telnetWriteStream;
private static Integer[] telnetComPortOptionCounter = {0};
private int telnetWriteDelay = 0;
+ private boolean isCp21xxRestrictedPort = false; // second port of Cp2105 has limited dataBits, stopBits, parity
@BeforeClass
public static void setUpFixture() throws Exception {
@@ -149,10 +152,10 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
List availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(usbManager);
assertEquals("no usb device found", 1, availableDrivers.size());
usbSerialDriver = availableDrivers.get(0);
- assertEquals(1, usbSerialDriver.getPorts().size());
- usbSerialPort = usbSerialDriver.getPorts().get(0);
+ assertTrue( usbSerialDriver.getPorts().size() > test_device_port);
+ usbSerialPort = usbSerialDriver.getPorts().get(test_device_port);
Log.i(TAG, "Using USB device "+ usbSerialDriver.getClass().getSimpleName());
-
+ isCp21xxRestrictedPort = usbSerialDriver instanceof Cp21xxSerialDriver && usbSerialDriver.getPorts().size()==2 && test_device_port == 1;
if (!usbManager.hasPermission(usbSerialPort.getDriver().getDevice())) {
final Boolean[] granted = {Boolean.FALSE};
@@ -432,6 +435,7 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
; // todo: add range check in driver
else
fail("invalid baudrate 0");
+ } catch (java.io.IOException e) { // cp2105 second port
} catch (java.lang.IllegalArgumentException e) {
}
try {
@@ -445,6 +449,7 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
else
fail("invalid baudrate 0");
} catch (java.lang.ArithmeticException e) { // ch340
+ } catch (java.io.IOException e) { // cp2105 second port
} catch (java.lang.IllegalArgumentException e) {
}
try {
@@ -473,12 +478,21 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
else
fail("invalid baudrate 2^31");
} catch (java.lang.ArithmeticException e) { // ch340
+ } catch (java.io.IOException e) { // cp2105 second port
} catch (java.lang.IllegalArgumentException e) {
}
- for(int baudRate : new int[] {2400, 19200, 42000, 115200} ) {
+ for(int baudRate : new int[] {300, 2400, 19200, 42000, 115200} ) {
if(baudRate == 42000 && !rfc2217_server_nonstandard_baudrates)
continue; // rfc2217_server.py would terminate
+ if(baudRate == 300 && isCp21xxRestrictedPort) {
+ try {
+ usbParameters(baudRate, 8, 1, UsbSerialPort.PARITY_NONE);
+ assertTrue(false);
+ } catch (java.io.IOException e) {
+ }
+ continue;
+ }
telnetParameters(baudRate, 8, 1, UsbSerialPort.PARITY_NONE);
usbParameters(baudRate, 8, 1, UsbSerialPort.PARITY_NONE);
@@ -543,14 +557,18 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
assertThat("19000/5N1", data, equalTo(new byte[] {(byte)0xe0, (byte)0xff}));
// usb -> telnet
- telnetParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
- usbParameters(19200, 7, 1, UsbSerialPort.PARITY_NONE);
- usbWrite(new byte[] {0x00});
- Thread.sleep(1);
- usbWrite(new byte[] {(byte)0xff});
- data = telnetRead(2);
- assertThat("19000/7N1", data, equalTo(new byte[] {(byte)0x80, (byte)0xff}));
-
+ try {
+ telnetParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
+ usbParameters(19200, 7, 1, UsbSerialPort.PARITY_NONE);
+ usbWrite(new byte[]{0x00});
+ Thread.sleep(1);
+ usbWrite(new byte[]{(byte) 0xff});
+ data = telnetRead(2);
+ assertThat("19000/7N1", data, equalTo(new byte[]{(byte) 0x80, (byte) 0xff}));
+ } catch (java.lang.IllegalArgumentException e) {
+ if(!isCp21xxRestrictedPort)
+ throw e;
+ }
try {
usbParameters(19200, 6, 1, UsbSerialPort.PARITY_NONE);
usbWrite(new byte[]{0x00});
@@ -559,7 +577,7 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
data = telnetRead(2);
assertThat("19000/6N1", data, equalTo(new byte[]{(byte) 0xc0, (byte) 0xff}));
} catch (java.lang.IllegalArgumentException e) {
- if (!(usbSerialDriver instanceof FtdiSerialDriver))
+ if (!(isCp21xxRestrictedPort || usbSerialDriver instanceof FtdiSerialDriver))
throw e;
}
try {
@@ -570,7 +588,7 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
data = telnetRead(2);
assertThat("19000/5N1", data, equalTo(new byte[] {(byte)0xe0, (byte)0xff}));
} catch (java.lang.IllegalArgumentException e) {
- if (!(usbSerialDriver instanceof FtdiSerialDriver))
+ if (!(isCp21xxRestrictedPort || usbSerialDriver instanceof FtdiSerialDriver))
throw e;
}
}
@@ -592,6 +610,18 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
} catch (java.lang.IllegalArgumentException e) {
}
}
+ if(isCp21xxRestrictedPort) {
+ usbParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
+ usbParameters(19200, 8, 1, UsbSerialPort.PARITY_EVEN);
+ usbParameters(19200, 8, 1, UsbSerialPort.PARITY_ODD);
+ try {
+ usbParameters(19200, 8, 1, UsbSerialPort.PARITY_MARK);
+ usbParameters(19200, 8, 1, UsbSerialPort.PARITY_SPACE);
+ } catch (java.lang.IllegalArgumentException e) {
+ }
+ return;
+ // test below not possible as it requires unsupported 7 dataBits
+ }
// usb -> telnet
telnetParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
@@ -697,11 +727,16 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
// 1000001 0 10011111
// in 6N1: addddddo addddddo
// 100000 110100
- usbParameters(19200, 8, UsbSerialPort.STOPBITS_2, UsbSerialPort.PARITY_NONE);
- telnetParameters(19200, 6, 1, UsbSerialPort.PARITY_NONE);
- usbWrite(new byte[]{(byte)0x41, (byte)0xf9});
- data = telnetRead(2);
- assertThat("19200/8N1", data, equalTo(new byte[]{1, 11}));
+ try {
+ usbParameters(19200, 8, UsbSerialPort.STOPBITS_2, UsbSerialPort.PARITY_NONE);
+ telnetParameters(19200, 6, 1, UsbSerialPort.PARITY_NONE);
+ usbWrite(new byte[]{(byte) 0x41, (byte) 0xf9});
+ data = telnetRead(2);
+ assertThat("19200/8N1", data, equalTo(new byte[]{1, 11}));
+ } catch(java.lang.IllegalArgumentException e) {
+ if(!isCp21xxRestrictedPort)
+ throw e;
+ }
// todo: could create similar test for 1.5 stopbits, by reading at double speed
// but only some devices support 1.5 stopbits and it is basically not used any more
}
diff --git a/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/Ch34xSerialDriver.java b/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/Ch34xSerialDriver.java
index 7c8115c..48b26fc 100644
--- a/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/Ch34xSerialDriver.java
+++ b/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/Ch34xSerialDriver.java
@@ -84,9 +84,10 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
private boolean dtr = false;
private boolean rts = false;
- private final boolean mEnableAsyncReads;
+ private final Boolean mEnableAsyncReads;
private UsbEndpoint mReadEndpoint;
private UsbEndpoint mWriteEndpoint;
+ private UsbRequest mUsbRequest;
public Ch340SerialPort(UsbDevice device, int portNumber) {
super(device, portNumber);
@@ -109,10 +110,8 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
try {
for (int i = 0; i < mDevice.getInterfaceCount(); i++) {
UsbInterface usbIface = mDevice.getInterface(i);
- if (mConnection.claimInterface(usbIface, true)) {
- Log.d(TAG, "claimInterface " + i + " SUCCESS");
- } else {
- Log.d(TAG, "claimInterface " + i + " FAIL");
+ if (!mConnection.claimInterface(usbIface, true)) {
+ throw new IOException("Could not claim data interface.");
}
}
@@ -154,7 +153,10 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
if (mConnection == null) {
throw new IOException("Already closed");
}
-
+ synchronized (mEnableAsyncReads) {
+ if (mUsbRequest != null)
+ mUsbRequest.cancel();
+ }
// TODO: nothing sended on close, maybe needed?
try {
@@ -175,8 +177,11 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
if (!request.queue(buf, dest.length)) {
throw new IOException("Error queueing request.");
}
-
+ mUsbRequest = request;
final UsbRequest response = mConnection.requestWait();
+ synchronized (mEnableAsyncReads) {
+ mUsbRequest = null;
+ }
if (response == null) {
throw new IOException("Null response");
}
@@ -189,6 +194,7 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
return 0;
}
} finally {
+ mUsbRequest = null;
request.close();
}
} else {
diff --git a/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/Cp21xxSerialDriver.java b/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/Cp21xxSerialDriver.java
index e57d96a..2119130 100644
--- a/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/Cp21xxSerialDriver.java
+++ b/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/Cp21xxSerialDriver.java
@@ -32,7 +32,7 @@ import android.util.Log;
import java.io.IOException;
import java.nio.ByteBuffer;
-import java.util.Collections;
+import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -42,11 +42,14 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
private static final String TAG = Cp21xxSerialDriver.class.getSimpleName();
private final UsbDevice mDevice;
- private final UsbSerialPort mPort;
+ private final List mPorts;
public Cp21xxSerialDriver(UsbDevice device) {
mDevice = device;
- mPort = new Cp21xxSerialPort(mDevice, 0);
+ mPorts = new ArrayList<>();
+ for( int port = 0; port < device.getInterfaceCount(); port++) {
+ mPorts.add(new Cp21xxSerialPort(mDevice, port));
+ }
}
@Override
@@ -56,7 +59,7 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
@Override
public List getPorts() {
- return Collections.singletonList(mPort);
+ return mPorts;
}
public class Cp21xxSerialPort extends CommonUsbSerialPort {
@@ -104,9 +107,14 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
private static final int CONTROL_WRITE_DTR = 0x0100;
private static final int CONTROL_WRITE_RTS = 0x0200;
- private final boolean mEnableAsyncReads;
+ private final Boolean mEnableAsyncReads;
private UsbEndpoint mReadEndpoint;
private UsbEndpoint mWriteEndpoint;
+ private UsbRequest mUsbRequest;
+
+ // second port of Cp2105 has limited baudRate, dataBits, stopBits, parity
+ // unsupported baudrate returns error at controlTransfer(), other parameters are silently ignored
+ private boolean mIsRestrictedPort;
public Cp21xxSerialPort(UsbDevice device, int portNumber) {
super(device, portNumber);
@@ -120,7 +128,7 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
private int setConfigSingle(int request, int value) {
return mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, request, value,
- 0, null, 0, USB_WRITE_TIMEOUT_MILLIS);
+ mPortNumber, null, 0, USB_WRITE_TIMEOUT_MILLIS);
}
@Override
@@ -131,17 +139,15 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
mConnection = connection;
boolean opened = false;
+ mIsRestrictedPort = mDevice.getInterfaceCount() == 2 && mPortNumber == 1;
try {
- for (int i = 0; i < mDevice.getInterfaceCount(); i++) {
- UsbInterface usbIface = mDevice.getInterface(i);
- if (mConnection.claimInterface(usbIface, true)) {
- Log.d(TAG, "claimInterface " + i + " SUCCESS");
- } else {
- Log.d(TAG, "claimInterface " + i + " FAIL");
- }
+ if(mPortNumber >= mDevice.getInterfaceCount()) {
+ throw new IOException("Unknown port number");
+ }
+ UsbInterface dataIface = mDevice.getInterface(mPortNumber);
+ if (!mConnection.claimInterface(dataIface, true)) {
+ throw new IOException("Could not claim interface " + mPortNumber);
}
-
- UsbInterface dataIface = mDevice.getInterface(mDevice.getInterfaceCount() - 1);
for (int i = 0; i < dataIface.getEndpointCount(); i++) {
UsbEndpoint ep = dataIface.getEndpoint(i);
if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
@@ -174,6 +180,11 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
if (mConnection == null) {
throw new IOException("Already closed");
}
+ synchronized (mEnableAsyncReads) {
+ if(mUsbRequest != null) {
+ mUsbRequest.cancel();
+ }
+ }
try {
setConfigSingle(SILABSER_IFC_ENABLE_REQUEST_CODE, UART_DISABLE);
mConnection.close();
@@ -192,8 +203,11 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
if (!request.queue(buf, dest.length)) {
throw new IOException("Error queueing request.");
}
-
+ mUsbRequest = request;
final UsbRequest response = mConnection.requestWait();
+ synchronized (mEnableAsyncReads) {
+ mUsbRequest = null;
+ }
if (response == null) {
throw new IOException("Null response");
}
@@ -206,6 +220,7 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
return 0;
}
} finally {
+ mUsbRequest = null;
request.close();
}
} else {
@@ -269,7 +284,7 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
(byte) ((baudRate >> 24) & 0xff)
};
int ret = mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, SILABSER_SET_BAUDRATE,
- 0, 0, data, 4, USB_WRITE_TIMEOUT_MILLIS);
+ 0, mPortNumber, data, 4, USB_WRITE_TIMEOUT_MILLIS);
if (ret < 0) {
throw new IOException("Error setting baud rate.");
}
@@ -283,12 +298,18 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
int configDataBits = 0;
switch (dataBits) {
case DATABITS_5:
+ if(mIsRestrictedPort)
+ throw new IllegalArgumentException("Unsupported dataBits value: " + dataBits);
configDataBits |= 0x0500;
break;
case DATABITS_6:
+ if(mIsRestrictedPort)
+ throw new IllegalArgumentException("Unsupported dataBits value: " + dataBits);
configDataBits |= 0x0600;
break;
case DATABITS_7:
+ if(mIsRestrictedPort)
+ throw new IllegalArgumentException("Unsupported dataBits value: " + dataBits);
configDataBits |= 0x0700;
break;
case DATABITS_8:
@@ -308,9 +329,13 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
configDataBits |= 0x0020;
break;
case PARITY_MARK:
+ if(mIsRestrictedPort)
+ throw new IllegalArgumentException("Unsupported parity value: mark");
configDataBits |= 0x0030;
break;
case PARITY_SPACE:
+ if(mIsRestrictedPort)
+ throw new IllegalArgumentException("Unsupported parity value: space");
configDataBits |= 0x0040;
break;
default:
@@ -323,6 +348,8 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
case STOPBITS_1_5:
throw new IllegalArgumentException("Unsupported stopBits value: 1.5");
case STOPBITS_2:
+ if(mIsRestrictedPort)
+ throw new IllegalArgumentException("Unsupported stopBits value: 2");
configDataBits |= 2;
break;
default:
diff --git a/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/FtdiSerialDriver.java b/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/FtdiSerialDriver.java
index 56b98b8..757c567 100644
--- a/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/FtdiSerialDriver.java
+++ b/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/FtdiSerialDriver.java
@@ -29,11 +29,9 @@ import android.hardware.usb.UsbRequest;
import android.os.Build;
import android.util.Log;
-import com.hoho.android.usbserial.util.HexDump;
-
import java.io.IOException;
import java.nio.ByteBuffer;
-import java.util.Collections;
+import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -73,6 +71,8 @@ import java.util.Map;
* Supported and tested devices:
*
* - {@value DeviceType#TYPE_R}
+ * - {@value DeviceType#TYPE_2232H}
+ * - {@value DeviceType#TYPE_4232H}
*
*
*
@@ -80,8 +80,6 @@ import java.util.Map;
* feedback or patches):
*
* - {@value DeviceType#TYPE_2232C}
- * - {@value DeviceType#TYPE_2232H}
- * - {@value DeviceType#TYPE_4232H}
* - {@value DeviceType#TYPE_AM}
* - {@value DeviceType#TYPE_BM}
*
@@ -96,7 +94,7 @@ import java.util.Map;
public class FtdiSerialDriver implements UsbSerialDriver {
private final UsbDevice mDevice;
- private final UsbSerialPort mPort;
+ private final List mPorts;
/**
* FTDI chip types.
@@ -107,8 +105,12 @@ public class FtdiSerialDriver implements UsbSerialDriver {
public FtdiSerialDriver(UsbDevice device) {
mDevice = device;
- mPort = new FtdiSerialPort(mDevice, 0);
+ mPorts = new ArrayList<>();
+ for( int port = 0; port < device.getInterfaceCount(); port++) {
+ mPorts.add(new FtdiSerialPort(mDevice, port));
+ }
}
+
@Override
public UsbDevice getDevice() {
return mDevice;
@@ -116,7 +118,7 @@ public class FtdiSerialDriver implements UsbSerialDriver {
@Override
public List getPorts() {
- return Collections.singletonList(mPort);
+ return mPorts;
}
private class FtdiSerialPort extends CommonUsbSerialPort {
@@ -182,9 +184,7 @@ public class FtdiSerialDriver implements UsbSerialDriver {
private DeviceType mType;
- private int mInterface = 0; /* INTERFACE_ANY */
-
- private int mMaxPacketSize = 64; // TODO(mikey): detect
+ private int mIndex = 0;
/**
* Due to http://b.android.com/28023 , we cannot use UsbRequest async reads
@@ -230,14 +230,21 @@ public class FtdiSerialDriver implements UsbSerialDriver {
}
public void reset() throws IOException {
+ // TODO(mikey): autodetect.
+ mType = DeviceType.TYPE_R;
+ if(mDevice.getInterfaceCount() > 1) {
+ mIndex = mPortNumber + 1;
+ if (mDevice.getInterfaceCount() == 2)
+ mType = DeviceType.TYPE_2232H;
+ if (mDevice.getInterfaceCount() == 4)
+ mType = DeviceType.TYPE_4232H;
+ }
+
int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST,
- SIO_RESET_SIO, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS);
+ SIO_RESET_SIO, mIndex, null, 0, USB_WRITE_TIMEOUT_MILLIS);
if (result != 0) {
throw new IOException("Reset failed: result=" + result);
}
-
- // TODO(mikey): autodetect.
- mType = DeviceType.TYPE_R;
}
@Override
@@ -249,12 +256,10 @@ public class FtdiSerialDriver implements UsbSerialDriver {
boolean opened = false;
try {
- for (int i = 0; i < mDevice.getInterfaceCount(); i++) {
- if (connection.claimInterface(mDevice.getInterface(i), true)) {
- Log.d(TAG, "claimInterface " + i + " SUCCESS");
- } else {
- throw new IOException("Error claiming interface " + i);
- }
+ if (connection.claimInterface(mDevice.getInterface(mPortNumber), true)) {
+ Log.d(TAG, "claimInterface " + mPortNumber + " SUCCESS");
+ } else {
+ throw new IOException("Error claiming interface " + mPortNumber);
}
reset();
opened = true;
@@ -280,7 +285,7 @@ public class FtdiSerialDriver implements UsbSerialDriver {
@Override
public int read(byte[] dest, int timeoutMillis) throws IOException {
- final UsbEndpoint endpoint = mDevice.getInterface(0).getEndpoint(0);
+ final UsbEndpoint endpoint = mDevice.getInterface(mPortNumber).getEndpoint(0);
if (mEnableAsyncReads) {
final UsbRequest request = new UsbRequest();
@@ -325,7 +330,7 @@ public class FtdiSerialDriver implements UsbSerialDriver {
@Override
public int write(byte[] src, int timeoutMillis) throws IOException {
- final UsbEndpoint endpoint = mDevice.getInterface(0).getEndpoint(1);
+ final UsbEndpoint endpoint = mDevice.getInterface(mPortNumber).getEndpoint(1);
int offset = 0;
while (offset < src.length) {
@@ -425,7 +430,7 @@ public class FtdiSerialDriver implements UsbSerialDriver {
}
int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE,
- SIO_SET_DATA_REQUEST, config, 0 /* index */,
+ SIO_SET_DATA_REQUEST, config, mIndex,
null, 0, USB_WRITE_TIMEOUT_MILLIS);
if (result != 0) {
throw new IOException("Setting parameters failed: result=" + result);
@@ -505,9 +510,8 @@ public class FtdiSerialDriver implements UsbSerialDriver {
long index;
if (mType == DeviceType.TYPE_2232C || mType == DeviceType.TYPE_2232H
|| mType == DeviceType.TYPE_4232H) {
- index = (encodedDivisor >> 8) & 0xffff;
- index &= 0xFF00;
- index |= 0 /* TODO mIndex */;
+ index = (encodedDivisor >> 8) & 0xff00;
+ index |= mIndex;
} else {
index = (encodedDivisor >> 16) & 0xffff;
}
@@ -560,7 +564,7 @@ public class FtdiSerialDriver implements UsbSerialDriver {
public boolean purgeHwBuffers(boolean purgeReadBuffers, boolean purgeWriteBuffers) throws IOException {
if (purgeReadBuffers) {
int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST,
- SIO_RESET_PURGE_RX, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS);
+ SIO_RESET_PURGE_RX, mIndex, null, 0, USB_WRITE_TIMEOUT_MILLIS);
if (result != 0) {
throw new IOException("Flushing RX failed: result=" + result);
}
@@ -568,7 +572,7 @@ public class FtdiSerialDriver implements UsbSerialDriver {
if (purgeWriteBuffers) {
int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST,
- SIO_RESET_PURGE_TX, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS);
+ SIO_RESET_PURGE_TX, mIndex, null, 0, USB_WRITE_TIMEOUT_MILLIS);
if (result != 0) {
throw new IOException("Flushing RX failed: result=" + result);
}
@@ -582,6 +586,9 @@ public class FtdiSerialDriver implements UsbSerialDriver {
supportedDevices.put(Integer.valueOf(UsbId.VENDOR_FTDI),
new int[] {
UsbId.FTDI_FT232R,
+ UsbId.FTDI_FT232H,
+ UsbId.FTDI_FT2232H,
+ UsbId.FTDI_FT4232H,
UsbId.FTDI_FT231X,
});
return supportedDevices;
diff --git a/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/UsbId.java b/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/UsbId.java
index fda7d1f..7bba4db 100644
--- a/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/UsbId.java
+++ b/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/UsbId.java
@@ -33,6 +33,9 @@ public final class UsbId {
public static final int VENDOR_FTDI = 0x0403;
public static final int FTDI_FT232R = 0x6001;
+ public static final int FTDI_FT2232H = 0x6010;
+ public static final int FTDI_FT4232H = 0x6011;
+ public static final int FTDI_FT232H = 0x6014;
public static final int FTDI_FT231X = 0x6015;
public static final int VENDOR_ATMEL = 0x03EB;