mirror of
				https://github.com/mik3y/usb-serial-for-android
				synced 2025-10-31 10:27:27 +00:00 
			
		
		
		
	read with timeout now throws error on connection lost, e.g. device disconnected
and similar connection lost detection for prolific input control lines
This commit is contained in:
		
							parent
							
								
									c53c3ed0ae
								
							
						
					
					
						commit
						26999e3626
					
				| @ -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) { | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user