read with timeout now throws error on connection lost, e.g. device disconnected

and similar connection lost detection for prolific input control lines
pull/330/head v3.1.0
kai-morich 2020-09-06 19:58:18 +02:00
rodzic c53c3ed0ae
commit 26999e3626
4 zmienionych plików z 43 dodań i 13 usunięć

Wyświetl plik

@ -1660,18 +1660,27 @@ public class DeviceTest {
purged = false;
}
usb.deviceConnection.close();
try {
try { // only Prolific driver has early exit if nothing changed
usb.setParameters(115200, 8, 1, UsbSerialPort.PARITY_NONE);
if(!(usb.serialDriver instanceof ProlificSerialDriver))
fail("setParameters error expected");
} catch (IOException ignored) {
}
try {
usb.setParameters(57600, 8, 1, UsbSerialPort.PARITY_NONE);
fail("setParameters error expected");
} catch (IOException ignored) {
}
try {
usb.write("x".getBytes());
fail("write error expected");
} catch (IOException ignored) {
}
usb.serialPort.read(buf, 1000); // bulkTransfer returns -1 on timeout and error, so no exception thrown here
try {
usb.serialPort.read(buf, 1000);
fail("read error expected");
} catch (IOException ignored) {
}
try {
usb.serialPort.read(buf, 0);
fail("read error expected");
@ -1683,16 +1692,17 @@ public class DeviceTest {
} catch (IOException ignored) {
}
try {
if(usb.serialDriver instanceof ProlificSerialDriver)
Thread.sleep(600); // wait for background thread
usb.serialPort.getRI();
if(!(usb.serialDriver instanceof ProlificSerialDriver))
fail("getRI error expected");
fail("getRI error expected");
} catch (IOException ignored) {
} catch (UnsupportedOperationException ignored) {
}
if(purged) {
try {
usb.serialPort.purgeHwBuffers(true, true);
fail("setRts error expected");
fail("purgeHwBuffers error expected");
} catch (IOException ignored) {
}
}

Wyświetl plik

@ -129,13 +129,27 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort {
protected abstract void closeInt();
/**
* use simple USB request supported by all devices to test if connection is still valid
*/
protected void testConnection() throws IOException {
byte[] buf = new byte[2];
int len = mConnection.controlTransfer(0x80 /*DEVICE*/, 0 /*GET_STATUS*/, 0, 0, buf, buf.length, 200);
if(len < 0)
throw new IOException("USB get_status request failed");
}
@Override
public int read(final byte[] dest, final int timeout) throws IOException {
return read(dest, timeout, true);
}
protected int read(final byte[] dest, final int timeout, boolean testConnection) throws IOException {
if(mConnection == null) {
throw new IOException("Connection closed");
}
if(dest.length <= 0) {
throw new IllegalArgumentException("read buffer to small");
throw new IllegalArgumentException("Read buffer to small");
}
final int nread;
if (timeout != 0) {
@ -147,8 +161,12 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort {
// /system/lib64/libusbhost.so (usb_request_wait+192)
// /system/lib64/libandroid_runtime.so (android_hardware_UsbDeviceConnection_request_wait(_JNIEnv*, _jobject*, long)+84)
// data loss / crashes were observed with timeout up to 200 msec
long endTime = testConnection ? System.currentTimeMillis() + timeout : 0;
int readMax = Math.min(dest.length, MAX_READ_SIZE);
nread = mConnection.bulkTransfer(mReadEndpoint, dest, readMax, timeout);
// Android error propagation is improvable, nread == -1 can be: timeout, connection lost, buffer undersized, ...
if(nread == -1 && testConnection && System.currentTimeMillis() < endTime)
testConnection();
} else {
final ByteBuffer buf = ByteBuffer.wrap(dest);

Wyświetl plik

@ -138,7 +138,7 @@ public class FtdiSerialDriver implements UsbSerialDriver {
@Override
public int read(final byte[] dest, final int timeout) throws IOException {
if(dest.length <= READ_HEADER_LENGTH) {
throw new IllegalArgumentException("read buffer to small");
throw new IllegalArgumentException("Read buffer to small");
// could allocate larger buffer, including space for 2 header bytes, but this would
// result in buffers not being 64 byte aligned any more, causing data loss at continuous
// data transfer at high baud rates when buffers are fully filled.
@ -147,11 +147,13 @@ public class FtdiSerialDriver implements UsbSerialDriver {
if (timeout != 0) {
long endTime = System.currentTimeMillis() + timeout;
do {
nread = super.read(dest, Math.max(1, (int)(endTime - System.currentTimeMillis())));
nread = super.read(dest, Math.max(1, (int)(endTime - System.currentTimeMillis())), false);
} while (nread == READ_HEADER_LENGTH && System.currentTimeMillis() < endTime);
if(nread <= 0 && System.currentTimeMillis() < endTime)
testConnection();
} else {
do {
nread = super.read(dest, timeout);
nread = super.read(dest, timeout, false);
} while (nread == READ_HEADER_LENGTH);
}
return readFilter(dest, nread);

Wyświetl plik

@ -184,10 +184,10 @@ public class ProlificSerialDriver implements UsbSerialDriver {
try {
while (!mStopReadStatusThread) {
byte[] buffer = new byte[STATUS_BUFFER_SIZE];
int readBytesCount = mConnection.bulkTransfer(mInterruptEndpoint,
buffer,
STATUS_BUFFER_SIZE,
500);
long endTime = System.currentTimeMillis() + 500;
int readBytesCount = mConnection.bulkTransfer(mInterruptEndpoint, buffer, STATUS_BUFFER_SIZE, 500);
if(readBytesCount == -1 && System.currentTimeMillis() < endTime)
testConnection();
if (readBytesCount > 0) {
if (readBytesCount == STATUS_BUFFER_SIZE) {
mStatus = buffer[STATUS_BYTE_IDX] & 0xff;