Skip to content

Commit d912d06

Browse files
authored
Merge pull request #30 from AveiaTechnology/main
Add new Prolific device types
2 parents 4d73ca7 + 133ea47 commit d912d06

2 files changed

Lines changed: 131 additions & 93 deletions

File tree

UsbSerialExampleApp/Resources/xml/device_filter.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717

1818
<!-- 0x067B / 0x2303: Prolific PL2303 -->
1919
<usb-device vendor-id="1659" product-id="8963" />
20+
<usb-device vendor-id="1659" product-id="9123" />
21+
<usb-device vendor-id="1659" product-id="9139" />
22+
<usb-device vendor-id="1659" product-id="9155" />
23+
<usb-device vendor-id="1659" product-id="9171" />
24+
<usb-device vendor-id="1659" product-id="9187" />
25+
<usb-device vendor-id="1659" product-id="9203" />
2026

2127
<!-- 0x1b4f / 0x0008: IOIO OTG -->
2228
<usb-device vendor-id="6991" product-id="8" />

UsbSerialForAndroid/driver/ProlificSerialDriver.cs

Lines changed: 125 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace Hoho.Android.UsbSerial.Driver
2323
{
2424
public class ProlificSerialDriver : UsbSerialDriver
2525
{
26-
private readonly string TAG = typeof (ProlificSerialDriver).Name;
26+
private readonly string TAG = typeof(ProlificSerialDriver).Name;
2727

2828
public ProlificSerialDriver(UsbDevice device)
2929
{
@@ -38,7 +38,14 @@ public static Dictionary<int, int[]> GetSupportedDevices()
3838
{
3939
UsbId.VENDOR_PROLIFIC, new int[]
4040
{
41-
UsbId.VENDOR_PROLIFIC
41+
UsbId.PROLIFIC_PL2303,
42+
UsbId.PROLIFIC_PL2303GC,
43+
UsbId.PROLIFIC_PL2303GB,
44+
UsbId.PROLIFIC_PL2303GT,
45+
UsbId.PROLIFIC_PL2303GL,
46+
UsbId.PROLIFIC_PL2303GE,
47+
UsbId.PROLIFIC_PL2303GS
48+
4249
}
4350
}
4451
};
@@ -47,49 +54,67 @@ public static Dictionary<int, int[]> GetSupportedDevices()
4754

4855
class ProlificSerialPort : CommonUsbSerialPort
4956
{
57+
protected enum DeviceType { DEVICE_TYPE_01, DEVICE_TYPE_T, DEVICE_TYPE_HX, DEVICE_TYPE_HXN }
58+
5059
private static int USB_READ_TIMEOUT_MILLIS = 1000;
5160
private static int USB_WRITE_TIMEOUT_MILLIS = 5000;
5261

5362
private static int USB_RECIP_INTERFACE = 0x01;
5463

55-
private static int PROLIFIC_VENDOR_READ_REQUEST = 0x01;
56-
private static int PROLIFIC_VENDOR_WRITE_REQUEST = 0x01;
57-
58-
private static int PROLIFIC_VENDOR_OUT_REQTYPE = UsbSupport.UsbDirOut
59-
| UsbConstants.UsbTypeVendor;
60-
61-
private static int PROLIFIC_VENDOR_IN_REQTYPE = UsbSupport.UsbDirIn
62-
| 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;
6368

64-
private static int PROLIFIC_CTRL_OUT_REQTYPE = UsbSupport.UsbDirOut
65-
| 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;
6672

6773
private const int WRITE_ENDPOINT = 0x02;
6874
private const int READ_ENDPOINT = 0x83;
6975
private const int INTERRUPT_ENDPOINT = 0x81;
7076

77+
private static int RESET_HXN_REQUEST = 0x07;
7178
private static int FLUSH_RX_REQUEST = 0x08;
7279
private static int FLUSH_TX_REQUEST = 0x09;
7380

74-
private static int SET_LINE_REQUEST = 0x20;
75-
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
7687

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 */
7793
private static int CONTROL_DTR = 0x01;
7894
private static int CONTROL_RTS = 0x02;
7995

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 */
80109
private static int STATUS_FLAG_CD = 0x01;
81110
private static int STATUS_FLAG_DSR = 0x02;
82111
private static int STATUS_FLAG_RI = 0x08;
83112
private static int STATUS_FLAG_CTS = 0x80;
84113

85114
private static int STATUS_BUFFER_SIZE = 10;
86115
private static int STATUS_BYTE_IDX = 8;
87-
88-
private static int DEVICE_TYPE_HX = 0;
89-
private static int DEVICE_TYPE_0 = 1;
90-
private static int DEVICE_TYPE_1 = 2;
91-
92-
private int mDeviceType = DEVICE_TYPE_HX;
116+
117+
private DeviceType mDeviceType = DeviceType.DEVICE_TYPE_HX;
93118

94119
private UsbEndpoint mReadEndpoint;
95120
private UsbEndpoint mWriteEndpoint;
@@ -126,7 +151,7 @@ private byte[] InControlTransfer(int requestType, int request,
126151
int value, int index, int length)
127152
{
128153
byte[] buffer = new byte[length];
129-
int result = mConnection.ControlTransfer((UsbAddressing) requestType, request, value,
154+
int result = mConnection.ControlTransfer((UsbAddressing)requestType, request, value,
130155
index, buffer, length, USB_READ_TIMEOUT_MILLIS);
131156
if (result != length)
132157
{
@@ -139,7 +164,7 @@ private void OutControlTransfer(int requestType, int request,
139164
int value, int index, byte[] data)
140165
{
141166
int length = data?.Length ?? 0;
142-
int result = mConnection.ControlTransfer((UsbAddressing) requestType, request, value,
167+
int result = mConnection.ControlTransfer((UsbAddressing)requestType, request, value,
143168
index, data, length, USB_WRITE_TIMEOUT_MILLIS);
144169
if (result != length)
145170
{
@@ -149,14 +174,14 @@ private void OutControlTransfer(int requestType, int request,
149174

150175
private byte[] VendorIn(int value, int index, int length)
151176
{
152-
return InControlTransfer(PROLIFIC_VENDOR_IN_REQTYPE,
153-
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);
154179
}
155180

156181
private void VendorOut(int value, int index, byte[] data)
157182
{
158-
OutControlTransfer(PROLIFIC_VENDOR_OUT_REQTYPE,
159-
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);
160185
}
161186

162187
private void ResetDevice()
@@ -166,12 +191,27 @@ private void ResetDevice()
166191

167192
private void CtrlOut(int request, int value, int index, byte[] data)
168193
{
169-
OutControlTransfer(PROLIFIC_CTRL_OUT_REQTYPE, request, value, index,
170-
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+
}
171208
}
172209

173210
private void DoBlackMagic()
174211
{
212+
if (mDeviceType == DeviceType.DEVICE_TYPE_HXN)
213+
return;
214+
175215
VendorIn(0x8484, 0, 1);
176216
VendorOut(0x0404, 0, null);
177217
VendorIn(0x8484, 0, 1);
@@ -182,7 +222,7 @@ private void DoBlackMagic()
182222
VendorIn(0x8383, 0, 1);
183223
VendorOut(0, 1, null);
184224
VendorOut(1, 0, null);
185-
VendorOut(2, (mDeviceType == DEVICE_TYPE_HX) ? 0x44 : 0x24, null);
225+
VendorOut(2, (mDeviceType == DeviceType.DEVICE_TYPE_HX) ? 0x44 : 0x24, null);
186226
}
187227

188228
private void SetControlLines(int newControlLinesValue)
@@ -230,20 +270,23 @@ private int GetStatus()
230270
{
231271
if (mReadStatusThread == null)
232272
{
233-
byte[] buffer = new byte[STATUS_BUFFER_SIZE];
234-
int readBytes = mConnection.BulkTransfer(mInterruptEndpoint,
235-
buffer,
236-
STATUS_BUFFER_SIZE,
237-
100);
238-
if (readBytes != STATUS_BUFFER_SIZE)
273+
mStatus = 0;
274+
if (mDeviceType == DeviceType.DEVICE_TYPE_HXN)
239275
{
240-
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;
241281
}
242282
else
243283
{
244-
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;
245289
}
246-
247290
ThreadStart mReadStatusThreadDelegate = new ThreadStart(ReadStatusThreadFunction);
248291

249292
mReadStatusThread = new Thread(mReadStatusThreadDelegate);
@@ -303,66 +346,50 @@ public override void Open(UsbDeviceConnection connection)
303346

304347
switch (currentEndpoint.Address)
305348
{
306-
case (UsbAddressing) READ_ENDPOINT:
349+
case (UsbAddressing)READ_ENDPOINT:
307350
mReadEndpoint = currentEndpoint;
308351
break;
309352

310-
case (UsbAddressing) WRITE_ENDPOINT:
353+
case (UsbAddressing)WRITE_ENDPOINT:
311354
mWriteEndpoint = currentEndpoint;
312355
break;
313356

314-
case (UsbAddressing) INTERRUPT_ENDPOINT:
357+
case (UsbAddressing)INTERRUPT_ENDPOINT:
315358
mInterruptEndpoint = currentEndpoint;
316359
break;
317360
}
318361
}
319362

320-
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)
321373
{
322-
mDeviceType = DEVICE_TYPE_0;
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)
381+
{
382+
mDeviceType = DeviceType.DEVICE_TYPE_T; // TB
383+
}
384+
else if (usbVersion == 0x200 && !TestHxStatus())
385+
{
386+
mDeviceType = DeviceType.DEVICE_TYPE_HXN;
323387
}
324388
else
325389
{
326-
try
327-
{
328-
//Method getRawDescriptorsMethod
329-
// = mConnection.getClass().getMethod("getRawDescriptors");
330-
//byte[] rawDescriptors
331-
// = (byte[])getRawDescriptorsMethod.invoke(mConnection);
332-
333-
byte[] rawDescriptors = mConnection.GetRawDescriptors();
334-
335-
byte maxPacketSize0 = rawDescriptors[7];
336-
if (maxPacketSize0 == 64)
337-
{
338-
mDeviceType = DEVICE_TYPE_HX;
339-
}
340-
else if ((mDevice.DeviceClass == 0x00)
341-
|| (mDevice.DeviceClass == (UsbClass) 0xff))
342-
{
343-
mDeviceType = DEVICE_TYPE_1;
344-
}
345-
else
346-
{
347-
Log.Warn(TAG, "Could not detect PL2303 subtype, "
348-
+ "Assuming that it is a HX device");
349-
mDeviceType = DEVICE_TYPE_HX;
350-
}
351-
}
352-
catch (NoSuchMethodException e)
353-
{
354-
Log.Warn(TAG, "Method UsbDeviceConnection.getRawDescriptors, "
355-
+ "required for PL2303 subtype detection, not "
356-
+ "available! Assuming that it is a HX device");
357-
mDeviceType = DEVICE_TYPE_HX;
358-
}
359-
catch (Exception e)
360-
{
361-
Log.Error(TAG, "An unexpected exception occured while trying "
362-
+ "to detect PL2303 subtype", e);
363-
}
390+
mDeviceType = DeviceType.DEVICE_TYPE_HX;
364391
}
365-
392+
366393
SetControlLines(mControlLinesValue);
367394
ResetDevice();
368395

@@ -484,10 +511,10 @@ public override void SetParameters(int baudRate, int dataBits, StopBits stopBits
484511

485512
byte[] lineRequestData = new byte[7];
486513

487-
lineRequestData[0] = (byte) (baudRate & 0xff);
488-
lineRequestData[1] = (byte) ((baudRate >> 8) & 0xff);
489-
lineRequestData[2] = (byte) ((baudRate >> 16) & 0xff);
490-
lineRequestData[3] = (byte) ((baudRate >> 24) & 0xff);
514+
lineRequestData[0] = (byte)(baudRate & 0xff);
515+
lineRequestData[1] = (byte)((baudRate >> 8) & 0xff);
516+
lineRequestData[2] = (byte)((baudRate >> 16) & 0xff);
517+
lineRequestData[3] = (byte)((baudRate >> 24) & 0xff);
491518

492519
switch (stopBits)
493520
{
@@ -533,7 +560,7 @@ public override void SetParameters(int baudRate, int dataBits, StopBits stopBits
533560
throw new IllegalArgumentException("Unknown parity value: " + parity);
534561
}
535562

536-
lineRequestData[6] = (byte) dataBits;
563+
lineRequestData[6] = (byte)dataBits;
537564

538565
CtrlOut(SET_LINE_REQUEST, 0, 0, lineRequestData);
539566

@@ -612,16 +639,21 @@ public override void SetRTS(Boolean value)
612639

613640
public override Boolean PurgeHwBuffers(Boolean purgeReadBuffers, Boolean purgeWriteBuffers)
614641
{
615-
if (purgeReadBuffers)
642+
if (mDeviceType == DeviceType.DEVICE_TYPE_HXN)
616643
{
617-
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);
618649
}
619-
620-
if (purgeWriteBuffers)
650+
else
621651
{
622-
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);
623656
}
624-
625657
return purgeReadBuffers || purgeWriteBuffers;
626658
}
627659
}

0 commit comments

Comments
 (0)