mirror of
https://github.com/mik3y/usb-serial-for-android
synced 2025-06-07 16:06:10 +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="60016" /> <!-- 0xea70: CP2105 -->
|
||||||
<usb-device vendor-id="4292" product-id="60017" /> <!-- 0xea71: CP2108 -->
|
<usb-device vendor-id="4292" product-id="60017" /> <!-- 0xea71: CP2108 -->
|
||||||
|
|
||||||
<!-- 0x067B / 0x2303: Prolific PL2303 -->
|
<!-- 0x067B / 0x23?3: Prolific PL2303x -->
|
||||||
<usb-device vendor-id="1659" product-id="8963" />
|
<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 -->
|
<!-- 0x1a86 / 0x?523: Qinheng CH34x -->
|
||||||
<usb-device vendor-id="6790" product-id="21795" /> <!-- 0x5523: CH341A -->
|
<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*/
|
403200, 460800, 614400, 806400, 921600, 1228800, 2457600, 3000000, /*6000000*/
|
||||||
};
|
};
|
||||||
usb.open();
|
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;
|
int minBaudRate = ProlificWrapper.isDeviceTypeT(usb.serialPort) ? 6 : 46;
|
||||||
try {
|
try {
|
||||||
@ -1675,7 +1676,7 @@ public class DeviceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
/* test not done by RFC2217 server. Instead output control lines are connected to
|
/* 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
|
in
|
||||||
A0 = RTS
|
A0 = RTS
|
||||||
A1 = DTR
|
A1 = DTR
|
||||||
|
@ -5,4 +5,9 @@ public class ProlificWrapper {
|
|||||||
ProlificSerialDriver.ProlificSerialPort prolificSerialPort = (ProlificSerialDriver.ProlificSerialPort) serialPort;
|
ProlificSerialDriver.ProlificSerialPort prolificSerialPort = (ProlificSerialDriver.ProlificSerialPort) serialPort;
|
||||||
return prolificSerialPort.mDeviceType == ProlificSerialDriver.DeviceType.DEVICE_TYPE_T;
|
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,
|
28800, 38400, 57600, 115200, 128000, 134400, 161280, 201600, 230400, 268800,
|
||||||
403200, 460800, 614400, 806400, 921600, 1228800, 2457600, 3000000, 6000000
|
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 UsbDevice mDevice;
|
||||||
private final UsbSerialPort mPort;
|
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 USB_RECIP_INTERFACE = 0x01;
|
||||||
|
|
||||||
private static final int PROLIFIC_VENDOR_READ_REQUEST = 0x01;
|
private static final int VENDOR_READ_REQUEST = 0x01;
|
||||||
private static final int PROLIFIC_VENDOR_WRITE_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 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 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 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 WRITE_ENDPOINT = 0x02;
|
||||||
private static final int READ_ENDPOINT = 0x83;
|
private static final int READ_ENDPOINT = 0x83;
|
||||||
private static final int INTERRUPT_ENDPOINT = 0x81;
|
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 FLUSH_TX_REQUEST = 0x09;
|
||||||
|
|
||||||
private static final int SET_LINE_REQUEST = 0x20; // same as CDC SET_LINE_CODING
|
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 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 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 GET_CONTROL_REQUEST = 0x87;
|
||||||
private static final int STATUS_NOTIFICATION = 0xa1; // similar to CDC SERIAL_STATE but different length
|
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_DTR = 0x01;
|
||||||
private static final int CONTROL_RTS = 0x02;
|
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_CD = 0x02;
|
||||||
private static final int GET_CONTROL_FLAG_DSR = 0x04;
|
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_RI = 0x01;
|
||||||
private static final int GET_CONTROL_FLAG_CTS = 0x08;
|
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_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;
|
||||||
@ -137,11 +153,13 @@ public class ProlificSerialDriver implements UsbSerialDriver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private byte[] vendorIn(int value, int index, int length) throws IOException {
|
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 {
|
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 {
|
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 {
|
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 {
|
private void doBlackMagic() throws IOException {
|
||||||
|
if (mDeviceType == DeviceType.DEVICE_TYPE_HXN)
|
||||||
|
return;
|
||||||
vendorIn(0x8484, 0, 1);
|
vendorIn(0x8484, 0, 1);
|
||||||
vendorOut(0x0404, 0, null);
|
vendorOut(0x0404, 0, null);
|
||||||
vendorIn(0x8484, 0, 1);
|
vendorIn(0x8484, 0, 1);
|
||||||
@ -199,12 +228,20 @@ public class ProlificSerialDriver implements UsbSerialDriver {
|
|||||||
if ((mReadStatusThread == null) && (mReadStatusException == null)) {
|
if ((mReadStatusThread == null) && (mReadStatusException == null)) {
|
||||||
synchronized (mReadStatusThreadLock) {
|
synchronized (mReadStatusThreadLock) {
|
||||||
if (mReadStatusThread == null) {
|
if (mReadStatusThread == null) {
|
||||||
byte[] data = vendorIn(GET_CONTROL_REQUEST, 0, 1);
|
|
||||||
mStatus = 0;
|
mStatus = 0;
|
||||||
if((data[0] & GET_CONTROL_FLAG_CTS) == 0) mStatus |= STATUS_FLAG_CTS;
|
if(mDeviceType == DeviceType.DEVICE_TYPE_HXN) {
|
||||||
if((data[0] & GET_CONTROL_FLAG_DSR) == 0) mStatus |= STATUS_FLAG_DSR;
|
byte[] data = vendorIn(GET_CONTROL_HXN_REQUEST, 0, 1);
|
||||||
if((data[0] & GET_CONTROL_FLAG_CD) == 0) mStatus |= STATUS_FLAG_CD;
|
if ((data[0] & GET_CONTROL_HXN_FLAG_CTS) == 0) mStatus |= STATUS_FLAG_CTS;
|
||||||
if((data[0] & GET_CONTROL_FLAG_RI) == 0) mStatus |= STATUS_FLAG_RI;
|
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);
|
//Log.d(TAG, "start control line status thread " + mStatus);
|
||||||
mReadStatusThread = new Thread(this::readStatusThreadFunction);
|
mReadStatusThread = new Thread(this::readStatusThreadFunction);
|
||||||
mReadStatusThread.setDaemon(true);
|
mReadStatusThread.setDaemon(true);
|
||||||
@ -266,12 +303,14 @@ public class ProlificSerialDriver implements UsbSerialDriver {
|
|||||||
mDeviceType = DeviceType.DEVICE_TYPE_T; // TA
|
mDeviceType = DeviceType.DEVICE_TYPE_T; // TA
|
||||||
} else if(deviceVersion == 0x500) {
|
} else if(deviceVersion == 0x500) {
|
||||||
mDeviceType = DeviceType.DEVICE_TYPE_T; // TB
|
mDeviceType = DeviceType.DEVICE_TYPE_T; // TB
|
||||||
|
} else if(usbVersion == 0x200 && !testHxStatus()) {
|
||||||
|
mDeviceType = DeviceType.DEVICE_TYPE_HXN;
|
||||||
} else {
|
} else {
|
||||||
mDeviceType = DeviceType.DEVICE_TYPE_HX;
|
mDeviceType = DeviceType.DEVICE_TYPE_HX;
|
||||||
}
|
}
|
||||||
setControlLines(mControlLinesValue);
|
|
||||||
resetDevice();
|
resetDevice();
|
||||||
doBlackMagic();
|
doBlackMagic();
|
||||||
|
setControlLines(mControlLinesValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -304,6 +343,9 @@ public class ProlificSerialDriver implements UsbSerialDriver {
|
|||||||
if (baudRate <= 0) {
|
if (baudRate <= 0) {
|
||||||
throw new IllegalArgumentException("Invalid baud rate: " + baudRate);
|
throw new IllegalArgumentException("Invalid baud rate: " + baudRate);
|
||||||
}
|
}
|
||||||
|
if (mDeviceType == DeviceType.DEVICE_TYPE_HXN) {
|
||||||
|
return baudRate;
|
||||||
|
}
|
||||||
for(int br : standardBaudRates) {
|
for(int br : standardBaudRates) {
|
||||||
if (br == baudRate) {
|
if (br == baudRate) {
|
||||||
return baudRate;
|
return baudRate;
|
||||||
@ -501,12 +543,17 @@ public class ProlificSerialDriver implements UsbSerialDriver {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void purgeHwBuffers(boolean purgeWriteBuffers, boolean purgeReadBuffers) throws IOException {
|
public void purgeHwBuffers(boolean purgeWriteBuffers, boolean purgeReadBuffers) throws IOException {
|
||||||
if (purgeWriteBuffers) {
|
if (mDeviceType == DeviceType.DEVICE_TYPE_HXN) {
|
||||||
vendorOut(FLUSH_RX_REQUEST, 0, null);
|
int index = 0;
|
||||||
}
|
if(purgeWriteBuffers) index |= RESET_HXN_RX_PIPE;
|
||||||
|
if(purgeReadBuffers) index |= RESET_HXN_TX_PIPE;
|
||||||
if (purgeReadBuffers) {
|
if(index != 0)
|
||||||
vendorOut(FLUSH_TX_REQUEST, 0, null);
|
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() {
|
public static Map<Integer, int[]> getSupportedDevices() {
|
||||||
final Map<Integer, int[]> supportedDevices = new LinkedHashMap<>();
|
final Map<Integer, int[]> supportedDevices = new LinkedHashMap<>();
|
||||||
supportedDevices.put(UsbId.VENDOR_PROLIFIC,
|
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;
|
return supportedDevices;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,13 @@ public final class UsbId {
|
|||||||
public static final int SILABS_CP2108 = 0xea71;
|
public static final int SILABS_CP2108 = 0xea71;
|
||||||
|
|
||||||
public static final int VENDOR_PROLIFIC = 0x067b;
|
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 VENDOR_QINHENG = 0x1a86;
|
||||||
public static final int QINHENG_CH340 = 0x7523;
|
public static final int QINHENG_CH340 = 0x7523;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user