1
0
mirror of https://github.com/mik3y/usb-serial-for-android synced 2025-06-07 16:06:10 +00:00

unify open() error handling, more tests, minor cleanup

This commit is contained in:
kai-morich 2019-11-02 13:03:11 +01:00
parent 6869eff88a
commit 18b5b6e648
8 changed files with 618 additions and 507 deletions

View File

@ -229,7 +229,7 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
private byte[] telnetRead(int expectedLength) throws Exception {
long end = System.currentTimeMillis() + TELNET_READ_WAIT;
ByteBuffer buf = ByteBuffer.allocate(4096);
ByteBuffer buf = ByteBuffer.allocate(8192);
while(System.currentTimeMillis() < end) {
if(telnetReadStream.available() > 0) {
buf.put((byte) telnetReadStream.read());
@ -498,23 +498,21 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
doReadWrite("");
usbClose();
usbSerialPort = usbSerialDriver.getPorts().get(test_device_port);
try {
usbSerialPort.close();
fail("already closed expected");
} catch (IOException ignored) {
} catch (NullPointerException ignored) {
}
try {
usbWrite(new byte[]{0x00});
fail("write error expected");
} catch (IOException ignored) {
} catch (NullPointerException ignored) {
}
try {
usbRead(1);
//fail("read error expected");
fail("read error expected");
} catch (IOException ignored) {
} catch (NullPointerException ignored) {
}
try {
usbParameters(9600, 8, 1, UsbSerialPort.PARITY_NONE);
@ -522,11 +520,22 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
} catch (IOException ignored) {
} catch (NullPointerException ignored) {
}
usbSerialPort = null;
usbOpen(true);
telnetParameters(9600, 8, 1, UsbSerialPort.PARITY_NONE);
usbParameters(9600, 8, 1, UsbSerialPort.PARITY_NONE);
doReadWrite("");
// close before iomanager
assertEquals(SerialInputOutputManager.State.RUNNING, usbIoManager.getState());
usbSerialPort.close();
for (int i = 0; i < 1000; i++) {
if (usbIoManager.getState() == SerialInputOutputManager.State.STOPPED)
break;
Thread.sleep(1);
}
assertEquals(SerialInputOutputManager.State.STOPPED, usbIoManager.getState());
}
@Test
@ -684,21 +693,21 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
usbParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
telnetParameters(19200, 7, 1, UsbSerialPort.PARITY_NONE);
telnetWrite(new byte[] {0x00});
Thread.sleep(1); // one bit is 0.05 milliseconds long, wait >> stop bit
Thread.sleep(10); // one bit is 0.05 milliseconds long, wait >> stop bit
telnetWrite(new byte[] {(byte)0xff});
data = usbRead(2);
assertThat("19200/7N1", data, equalTo(new byte[] {(byte)0x80, (byte)0xff}));
telnetParameters(19200, 6, 1, UsbSerialPort.PARITY_NONE);
telnetWrite(new byte[] {0x00});
Thread.sleep(1);
Thread.sleep(10);
telnetWrite(new byte[] {(byte)0xff});
data = usbRead(2);
assertThat("19000/6N1", data, equalTo(new byte[] {(byte)0xc0, (byte)0xff}));
telnetParameters(19200, 5, 1, UsbSerialPort.PARITY_NONE);
telnetWrite(new byte[] {0x00});
Thread.sleep(1);
Thread.sleep(10);
telnetWrite(new byte[] {(byte)0xff});
data = usbRead(2);
assertThat("19000/5N1", data, equalTo(new byte[] {(byte)0xe0, (byte)0xff}));
@ -708,7 +717,7 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
telnetParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
usbParameters(19200, 7, 1, UsbSerialPort.PARITY_NONE);
usbWrite(new byte[]{0x00});
Thread.sleep(1);
Thread.sleep(10);
usbWrite(new byte[]{(byte) 0xff});
data = telnetRead(2);
assertThat("19000/7N1", data, equalTo(new byte[]{(byte) 0x80, (byte) 0xff}));
@ -719,7 +728,7 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
try {
usbParameters(19200, 6, 1, UsbSerialPort.PARITY_NONE);
usbWrite(new byte[]{0x00});
Thread.sleep(1);
Thread.sleep(10);
usbWrite(new byte[]{(byte) 0xff});
data = telnetRead(2);
assertThat("19000/6N1", data, equalTo(new byte[]{(byte) 0xc0, (byte) 0xff}));
@ -730,7 +739,7 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
try {
usbParameters(19200, 5, 1, UsbSerialPort.PARITY_NONE);
usbWrite(new byte[] {0x00});
Thread.sleep(1);
Thread.sleep(5);
usbWrite(new byte[] {(byte)0xff});
data = telnetRead(2);
assertThat("19000/5N1", data, equalTo(new byte[] {(byte)0xe0, (byte)0xff}));
@ -1218,4 +1227,108 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
Thread.sleep(1);
}
}
@Test
public void wrongDriver() throws Exception {
UsbDeviceConnection wrongDeviceConnection;
UsbSerialDriver wrongSerialDriver;
UsbSerialPort wrongSerialPort;
if(!(usbSerialDriver instanceof CdcAcmSerialDriver)) {
wrongDeviceConnection = usbManager.openDevice(usbSerialDriver.getDevice());
wrongSerialDriver = new CdcAcmSerialDriver(usbSerialDriver.getDevice());
wrongSerialPort = wrongSerialDriver.getPorts().get(0);
try {
wrongSerialPort.open(wrongDeviceConnection);
wrongSerialPort.setParameters(115200, UsbSerialPort.DATABITS_8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE); // ch340 fails here
wrongSerialPort.write(new byte[]{1}, 1000); // pl2302 does not fail, but sends with wrong baud rate
if(!(usbSerialDriver instanceof ProlificSerialDriver))
fail("error expected");
} catch (IOException ignored) {
}
try {
if(usbSerialDriver instanceof ProlificSerialDriver) {
assertNotEquals(new byte[]{1}, telnetRead());
}
wrongSerialPort.close();
if(!(usbSerialDriver instanceof Ch34xSerialDriver |
usbSerialDriver instanceof ProlificSerialDriver))
fail("error expected");
} catch (IOException ignored) {
}
}
if(!(usbSerialDriver instanceof Ch34xSerialDriver)) {
wrongDeviceConnection = usbManager.openDevice(usbSerialDriver.getDevice());
wrongSerialDriver = new Ch34xSerialDriver(usbSerialDriver.getDevice());
wrongSerialPort = wrongSerialDriver.getPorts().get(0);
try {
wrongSerialPort.open(wrongDeviceConnection);
fail("error expected");
} catch (IOException ignored) {
}
try {
wrongSerialPort.close();
fail("error expected");
} catch (IOException ignored) {
}
}
// FTDI only recovers from Cp21xx control commands with power toggle, so skip this combination!
if(!(usbSerialDriver instanceof Cp21xxSerialDriver | usbSerialDriver instanceof FtdiSerialDriver)) {
wrongDeviceConnection = usbManager.openDevice(usbSerialDriver.getDevice());
wrongSerialDriver = new Cp21xxSerialDriver(usbSerialDriver.getDevice());
wrongSerialPort = wrongSerialDriver.getPorts().get(0);
try {
wrongSerialPort.open(wrongDeviceConnection);
//if(usbSerialDriver instanceof FtdiSerialDriver)
// wrongSerialPort.setParameters(115200, UsbSerialPort.DATABITS_8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE); // ch340 fails here
fail("error expected");
} catch (IOException ignored) {
}
try {
wrongSerialPort.close();
//if(!(usbSerialDriver instanceof FtdiSerialDriver))
// fail("error expected");
} catch (IOException ignored) {
}
}
if(!(usbSerialDriver instanceof FtdiSerialDriver)) {
wrongDeviceConnection = usbManager.openDevice(usbSerialDriver.getDevice());
wrongSerialDriver = new FtdiSerialDriver(usbSerialDriver.getDevice());
wrongSerialPort = wrongSerialDriver.getPorts().get(0);
try {
wrongSerialPort.open(wrongDeviceConnection);
if(usbSerialDriver instanceof Cp21xxSerialDriver)
wrongSerialPort.setParameters(115200, UsbSerialPort.DATABITS_8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE); // ch340 fails here
fail("error expected");
} catch (IOException ignored) {
}
try {
wrongSerialPort.close();
if(!(usbSerialDriver instanceof Cp21xxSerialDriver))
fail("error expected");
} catch (IOException ignored) {
}
}
if(!(usbSerialDriver instanceof ProlificSerialDriver)) {
wrongDeviceConnection = usbManager.openDevice(usbSerialDriver.getDevice());
wrongSerialDriver = new ProlificSerialDriver(usbSerialDriver.getDevice());
wrongSerialPort = wrongSerialDriver.getPorts().get(0);
try {
wrongSerialPort.open(wrongDeviceConnection);
fail("error expected");
} catch (IOException ignored) {
}
try {
wrongSerialPort.close();
fail("error expected");
} catch (IOException ignored) {
}
}
// test that device recovers from wrong commands
usbOpen(true);
telnetParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
usbParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
doReadWrite("");
}
}

View File

@ -107,7 +107,6 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
mConnection = connection;
boolean opened = false;
try {
if (1 == mDevice.getInterfaceCount()) {
Log.d(TAG,"device might be castrated ACM device, trying single interface logic");
openSingleInterface();
@ -115,15 +114,10 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
Log.d(TAG,"trying default interface logic");
openInterface();
}
opened = true;
} finally {
if (!opened) {
mConnection = null;
// just to be on the save side
mControlEndpoint = null;
mReadEndpoint = null;
mWriteEndpoint = null;
close();
}
}
}
@ -258,6 +252,9 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
if (mUsbRequest != null)
mUsbRequest.cancel();
}
mControlEndpoint = null;
mReadEndpoint = null;
mWriteEndpoint = null;
try {
mConnection.releaseInterface(mControlInterface);
mConnection.releaseInterface(mDataInterface);
@ -271,10 +268,11 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
@Override
public int read(byte[] dest, int timeoutMillis) throws IOException {
if(mConnection == null) {
throw new IOException("Connection closed");
}
final UsbRequest request = new UsbRequest();
try {
if(mConnection == null)
throw new IOException("Connection closed");
request.initialize(mConnection, mReadEndpoint);
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) {
@ -307,6 +305,9 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
// TODO(mikey): Nearly identical to FtdiSerial write. Refactor.
int offset = 0;
if(mConnection == null) {
throw new IOException("Connection closed");
}
while (offset < src.length) {
final int writeLength;
final int amtWritten;

View File

@ -130,11 +130,7 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
opened = true;
} finally {
if (!opened) {
try {
close();
} catch (IOException e) {
// Ignore IOExceptions during close()
}
}
}
}
@ -162,10 +158,11 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
@Override
public int read(byte[] dest, int timeoutMillis) throws IOException {
if(mConnection == null) {
throw new IOException("Connection closed");
}
final UsbRequest request = new UsbRequest();
try {
if(mConnection == null)
throw new IOException("Connection closed");
request.initialize(mConnection, mReadEndpoint);
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) {
@ -197,6 +194,9 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
public int write(byte[] src, int timeoutMillis) throws IOException {
int offset = 0;
if(mConnection == null) {
throw new IOException("Connection closed");
}
while (offset < src.length) {
final int writeLength;
final int amtWritten;

View File

@ -123,9 +123,13 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
return Cp21xxSerialDriver.this;
}
private int setConfigSingle(int request, int value) {
return mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, request, value,
private int setConfigSingle(int request, int value) throws IOException {
int result = mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, request, value,
mPortNumber, null, 0, USB_WRITE_TIMEOUT_MILLIS);
if (result != 0) {
throw new IOException("Setting baudrate failed: result=" + result);
}
return result;
}
@Override
@ -163,11 +167,7 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
opened = true;
} finally {
if (!opened) {
try {
close();
} catch (IOException e) {
// Ignore IOExceptions during close()
}
}
}
}
@ -197,10 +197,11 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
@Override
public int read(byte[] dest, int timeoutMillis) throws IOException {
if(mConnection == null) {
throw new IOException("Connection closed");
}
final UsbRequest request = new UsbRequest();
try {
if(mConnection == null)
throw new IOException("Connection closed");
request.initialize(mConnection, mReadEndpoint);
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) {
@ -232,6 +233,9 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
public int write(byte[] src, int timeoutMillis) throws IOException {
int offset = 0;
if(mConnection == null) {
throw new IOException("Connection closed");
}
while (offset < src.length) {
final int writeLength;
final int amtWritten;

View File

@ -257,7 +257,6 @@ public class FtdiSerialDriver implements UsbSerialDriver {
} finally {
if (!opened) {
close();
mConnection = null;
}
}
}
@ -279,12 +278,13 @@ public class FtdiSerialDriver implements UsbSerialDriver {
@Override
public int read(byte[] dest, int timeoutMillis) throws IOException {
if(mConnection == null) {
throw new IOException("Connection closed");
}
final UsbEndpoint endpoint = mDevice.getInterface(mPortNumber).getEndpoint(0);
final UsbRequest request = new UsbRequest();
final ByteBuffer buf = ByteBuffer.wrap(dest);
try {
if(mConnection == null)
throw new IOException("Connection closed");
request.initialize(mConnection, endpoint);
if (!request.queue(buf, dest.length)) {
throw new IOException("Error queueing request.");
@ -308,6 +308,9 @@ public class FtdiSerialDriver implements UsbSerialDriver {
@Override
public int write(byte[] src, int timeoutMillis) throws IOException {
if(mConnection == null) {
throw new IOException("Connection closed");
}
final UsbEndpoint endpoint = mDevice.getInterface(mPortNumber).getEndpoint(1);
int offset = 0;

View File

@ -65,25 +65,19 @@ public class ProbeTable {
try {
method = driverClass.getMethod("getSupportedDevices");
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
} catch (SecurityException | NoSuchMethodException e) {
throw new RuntimeException(e);
}
final Map<Integer, int[]> devices;
try {
devices = (Map<Integer, int[]>) method.invoke(null);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
} catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
for (Map.Entry<Integer, int[]> entry : devices.entrySet()) {
final int vendorId = entry.getKey().intValue();
final int vendorId = entry.getKey();
for (int productId : entry.getValue()) {
addProduct(vendorId, productId, driverClass);
}

View File

@ -336,8 +336,7 @@ public class ProlificSerialDriver implements UsbSerialDriver {
opened = true;
} finally {
if (!opened) {
mConnection = null;
connection.releaseInterface(usbInterface);
close();
}
}
}
@ -373,10 +372,11 @@ public class ProlificSerialDriver implements UsbSerialDriver {
@Override
public int read(byte[] dest, int timeoutMillis) throws IOException {
if(mConnection == null) {
throw new IOException("Connection closed");
}
final UsbRequest request = new UsbRequest();
try {
if(mConnection == null)
throw new IOException("Connection closed");
request.initialize(mConnection, mReadEndpoint);
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) {
@ -404,6 +404,9 @@ public class ProlificSerialDriver implements UsbSerialDriver {
public int write(byte[] src, int timeoutMillis) throws IOException {
int offset = 0;
if(mConnection == null) {
throw new IOException("Connection closed");
}
while (offset < src.length) {
final int writeLength;
final int amtWritten;

View File

@ -95,15 +95,8 @@ public class UsbSerialProber {
final Constructor<? extends UsbSerialDriver> ctor =
driverClass.getConstructor(UsbDevice.class);
driver = ctor.newInstance(usbDevice);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
} catch (NoSuchMethodException | IllegalArgumentException | InstantiationException |
IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
return driver;