mirror of
				https://github.com/mik3y/usb-serial-for-android
				synced 2025-10-31 10:27:27 +00:00 
			
		
		
		
	support PL2303GC/GB/GT/GL/GE/GS
see https://lore.kernel.org/linux-usb/20190213123000.4656-1-charlesyeh522@gmail.com/
This commit is contained in:
		
							parent
							
								
									2f23bdfb6d
								
							
						
					
					
						commit
						c82cd284ae
					
				| @ -12,8 +12,14 @@ | ||||
|     <usb-device vendor-id="4292" product-id="60016" /> <!-- 0xea70: CP2105 --> | ||||
|     <usb-device vendor-id="4292" product-id="60017" /> <!-- 0xea71: CP2108 --> | ||||
| 
 | ||||
|     <!-- 0x067B / 0x2303: Prolific PL2303 --> | ||||
|     <usb-device vendor-id="1659" product-id="8963" /> | ||||
|     <!-- 0x067B / 0x23?3: Prolific PL2303x --> | ||||
|     <usb-device vendor-id="1659" product-id="8963" /> <!-- 0x2303: PL2303HX, HXD, TA, ... --> | ||||
|     <usb-device vendor-id="1659" product-id="9123" /> <!-- 0x23a3: PL2303GC --> | ||||
|     <usb-device vendor-id="1659" product-id="9139" /> <!-- 0x23b3: PL2303GB --> | ||||
|     <usb-device vendor-id="1659" product-id="9155" /> <!-- 0x23c3: PL2303GT --> | ||||
|     <usb-device vendor-id="1659" product-id="9171" /> <!-- 0x23d3: PL2303GL --> | ||||
|     <usb-device vendor-id="1659" product-id="9187" /> <!-- 0x23e3: PL2303GE --> | ||||
|     <usb-device vendor-id="1659" product-id="9203" /> <!-- 0x23f3: PL2303GS --> | ||||
| 
 | ||||
|     <!-- 0x1a86 / 0x?523: Qinheng CH34x --> | ||||
|     <usb-device vendor-id="6790" product-id="21795" /> <!-- 0x5523: CH341A --> | ||||
|  | ||||
| @ -323,6 +323,7 @@ public class DeviceTest { | ||||
|                 403200, 460800, 614400, 806400, 921600, 1228800, 2457600, 3000000, /*6000000*/ | ||||
|         }; | ||||
|         usb.open(); | ||||
|         Assume.assumeFalse("only for non PL2303G*", ProlificWrapper.isDeviceTypeHxn(usb.serialPort)); // HXN does not use divisor | ||||
| 
 | ||||
|         int minBaudRate = ProlificWrapper.isDeviceTypeT(usb.serialPort) ? 6 : 46; | ||||
|         try { | ||||
| @ -1675,7 +1676,7 @@ public class DeviceTest { | ||||
| 
 | ||||
|     @Test | ||||
|     /* test not done by RFC2217 server. Instead output control lines are connected to | ||||
|          input control lines with a binary decoder 74LS138, 74LS139, 74HC... or ... | ||||
|          input control lines with a binary decoder 74LS42, 74LS138, 74LS139, 74HC... or ... | ||||
|         in | ||||
|             A0 = RTS | ||||
|             A1 = DTR | ||||
|  | ||||
| @ -5,4 +5,9 @@ public class ProlificWrapper { | ||||
|         ProlificSerialDriver.ProlificSerialPort prolificSerialPort = (ProlificSerialDriver.ProlificSerialPort) serialPort; | ||||
|         return prolificSerialPort.mDeviceType == ProlificSerialDriver.DeviceType.DEVICE_TYPE_T; | ||||
|     } | ||||
| 
 | ||||
|     public static boolean isDeviceTypeHxn(UsbSerialPort serialPort) { | ||||
|         ProlificSerialDriver.ProlificSerialPort prolificSerialPort = (ProlificSerialDriver.ProlificSerialPort) serialPort; | ||||
|         return prolificSerialPort.mDeviceType == ProlificSerialDriver.DeviceType.DEVICE_TYPE_HXN; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -35,7 +35,7 @@ public class ProlificSerialDriver implements UsbSerialDriver { | ||||
|             28800, 38400, 57600, 115200, 128000, 134400, 161280, 201600, 230400, 268800, | ||||
|             403200, 460800, 614400, 806400, 921600, 1228800, 2457600, 3000000, 6000000 | ||||
|     }; | ||||
|     protected enum DeviceType { DEVICE_TYPE_01, DEVICE_TYPE_T, DEVICE_TYPE_HX} | ||||
|     protected enum DeviceType { DEVICE_TYPE_01, DEVICE_TYPE_T, DEVICE_TYPE_HX, DEVICE_TYPE_HXN} | ||||
| 
 | ||||
|     private final UsbDevice mDevice; | ||||
|     private final UsbSerialPort mPort; | ||||
| @ -62,34 +62,50 @@ public class ProlificSerialDriver implements UsbSerialDriver { | ||||
| 
 | ||||
|         private static final int USB_RECIP_INTERFACE = 0x01; | ||||
| 
 | ||||
|         private static final int PROLIFIC_VENDOR_READ_REQUEST = 0x01; | ||||
|         private static final int PROLIFIC_VENDOR_WRITE_REQUEST = 0x01; | ||||
|         private static final int VENDOR_READ_REQUEST = 0x01; | ||||
|         private static final int VENDOR_WRITE_REQUEST = 0x01; | ||||
|         private static final int VENDOR_READ_HXN_REQUEST = 0x81; | ||||
|         private static final int VENDOR_WRITE_HXN_REQUEST = 0x80; | ||||
| 
 | ||||
|         private static final int PROLIFIC_VENDOR_OUT_REQTYPE = UsbConstants.USB_DIR_OUT | UsbConstants.USB_TYPE_VENDOR; | ||||
|         private static final int PROLIFIC_VENDOR_IN_REQTYPE = UsbConstants.USB_DIR_IN | UsbConstants.USB_TYPE_VENDOR; | ||||
|         private static final int PROLIFIC_CTRL_OUT_REQTYPE = UsbConstants.USB_DIR_OUT | UsbConstants.USB_TYPE_CLASS | USB_RECIP_INTERFACE; | ||||
|         private static final int VENDOR_OUT_REQTYPE = UsbConstants.USB_DIR_OUT | UsbConstants.USB_TYPE_VENDOR; | ||||
|         private static final int VENDOR_IN_REQTYPE = UsbConstants.USB_DIR_IN | UsbConstants.USB_TYPE_VENDOR; | ||||
|         private static final int CTRL_OUT_REQTYPE = UsbConstants.USB_DIR_OUT | UsbConstants.USB_TYPE_CLASS | USB_RECIP_INTERFACE; | ||||
| 
 | ||||
|         private static final int WRITE_ENDPOINT = 0x02; | ||||
|         private static final int READ_ENDPOINT = 0x83; | ||||
|         private static final int INTERRUPT_ENDPOINT = 0x81; | ||||
| 
 | ||||
|         private static final int FLUSH_RX_REQUEST = 0x08; // RX @ Prolific device = write @ usb-serial-for-android library | ||||
|         private static final int RESET_HXN_REQUEST = 0x07; | ||||
|         private static final int FLUSH_RX_REQUEST = 0x08; | ||||
|         private static final int FLUSH_TX_REQUEST = 0x09; | ||||
| 
 | ||||
|         private static final int SET_LINE_REQUEST = 0x20; // same as CDC SET_LINE_CODING | ||||
|         private static final int SET_CONTROL_REQUEST = 0x22; // same as CDC SET_CONTROL_LINE_STATE | ||||
|         private static final int SEND_BREAK_REQUEST = 0x23; // same as CDC SEND_BREAK | ||||
|         private static final int GET_CONTROL_HXN_REQUEST = 0x80; | ||||
|         private static final int GET_CONTROL_REQUEST = 0x87; | ||||
|         private static final int STATUS_NOTIFICATION = 0xa1; // similar to CDC SERIAL_STATE but different length | ||||
| 
 | ||||
|         /* RESET_HXN_REQUEST */ | ||||
|         private static final int RESET_HXN_RX_PIPE = 1; | ||||
|         private static final int RESET_HXN_TX_PIPE = 2; | ||||
| 
 | ||||
|         /* SET_CONTROL_REQUEST */ | ||||
|         private static final int CONTROL_DTR = 0x01; | ||||
|         private static final int CONTROL_RTS = 0x02; | ||||
| 
 | ||||
|         /* GET_CONTROL_REQUEST */ | ||||
|         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; | ||||
| 
 | ||||
|         /* GET_CONTROL_HXN_REQUEST */ | ||||
|         private static final int GET_CONTROL_HXN_FLAG_CD = 0x40; | ||||
|         private static final int GET_CONTROL_HXN_FLAG_DSR = 0x20; | ||||
|         private static final int GET_CONTROL_HXN_FLAG_RI = 0x80; | ||||
|         private static final int GET_CONTROL_HXN_FLAG_CTS = 0x08; | ||||
| 
 | ||||
|         /* interrupt endpoint read */ | ||||
|         private static final int STATUS_FLAG_CD = 0x01; | ||||
|         private static final int STATUS_FLAG_DSR = 0x02; | ||||
|         private static final int STATUS_FLAG_RI = 0x08; | ||||
| @ -137,11 +153,13 @@ public class ProlificSerialDriver implements UsbSerialDriver { | ||||
|         } | ||||
| 
 | ||||
|         private byte[] vendorIn(int value, int index, int length) throws IOException { | ||||
|             return inControlTransfer(PROLIFIC_VENDOR_IN_REQTYPE, PROLIFIC_VENDOR_READ_REQUEST, value, index, length); | ||||
|             int request = (mDeviceType == DeviceType.DEVICE_TYPE_HXN) ? VENDOR_READ_HXN_REQUEST : VENDOR_READ_REQUEST; | ||||
|             return inControlTransfer(VENDOR_IN_REQTYPE, request, value, index, length); | ||||
|         } | ||||
| 
 | ||||
|         private void vendorOut(int value, int index, byte[] data) throws IOException { | ||||
|             outControlTransfer(PROLIFIC_VENDOR_OUT_REQTYPE, PROLIFIC_VENDOR_WRITE_REQUEST, value, index, data); | ||||
|             int request = (mDeviceType == DeviceType.DEVICE_TYPE_HXN) ? VENDOR_WRITE_HXN_REQUEST : VENDOR_WRITE_REQUEST; | ||||
|             outControlTransfer(VENDOR_OUT_REQTYPE, request, value, index, data); | ||||
|         } | ||||
| 
 | ||||
|         private void resetDevice() throws IOException { | ||||
| @ -149,10 +167,21 @@ public class ProlificSerialDriver implements UsbSerialDriver { | ||||
|         } | ||||
| 
 | ||||
|         private void ctrlOut(int request, int value, int index, byte[] data) throws IOException { | ||||
|             outControlTransfer(PROLIFIC_CTRL_OUT_REQTYPE, request, value, index, data); | ||||
|             outControlTransfer(CTRL_OUT_REQTYPE, request, value, index, data); | ||||
|         } | ||||
| 
 | ||||
|         private boolean testHxStatus() { | ||||
|             try { | ||||
|                 inControlTransfer(VENDOR_IN_REQTYPE, VENDOR_READ_REQUEST, 0x8080, 0, 1); | ||||
|                 return true; | ||||
|             } catch(IOException ignored) { | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private void doBlackMagic() throws IOException { | ||||
|             if (mDeviceType == DeviceType.DEVICE_TYPE_HXN) | ||||
|                 return; | ||||
|             vendorIn(0x8484, 0, 1); | ||||
|             vendorOut(0x0404, 0, null); | ||||
|             vendorIn(0x8484, 0, 1); | ||||
| @ -199,12 +228,20 @@ public class ProlificSerialDriver implements UsbSerialDriver { | ||||
|             if ((mReadStatusThread == null) && (mReadStatusException == null)) { | ||||
|                 synchronized (mReadStatusThreadLock) { | ||||
|                     if (mReadStatusThread == null) { | ||||
|                         byte[] data = vendorIn(GET_CONTROL_REQUEST, 0, 1); | ||||
|                         mStatus = 0; | ||||
|                         if((data[0] & GET_CONTROL_FLAG_CTS) == 0) mStatus |= STATUS_FLAG_CTS; | ||||
|                         if((data[0] & GET_CONTROL_FLAG_DSR) == 0) mStatus |= STATUS_FLAG_DSR; | ||||
|                         if((data[0] & GET_CONTROL_FLAG_CD) == 0) mStatus |= STATUS_FLAG_CD; | ||||
|                         if((data[0] & GET_CONTROL_FLAG_RI) == 0) mStatus |= STATUS_FLAG_RI; | ||||
|                         if(mDeviceType == DeviceType.DEVICE_TYPE_HXN) { | ||||
|                             byte[] data = vendorIn(GET_CONTROL_HXN_REQUEST, 0, 1); | ||||
|                             if ((data[0] & GET_CONTROL_HXN_FLAG_CTS) == 0) mStatus |= STATUS_FLAG_CTS; | ||||
|                             if ((data[0] & GET_CONTROL_HXN_FLAG_DSR) == 0) mStatus |= STATUS_FLAG_DSR; | ||||
|                             if ((data[0] & GET_CONTROL_HXN_FLAG_CD) == 0) mStatus |= STATUS_FLAG_CD; | ||||
|                             if ((data[0] & GET_CONTROL_HXN_FLAG_RI) == 0) mStatus |= STATUS_FLAG_RI; | ||||
|                         } else { | ||||
|                             byte[] data = vendorIn(GET_CONTROL_REQUEST, 0, 1); | ||||
|                             if ((data[0] & GET_CONTROL_FLAG_CTS) == 0) mStatus |= STATUS_FLAG_CTS; | ||||
|                             if ((data[0] & GET_CONTROL_FLAG_DSR) == 0) mStatus |= STATUS_FLAG_DSR; | ||||
|                             if ((data[0] & GET_CONTROL_FLAG_CD) == 0) mStatus |= STATUS_FLAG_CD; | ||||
|                             if ((data[0] & GET_CONTROL_FLAG_RI) == 0) mStatus |= STATUS_FLAG_RI; | ||||
|                         } | ||||
|                         //Log.d(TAG, "start control line status thread " + mStatus); | ||||
|                         mReadStatusThread = new Thread(this::readStatusThreadFunction); | ||||
|                         mReadStatusThread.setDaemon(true); | ||||
| @ -266,12 +303,14 @@ public class ProlificSerialDriver implements UsbSerialDriver { | ||||
|                 mDeviceType = DeviceType.DEVICE_TYPE_T; // TA | ||||
|             } else if(deviceVersion == 0x500) { | ||||
|                 mDeviceType = DeviceType.DEVICE_TYPE_T; // TB | ||||
|             } else if(usbVersion == 0x200 && !testHxStatus()) { | ||||
|                 mDeviceType = DeviceType.DEVICE_TYPE_HXN; | ||||
|             } else { | ||||
|                 mDeviceType = DeviceType.DEVICE_TYPE_HX; | ||||
|             } | ||||
|             setControlLines(mControlLinesValue); | ||||
|             resetDevice(); | ||||
|             doBlackMagic(); | ||||
|             setControlLines(mControlLinesValue); | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
| @ -304,6 +343,9 @@ public class ProlificSerialDriver implements UsbSerialDriver { | ||||
|             if (baudRate <= 0) { | ||||
|                 throw new IllegalArgumentException("Invalid baud rate: " + baudRate); | ||||
|             } | ||||
|             if (mDeviceType == DeviceType.DEVICE_TYPE_HXN) { | ||||
|                 return baudRate; | ||||
|             } | ||||
|             for(int br : standardBaudRates) { | ||||
|                 if (br == baudRate) { | ||||
|                     return baudRate; | ||||
| @ -501,12 +543,17 @@ public class ProlificSerialDriver implements UsbSerialDriver { | ||||
| 
 | ||||
|         @Override | ||||
|         public void purgeHwBuffers(boolean purgeWriteBuffers, boolean purgeReadBuffers) throws IOException { | ||||
|             if (purgeWriteBuffers) { | ||||
|                 vendorOut(FLUSH_RX_REQUEST, 0, null); | ||||
|             } | ||||
| 
 | ||||
|             if (purgeReadBuffers) { | ||||
|                 vendorOut(FLUSH_TX_REQUEST, 0, null); | ||||
|             if (mDeviceType == DeviceType.DEVICE_TYPE_HXN) { | ||||
|                 int index = 0; | ||||
|                 if(purgeWriteBuffers) index |= RESET_HXN_RX_PIPE; | ||||
|                 if(purgeReadBuffers) index |= RESET_HXN_TX_PIPE; | ||||
|                 if(index != 0) | ||||
|                     vendorOut(RESET_HXN_REQUEST, index, null); | ||||
|             } else { | ||||
|                 if (purgeWriteBuffers) | ||||
|                     vendorOut(FLUSH_RX_REQUEST, 0, null); | ||||
|                 if (purgeReadBuffers) | ||||
|                     vendorOut(FLUSH_TX_REQUEST, 0, null); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @ -519,7 +566,15 @@ public class ProlificSerialDriver implements UsbSerialDriver { | ||||
|     public static Map<Integer, int[]> getSupportedDevices() { | ||||
|         final Map<Integer, int[]> supportedDevices = new LinkedHashMap<>(); | ||||
|         supportedDevices.put(UsbId.VENDOR_PROLIFIC, | ||||
|                 new int[] { UsbId.PROLIFIC_PL2303, }); | ||||
|                 new int[] { | ||||
|                         UsbId.PROLIFIC_PL2303, | ||||
|                         UsbId.PROLIFIC_PL2303GC, | ||||
|                         UsbId.PROLIFIC_PL2303GB, | ||||
|                         UsbId.PROLIFIC_PL2303GT, | ||||
|                         UsbId.PROLIFIC_PL2303GL, | ||||
|                         UsbId.PROLIFIC_PL2303GE, | ||||
|                         UsbId.PROLIFIC_PL2303GS, | ||||
|                 }); | ||||
|         return supportedDevices; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -50,7 +50,13 @@ public final class UsbId { | ||||
|     public static final int SILABS_CP2108 = 0xea71; | ||||
| 
 | ||||
|     public static final int VENDOR_PROLIFIC = 0x067b; | ||||
|     public static final int PROLIFIC_PL2303 = 0x2303; | ||||
|     public static final int PROLIFIC_PL2303 = 0x2303;   // device type 01, T, HX | ||||
|     public static final int PROLIFIC_PL2303GC = 0x23a3; // device type HXN | ||||
|     public static final int PROLIFIC_PL2303GB = 0x23b3; // " | ||||
|     public static final int PROLIFIC_PL2303GT = 0x23cd; // " | ||||
|     public static final int PROLIFIC_PL2303GL = 0x23e3; // " | ||||
|     public static final int PROLIFIC_PL2303GE = 0x23e3; // " | ||||
|     public static final int PROLIFIC_PL2303GS = 0x23f3; // " | ||||
| 
 | ||||
|     public static final int VENDOR_QINHENG = 0x1a86; | ||||
|     public static final int QINHENG_CH340 = 0x7523; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user