Skip to content

Commit 9530aa6

Browse files
Alex van HerwijnenAlex van Herwijnen
authored andcommitted
Porting support for Prolific PL2303Gx types
1 parent 72478cb commit 9530aa6

1 file changed

Lines changed: 106 additions & 81 deletions

File tree

UsbSerialForAndroid/driver/ProlificSerialDriver.cs

Lines changed: 106 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -54,49 +54,67 @@ public static Dictionary<int, int[]> GetSupportedDevices()
5454

5555
class ProlificSerialPort : CommonUsbSerialPort
5656
{
57+
protected enum DeviceType { DEVICE_TYPE_01, DEVICE_TYPE_T, DEVICE_TYPE_HX, DEVICE_TYPE_HXN }
58+
5759
private static int USB_READ_TIMEOUT_MILLIS = 1000;
5860
private static int USB_WRITE_TIMEOUT_MILLIS = 5000;
5961

6062
private static int USB_RECIP_INTERFACE = 0x01;
6163

62-
private static int PROLIFIC_VENDOR_READ_REQUEST = 0x01;
63-
private static int PROLIFIC_VENDOR_WRITE_REQUEST = 0x01;
64-
65-
private static int PROLIFIC_VENDOR_OUT_REQTYPE = UsbSupport.UsbDirOut
66-
| UsbConstants.UsbTypeVendor;
67-
68-
private static int PROLIFIC_VENDOR_IN_REQTYPE = UsbSupport.UsbDirIn
69-
| UsbConstants.UsbTypeVendor;
64+
private static int VENDOR_READ_REQUEST = 0x01;
65+
private static int VENDOR_WRITE_REQUEST = 0x01;
66+
private static int VENDOR_READ_HXN_REQUEST = 0x81;
67+
private static int VENDOR_WRITE_HXN_REQUEST = 0x80;
7068

71-
private static int PROLIFIC_CTRL_OUT_REQTYPE = UsbSupport.UsbDirOut
72-
| UsbConstants.UsbTypeClass | USB_RECIP_INTERFACE;
69+
private static int VENDOR_OUT_REQTYPE = UsbSupport.UsbDirOut | UsbConstants.UsbTypeVendor;
70+
private static int VENDOR_IN_REQTYPE = UsbSupport.UsbDirIn | UsbConstants.UsbTypeVendor;
71+
private static int CTRL_OUT_REQTYPE = UsbSupport.UsbDirOut | UsbConstants.UsbTypeClass | USB_RECIP_INTERFACE;
7372

7473
private const int WRITE_ENDPOINT = 0x02;
7574
private const int READ_ENDPOINT = 0x83;
7675
private const int INTERRUPT_ENDPOINT = 0x81;
7776

77+
private static int RESET_HXN_REQUEST = 0x07;
7878
private static int FLUSH_RX_REQUEST = 0x08;
7979
private static int FLUSH_TX_REQUEST = 0x09;
8080

81-
private static int SET_LINE_REQUEST = 0x20;
82-
private static int SET_CONTROL_REQUEST = 0x22;
81+
private static int SET_LINE_REQUEST = 0x20; // same as CDC SET_LINE_CODING
82+
private static int SET_CONTROL_REQUEST = 0x22; // same as CDC SET_CONTROL_LINE_STATE
83+
private static int SEND_BREAK_REQUEST = 0x23; // same as CDC SEND_BREAK
84+
private static int GET_CONTROL_HXN_REQUEST = 0x80;
85+
private static int GET_CONTROL_REQUEST = 0x87;
86+
private static int STATUS_NOTIFICATION = 0xa1; // similar to CDC SERIAL_STATE but different length
8387

88+
/* RESET_HXN_REQUEST */
89+
private static int RESET_HXN_RX_PIPE = 1;
90+
private static int RESET_HXN_TX_PIPE = 2;
91+
92+
/* SET_CONTROL_REQUEST */
8493
private static int CONTROL_DTR = 0x01;
8594
private static int CONTROL_RTS = 0x02;
8695

96+
/* GET_CONTROL_REQUEST */
97+
private static int GET_CONTROL_FLAG_CD = 0x02;
98+
private static int GET_CONTROL_FLAG_DSR = 0x04;
99+
private static int GET_CONTROL_FLAG_RI = 0x01;
100+
private static int GET_CONTROL_FLAG_CTS = 0x08;
101+
102+
/* GET_CONTROL_HXN_REQUEST */
103+
private static int GET_CONTROL_HXN_FLAG_CD = 0x40;
104+
private static int GET_CONTROL_HXN_FLAG_DSR = 0x20;
105+
private static int GET_CONTROL_HXN_FLAG_RI = 0x80;
106+
private static int GET_CONTROL_HXN_FLAG_CTS = 0x08;
107+
108+
/* interrupt endpoint read */
87109
private static int STATUS_FLAG_CD = 0x01;
88110
private static int STATUS_FLAG_DSR = 0x02;
89111
private static int STATUS_FLAG_RI = 0x08;
90112
private static int STATUS_FLAG_CTS = 0x80;
91113

92114
private static int STATUS_BUFFER_SIZE = 10;
93115
private static int STATUS_BYTE_IDX = 8;
94-
95-
private static int DEVICE_TYPE_HX = 0;
96-
private static int DEVICE_TYPE_0 = 1;
97-
private static int DEVICE_TYPE_1 = 2;
98-
99-
private int mDeviceType = DEVICE_TYPE_HX;
116+
117+
private DeviceType mDeviceType = DeviceType.DEVICE_TYPE_HX;
100118

101119
private UsbEndpoint mReadEndpoint;
102120
private UsbEndpoint mWriteEndpoint;
@@ -156,14 +174,14 @@ private void OutControlTransfer(int requestType, int request,
156174

157175
private byte[] VendorIn(int value, int index, int length)
158176
{
159-
return InControlTransfer(PROLIFIC_VENDOR_IN_REQTYPE,
160-
PROLIFIC_VENDOR_READ_REQUEST, value, index, length);
177+
int request = (mDeviceType == DeviceType.DEVICE_TYPE_HXN) ? VENDOR_READ_HXN_REQUEST : VENDOR_READ_REQUEST;
178+
return InControlTransfer(VENDOR_IN_REQTYPE, request, value, index, length);
161179
}
162180

163181
private void VendorOut(int value, int index, byte[] data)
164182
{
165-
OutControlTransfer(PROLIFIC_VENDOR_OUT_REQTYPE,
166-
PROLIFIC_VENDOR_WRITE_REQUEST, value, index, data);
183+
int request = (mDeviceType == DeviceType.DEVICE_TYPE_HXN) ? VENDOR_WRITE_HXN_REQUEST : VENDOR_WRITE_REQUEST;
184+
OutControlTransfer(VENDOR_OUT_REQTYPE, request, value, index, data);
167185
}
168186

169187
private void ResetDevice()
@@ -173,12 +191,27 @@ private void ResetDevice()
173191

174192
private void CtrlOut(int request, int value, int index, byte[] data)
175193
{
176-
OutControlTransfer(PROLIFIC_CTRL_OUT_REQTYPE, request, value, index,
177-
data);
194+
OutControlTransfer(CTRL_OUT_REQTYPE, request, value, index, data);
195+
}
196+
197+
private Boolean TestHxStatus()
198+
{
199+
try
200+
{
201+
InControlTransfer(VENDOR_IN_REQTYPE, VENDOR_READ_REQUEST, 0x8080, 0, 1);
202+
return true;
203+
}
204+
catch (IOException ignored)
205+
{
206+
return false;
207+
}
178208
}
179209

180210
private void DoBlackMagic()
181211
{
212+
if (mDeviceType == DeviceType.DEVICE_TYPE_HXN)
213+
return;
214+
182215
VendorIn(0x8484, 0, 1);
183216
VendorOut(0x0404, 0, null);
184217
VendorIn(0x8484, 0, 1);
@@ -189,7 +222,7 @@ private void DoBlackMagic()
189222
VendorIn(0x8383, 0, 1);
190223
VendorOut(0, 1, null);
191224
VendorOut(1, 0, null);
192-
VendorOut(2, (mDeviceType == DEVICE_TYPE_HX) ? 0x44 : 0x24, null);
225+
VendorOut(2, (mDeviceType == DeviceType.DEVICE_TYPE_HX) ? 0x44 : 0x24, null);
193226
}
194227

195228
private void SetControlLines(int newControlLinesValue)
@@ -237,20 +270,23 @@ private int GetStatus()
237270
{
238271
if (mReadStatusThread == null)
239272
{
240-
byte[] buffer = new byte[STATUS_BUFFER_SIZE];
241-
int readBytes = mConnection.BulkTransfer(mInterruptEndpoint,
242-
buffer,
243-
STATUS_BUFFER_SIZE,
244-
100);
245-
if (readBytes != STATUS_BUFFER_SIZE)
273+
mStatus = 0;
274+
if (mDeviceType == DeviceType.DEVICE_TYPE_HXN)
246275
{
247-
Log.Warn(TAG, "Could not read initial CTS / DSR / CD / RI status");
276+
byte[] data = VendorIn(GET_CONTROL_HXN_REQUEST, 0, 1);
277+
if ((data[0] & GET_CONTROL_HXN_FLAG_CTS) == 0) mStatus |= STATUS_FLAG_CTS;
278+
if ((data[0] & GET_CONTROL_HXN_FLAG_DSR) == 0) mStatus |= STATUS_FLAG_DSR;
279+
if ((data[0] & GET_CONTROL_HXN_FLAG_CD) == 0) mStatus |= STATUS_FLAG_CD;
280+
if ((data[0] & GET_CONTROL_HXN_FLAG_RI) == 0) mStatus |= STATUS_FLAG_RI;
248281
}
249282
else
250283
{
251-
mStatus = buffer[STATUS_BYTE_IDX] & 0xff;
284+
byte[] data = VendorIn(GET_CONTROL_REQUEST, 0, 1);
285+
if ((data[0] & GET_CONTROL_FLAG_CTS) == 0) mStatus |= STATUS_FLAG_CTS;
286+
if ((data[0] & GET_CONTROL_FLAG_DSR) == 0) mStatus |= STATUS_FLAG_DSR;
287+
if ((data[0] & GET_CONTROL_FLAG_CD) == 0) mStatus |= STATUS_FLAG_CD;
288+
if ((data[0] & GET_CONTROL_FLAG_RI) == 0) mStatus |= STATUS_FLAG_RI;
252289
}
253-
254290
ThreadStart mReadStatusThreadDelegate = new ThreadStart(ReadStatusThreadFunction);
255291

256292
mReadStatusThread = new Thread(mReadStatusThreadDelegate);
@@ -324,52 +360,36 @@ public override void Open(UsbDeviceConnection connection)
324360
}
325361
}
326362

327-
if (mDevice.DeviceClass == (UsbClass)0x02)
363+
byte[] rawDescriptors = connection.GetRawDescriptors();
364+
if (rawDescriptors == null || rawDescriptors.Length < 14)
365+
{
366+
throw new IOException("Could not get device descriptors");
367+
}
368+
int usbVersion = (rawDescriptors[3] << 8) + rawDescriptors[2];
369+
int deviceVersion = (rawDescriptors[13] << 8) + rawDescriptors[12];
370+
byte maxPacketSize0 = rawDescriptors[7];
371+
372+
if (mDevice.DeviceClass == UsbClass.Comm || maxPacketSize0 != 64)
373+
{
374+
mDeviceType = DeviceType.DEVICE_TYPE_01;
375+
}
376+
else if (deviceVersion == 0x300 && usbVersion == 0x200)
377+
{
378+
mDeviceType = DeviceType.DEVICE_TYPE_T; // TA
379+
}
380+
else if (deviceVersion == 0x500)
328381
{
329-
mDeviceType = DEVICE_TYPE_0;
382+
mDeviceType = DeviceType.DEVICE_TYPE_T; // TB
383+
}
384+
else if (usbVersion == 0x200 && !TestHxStatus())
385+
{
386+
mDeviceType = DeviceType.DEVICE_TYPE_HXN;
330387
}
331388
else
332389
{
333-
try
334-
{
335-
//Method getRawDescriptorsMethod
336-
// = mConnection.getClass().getMethod("getRawDescriptors");
337-
//byte[] rawDescriptors
338-
// = (byte[])getRawDescriptorsMethod.invoke(mConnection);
339-
340-
byte[] rawDescriptors = mConnection.GetRawDescriptors();
341-
342-
byte maxPacketSize0 = rawDescriptors[7];
343-
if (maxPacketSize0 == 64)
344-
{
345-
mDeviceType = DEVICE_TYPE_HX;
346-
}
347-
else if ((mDevice.DeviceClass == 0x00)
348-
|| (mDevice.DeviceClass == (UsbClass)0xff))
349-
{
350-
mDeviceType = DEVICE_TYPE_1;
351-
}
352-
else
353-
{
354-
Log.Warn(TAG, "Could not detect PL2303 subtype, "
355-
+ "Assuming that it is a HX device");
356-
mDeviceType = DEVICE_TYPE_HX;
357-
}
358-
}
359-
catch (NoSuchMethodException e)
360-
{
361-
Log.Warn(TAG, "Method UsbDeviceConnection.getRawDescriptors, "
362-
+ "required for PL2303 subtype detection, not "
363-
+ "available! Assuming that it is a HX device");
364-
mDeviceType = DEVICE_TYPE_HX;
365-
}
366-
catch (Exception e)
367-
{
368-
Log.Error(TAG, "An unexpected exception occured while trying "
369-
+ "to detect PL2303 subtype", e);
370-
}
390+
mDeviceType = DeviceType.DEVICE_TYPE_HX;
371391
}
372-
392+
373393
SetControlLines(mControlLinesValue);
374394
ResetDevice();
375395

@@ -619,16 +639,21 @@ public override void SetRTS(Boolean value)
619639

620640
public override Boolean PurgeHwBuffers(Boolean purgeReadBuffers, Boolean purgeWriteBuffers)
621641
{
622-
if (purgeReadBuffers)
642+
if (mDeviceType == DeviceType.DEVICE_TYPE_HXN)
623643
{
624-
VendorOut(FLUSH_RX_REQUEST, 0, null);
644+
int index = 0;
645+
if (purgeWriteBuffers) index |= RESET_HXN_RX_PIPE;
646+
if (purgeReadBuffers) index |= RESET_HXN_TX_PIPE;
647+
if (index != 0)
648+
VendorOut(RESET_HXN_REQUEST, index, null);
625649
}
626-
627-
if (purgeWriteBuffers)
650+
else
628651
{
629-
VendorOut(FLUSH_TX_REQUEST, 0, null);
652+
if (purgeWriteBuffers)
653+
VendorOut(FLUSH_RX_REQUEST, 0, null);
654+
if (purgeReadBuffers)
655+
VendorOut(FLUSH_TX_REQUEST, 0, null);
630656
}
631-
632657
return purgeReadBuffers || purgeWriteBuffers;
633658
}
634659
}

0 commit comments

Comments
 (0)