mirror of
				https://github.com/mik3y/usb-serial-for-android
				synced 2025-10-31 02:17:23 +00:00 
			
		
		
		
	PL2303 fix initial input control line values
This commit is contained in:
		
							parent
							
								
									732e138630
								
							
						
					
					
						commit
						08a93ec530
					
				| @ -1573,14 +1573,6 @@ public class DeviceTest { | |||||||
|         Thread.sleep(sleep); |         Thread.sleep(sleep); | ||||||
| 
 | 
 | ||||||
|         assertEquals(supportedControlLines, usb.serialPort.getSupportedControlLines()); |         assertEquals(supportedControlLines, usb.serialPort.getSupportedControlLines()); | ||||||
|         if(usb.serialDriver instanceof ProlificSerialDriver) { |  | ||||||
|             // the initial status is sometimes not available or wrong. |  | ||||||
|             // this is more likely if other tests have been executed before. |  | ||||||
|             // start thread and wait until status hopefully updated. |  | ||||||
|             usb.serialPort.getRI(); // todo |  | ||||||
|             Thread.sleep(sleep); |  | ||||||
|             assertTrue(usb.serialPort.getRI()); |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         // control lines reset on initial open |         // control lines reset on initial open | ||||||
|         data = "none".getBytes(); |         data = "none".getBytes(); | ||||||
| @ -1680,27 +1672,59 @@ public class DeviceTest { | |||||||
|         assertThat(usb.getControlLine(usb.serialPort::getCD), equalTo(inputLineFalse)); |         assertThat(usb.getControlLine(usb.serialPort::getCD), equalTo(inputLineFalse)); | ||||||
|         assertThat(usb.getControlLine(usb.serialPort::getRI), equalTo(inputLineFalse)); |         assertThat(usb.getControlLine(usb.serialPort::getRI), equalTo(inputLineFalse)); | ||||||
| 
 | 
 | ||||||
|  |         if (usb.serialDriver instanceof ProlificSerialDriver) { // check different control line mapping in GET_CONTROL_REQUEST | ||||||
|  |             usb.serialPort.setRTS(false); | ||||||
|  |             usb.serialPort.setDTR(false); | ||||||
|  |             usb.close(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT)); | ||||||
|  |             usb.open(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT, UsbWrapper.OpenCloseFlags.NO_IOMANAGER_THREAD)); | ||||||
|  |             assertEquals(EnumSet.of(UsbSerialPort.ControlLine.RI), usb.serialPort.getControlLines()); | ||||||
|  | 
 | ||||||
|  |             usb.serialPort.setRTS(true); | ||||||
|  |             usb.serialPort.setDTR(false); | ||||||
|  |             usb.close(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT)); | ||||||
|  |             usb.open(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT, UsbWrapper.OpenCloseFlags.NO_IOMANAGER_THREAD)); | ||||||
|  |             assertEquals(EnumSet.of(UsbSerialPort.ControlLine.RTS, UsbSerialPort.ControlLine.CTS), usb.serialPort.getControlLines()); | ||||||
|  | 
 | ||||||
|  |             usb.serialPort.setRTS(false); | ||||||
|  |             usb.serialPort.setDTR(true); | ||||||
|  |             usb.close(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT)); | ||||||
|  |             usb.open(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT, UsbWrapper.OpenCloseFlags.NO_IOMANAGER_THREAD)); | ||||||
|  |             assertEquals(EnumSet.of(UsbSerialPort.ControlLine.DTR, UsbSerialPort.ControlLine.DSR), usb.serialPort.getControlLines()); | ||||||
|  | 
 | ||||||
|  |             usb.serialPort.setRTS(true); | ||||||
|  |             usb.serialPort.setDTR(true); | ||||||
|  |             usb.close(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT)); | ||||||
|  |             usb.open(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT, UsbWrapper.OpenCloseFlags.NO_IOMANAGER_THREAD)); | ||||||
|  |             assertEquals(EnumSet.of(UsbSerialPort.ControlLine.RTS, UsbSerialPort.ControlLine.DTR, UsbSerialPort.ControlLine.CD), usb.serialPort.getControlLines()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // force error | ||||||
|         usb.close(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT)); |         usb.close(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT)); | ||||||
|         usb.open(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT, UsbWrapper.OpenCloseFlags.NO_IOMANAGER_THREAD)); |         usb.open(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT, UsbWrapper.OpenCloseFlags.NO_IOMANAGER_THREAD)); | ||||||
|  |         if (usb.serialDriver instanceof ProlificSerialDriver) { | ||||||
|  |             usb.serialPort.getRI(); // start background thread | ||||||
|  |         } | ||||||
|         usb.setParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE); |         usb.setParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE); | ||||||
|         for (int i = 0; i < usb.serialDriver.getDevice().getInterfaceCount(); i++) |         for (int i = 0; i < usb.serialDriver.getDevice().getInterfaceCount(); i++) | ||||||
|             usb.deviceConnection.releaseInterface(usb.serialDriver.getDevice().getInterface(i)); |             usb.deviceConnection.releaseInterface(usb.serialDriver.getDevice().getInterface(i)); | ||||||
|         usb.deviceConnection.close(); |         usb.deviceConnection.close(); | ||||||
| 
 | 
 | ||||||
|         // set... error |  | ||||||
|         try { |         try { | ||||||
|             usb.serialPort.setRTS(true); |             usb.serialPort.setRTS(true); | ||||||
|             fail("error expected"); |             fail("error expected"); | ||||||
|         } catch (IOException ignored) { |         } catch (IOException ignored) { | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // get... error |  | ||||||
|         try { |         try { | ||||||
|             usb.serialPort.getRI(); |             if (usb.serialDriver instanceof ProlificSerialDriver) { | ||||||
|             if (usb.serialDriver instanceof ProlificSerialDriver) |                 for(int i = 0; i < 10; i++) { // can take some time until background thread fails | ||||||
|                 ; // todo: currently not possible to detect, as bulkTransfer in background thread does not distinguish timeout and error |                     usb.serialPort.getRI(); | ||||||
|             else |                     Thread.sleep(100); | ||||||
|                 fail("error expected"); |                 } | ||||||
|  |             } else { | ||||||
|  |                 usb.serialPort.getRI(); | ||||||
|  |             } | ||||||
|  |             fail("error expected"); | ||||||
|         } catch (IOException ignored) { |         } catch (IOException ignored) { | ||||||
|         } catch (UnsupportedOperationException ignored) { |         } catch (UnsupportedOperationException ignored) { | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -19,7 +19,6 @@ import android.util.Log; | |||||||
| import com.hoho.android.usbserial.BuildConfig; | import com.hoho.android.usbserial.BuildConfig; | ||||||
| 
 | 
 | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.util.Arrays; |  | ||||||
| import java.util.Collections; | import java.util.Collections; | ||||||
| import java.util.EnumSet; | import java.util.EnumSet; | ||||||
| import java.util.LinkedHashMap; | import java.util.LinkedHashMap; | ||||||
| @ -76,12 +75,19 @@ public class ProlificSerialDriver implements UsbSerialDriver { | |||||||
|         private static final int FLUSH_RX_REQUEST = 0x08; // RX @ Prolific device = write @ usb-serial-for-android library |         private static final int FLUSH_RX_REQUEST = 0x08; // RX @ Prolific device = write @ usb-serial-for-android library | ||||||
|         private static final int FLUSH_TX_REQUEST = 0x09; |         private static final int FLUSH_TX_REQUEST = 0x09; | ||||||
| 
 | 
 | ||||||
|         private static final int SET_LINE_REQUEST = 0x20; |         private static final int SET_LINE_REQUEST = 0x20; // same as CDC SET_LINE_CODING | ||||||
|         private static final int SET_CONTROL_REQUEST = 0x22; |         private static final int SET_CONTROL_REQUEST = 0x22; // same as CDC SET_CONTROL_LINE_STATE | ||||||
|  |         private static final int GET_CONTROL_REQUEST = 0x87; | ||||||
|  |         private static final int STATUS_NOTIFICATION = 0xa1; // similar to CDC SERIAL_STATE but different length | ||||||
| 
 | 
 | ||||||
|         private static final int CONTROL_DTR = 0x01; |         private static final int CONTROL_DTR = 0x01; | ||||||
|         private static final int CONTROL_RTS = 0x02; |         private static final int CONTROL_RTS = 0x02; | ||||||
| 
 | 
 | ||||||
|  |         private static final int GET_CONTROL_FLAG_CD = 0x02; | ||||||
|  |         private static final int GET_CONTROL_FLAG_DSR = 0x04; | ||||||
|  |         private static final int GET_CONTROL_FLAG_RI = 0x01; | ||||||
|  |         private static final int GET_CONTROL_FLAG_CTS = 0x08; | ||||||
|  | 
 | ||||||
|         private static final int STATUS_FLAG_CD = 0x01; |         private static final int STATUS_FLAG_CD = 0x01; | ||||||
|         private static final int STATUS_FLAG_DSR = 0x02; |         private static final int STATUS_FLAG_DSR = 0x02; | ||||||
|         private static final int STATUS_FLAG_RI = 0x08; |         private static final int STATUS_FLAG_RI = 0x08; | ||||||
| @ -98,7 +104,7 @@ public class ProlificSerialDriver implements UsbSerialDriver { | |||||||
|         private int mStatus = 0; |         private int mStatus = 0; | ||||||
|         private volatile Thread mReadStatusThread = null; |         private volatile Thread mReadStatusThread = null; | ||||||
|         private final Object mReadStatusThreadLock = new Object(); |         private final Object mReadStatusThreadLock = new Object(); | ||||||
|         boolean mStopReadStatusThread = false; |         private boolean mStopReadStatusThread = false; | ||||||
|         private IOException mReadStatusException = null; |         private IOException mReadStatusException = null; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -111,51 +117,37 @@ public class ProlificSerialDriver implements UsbSerialDriver { | |||||||
|             return ProlificSerialDriver.this; |             return ProlificSerialDriver.this; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private final byte[] inControlTransfer(int requestType, int request, |         private byte[] inControlTransfer(int requestType, int request, int value, int index, int length) throws IOException { | ||||||
|                 int value, int index, int length) throws IOException { |  | ||||||
|             byte[] buffer = new byte[length]; |             byte[] buffer = new byte[length]; | ||||||
|             int result = mConnection.controlTransfer(requestType, request, value, |             int result = mConnection.controlTransfer(requestType, request, value, index, buffer, length, USB_READ_TIMEOUT_MILLIS); | ||||||
|                     index, buffer, length, USB_READ_TIMEOUT_MILLIS); |  | ||||||
|             if (result != length) { |             if (result != length) { | ||||||
|                 throw new IOException( |                 throw new IOException(String.format("ControlTransfer 0x%x failed: %d",value, result)); | ||||||
|                         String.format("ControlTransfer with value 0x%x failed: %d", |  | ||||||
|                                 value, result)); |  | ||||||
|             } |             } | ||||||
|             return buffer; |             return buffer; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private final void outControlTransfer(int requestType, int request, |         private void outControlTransfer(int requestType, int request, int value, int index, byte[] data) throws IOException { | ||||||
|                 int value, int index, byte[] data) throws IOException { |  | ||||||
|             int length = (data == null) ? 0 : data.length; |             int length = (data == null) ? 0 : data.length; | ||||||
|             int result = mConnection.controlTransfer(requestType, request, value, |             int result = mConnection.controlTransfer(requestType, request, value, index, data, length, USB_WRITE_TIMEOUT_MILLIS); | ||||||
|                     index, data, length, USB_WRITE_TIMEOUT_MILLIS); |  | ||||||
|             if (result != length) { |             if (result != length) { | ||||||
|                 throw new IOException( |                 throw new IOException( String.format("ControlTransfer 0x%x failed: %d", value, result)); | ||||||
|                         String.format("ControlTransfer with value 0x%x failed: %d", |  | ||||||
|                                 value, result)); |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private final byte[] vendorIn(int value, int index, int length) |         private byte[] vendorIn(int value, int index, int length) throws IOException { | ||||||
|                 throws IOException { |             return inControlTransfer(PROLIFIC_VENDOR_IN_REQTYPE, PROLIFIC_VENDOR_READ_REQUEST, value, index, length); | ||||||
|             return inControlTransfer(PROLIFIC_VENDOR_IN_REQTYPE, |  | ||||||
|                     PROLIFIC_VENDOR_READ_REQUEST, value, index, length); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private final void vendorOut(int value, int index, byte[] data) |         private void vendorOut(int value, int index, byte[] data) throws IOException { | ||||||
|                 throws IOException { |             outControlTransfer(PROLIFIC_VENDOR_OUT_REQTYPE, PROLIFIC_VENDOR_WRITE_REQUEST, value, index, data); | ||||||
|             outControlTransfer(PROLIFIC_VENDOR_OUT_REQTYPE, |  | ||||||
|                     PROLIFIC_VENDOR_WRITE_REQUEST, value, index, data); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private void resetDevice() throws IOException { |         private void resetDevice() throws IOException { | ||||||
|             purgeHwBuffers(true, true); |             purgeHwBuffers(true, true); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private final void ctrlOut(int request, int value, int index, byte[] data) |         private void ctrlOut(int request, int value, int index, byte[] data) throws IOException { | ||||||
|                 throws IOException { |             outControlTransfer(PROLIFIC_CTRL_OUT_REQTYPE, request, value, index, data); | ||||||
|             outControlTransfer(PROLIFIC_CTRL_OUT_REQTYPE, request, value, index, |  | ||||||
|                     data); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private void doBlackMagic() throws IOException { |         private void doBlackMagic() throws IOException { | ||||||
| @ -177,7 +169,7 @@ public class ProlificSerialDriver implements UsbSerialDriver { | |||||||
|             mControlLinesValue = newControlLinesValue; |             mControlLinesValue = newControlLinesValue; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private final void readStatusThreadFunction() { |         private void readStatusThreadFunction() { | ||||||
|             try { |             try { | ||||||
|                 while (!mStopReadStatusThread) { |                 while (!mStopReadStatusThread) { | ||||||
|                     byte[] buffer = new byte[STATUS_BUFFER_SIZE]; |                     byte[] buffer = new byte[STATUS_BUFFER_SIZE]; | ||||||
| @ -186,42 +178,33 @@ public class ProlificSerialDriver implements UsbSerialDriver { | |||||||
|                     if(readBytesCount == -1 && System.currentTimeMillis() < endTime) |                     if(readBytesCount == -1 && System.currentTimeMillis() < endTime) | ||||||
|                         testConnection(); |                         testConnection(); | ||||||
|                     if (readBytesCount > 0) { |                     if (readBytesCount > 0) { | ||||||
|                         if (readBytesCount == STATUS_BUFFER_SIZE) { |                         if (readBytesCount != STATUS_BUFFER_SIZE) { | ||||||
|                             mStatus = buffer[STATUS_BYTE_IDX] & 0xff; |                             throw new IOException("Invalid status notification, expected " + STATUS_BUFFER_SIZE + " bytes, got " + readBytesCount); | ||||||
|  |                         } else if(buffer[0] != (byte)STATUS_NOTIFICATION ) { | ||||||
|  |                             throw new IOException("Invalid status notification, expected " + STATUS_NOTIFICATION + " request, got " + buffer[0]); | ||||||
|                         } else { |                         } else { | ||||||
|                             throw new IOException( |                             mStatus = buffer[STATUS_BYTE_IDX] & 0xff; | ||||||
|                                     String.format("Invalid CTS / DSR / CD / RI status buffer received, expected %d bytes, but received %d", |  | ||||||
|                                             STATUS_BUFFER_SIZE, |  | ||||||
|                                             readBytesCount)); |  | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } catch (IOException e) { |             } catch (IOException e) { | ||||||
|                 mReadStatusException = e; |                 mReadStatusException = e; | ||||||
|             } |             } | ||||||
|  |             //Log.d(TAG, "end control line status thread " + mStopReadStatusThread + " " + (mReadStatusException == null ? "-" : mReadStatusException.getMessage())); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private final int getStatus() throws IOException { |         private int getStatus() throws IOException { | ||||||
|             if ((mReadStatusThread == null) && (mReadStatusException == null)) { |             if ((mReadStatusThread == null) && (mReadStatusException == null)) { | ||||||
|                 synchronized (mReadStatusThreadLock) { |                 synchronized (mReadStatusThreadLock) { | ||||||
|                     if (mReadStatusThread == null) { |                     if (mReadStatusThread == null) { | ||||||
|                         byte[] buffer = new byte[STATUS_BUFFER_SIZE]; |                         byte[] data = vendorIn(GET_CONTROL_REQUEST, 0, 1); | ||||||
|                         int readBytes = mConnection.bulkTransfer(mInterruptEndpoint, |                         mStatus = 0; | ||||||
|                                 buffer, |                         if((data[0] & GET_CONTROL_FLAG_CTS) == 0) mStatus |= STATUS_FLAG_CTS; | ||||||
|                                 STATUS_BUFFER_SIZE, |                         if((data[0] & GET_CONTROL_FLAG_DSR) == 0) mStatus |= STATUS_FLAG_DSR; | ||||||
|                                 100); |                         if((data[0] & GET_CONTROL_FLAG_CD) == 0) mStatus |= STATUS_FLAG_CD; | ||||||
|                         if (readBytes != STATUS_BUFFER_SIZE) { |                         if((data[0] & GET_CONTROL_FLAG_RI) == 0) mStatus |= STATUS_FLAG_RI; | ||||||
|                             Log.w(TAG, "Could not read initial CTS / DSR / CD / RI status"); |                         //Log.d(TAG, "start control line status thread " + mStatus); | ||||||
|                         } else { |                         mReadStatusThread = new Thread(this::readStatusThreadFunction); | ||||||
|                             mStatus = buffer[STATUS_BYTE_IDX] & 0xff; |  | ||||||
|                         } |  | ||||||
| 
 |  | ||||||
|                         mReadStatusThread = new Thread(new Runnable() { |  | ||||||
|                             @Override |  | ||||||
|                             public void run() { |  | ||||||
|                                 readStatusThreadFunction(); |  | ||||||
|                             } |  | ||||||
|                         }); |  | ||||||
|                         mReadStatusThread.setDaemon(true); |                         mReadStatusThread.setDaemon(true); | ||||||
|                         mReadStatusThread.start(); |                         mReadStatusThread.start(); | ||||||
|                     } |                     } | ||||||
| @ -238,7 +221,7 @@ public class ProlificSerialDriver implements UsbSerialDriver { | |||||||
|             return mStatus; |             return mStatus; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private final boolean testStatusFlag(int flag) throws IOException { |         private boolean testStatusFlag(int flag) throws IOException { | ||||||
|             return ((getStatus() & flag) == flag); |             return ((getStatus() & flag) == flag); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -296,14 +279,17 @@ public class ProlificSerialDriver implements UsbSerialDriver { | |||||||
|         @Override |         @Override | ||||||
|         public void closeInt() { |         public void closeInt() { | ||||||
|             try { |             try { | ||||||
|                 mStopReadStatusThread = true; |  | ||||||
|                 synchronized (mReadStatusThreadLock) { |                 synchronized (mReadStatusThreadLock) { | ||||||
|                     if (mReadStatusThread != null) { |                     if (mReadStatusThread != null) { | ||||||
|                         try { |                         try { | ||||||
|  |                             mStopReadStatusThread = true; | ||||||
|                             mReadStatusThread.join(); |                             mReadStatusThread.join(); | ||||||
|                         } catch (Exception e) { |                         } catch (Exception e) { | ||||||
|                             Log.w(TAG, "An error occured while waiting for status read thread", e); |                             Log.w(TAG, "An error occured while waiting for status read thread", e); | ||||||
|                         } |                         } | ||||||
|  |                         mStopReadStatusThread = false; | ||||||
|  |                         mReadStatusThread = null; | ||||||
|  |                         mReadStatusException = null; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 resetDevice(); |                 resetDevice(); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user