diff --git a/.idea/misc.xml b/.idea/misc.xml
index c0f68ed..e0d5b93 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -5,27 +5,31 @@
-
+
diff --git a/README.md b/README.md
index 50a9551..e2fb7b2 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
This is a driver library for communication with Arduinos and other USB serial hardware on
Android, using the
[Android USB Host API](http://developer.android.com/guide/topics/connectivity/usb/host.html)
-available on Android 3.1+.
+available since Android 3.1 and asynchronous interrupt transfer working reliably since Android 4.2
No root access, ADK, or special kernel drivers are required; all drivers are implemented in
Java. You get a raw serial port with `read()`, `write()`, and other basic
diff --git a/build.gradle b/build.gradle
index df159ef..f055c90 100644
--- a/build.gradle
+++ b/build.gradle
@@ -6,7 +6,7 @@ buildscript {
google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.1.2'
+ classpath 'com.android.tools.build:gradle:3.3.0'
}
}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index eb10a04..b2a4404 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Tue Mar 27 21:28:01 CEST 2018
+#Sun Feb 03 09:37:03 CET 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
diff --git a/usbSerialExamples/build.gradle b/usbSerialExamples/build.gradle
index cde7b10..b45091c 100644
--- a/usbSerialExamples/build.gradle
+++ b/usbSerialExamples/build.gradle
@@ -1,12 +1,12 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 27
- buildToolsVersion '27.0.3'
+ compileSdkVersion 28
+ buildToolsVersion '28.0.3'
defaultConfig {
- minSdkVersion 14
- targetSdkVersion 27
+ minSdkVersion 17
+ targetSdkVersion 28
testInstrumentationRunner "android.test.InstrumentationTestRunner"
}
diff --git a/usbSerialExamples/src/main/AndroidManifest.xml b/usbSerialExamples/src/main/AndroidManifest.xml
index 26ca72c..efa205f 100644
--- a/usbSerialExamples/src/main/AndroidManifest.xml
+++ b/usbSerialExamples/src/main/AndroidManifest.xml
@@ -4,8 +4,6 @@
android:versionCode="1"
android:versionName="1.0" >
-
-
-
diff --git a/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/CdcAcmSerialDriver.java b/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/CdcAcmSerialDriver.java
index 3f4b96d..a3d9a76 100644
--- a/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/CdcAcmSerialDriver.java
+++ b/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/CdcAcmSerialDriver.java
@@ -27,7 +27,6 @@ import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbRequest;
-import android.os.Build;
import android.util.Log;
import java.io.IOException;
@@ -69,7 +68,6 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
class CdcAcmSerialPort extends CommonUsbSerialPort {
- private final boolean mEnableAsyncReads;
private UsbInterface mControlInterface;
private UsbInterface mDataInterface;
@@ -92,7 +90,6 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
public CdcAcmSerialPort(UsbDevice device, int portNumber) {
super(device, portNumber);
- mEnableAsyncReads = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1);
}
@Override
@@ -118,13 +115,6 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
openInterface();
}
- if (mEnableAsyncReads) {
- Log.d(TAG, "Async reads enabled");
- } else {
- Log.d(TAG, "Async reads disabled.");
- }
-
-
opened = true;
} finally {
if (!opened) {
@@ -269,51 +259,29 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
@Override
public int read(byte[] dest, int timeoutMillis) throws IOException {
- if (mEnableAsyncReads) {
- final UsbRequest request = new UsbRequest();
- try {
+ final UsbRequest request = new UsbRequest();
+ try {
request.initialize(mConnection, mReadEndpoint);
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) {
- throw new IOException("Error queueing request.");
+ throw new IOException("Error queueing request.");
}
final UsbRequest response = mConnection.requestWait();
if (response == null) {
- throw new IOException("Null response");
+ throw new IOException("Null response");
}
final int nread = buf.position();
if (nread > 0) {
- //Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
- return nread;
+ //Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
+ return nread;
} else {
- return 0;
- }
- } finally {
- request.close();
- }
- }
-
- final int numBytesRead;
- synchronized (mReadBufferLock) {
- int readAmt = Math.min(dest.length, mReadBuffer.length);
- numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
- timeoutMillis);
- if (numBytesRead < 0) {
- // This sucks: we get -1 on timeout, not 0 as preferred.
- // We *should* use UsbRequest, except it has a bug/api oversight
- // where there is no way to determine the number of bytes read
- // in response :\ -- http://b.android.com/28023
- if (timeoutMillis == Integer.MAX_VALUE) {
- // Hack: Special case "~infinite timeout" as an error.
- return -1;
- }
return 0;
}
- System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
+ } finally {
+ request.close();
}
- return numBytesRead;
}
@Override
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 48b26fc..0b0ae97 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
@@ -26,7 +26,6 @@ import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbRequest;
-import android.os.Build;
import android.util.Log;
import java.io.IOException;
@@ -84,14 +83,12 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
private boolean dtr = false;
private boolean rts = false;
- private final Boolean mEnableAsyncReads;
private UsbEndpoint mReadEndpoint;
private UsbEndpoint mWriteEndpoint;
private UsbRequest mUsbRequest;
public Ch340SerialPort(UsbDevice device, int portNumber) {
super(device, portNumber);
- mEnableAsyncReads = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1);
}
@Override
@@ -127,12 +124,6 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
}
}
- if (mEnableAsyncReads) {
- Log.d(TAG, "Async reads enabled");
- } else {
- Log.d(TAG, "Async reads disabled.");
- }
-
initialize();
setBaudRate(DEFAULT_BAUD_RATE);
@@ -153,12 +144,10 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
if (mConnection == null) {
throw new IOException("Already closed");
}
- synchronized (mEnableAsyncReads) {
+ synchronized (this) {
if (mUsbRequest != null)
mUsbRequest.cancel();
}
- // TODO: nothing sended on close, maybe needed?
-
try {
mConnection.close();
} finally {
@@ -169,50 +158,32 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
@Override
public int read(byte[] dest, int timeoutMillis) throws IOException {
- if (mEnableAsyncReads) {
- final UsbRequest request = new UsbRequest();
- try {
- request.initialize(mConnection, mReadEndpoint);
- final ByteBuffer buf = ByteBuffer.wrap(dest);
- 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");
- }
-
- final int nread = buf.position();
- if (nread > 0) {
- //Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
- return nread;
- } else {
- return 0;
- }
- } finally {
+ final UsbRequest request = new UsbRequest();
+ try {
+ request.initialize(mConnection, mReadEndpoint);
+ final ByteBuffer buf = ByteBuffer.wrap(dest);
+ if (!request.queue(buf, dest.length)) {
+ throw new IOException("Error queueing request.");
+ }
+ mUsbRequest = request;
+ final UsbRequest response = mConnection.requestWait();
+ synchronized (this) {
mUsbRequest = null;
- request.close();
}
- } else {
- final int numBytesRead;
- synchronized (mReadBufferLock) {
- int readAmt = Math.min(dest.length, mReadBuffer.length);
- numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
- timeoutMillis);
- if (numBytesRead < 0) {
- // This sucks: we get -1 on timeout, not 0 as preferred.
- // We *should* use UsbRequest, except it has a bug/api oversight
- // where there is no way to determine the number of bytes read
- // in response :\ -- http://b.android.com/28023
- return 0;
- }
- System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
+ if (response == null) {
+ throw new IOException("Null response");
}
- return numBytesRead;
+
+ final int nread = buf.position();
+ if (nread > 0) {
+ //Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
+ return nread;
+ } else {
+ return 0;
+ }
+ } finally {
+ mUsbRequest = null;
+ request.close();
}
}
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 2119130..4bc07ee 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
@@ -27,7 +27,6 @@ import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbRequest;
-import android.os.Build;
import android.util.Log;
import java.io.IOException;
@@ -107,7 +106,6 @@ 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 UsbEndpoint mReadEndpoint;
private UsbEndpoint mWriteEndpoint;
private UsbRequest mUsbRequest;
@@ -118,7 +116,6 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
public Cp21xxSerialPort(UsbDevice device, int portNumber) {
super(device, portNumber);
- mEnableAsyncReads = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1);
}
@Override
@@ -180,13 +177,16 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
if (mConnection == null) {
throw new IOException("Already closed");
}
- synchronized (mEnableAsyncReads) {
+ synchronized (this) {
if(mUsbRequest != null) {
mUsbRequest.cancel();
}
}
try {
setConfigSingle(SILABSER_IFC_ENABLE_REQUEST_CODE, UART_DISABLE);
+ } catch (Exception ignored)
+ {}
+ try {
mConnection.close();
} finally {
mConnection = null;
@@ -195,50 +195,32 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
@Override
public int read(byte[] dest, int timeoutMillis) throws IOException {
- if (mEnableAsyncReads) {
- final UsbRequest request = new UsbRequest();
- try {
- request.initialize(mConnection, mReadEndpoint);
- final ByteBuffer buf = ByteBuffer.wrap(dest);
- 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");
- }
-
- final int nread = buf.position();
- if (nread > 0) {
- //Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
- return nread;
- } else {
- return 0;
- }
- } finally {
+ final UsbRequest request = new UsbRequest();
+ try {
+ request.initialize(mConnection, mReadEndpoint);
+ final ByteBuffer buf = ByteBuffer.wrap(dest);
+ if (!request.queue(buf, dest.length)) {
+ throw new IOException("Error queueing request.");
+ }
+ mUsbRequest = request;
+ final UsbRequest response = mConnection.requestWait();
+ synchronized (this) {
mUsbRequest = null;
- request.close();
}
- } else {
- final int numBytesRead;
- synchronized (mReadBufferLock) {
- int readAmt = Math.min(dest.length, mReadBuffer.length);
- numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
- timeoutMillis);
- if (numBytesRead < 0) {
- // This sucks: we get -1 on timeout, not 0 as preferred.
- // We *should* use UsbRequest, except it has a bug/api oversight
- // where there is no way to determine the number of bytes read
- // in response :\ -- http://b.android.com/28023
- return 0;
- }
- System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
+ if (response == null) {
+ throw new IOException("Null response");
}
- return numBytesRead;
+
+ final int nread = buf.position();
+ if (nread > 0) {
+ //Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
+ return nread;
+ } else {
+ return 0;
+ }
+ } finally {
+ mUsbRequest = null;
+ request.close();
}
}
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 757c567..ccdc25e 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
@@ -26,7 +26,6 @@ import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbRequest;
-import android.os.Build;
import android.util.Log;
import java.io.IOException;
@@ -186,16 +185,8 @@ public class FtdiSerialDriver implements UsbSerialDriver {
private int mIndex = 0;
- /**
- * Due to http://b.android.com/28023 , we cannot use UsbRequest async reads
- * since it gives no indication of number of bytes read. Set this to
- * {@code true} on platforms where it is fixed.
- */
- private final boolean mEnableAsyncReads;
-
public FtdiSerialPort(UsbDevice device, int portNumber) {
super(device, portNumber);
- mEnableAsyncReads = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1);
}
@Override
@@ -286,46 +277,28 @@ public class FtdiSerialDriver implements UsbSerialDriver {
@Override
public int read(byte[] dest, int timeoutMillis) throws IOException {
final UsbEndpoint endpoint = mDevice.getInterface(mPortNumber).getEndpoint(0);
-
- if (mEnableAsyncReads) {
- final UsbRequest request = new UsbRequest();
- final ByteBuffer buf = ByteBuffer.wrap(dest);
- try {
- request.initialize(mConnection, endpoint);
- if (!request.queue(buf, dest.length)) {
- throw new IOException("Error queueing request.");
- }
-
- final UsbRequest response = mConnection.requestWait();
- if (response == null) {
- throw new IOException("Null response");
- }
- } finally {
- request.close();
+ final UsbRequest request = new UsbRequest();
+ final ByteBuffer buf = ByteBuffer.wrap(dest);
+ try {
+ request.initialize(mConnection, endpoint);
+ if (!request.queue(buf, dest.length)) {
+ throw new IOException("Error queueing request.");
}
- final int totalBytesRead = buf.position();
- if (totalBytesRead < MODEM_STATUS_HEADER_LENGTH) {
- throw new IOException("Expected at least " + MODEM_STATUS_HEADER_LENGTH + " bytes");
- }
-
- return filterStatusBytes(dest, dest, totalBytesRead, endpoint.getMaxPacketSize());
-
- } else {
- final int totalBytesRead;
-
- synchronized (mReadBufferLock) {
- final int readAmt = Math.min(dest.length, mReadBuffer.length);
- totalBytesRead = mConnection.bulkTransfer(endpoint, mReadBuffer,
- readAmt, timeoutMillis);
-
- if (totalBytesRead < MODEM_STATUS_HEADER_LENGTH) {
- throw new IOException("Expected at least " + MODEM_STATUS_HEADER_LENGTH + " bytes");
- }
-
- return filterStatusBytes(mReadBuffer, dest, totalBytesRead, endpoint.getMaxPacketSize());
+ final UsbRequest response = mConnection.requestWait();
+ if (response == null) {
+ throw new IOException("Null response");
}
+ } finally {
+ request.close();
}
+
+ final int totalBytesRead = buf.position();
+ if (totalBytesRead < MODEM_STATUS_HEADER_LENGTH) {
+ throw new IOException("Expected at least " + MODEM_STATUS_HEADER_LENGTH + " bytes");
+ }
+
+ return filterStatusBytes(dest, dest, totalBytesRead, endpoint.getMaxPacketSize());
}
@Override
diff --git a/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/ProlificSerialDriver.java b/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/ProlificSerialDriver.java
index 550350c..c3c8b23 100644
--- a/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/ProlificSerialDriver.java
+++ b/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/ProlificSerialDriver.java
@@ -33,7 +33,6 @@ import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbRequest;
-import android.os.Build;
import android.util.Log;
import java.io.IOException;
@@ -112,7 +111,6 @@ public class ProlificSerialDriver implements UsbSerialDriver {
private int mDeviceType = DEVICE_TYPE_HX;
- private final boolean mEnableAsyncReads;
private UsbEndpoint mReadEndpoint;
private UsbEndpoint mWriteEndpoint;
private UsbEndpoint mInterruptEndpoint;
@@ -130,7 +128,6 @@ public class ProlificSerialDriver implements UsbSerialDriver {
public ProlificSerialPort(UsbDevice device, int portNumber) {
super(device, portNumber);
- mEnableAsyncReads = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1);
}
@Override
@@ -373,41 +370,28 @@ public class ProlificSerialDriver implements UsbSerialDriver {
@Override
public int read(byte[] dest, int timeoutMillis) throws IOException {
- if (mEnableAsyncReads) {
- final UsbRequest request = new UsbRequest();
- try {
- request.initialize(mConnection, mReadEndpoint);
- final ByteBuffer buf = ByteBuffer.wrap(dest);
- if (!request.queue(buf, dest.length)) {
- throw new IOException("Error queueing request.");
- }
-
- final UsbRequest response = mConnection.requestWait();
- if (response == null) {
- throw new IOException("Null response");
- }
-
- final int nread = buf.position();
- if (nread > 0) {
- //Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
- return nread;
- } else {
- return 0;
- }
- } finally {
- request.close();
+ final UsbRequest request = new UsbRequest();
+ try {
+ request.initialize(mConnection, mReadEndpoint);
+ final ByteBuffer buf = ByteBuffer.wrap(dest);
+ if (!request.queue(buf, dest.length)) {
+ throw new IOException("Error queueing request.");
}
- } else {
- synchronized (mReadBufferLock) {
- int readAmt = Math.min(dest.length, mReadBuffer.length);
- int numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer,
- readAmt, timeoutMillis);
- if (numBytesRead < 0) {
- return 0;
- }
- System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
- return numBytesRead;
+
+ final UsbRequest response = mConnection.requestWait();
+ if (response == null) {
+ throw new IOException("Null response");
}
+
+ final int nread = buf.position();
+ if (nread > 0) {
+ //Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
+ return nread;
+ } else {
+ return 0;
+ }
+ } finally {
+ request.close();
}
}