@@ -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