0
# Device Communication
1
2
Device communication provides methods to open USB devices and perform control transfers for device configuration and data exchange. This includes device initialization, configuration management, and low-level control operations.
3
4
## Capabilities
5
6
### Device Opening and Closing
7
8
Open and close USB devices for communication.
9
10
```typescript { .api }
11
/**
12
* Open the device for communication
13
* @param defaultConfig - Whether to automatically configure the device with the default configuration (default: true)
14
*/
15
open(defaultConfig?: boolean): void;
16
17
/**
18
* Close the device
19
* The device must be open to use other methods
20
*/
21
close(): void;
22
```
23
24
**Usage Examples:**
25
26
```typescript
27
import { findByIds } from 'usb';
28
29
const device = findByIds(0x1234, 0x5678);
30
if (device) {
31
// Open with default configuration
32
device.open();
33
console.log('Device opened with default configuration');
34
35
// Access interfaces after opening
36
console.log(`Device has ${device.interfaces?.length || 0} interfaces`);
37
38
// Close when done
39
device.close();
40
console.log('Device closed');
41
}
42
43
// Open without default configuration (for manual configuration)
44
if (device) {
45
device.open(false);
46
console.log('Device opened without auto-configuration');
47
48
// You can now manually set configuration before using interfaces
49
device.setConfiguration(1, (error) => {
50
if (!error) {
51
console.log('Configuration set successfully');
52
// Now interfaces are available
53
}
54
});
55
56
device.close();
57
}
58
```
59
60
### Device Configuration
61
62
Set the device configuration to something other than the default.
63
64
```typescript { .api }
65
/**
66
* Set the device configuration
67
* To use this, first call .open(false), then before claiming an interface, call this method
68
* @param desired - Configuration value to set
69
* @param callback - Optional callback called when complete
70
*/
71
setConfiguration(desired: number, callback?: (error?: LibUSBException) => void): void;
72
```
73
74
**Usage Examples:**
75
76
```typescript
77
import { findByIds } from 'usb';
78
79
const device = findByIds(0x1234, 0x5678);
80
if (device) {
81
// Open without default configuration
82
device.open(false);
83
84
// Set specific configuration
85
device.setConfiguration(2, (error) => {
86
if (error) {
87
console.error('Failed to set configuration:', error.message);
88
return;
89
}
90
91
console.log('Configuration 2 set successfully');
92
console.log(`Device now has ${device.interfaces?.length || 0} interfaces`);
93
94
// Now you can claim interfaces and use endpoints
95
if (device.interfaces && device.interfaces.length > 0) {
96
const interface0 = device.interfaces[0];
97
interface0.claim();
98
console.log('Interface 0 claimed');
99
100
// Use interface...
101
102
interface0.release((error) => {
103
if (!error) console.log('Interface released');
104
device.close();
105
});
106
}
107
});
108
}
109
```
110
111
### Control Transfers
112
113
Perform control transfers for device configuration and vendor-specific commands.
114
115
```typescript { .api }
116
/**
117
* Perform a control transfer with libusb_control_transfer
118
* Parameter data_or_length can be an integer length for an IN transfer, or a Buffer for an OUT transfer
119
* The type must match the direction specified in the MSB of bmRequestType
120
* @param bmRequestType - Request type (direction, type, recipient)
121
* @param bRequest - Specific request
122
* @param wValue - Request-specific value
123
* @param wIndex - Request-specific index
124
* @param data_or_length - Buffer for OUT transfer or length for IN transfer
125
* @param callback - Completion callback
126
* @returns Device instance for chaining
127
*/
128
controlTransfer(
129
bmRequestType: number,
130
bRequest: number,
131
wValue: number,
132
wIndex: number,
133
data_or_length: number | Buffer,
134
callback?: (error?: LibUSBException, buffer?: Buffer | number) => void
135
): Device;
136
```
137
138
**Usage Examples:**
139
140
```typescript
141
import { findByIds, LIBUSB_ENDPOINT_IN, LIBUSB_ENDPOINT_OUT, LIBUSB_REQUEST_TYPE_VENDOR, LIBUSB_RECIPIENT_DEVICE } from 'usb';
142
143
const device = findByIds(0x1234, 0x5678);
144
if (device) {
145
device.open();
146
147
// Vendor-specific IN control transfer
148
const bmRequestType = LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE;
149
device.controlTransfer(bmRequestType, 0x01, 0x0000, 0x0000, 64, (error, data) => {
150
if (error) {
151
console.error('Control transfer failed:', error.message);
152
return;
153
}
154
155
console.log('Received data:', data);
156
if (data instanceof Buffer) {
157
console.log('Data length:', data.length);
158
console.log('Data hex:', data.toString('hex'));
159
}
160
});
161
162
// Vendor-specific OUT control transfer
163
const outData = Buffer.from([0x01, 0x02, 0x03, 0x04]);
164
const bmRequestTypeOut = LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE;
165
device.controlTransfer(bmRequestTypeOut, 0x02, 0x1234, 0x0000, outData, (error, bytesWritten) => {
166
if (error) {
167
console.error('Control transfer failed:', error.message);
168
return;
169
}
170
171
console.log('Bytes written:', bytesWritten);
172
});
173
174
device.close();
175
}
176
```
177
178
### String Descriptor Access
179
180
Retrieve string descriptors from the device.
181
182
```typescript { .api }
183
/**
184
* Perform a control transfer to retrieve a string descriptor
185
* @param desc_index - String descriptor index
186
* @param callback - Callback with error and string value
187
*/
188
getStringDescriptor(desc_index: number, callback: (error?: LibUSBException, value?: string) => void): void;
189
```
190
191
**Usage Examples:**
192
193
```typescript
194
import { findByIds } from 'usb';
195
196
const device = findByIds(0x1234, 0x5678);
197
if (device) {
198
device.open();
199
200
const descriptor = device.deviceDescriptor;
201
202
// Get manufacturer string
203
if (descriptor.iManufacturer > 0) {
204
device.getStringDescriptor(descriptor.iManufacturer, (error, manufacturer) => {
205
if (!error && manufacturer) {
206
console.log('Manufacturer:', manufacturer);
207
}
208
});
209
}
210
211
// Get product string
212
if (descriptor.iProduct > 0) {
213
device.getStringDescriptor(descriptor.iProduct, (error, product) => {
214
if (!error && product) {
215
console.log('Product:', product);
216
}
217
});
218
}
219
220
// Get serial number string
221
if (descriptor.iSerialNumber > 0) {
222
device.getStringDescriptor(descriptor.iSerialNumber, (error, serial) => {
223
if (!error && serial) {
224
console.log('Serial Number:', serial);
225
}
226
});
227
}
228
229
device.close();
230
}
231
```
232
233
### Kernel Driver Management
234
235
Manage automatic kernel driver detachment for device access.
236
237
```typescript { .api }
238
/**
239
* Enable/disable libusb's automatic kernel driver detachment
240
* When enabled, libusb will automatically detach the kernel driver on an interface
241
* when claiming the interface, and attach it when releasing the interface
242
* @param enable - Whether to enable automatic detachment
243
*/
244
setAutoDetachKernelDriver(enable: boolean): void;
245
```
246
247
**Usage Examples:**
248
249
```typescript
250
import { findByIds } from 'usb';
251
252
const device = findByIds(0x1234, 0x5678);
253
if (device) {
254
device.open();
255
256
// Enable automatic kernel driver detachment
257
device.setAutoDetachKernelDriver(true);
258
console.log('Auto kernel driver detach enabled');
259
260
// Now when you claim an interface, the kernel driver will be automatically detached
261
if (device.interfaces && device.interfaces.length > 0) {
262
const interface0 = device.interfaces[0];
263
264
// This will automatically detach kernel driver if needed
265
interface0.claim();
266
console.log('Interface claimed (kernel driver automatically detached if needed)');
267
268
// Use interface...
269
270
// This will automatically reattach kernel driver
271
interface0.release((error) => {
272
if (!error) {
273
console.log('Interface released (kernel driver automatically reattached)');
274
}
275
device.close();
276
});
277
}
278
}
279
280
// Disable automatic detachment for manual control
281
const device2 = findByIds(0x5678, 0x1234);
282
if (device2) {
283
device2.open();
284
device2.setAutoDetachKernelDriver(false);
285
286
if (device2.interfaces && device2.interfaces.length > 0) {
287
const interface0 = device2.interfaces[0];
288
289
// Manually check and detach kernel driver if needed
290
if (interface0.isKernelDriverActive()) {
291
console.log('Kernel driver is active, detaching...');
292
interface0.detachKernelDriver();
293
}
294
295
interface0.claim();
296
// Use interface...
297
298
// Manually reattach kernel driver
299
interface0.release((error) => {
300
if (!error) {
301
interface0.attachKernelDriver();
302
console.log('Kernel driver reattached');
303
}
304
device2.close();
305
});
306
}
307
}
308
```
309
310
### Device Reset
311
312
Reset the USB device.
313
314
```typescript { .api }
315
/**
316
* Performs a reset of the device. Callback is called when complete.
317
* The device must be open to use this method.
318
* @param callback - Completion callback
319
*/
320
reset(callback: (error?: LibUSBException) => void): void;
321
```
322
323
**Usage Examples:**
324
325
```typescript
326
import { findByIds } from 'usb';
327
328
const device = findByIds(0x1234, 0x5678);
329
if (device) {
330
device.open();
331
332
// Reset the device
333
device.reset((error) => {
334
if (error) {
335
console.error('Device reset failed:', error.message);
336
return;
337
}
338
339
console.log('Device reset successfully');
340
341
// Note: After reset, you may need to re-open the device
342
// as the device may re-enumerate with new addresses
343
device.close();
344
345
// Wait a moment for re-enumeration
346
setTimeout(() => {
347
// Find device again (it may have new bus/address)
348
const resetDevice = findByIds(0x1234, 0x5678);
349
if (resetDevice) {
350
resetDevice.open();
351
console.log('Device reconnected after reset');
352
resetDevice.close();
353
}
354
}, 1000);
355
});
356
}
357
```
358
359
### Timeout Configuration
360
361
Configure timeout for control transfers.
362
363
```typescript { .api }
364
/**
365
* Device timeout property
366
* Timeout in milliseconds to use for control transfers (default: 1000)
367
*/
368
timeout: number;
369
```
370
371
**Usage Examples:**
372
373
```typescript
374
import { findByIds } from 'usb';
375
376
const device = findByIds(0x1234, 0x5678);
377
if (device) {
378
device.open();
379
380
// Set custom timeout (5 seconds)
381
device.timeout = 5000;
382
console.log(`Device timeout set to ${device.timeout}ms`);
383
384
// Control transfers will now use the 5-second timeout
385
device.controlTransfer(0x80, 0x06, 0x0100, 0x0000, 18, (error, data) => {
386
if (error) {
387
console.error('Control transfer timed out or failed:', error.message);
388
} else {
389
console.log('Control transfer completed within timeout');
390
}
391
});
392
393
device.close();
394
}
395
```
396
397
### BOS Descriptor Access
398
399
Retrieve Binary Object Store (BOS) descriptors for USB 2.0.1+ devices.
400
401
```typescript { .api }
402
/**
403
* Perform a control transfer to retrieve BOS descriptor
404
* BOS is only supported from USB 2.0.1
405
* @param callback - Callback with error and BOS descriptor
406
*/
407
getBosDescriptor(callback: (error?: LibUSBException, descriptor?: BosDescriptor) => void): void;
408
409
/**
410
* Retrieve array of Capability objects for BOS capabilities
411
* @param callback - Callback with error and capabilities array
412
*/
413
getCapabilities(callback: (error?: LibUSBException, capabilities?: Capability[]) => void): void;
414
415
/**
416
* Binary Object Store (BOS) Descriptor
417
*/
418
interface BosDescriptor {
419
/** Size of this descriptor (in bytes) */
420
bLength: number;
421
422
/** Descriptor type */
423
bDescriptorType: number;
424
425
/** Length of this descriptor and all sub descriptors */
426
wTotalLength: number;
427
428
/** Number of separate device capability descriptors */
429
bNumDeviceCaps: number;
430
431
/** Device Capability Descriptors */
432
capabilities: CapabilityDescriptor[];
433
}
434
435
/**
436
* Device Capability Descriptor
437
*/
438
interface CapabilityDescriptor {
439
/** Size of this descriptor (in bytes) */
440
bLength: number;
441
442
/** Descriptor type */
443
bDescriptorType: number;
444
445
/** Device Capability type */
446
bDevCapabilityType: number;
447
448
/** Device Capability data */
449
dev_capability_data: Buffer;
450
}
451
452
/**
453
* Capability class for device capabilities
454
*/
455
class Capability {
456
/** Capability type */
457
readonly type: number;
458
459
/** Capability data buffer */
460
readonly data: Buffer;
461
462
/** Capability descriptor */
463
readonly descriptor: CapabilityDescriptor;
464
}
465
```
466
467
**Usage Examples:**
468
469
```typescript
470
import { findByIds } from 'usb';
471
472
const device = findByIds(0x1234, 0x5678);
473
if (device) {
474
device.open();
475
476
// Check USB version before attempting BOS
477
const usbVersion = device.deviceDescriptor.bcdUSB;
478
console.log(`USB Version: ${(usbVersion >> 8).toString(16)}.${((usbVersion & 0xFF) >> 4).toString(16)}.${(usbVersion & 0x0F).toString(16)}`);
479
480
if (usbVersion >= 0x0201) { // USB 2.0.1 or higher
481
// Get BOS descriptor
482
device.getBosDescriptor((error, bosDescriptor) => {
483
if (error) {
484
console.error('Failed to get BOS descriptor:', error.message);
485
device.close();
486
return;
487
}
488
489
if (!bosDescriptor) {
490
console.log('Device does not support BOS descriptor');
491
device.close();
492
return;
493
}
494
495
console.log('BOS Descriptor:');
496
console.log(` Total Length: ${bosDescriptor.wTotalLength}`);
497
console.log(` Number of Capabilities: ${bosDescriptor.bNumDeviceCaps}`);
498
499
// List capability types
500
bosDescriptor.capabilities.forEach((cap, index) => {
501
console.log(` Capability ${index}:`);
502
console.log(` Type: ${cap.bDevCapabilityType}`);
503
console.log(` Length: ${cap.bLength}`);
504
console.log(` Data: ${cap.dev_capability_data.toString('hex')}`);
505
});
506
507
device.close();
508
});
509
510
// Get device capabilities
511
device.getCapabilities((error, capabilities) => {
512
if (error) {
513
console.error('Failed to get capabilities:', error.message);
514
return;
515
}
516
517
if (capabilities && capabilities.length > 0) {
518
console.log(`Device has ${capabilities.length} capabilities:`);
519
capabilities.forEach((capability, index) => {
520
console.log(` Capability ${index}:`);
521
console.log(` Type: ${capability.type}`);
522
console.log(` Data Length: ${capability.data.length}`);
523
console.log(` Descriptor Type: ${capability.descriptor.bDevCapabilityType}`);
524
});
525
} else {
526
console.log('Device has no BOS capabilities');
527
}
528
});
529
530
} else {
531
console.log('Device USB version is below 2.0.1, BOS not supported');
532
device.close();
533
}
534
}
535
```