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;