0
# Interface and Endpoint Management
1
2
Interface and endpoint management provides methods to claim USB interfaces and manage data endpoints for bulk and interrupt transfers. This includes interface claiming/releasing, alternate setting management, and endpoint access.
3
4
## Capabilities
5
6
### Interface Access
7
8
Access and manage USB interfaces on a device.
9
10
```typescript { .api }
11
/**
12
* Return the interface with the specified interface number
13
* The device must be open to use this method
14
* @param addr - Interface number (default: 0)
15
* @returns Interface object
16
*/
17
interface(addr: number): Interface;
18
19
/**
20
* USB Interface class for device communication
21
*/
22
interface Interface {
23
/** Integer interface number */
24
interfaceNumber: number;
25
26
/** Integer alternate setting number */
27
altSetting: number;
28
29
/** Object with fields from the interface descriptor */
30
descriptor: InterfaceDescriptor;
31
32
/** List of endpoints on this interface: InEndpoint and OutEndpoint objects */
33
endpoints: Endpoint[];
34
}
35
```
36
37
**Usage Examples:**
38
39
```typescript
40
import { findByIds } from 'usb';
41
42
const device = findByIds(0x1234, 0x5678);
43
if (device) {
44
device.open();
45
46
// Get the first interface (interface 0)
47
const interface0 = device.interface(0);
48
console.log(`Interface Number: ${interface0.interfaceNumber}`);
49
console.log(`Alternate Setting: ${interface0.altSetting}`);
50
console.log(`Interface Class: ${interface0.descriptor.bInterfaceClass}`);
51
console.log(`Number of Endpoints: ${interface0.endpoints.length}`);
52
53
// Access interface descriptor properties
54
const desc = interface0.descriptor;
55
console.log('Interface Descriptor:');
56
console.log(` Class: ${desc.bInterfaceClass}`);
57
console.log(` Subclass: ${desc.bInterfaceSubClass}`);
58
console.log(` Protocol: ${desc.bInterfaceProtocol}`);
59
console.log(` Endpoints: ${desc.bNumEndpoints}`);
60
61
device.close();
62
}
63
```
64
65
### Interface Claiming and Releasing
66
67
Claim interfaces for exclusive access and release them when done.
68
69
```typescript { .api }
70
/**
71
* Claims the interface. This method must be called before using any endpoints of this interface.
72
* The device must be open to use this method.
73
*/
74
claim(): void;
75
76
/**
77
* Releases the interface and resets the alternate setting. Calls callback when complete.
78
* It is an error to release an interface with pending transfers.
79
* @param callback - Completion callback
80
*/
81
release(callback?: (error?: LibUSBException) => void): void;
82
83
/**
84
* Releases the interface with optional endpoint stream control
85
* @param closeEndpoints - If true, any active endpoint streams are stopped
86
* @param callback - Completion callback
87
*/
88
release(closeEndpoints?: boolean, callback?: (error?: LibUSBException) => void): void;
89
90
/**
91
* Async version of release
92
*/
93
releaseAsync(): Promise<void>;
94
```
95
96
**Usage Examples:**
97
98
```typescript
99
import { findByIds } from 'usb';
100
101
const device = findByIds(0x1234, 0x5678);
102
if (device) {
103
device.open();
104
105
const interface0 = device.interface(0);
106
107
try {
108
// Claim the interface for exclusive access
109
interface0.claim();
110
console.log('Interface claimed successfully');
111
112
// Now you can use the interface endpoints
113
console.log(`Interface has ${interface0.endpoints.length} endpoints`);
114
115
// Use endpoints here...
116
117
// Release the interface when done (callback version)
118
interface0.release((error) => {
119
if (error) {
120
console.error('Failed to release interface:', error.message);
121
} else {
122
console.log('Interface released successfully');
123
}
124
device.close();
125
});
126
127
} catch (error) {
128
console.error('Failed to claim interface:', error);
129
device.close();
130
}
131
}
132
133
// Using async/await pattern
134
async function useInterfaceAsync() {
135
const device = findByIds(0x1234, 0x5678);
136
if (!device) return;
137
138
device.open();
139
const interface0 = device.interface(0);
140
141
try {
142
interface0.claim();
143
console.log('Interface claimed');
144
145
// Use interface...
146
147
// Release with async
148
await interface0.releaseAsync();
149
console.log('Interface released');
150
151
} catch (error) {
152
console.error('Interface error:', error);
153
} finally {
154
device.close();
155
}
156
}
157
158
// Release with endpoint stream closure
159
const deviceWithStreams = findByIds(0x5678, 0x1234);
160
if (deviceWithStreams) {
161
deviceWithStreams.open();
162
const interface0 = deviceWithStreams.interface(0);
163
164
interface0.claim();
165
166
// ... start some endpoint streams/polling ...
167
168
// Release and stop all endpoint streams
169
interface0.release(true, (error) => {
170
if (!error) {
171
console.log('Interface released and all endpoint streams stopped');
172
}
173
deviceWithStreams.close();
174
});
175
}
176
```
177
178
### Alternate Setting Management
179
180
Manage alternate interface settings.
181
182
```typescript { .api }
183
/**
184
* Sets the alternate setting. It updates the interface.endpoints array
185
* to reflect the endpoints found in the alternate setting.
186
* The device must be open to use this method.
187
* @param altSetting - Alternate setting number
188
* @param callback - Completion callback
189
*/
190
setAltSetting(altSetting: number, callback?: (error?: LibUSBException) => void): void;
191
192
/**
193
* Async version of setAltSetting
194
* @param alternateSetting - Alternate setting number
195
*/
196
setAltSettingAsync(alternateSetting: number): Promise<void>;
197
```
198
199
**Usage Examples:**
200
201
```typescript
202
import { findByIds } from 'usb';
203
204
const device = findByIds(0x1234, 0x5678);
205
if (device) {
206
device.open();
207
const interface0 = device.interface(0);
208
209
interface0.claim();
210
211
console.log(`Current alternate setting: ${interface0.altSetting}`);
212
console.log(`Current endpoints: ${interface0.endpoints.length}`);
213
214
// Set alternate setting 1
215
interface0.setAltSetting(1, (error) => {
216
if (error) {
217
console.error('Failed to set alternate setting:', error.message);
218
return;
219
}
220
221
console.log(`New alternate setting: ${interface0.altSetting}`);
222
console.log(`New endpoints: ${interface0.endpoints.length}`);
223
224
// The endpoints array has been updated to reflect the new setting
225
interface0.endpoints.forEach((endpoint, index) => {
226
console.log(` Endpoint ${index}: 0x${endpoint.address.toString(16)}, ${endpoint.direction}`);
227
});
228
229
interface0.release(() => device.close());
230
});
231
}
232
233
// Using async/await
234
async function setAltSettingAsync() {
235
const device = findByIds(0x1234, 0x5678);
236
if (!device) return;
237
238
device.open();
239
const interface0 = device.interface(0);
240
241
try {
242
interface0.claim();
243
244
// Set alternate setting using async method
245
await interface0.setAltSettingAsync(2);
246
console.log('Alternate setting 2 activated');
247
248
await interface0.releaseAsync();
249
} catch (error) {
250
console.error('Error setting alternate setting:', error);
251
} finally {
252
device.close();
253
}
254
}
255
```
256
257
### Kernel Driver Management
258
259
Manage kernel driver attachment/detachment for interfaces.
260
261
```typescript { .api }
262
/**
263
* Returns false if a kernel driver is not active; true if active.
264
* The device must be open to use this method.
265
*/
266
isKernelDriverActive(): boolean;
267
268
/**
269
* Detaches the kernel driver from the interface.
270
* The device must be open to use this method.
271
*/
272
detachKernelDriver(): void;
273
274
/**
275
* Re-attaches the kernel driver for the interface.
276
* The device must be open to use this method.
277
*/
278
attachKernelDriver(): void;
279
```
280
281
**Usage Examples:**
282
283
```typescript
284
import { findByIds } from 'usb';
285
286
const device = findByIds(0x1234, 0x5678);
287
if (device) {
288
device.open();
289
const interface0 = device.interface(0);
290
291
// Check if kernel driver is active
292
if (interface0.isKernelDriverActive()) {
293
console.log('Kernel driver is active, need to detach');
294
295
try {
296
// Detach kernel driver
297
interface0.detachKernelDriver();
298
console.log('Kernel driver detached');
299
300
// Now we can claim the interface
301
interface0.claim();
302
console.log('Interface claimed after detaching kernel driver');
303
304
// Use interface...
305
306
// Release interface
307
interface0.release((error) => {
308
if (!error) {
309
// Reattach kernel driver
310
try {
311
interface0.attachKernelDriver();
312
console.log('Kernel driver reattached');
313
} catch (attachError) {
314
console.warn('Could not reattach kernel driver:', attachError);
315
}
316
}
317
device.close();
318
});
319
320
} catch (error) {
321
console.error('Failed to detach kernel driver:', error);
322
device.close();
323
}
324
} else {
325
console.log('No kernel driver active');
326
interface0.claim();
327
// ... use interface ...
328
interface0.release(() => device.close());
329
}
330
}
331
332
// Safe kernel driver management pattern
333
function safeInterfaceAccess(device: Device, interfaceNumber: number) {
334
const interface0 = device.interface(interfaceNumber);
335
let kernelDriverWasActive = false;
336
337
try {
338
// Check and detach kernel driver if needed
339
if (interface0.isKernelDriverActive()) {
340
kernelDriverWasActive = true;
341
interface0.detachKernelDriver();
342
console.log('Kernel driver detached');
343
}
344
345
// Claim interface
346
interface0.claim();
347
console.log('Interface claimed');
348
349
return {
350
interface: interface0,
351
cleanup: (callback?: () => void) => {
352
interface0.release((error) => {
353
if (!error && kernelDriverWasActive) {
354
try {
355
interface0.attachKernelDriver();
356
console.log('Kernel driver reattached');
357
} catch (attachError) {
358
console.warn('Could not reattach kernel driver');
359
}
360
}
361
if (callback) callback();
362
});
363
}
364
};
365
366
} catch (error) {
367
console.error('Failed to access interface:', error);
368
throw error;
369
}
370
}
371
```
372
373
### Endpoint Access
374
375
Access and manage endpoints on interfaces.
376
377
```typescript { .api }
378
/**
379
* Return the InEndpoint or OutEndpoint with the specified address.
380
* The device must be open to use this method.
381
* @param addr - Endpoint address
382
* @returns Endpoint object or undefined if not found
383
*/
384
endpoint(addr: number): Endpoint | undefined;
385
386
/**
387
* Base endpoint interface
388
*/
389
interface Endpoint {
390
/** Endpoint address */
391
address: number;
392
393
/** Endpoint direction: "in" or "out" */
394
direction: 'in' | 'out';
395
396
/** Endpoint type: BULK, INTERRUPT, etc. */
397
transferType: number;
398
399
/** Sets the timeout in milliseconds for transfers on this endpoint */
400
timeout: number;
401
402
/** Object with fields from the endpoint descriptor */
403
descriptor: EndpointDescriptor;
404
}
405
```
406
407
**Usage Examples:**
408
409
```typescript
410
import { findByIds, LIBUSB_TRANSFER_TYPE_BULK, LIBUSB_TRANSFER_TYPE_INTERRUPT } from 'usb';
411
412
const device = findByIds(0x1234, 0x5678);
413
if (device) {
414
device.open();
415
const interface0 = device.interface(0);
416
interface0.claim();
417
418
// List all endpoints
419
console.log('Available endpoints:');
420
interface0.endpoints.forEach((endpoint, index) => {
421
console.log(` Endpoint ${index}:`);
422
console.log(` Address: 0x${endpoint.address.toString(16)}`);
423
console.log(` Direction: ${endpoint.direction}`);
424
console.log(` Type: ${endpoint.transferType === LIBUSB_TRANSFER_TYPE_BULK ? 'BULK' :
425
endpoint.transferType === LIBUSB_TRANSFER_TYPE_INTERRUPT ? 'INTERRUPT' : 'OTHER'}`);
426
console.log(` Max Packet Size: ${endpoint.descriptor.wMaxPacketSize}`);
427
});
428
429
// Find specific endpoint by address
430
const endpoint1 = interface0.endpoint(0x81); // IN endpoint 1
431
if (endpoint1) {
432
console.log(`Found IN endpoint: 0x${endpoint1.address.toString(16)}`);
433
console.log(`Direction: ${endpoint1.direction}`);
434
435
// Configure endpoint timeout
436
endpoint1.timeout = 5000; // 5 second timeout
437
console.log(`Set endpoint timeout to ${endpoint1.timeout}ms`);
438
}
439
440
// Find OUT endpoint
441
const outEndpoint = interface0.endpoint(0x02); // OUT endpoint 2
442
if (outEndpoint) {
443
console.log(`Found OUT endpoint: 0x${outEndpoint.address.toString(16)}`);
444
console.log(`Max packet size: ${outEndpoint.descriptor.wMaxPacketSize}`);
445
}
446
447
// Find endpoints by direction
448
const inEndpoints = interface0.endpoints.filter(ep => ep.direction === 'in');
449
const outEndpoints = interface0.endpoints.filter(ep => ep.direction === 'out');
450
451
console.log(`Found ${inEndpoints.length} IN endpoints and ${outEndpoints.length} OUT endpoints`);
452
453
interface0.release(() => device.close());
454
}
455
456
// Helper function to find endpoints by type
457
function findEndpointsByType(interface0: Interface, transferType: number) {
458
return interface0.endpoints.filter(endpoint => endpoint.transferType === transferType);
459
}
460
461
// Usage
462
const device2 = findByIds(0x5678, 0x1234);
463
if (device2) {
464
device2.open();
465
const interface0 = device2.interface(0);
466
interface0.claim();
467
468
// Find all bulk endpoints
469
const bulkEndpoints = findEndpointsByType(interface0, LIBUSB_TRANSFER_TYPE_BULK);
470
console.log(`Found ${bulkEndpoints.length} bulk endpoints`);
471
472
// Find all interrupt endpoints
473
const interruptEndpoints = findEndpointsByType(interface0, LIBUSB_TRANSFER_TYPE_INTERRUPT);
474
console.log(`Found ${interruptEndpoints.length} interrupt endpoints`);
475
476
interface0.release(() => device2.close());
477
}
478
```