@@ -27,6 +27,59 @@ fn get_string(device: &nusb::Device, index: Option<std::num::NonZeroU8>) -> Resu
2727 }
2828}
2929
30+ fn control_type_from_request_type ( request_type : & str ) -> nusb:: transfer:: ControlType {
31+ match request_type {
32+ "standard" => nusb:: transfer:: ControlType :: Standard ,
33+ "class" => nusb:: transfer:: ControlType :: Class ,
34+ "vendor" => nusb:: transfer:: ControlType :: Vendor ,
35+ _ => nusb:: transfer:: ControlType :: Standard ,
36+ }
37+ }
38+
39+ fn recipient_from_request_recipient ( recipient : & str ) -> nusb:: transfer:: Recipient {
40+ match recipient {
41+ "device" => nusb:: transfer:: Recipient :: Device ,
42+ "interface" => nusb:: transfer:: Recipient :: Interface ,
43+ "endpoint" => nusb:: transfer:: Recipient :: Endpoint ,
44+ "other" => nusb:: transfer:: Recipient :: Other ,
45+ _ => nusb:: transfer:: Recipient :: Other ,
46+ }
47+ }
48+
49+ fn control_in_setup (
50+ setup : & UsbControlTransferParameters ,
51+ control_type : nusb:: transfer:: ControlType ,
52+ recipient : nusb:: transfer:: Recipient ,
53+ index : u16 ,
54+ length : u16 ,
55+ ) -> nusb:: transfer:: ControlIn {
56+ nusb:: transfer:: ControlIn {
57+ control_type,
58+ recipient,
59+ request : setup. request ,
60+ value : setup. value ,
61+ index,
62+ length,
63+ }
64+ }
65+
66+ fn control_out_setup < ' a > (
67+ setup : & UsbControlTransferParameters ,
68+ control_type : nusb:: transfer:: ControlType ,
69+ recipient : nusb:: transfer:: Recipient ,
70+ index : u16 ,
71+ data : & ' a [ u8 ] ,
72+ ) -> nusb:: transfer:: ControlOut < ' a > {
73+ nusb:: transfer:: ControlOut {
74+ control_type,
75+ recipient,
76+ request : setup. request ,
77+ value : setup. value ,
78+ index,
79+ data,
80+ }
81+ }
82+
3083pub ( crate ) async fn run_blocking < T , F > ( f : F ) -> Result < T >
3184where
3285 T : Send + ' static ,
@@ -533,44 +586,37 @@ impl UsbDevice {
533586 timeout : u32 ,
534587 length : u16 ,
535588 ) -> Result < Option < Uint8Array > > {
536- let control_type = match setup. requestType . as_str ( ) {
537- "standard" => nusb:: transfer:: ControlType :: Standard ,
538- "class" => nusb:: transfer:: ControlType :: Class ,
539- "vendor" => nusb:: transfer:: ControlType :: Vendor ,
540- _ => nusb:: transfer:: ControlType :: Standard ,
541- } ;
542- let recipient = match setup. recipient . as_str ( ) {
543- "device" => nusb:: transfer:: Recipient :: Device ,
544- "interface" => nusb:: transfer:: Recipient :: Interface ,
545- "endpoint" => nusb:: transfer:: Recipient :: Endpoint ,
546- "other" => nusb:: transfer:: Recipient :: Other ,
547- _ => nusb:: transfer:: Recipient :: Other ,
548- } ;
549- match self . get_interface ( recipient, setup. index ) {
550- Some ( interface) => {
551- let result = run_blocking ( move || {
552- interface
553- . control_in (
554- nusb:: transfer:: ControlIn {
555- control_type,
556- recipient,
557- request : setup. request ,
558- value : setup. value ,
559- index : setup. index ,
560- length,
561- } ,
562- Duration :: from_millis ( timeout as u64 ) ,
563- )
564- . wait ( )
565- . map_err ( |e| format ! ( "controlTransferIn error: {e}" ) )
566- } )
567- . await ?;
568- Ok ( Some ( Uint8Array :: from ( result) ) )
569- }
570- None => Err ( napi:: Error :: from_reason (
571- "controlTransferIn error: invalid state" ,
572- ) ) ,
589+ let control_type = control_type_from_request_type ( & setup. requestType ) ;
590+ let recipient = recipient_from_request_recipient ( & setup. recipient ) ;
591+
592+ #[ cfg( not( windows) ) ]
593+ if recipient == nusb:: transfer:: Recipient :: Device {
594+ let device = self . device . as_ref ( ) . cloned ( ) . ok_or_else ( || {
595+ napi:: Error :: from_reason ( format ! ( "controlTransferIn error: invalid state" ) )
596+ } ) ?;
597+ let request = control_in_setup ( & setup, control_type, recipient, setup. index , length) ;
598+ let result = run_blocking ( move || {
599+ device
600+ . control_in ( request, Duration :: from_millis ( timeout as u64 ) )
601+ . wait ( )
602+ . map_err ( |e| format ! ( "controlTransferIn error: {e}" ) )
603+ } )
604+ . await ?;
605+ return Ok ( Some ( Uint8Array :: from ( result) ) ) ;
573606 }
607+
608+ let interface = self . get_interface ( recipient, setup. index ) . ok_or_else ( || {
609+ napi:: Error :: from_reason ( format ! ( "controlTransferIn error: invalid state" ) )
610+ } ) ?;
611+ let request = control_in_setup ( & setup, control_type, recipient, setup. index , length) ;
612+ let result = run_blocking ( move || {
613+ interface
614+ . control_in ( request, Duration :: from_millis ( timeout as u64 ) )
615+ . wait ( )
616+ . map_err ( |e| format ! ( "controlTransferIn error: {e}" ) )
617+ } )
618+ . await ?;
619+ Ok ( Some ( Uint8Array :: from ( result) ) )
574620 }
575621
576622 #[ napi( js_name = "nativeControlTransferOut" ) ]
@@ -580,46 +626,40 @@ impl UsbDevice {
580626 timeout : u32 ,
581627 data : Option < Uint8Array > ,
582628 ) -> Result < u32 > {
583- let control_type = match setup. requestType . as_str ( ) {
584- "standard" => nusb:: transfer:: ControlType :: Standard ,
585- "class" => nusb:: transfer:: ControlType :: Class ,
586- "vendor" => nusb:: transfer:: ControlType :: Vendor ,
587- _ => nusb:: transfer:: ControlType :: Standard ,
588- } ;
589- let recipient = match setup. recipient . as_str ( ) {
590- "device" => nusb:: transfer:: Recipient :: Device ,
591- "interface" => nusb:: transfer:: Recipient :: Interface ,
592- "endpoint" => nusb:: transfer:: Recipient :: Endpoint ,
593- "other" => nusb:: transfer:: Recipient :: Other ,
594- _ => nusb:: transfer:: Recipient :: Other ,
595- } ;
596- match self . get_interface ( recipient, setup. index ) {
597- Some ( interface) => {
598- let bytes = data. map ( |b| b. to_vec ( ) ) . unwrap_or_default ( ) ;
599- let bytes_len = bytes. len ( ) ;
600- run_blocking ( move || {
601- interface
602- . control_out (
603- nusb:: transfer:: ControlOut {
604- control_type,
605- recipient,
606- request : setup. request ,
607- value : setup. value ,
608- index : setup. index ,
609- data : & bytes,
610- } ,
611- Duration :: from_millis ( timeout as u64 ) ,
612- )
613- . wait ( )
614- . map_err ( |e| format ! ( "controlTransferOut error: {e}" ) )
615- } )
616- . await ?;
617- Ok ( bytes_len as u32 )
618- }
619- None => Err ( napi:: Error :: from_reason (
620- "controlTransferOut error: invalid state" ,
621- ) ) ,
629+ let control_type = control_type_from_request_type ( & setup. requestType ) ;
630+ let recipient = recipient_from_request_recipient ( & setup. recipient ) ;
631+ let bytes = data. map ( |b| b. to_vec ( ) ) . unwrap_or_default ( ) ;
632+ let bytes_len = bytes. len ( ) ;
633+
634+ #[ cfg( not( windows) ) ]
635+ if recipient == nusb:: transfer:: Recipient :: Device {
636+ let device = self . device . as_ref ( ) . cloned ( ) . ok_or_else ( || {
637+ napi:: Error :: from_reason ( format ! ( "controlTransferOut error: invalid state" ) )
638+ } ) ?;
639+ run_blocking ( move || {
640+ let request =
641+ control_out_setup ( & setup, control_type, recipient, setup. index , & bytes) ;
642+ device
643+ . control_out ( request, Duration :: from_millis ( timeout as u64 ) )
644+ . wait ( )
645+ . map_err ( |e| format ! ( "controlTransferOut error: {e}" ) )
646+ } )
647+ . await ?;
648+ return Ok ( bytes_len as u32 ) ;
622649 }
650+
651+ let interface = self . get_interface ( recipient, setup. index ) . ok_or_else ( || {
652+ napi:: Error :: from_reason ( format ! ( "controlTransferOut error: invalid state" ) )
653+ } ) ?;
654+ run_blocking ( move || {
655+ let request = control_out_setup ( & setup, control_type, recipient, setup. index , & bytes) ;
656+ interface
657+ . control_out ( request, Duration :: from_millis ( timeout as u64 ) )
658+ . wait ( )
659+ . map_err ( |e| format ! ( "controlTransferOut error: {e}" ) )
660+ } )
661+ . await ?;
662+ Ok ( bytes_len as u32 )
623663 }
624664
625665 #[ napi( js_name = "nativeTransferIn" ) ]
@@ -830,7 +870,7 @@ impl UsbDevice {
830870 }
831871 }
832872
833- // Return any claimed interface
873+ // Return any claimed interface (e.g. for device control transfers on Windows)
834874 let maybe_iface = self . interfaces . iter ( ) . find_map ( |x| x. clone ( ) ) ;
835875 if maybe_iface. is_some ( ) {
836876 return maybe_iface;
0 commit comments