diff --git a/README.md b/README.md
index 5037cc6..4b2b32b 100644
--- a/README.md
+++ b/README.md
@@ -33,66 +33,67 @@ dependencies {
}
```
-**2.** Copy [device_filter.xml](https://github.com/mik3y/usb-serial-for-android/blob/master/usbSerialExamples/src/main/res/xml/device_filter.xml) to your project's `res/xml/` directory.
-
-**3.** Configure your `AndroidManifest.xml` to notify your app when a device is attached (see [Android USB Host documentation](http://developer.android.com/guide/topics/connectivity/usb/host.html#discovering-d) for help).
+**2.** If the app should be notified when a device is attached, add
+[device_filter.xml](https://github.com/mik3y/usb-serial-for-android/blob/master/usbSerialExamples/src/main/res/xml/device_filter.xml)
+to your project's `res/xml/` directory and configure in your `AndroidManifest.xml`.
```xml
-
-
-
-
+
+
+
+
```
-**4.** Use it! Example code snippet:
+**3.** Use it! Example code snippet:
```java
-// Find all available drivers from attached devices.
-UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
-List availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager);
-if (availableDrivers.isEmpty()) {
- return;
-}
+ // Find all available drivers from attached devices.
+ UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
+ List availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager);
+ if (availableDrivers.isEmpty()) {
+ return;
+ }
-// Open a connection to the first available driver.
-UsbSerialDriver driver = availableDrivers.get(0);
-UsbDeviceConnection connection = manager.openDevice(driver.getDevice());
-if (connection == null) {
- // You probably need to call UsbManager.requestPermission(driver.getDevice(), ..)
- return;
-}
+ // Open a connection to the first available driver.
+ UsbSerialDriver driver = availableDrivers.get(0);
+ UsbDeviceConnection connection = manager.openDevice(driver.getDevice());
+ if (connection == null) {
+ // add UsbManager.requestPermission(driver.getDevice(), ..) handling here
+ return;
+ }
-// Read some data! Most have just one port (port 0).
-UsbSerialPort port = driver.getPorts().get(0);
-try {
- port.open(connection);
- port.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
-
- byte buffer[] = new byte[16];
- int numBytesRead = port.read(buffer, 1000);
- Log.d(TAG, "Read " + numBytesRead + " bytes.");
-} catch (IOException e) {
- // Deal with error.
-} finally {
- port.close();
+ UsbSerialPort port = driver.getPorts().get(0); // Most devices have just one port (port 0)
+ port.open(connection);
+ port.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
+ usbIoManager = new SerialInputOutputManager(usbSerialPort, this);
+ Executors.newSingleThreadExecutor().submit(usbIoManager);
+```
+```java
+ port.write("hello".getBytes(), WRITE_WAIT_MILLIS);
+```
+```java
+@Override
+public void onNewData(byte[] data) {
+ runOnUiThread(() -> { textView.append(new String(data)); });
}
```
+```java
+ port.close();
+```
-For a simple example, see the
-[UsbSerialExamples project](https://github.com/mik3y/usb-serial-for-android/blob/master/usbSerialExamples)
-in git, which is a simple application for reading and showing serial data.
+
+For a simple example, see
+[UsbSerialExamples](https://github.com/mik3y/usb-serial-for-android/blob/master/usbSerialExamples)
+folder in this project.
For a more complete example, see separate github project
-[SimpleUsbTerminal](https://github.com/kai-morich/SimpleUsbTerminal)
-
-A [simple Arduino application](https://github.com/mik3y/usb-serial-for-android/blob/master/arduino)
-is also available which can be used for testing.
+[SimpleUsbTerminal](https://github.com/kai-morich/SimpleUsbTerminal).
## Probing for Unrecognized Devices
diff --git a/test/serial_test/serial_test.ino b/test/serial_test/serial_test.ino
deleted file mode 100644
index 6964001..0000000
--- a/test/serial_test/serial_test.ino
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Copyright 2012 Google Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- *
- * Project home page: http://code.google.com/p/usb-serial-for-android/
- */
-
-// Sample Arduino sketch for use with usb-serial-for-android.
-// Prints an ever-increasing counter, and writes back anything
-// it receives.
-
-static int counter = 0;
-void setup() {
- Serial.begin(115200);
-}
-
-void loop() {
- Serial.print("Tick #");
- Serial.print(counter++, DEC);
- Serial.print("\n");
-
- if (Serial.peek() != -1) {
- Serial.print("Read: ");
- do {
- Serial.print((char) Serial.read());
- } while (Serial.peek() != -1);
- Serial.print("\n");
- }
- delay(1000);
-}
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 0ac13b9..4d92811 100644
--- a/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/DeviceTest.java
+++ b/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/DeviceTest.java
@@ -194,22 +194,7 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
try {
telnetRead(0);
} catch (Exception ignored) {}
-
- try {
- usbIoManager.setListener(null);
- usbIoManager.stop();
- } catch (Exception ignored) {}
- try {
- usbSerialPort.setDTR(false);
- usbSerialPort.setRTS(false);
- usbSerialPort.close();
- } catch (Exception ignored) {}
- try {
- usbDeviceConnection.close();
- } catch (Exception ignored) {}
- usbIoManager = null;
- usbSerialPort = null;
- usbDeviceConnection = null;
+ usbClose();
usbSerialDriver = null;
}
@@ -261,10 +246,15 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
private void usbClose() {
if (usbIoManager != null) {
+ usbIoManager.setListener(null);
usbIoManager.stop();
- usbIoManager = null;
}
if (usbSerialPort != null) {
+ try {
+ usbSerialPort.setDTR(false);
+ usbSerialPort.setRTS(false);
+ } catch (Exception ignored) {
+ }
try {
usbSerialPort.close();
} catch (IOException ignored) {
@@ -274,6 +264,18 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
if(usbDeviceConnection != null)
usbDeviceConnection.close();
usbDeviceConnection = null;
+ if(usbIoManager != null) {
+ for(int i=0; i<2000; i++) {
+ if(SerialInputOutputManager.State.STOPPED == usbIoManager.getState()) break;
+ try {
+ Thread.sleep(1);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ assertEquals(SerialInputOutputManager.State.STOPPED, usbIoManager.getState());
+ usbIoManager = null;
+ }
}
private void usbOpen(boolean withIoManager) throws Exception {
@@ -520,6 +522,11 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
usbSerialPort.close();
} catch (IOException ignored) {
}
+
+ if (usbSerialDriver instanceof Cp21xxSerialDriver) { // why needed?
+ usbIoManager.stop();
+ usbIoManager = null;
+ }
// full re-open supported
usbClose();
usbOpen(true);
@@ -640,8 +647,8 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
assertNotEquals(data1, buf1);
assertNotEquals(data2, buf2);
}
- assertThat("42000/8N1", data1, equalTo(buf1));
} else {
+ assertThat("42000/8N1", data1, equalTo(buf1));
assertThat("42000/8N1", data2, equalTo(buf2));
}
}
@@ -1109,4 +1116,85 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
// todo: purge receive buffer
}
+
+ @Test
+ // WriteAsync rarely makes sense, as data is not written until something is read
+ public void writeAsync() throws Exception {
+ if (usbSerialDriver instanceof FtdiSerialDriver)
+ return; // periodically sends status messages, so does not block here
+ usbParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
+ telnetParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
+
+ SerialInputOutputManager ioManager;
+ ioManager = new SerialInputOutputManager(null);
+ assertEquals(null, ioManager.getListener());
+ ioManager.setListener(this);
+ assertEquals(this, ioManager.getListener());
+ ioManager = new SerialInputOutputManager(null, this);
+ assertEquals(this, ioManager.getListener());
+
+ byte[] data, buf = new byte[]{1};
+ int len;
+ usbIoManager.writeAsync(buf);
+ usbIoManager.writeAsync(buf);
+ data = telnetRead(1);
+ assertEquals(0, data.length);
+ telnetWrite(buf);
+ data = usbRead(1);
+ assertEquals(1, data.length);
+ data = telnetRead(2);
+ assertEquals(2, data.length);
+ }
+
+ @Test
+ // Blocking read should be avoided in the UI thread, as it makes the app unresponsive.
+ // You better use the SerialInputOutputManager.
+ //
+ // With the change from bulkTransfer to queued requests, the read timeout has no effect
+ // and the call blocks until close() if no data is available!
+ // The change from bulkTransfer to queued requests was necessary to prevent data loss.
+ public void readSync() throws Exception {
+ if (usbSerialDriver instanceof FtdiSerialDriver)
+ return; // periodically sends status messages, so does not block here
+
+ Runnable closeThread = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ usbClose();
+ }
+ };
+
+ usbClose();
+ usbOpen(false);
+ usbParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
+ telnetParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
+
+ byte[] buf = new byte[]{1};
+ int len;
+ long time;
+ telnetWrite(buf);
+ len = usbSerialPort.read(buf, 0); // not blocking because data is available
+ assertEquals(1, len);
+
+ time = System.currentTimeMillis();
+ Executors.newSingleThreadExecutor().submit(closeThread);
+ len = usbSerialPort.read(buf, 0); // blocking until close()
+ assertEquals(0, len);
+ assertTrue(System.currentTimeMillis()-time >= 100);
+
+ usbOpen(false);
+ usbParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
+ telnetParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
+
+ time = System.currentTimeMillis();
+ Executors.newSingleThreadExecutor().submit(closeThread);
+ len = usbSerialPort.read(buf, 10); // timeout not used any more -> blocking until close()
+ assertEquals(0, len);
+ assertTrue(System.currentTimeMillis()-time >= 100);
+ }
}
diff --git a/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/util/SerialInputOutputManager.java b/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/util/SerialInputOutputManager.java
index 78bcd0b..1ab3edf 100644
--- a/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/util/SerialInputOutputManager.java
+++ b/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/util/SerialInputOutputManager.java
@@ -50,7 +50,7 @@ public class SerialInputOutputManager implements Runnable {
// Synchronized by 'mWriteBuffer'
private final ByteBuffer mWriteBuffer = ByteBuffer.allocate(BUFSIZ);
- private enum State {
+ public enum State {
STOPPED,
RUNNING,
STOPPING
@@ -111,7 +111,7 @@ public class SerialInputOutputManager implements Runnable {
}
}
- private synchronized State getState() {
+ public synchronized State getState() {
return mState;
}