@@ -56,15 +56,18 @@ const IN_REPORT = 0x100;
5656export class WebUSB implements Transport {
5757
5858 private interfaceNumber ?: number ;
59+ private endpointIn ?: USBEndpoint ;
60+ private endpointOut ?: USBEndpoint ;
5961 public readonly packetSize = 64 ;
6062
6163 /**
6264 * WebUSB constructor
6365 * @param device WebUSB device to use
6466 * @param interfaceClass Optional interface class to use (default: 0xFF)
6567 * @param configuration Optional Configuration to use (default: 1)
68+ * @param alwaysControlTransfer Whether to always use control transfer instead of endpoints (default: false)
6669 */
67- constructor ( private device : USBDevice , private interfaceClass = DEFAULT_CLASS , private configuration = DEFAULT_CONFIGURATION ) {
70+ constructor ( private device : USBDevice , private interfaceClass = DEFAULT_CLASS , private configuration = DEFAULT_CONFIGURATION , private alwaysControlTransfer : boolean = false ) {
6871 }
6972
7073 private extendBuffer ( data : BufferSource , packetSize : number ) : BufferSource {
@@ -97,7 +100,29 @@ export class WebUSB implements Transport {
97100 throw new Error ( "No valid interfaces found." ) ;
98101 }
99102
100- this . interfaceNumber = interfaces [ 0 ] . interfaceNumber ;
103+ // Prefer interface with endpoints
104+ let selectedInterface = interfaces . find ( iface => iface . alternates [ 0 ] . endpoints . length > 0 ) ;
105+
106+ // Otherwise use the first
107+ if ( ! selectedInterface ) {
108+ selectedInterface = interfaces [ 0 ] ;
109+ }
110+
111+ this . interfaceNumber = selectedInterface . interfaceNumber ;
112+
113+ // If we always want to use control transfer, don't find/set endpoints and claim interface
114+ if ( ! this . alwaysControlTransfer ) {
115+ const endpoints = selectedInterface . alternates [ 0 ] . endpoints ;
116+
117+ this . endpointIn = undefined ;
118+ this . endpointOut = undefined ;
119+
120+ for ( const endpoint of endpoints ) {
121+ if ( endpoint . direction === "in" ) this . endpointIn = endpoint ;
122+ else this . endpointOut = endpoint ;
123+ }
124+ }
125+
101126 return this . device . claimInterface ( this . interfaceNumber ) ;
102127 } ) ;
103128 }
@@ -117,6 +142,16 @@ export class WebUSB implements Transport {
117142 public read ( ) : Promise < DataView > {
118143 if ( ! this . interfaceNumber ) return Promise . reject ( "No device opened" ) ;
119144
145+ // Use endpoint if it exists
146+ if ( this . endpointIn ) {
147+ return this . device . transferIn (
148+ this . endpointIn . endpointNumber ,
149+ this . packetSize
150+ )
151+ . then ( result => result . data ! ) ;
152+ }
153+
154+ // Fallback to using control transfer
120155 return this . device . controlTransferIn (
121156 {
122157 requestType : "class" ,
@@ -140,6 +175,16 @@ export class WebUSB implements Transport {
140175
141176 const buffer = this . extendBuffer ( data , this . packetSize ) ;
142177
178+ // Use endpoint if it exists
179+ if ( this . endpointOut ) {
180+ return this . device . transferOut (
181+ this . endpointOut . endpointNumber ,
182+ buffer
183+ )
184+ . then ( ( ) => undefined ) ;
185+ }
186+
187+ // Fallback to using control transfer
143188 return this . device . controlTransferOut (
144189 {
145190 requestType : "class" ,
0 commit comments