Skip to content

Commit 898e610

Browse files
committed
Support bulk endpoints
1 parent b0da20c commit 898e610

File tree

3 files changed

+56
-3
lines changed

3 files changed

+56
-3
lines changed

src/transport/usb.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,14 @@ export class USB implements Transport {
123123
throw new Error("No valid interfaces found.");
124124
}
125125

126-
const selectedInterface = interfaces[0];
126+
// Prefer interface with endpoints
127+
let selectedInterface = interfaces.find(iface => iface.endpoints.length > 0);
128+
129+
// Otherwise use the first
130+
if (!selectedInterface) {
131+
selectedInterface = interfaces[0];
132+
}
133+
127134
this.interfaceNumber = selectedInterface.interfaceNumber;
128135

129136
// If we always want to use control transfer, don't find/set endpoints and claim interface

src/transport/webusb.ts

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,18 @@ const IN_REPORT = 0x100;
5656
export 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",

tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"lib": [
66
"es5",
77
"dom",
8+
"es2015.core",
89
"es2015.promise"
910
],
1011
"strict": true,

0 commit comments

Comments
 (0)