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