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:
parent
6869eff88a
commit
18b5b6e648
@ -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("");
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user