0
# Constants and Error Handling
1
2
Constants and error handling provide USB constants, error codes, and exception handling for robust USB applications. This includes USB class codes, transfer types, error constants, and comprehensive error handling patterns.
3
4
## Capabilities
5
6
### LibUSB Exception Handling
7
8
Handle errors and exceptions from libusb operations.
9
10
```typescript { .api }
11
/**
12
* LibUSB Exception class for USB operation errors
13
*/
14
interface LibUSBException extends Error {
15
/** LibUSB error number/code */
16
errno: number;
17
18
/** Error message */
19
message: string;
20
21
/** Error name */
22
name: string;
23
}
24
```
25
26
**Usage Examples:**
27
28
```typescript
29
import { findByIds, LibUSBException } from 'usb';
30
31
function handleUSBErrors() {
32
const device = findByIds(0x1234, 0x5678);
33
if (!device) return;
34
35
try {
36
device.open();
37
38
// Attempt control transfer that might fail
39
device.controlTransfer(0x80, 0x06, 0x0100, 0x0000, 18, (error, data) => {
40
if (error) {
41
console.error('Control transfer failed:');
42
console.error(` Error: ${error.message}`);
43
console.error(` LibUSB Error Code: ${error.errno}`);
44
console.error(` Error Name: ${error.name}`);
45
46
// Handle specific error types
47
handleSpecificError(error);
48
} else {
49
console.log('Control transfer successful');
50
}
51
});
52
53
} catch (error) {
54
console.error('Device operation failed:', error);
55
56
if (error instanceof LibUSBException) {
57
console.error(`LibUSB Error Code: ${error.errno}`);
58
handleSpecificError(error);
59
}
60
} finally {
61
try {
62
device.close();
63
} catch (closeError) {
64
console.warn('Failed to close device:', closeError);
65
}
66
}
67
}
68
69
function handleSpecificError(error: LibUSBException) {
70
switch (error.errno) {
71
case LIBUSB_ERROR_TIMEOUT:
72
console.error('Operation timed out - device may be unresponsive');
73
break;
74
case LIBUSB_ERROR_NO_DEVICE:
75
console.error('Device was disconnected');
76
break;
77
case LIBUSB_ERROR_ACCESS:
78
console.error('Access denied - check permissions or kernel drivers');
79
break;
80
case LIBUSB_ERROR_BUSY:
81
console.error('Resource is busy - device may be in use by another process');
82
break;
83
case LIBUSB_ERROR_NOT_SUPPORTED:
84
console.error('Operation not supported by this device or platform');
85
break;
86
case LIBUSB_ERROR_PIPE:
87
console.error('Pipe error - endpoint may be stalled');
88
break;
89
default:
90
console.error(`Unhandled LibUSB error: ${error.errno}`);
91
}
92
}
93
```
94
95
### USB Error Constants
96
97
Standard libusb error codes for error handling.
98
99
```typescript { .api }
100
/**
101
* LibUSB Error Constants
102
*/
103
104
/** Input/output error */
105
const LIBUSB_ERROR_IO: number;
106
107
/** Invalid parameter */
108
const LIBUSB_ERROR_INVALID_PARAM: number;
109
110
/** Access denied (insufficient permissions) */
111
const LIBUSB_ERROR_ACCESS: number;
112
113
/** No such device (it may have been disconnected) */
114
const LIBUSB_ERROR_NO_DEVICE: number;
115
116
/** Entity not found */
117
const LIBUSB_ERROR_NOT_FOUND: number;
118
119
/** Resource busy */
120
const LIBUSB_ERROR_BUSY: number;
121
122
/** Operation timed out */
123
const LIBUSB_ERROR_TIMEOUT: number;
124
125
/** Overflow */
126
const LIBUSB_ERROR_OVERFLOW: number;
127
128
/** Pipe error */
129
const LIBUSB_ERROR_PIPE: number;
130
131
/** System call interrupted (perhaps due to signal) */
132
const LIBUSB_ERROR_INTERRUPTED: number;
133
134
/** Insufficient memory */
135
const LIBUSB_ERROR_NO_MEM: number;
136
137
/** Operation not supported or unimplemented on this platform */
138
const LIBUSB_ERROR_NOT_SUPPORTED: number;
139
140
/** Other error */
141
const LIBUSB_ERROR_OTHER: number;
142
```
143
144
**Usage Examples:**
145
146
```typescript
147
import {
148
findByIds,
149
LIBUSB_ERROR_TIMEOUT,
150
LIBUSB_ERROR_NO_DEVICE,
151
LIBUSB_ERROR_ACCESS,
152
LIBUSB_ERROR_BUSY,
153
LIBUSB_ERROR_NOT_SUPPORTED,
154
LIBUSB_ERROR_PIPE
155
} from 'usb';
156
157
async function robustDeviceOperation() {
158
const device = findByIds(0x1234, 0x5678);
159
if (!device) {
160
throw new Error('Device not found');
161
}
162
163
let attempts = 0;
164
const maxAttempts = 3;
165
166
while (attempts < maxAttempts) {
167
try {
168
device.open();
169
170
// Perform operation with timeout handling
171
const data = await performTransferWithRetry(device);
172
console.log('Operation successful:', data);
173
174
device.close();
175
return data;
176
177
} catch (error) {
178
attempts++;
179
console.error(`Attempt ${attempts} failed:`, error.message);
180
181
if (error.errno) {
182
switch (error.errno) {
183
case LIBUSB_ERROR_TIMEOUT:
184
console.log('Timeout - retrying with longer timeout');
185
if (attempts < maxAttempts) {
186
await sleep(1000 * attempts); // Progressive delay
187
continue;
188
}
189
break;
190
191
case LIBUSB_ERROR_NO_DEVICE:
192
console.error('Device disconnected - cannot retry');
193
throw error;
194
195
case LIBUSB_ERROR_ACCESS:
196
console.error('Access denied - check permissions');
197
throw error;
198
199
case LIBUSB_ERROR_BUSY:
200
console.log('Device busy - waiting before retry');
201
if (attempts < maxAttempts) {
202
await sleep(2000);
203
continue;
204
}
205
break;
206
207
case LIBUSB_ERROR_PIPE:
208
console.log('Pipe error - attempting to clear halt');
209
try {
210
// Clear halt and retry
211
await clearEndpointHalt(device);
212
continue;
213
} catch (clearError) {
214
console.error('Failed to clear halt:', clearError);
215
}
216
break;
217
218
default:
219
console.error('Unrecoverable error');
220
throw error;
221
}
222
}
223
224
if (attempts >= maxAttempts) {
225
throw new Error(`Operation failed after ${maxAttempts} attempts`);
226
}
227
}
228
}
229
}
230
231
function sleep(ms: number): Promise<void> {
232
return new Promise(resolve => setTimeout(resolve, ms));
233
}
234
```
235
236
### USB Class Constants
237
238
USB device and interface class codes.
239
240
```typescript { .api }
241
/**
242
* USB Class Constants
243
*/
244
245
/** Each interface specifies its own class information */
246
const LIBUSB_CLASS_PER_INTERFACE: number;
247
248
/** Audio class */
249
const LIBUSB_CLASS_AUDIO: number;
250
251
/** Communications class */
252
const LIBUSB_CLASS_COMM: number;
253
254
/** Human Interface Device class */
255
const LIBUSB_CLASS_HID: number;
256
257
/** Printer class */
258
const LIBUSB_CLASS_PRINTER: number;
259
260
/** Image class */
261
const LIBUSB_CLASS_PTP: number;
262
263
/** Mass storage class */
264
const LIBUSB_CLASS_MASS_STORAGE: number;
265
266
/** Hub class */
267
const LIBUSB_CLASS_HUB: number;
268
269
/** Data class */
270
const LIBUSB_CLASS_DATA: number;
271
272
/** Wireless class */
273
const LIBUSB_CLASS_WIRELESS: number;
274
275
/** Application class */
276
const LIBUSB_CLASS_APPLICATION: number;
277
278
/** Class is vendor-specific */
279
const LIBUSB_CLASS_VENDOR_SPEC: number;
280
```
281
282
**Usage Examples:**
283
284
```typescript
285
import {
286
getDeviceList,
287
LIBUSB_CLASS_HID,
288
LIBUSB_CLASS_MASS_STORAGE,
289
LIBUSB_CLASS_AUDIO,
290
LIBUSB_CLASS_HUB,
291
LIBUSB_CLASS_VENDOR_SPEC
292
} from 'usb';
293
294
function categorizeDevicesByClass() {
295
const devices = getDeviceList();
296
const devicesByClass: { [key: string]: Device[] } = {};
297
298
devices.forEach(device => {
299
const deviceClass = device.deviceDescriptor.bDeviceClass;
300
const className = getClassNameFromCode(deviceClass);
301
302
if (!devicesByClass[className]) {
303
devicesByClass[className] = [];
304
}
305
306
devicesByClass[className].push(device);
307
});
308
309
// Display results
310
Object.entries(devicesByClass).forEach(([className, devices]) => {
311
console.log(`${className} devices: ${devices.length}`);
312
devices.forEach(device => {
313
console.log(` VID:PID = ${device.deviceDescriptor.idVendor.toString(16)}:${device.deviceDescriptor.idProduct.toString(16)}`);
314
});
315
});
316
317
return devicesByClass;
318
}
319
320
function getClassNameFromCode(classCode: number): string {
321
switch (classCode) {
322
case LIBUSB_CLASS_AUDIO:
323
return 'Audio';
324
case LIBUSB_CLASS_COMM:
325
return 'Communications';
326
case LIBUSB_CLASS_HID:
327
return 'HID';
328
case LIBUSB_CLASS_PRINTER:
329
return 'Printer';
330
case LIBUSB_CLASS_PTP:
331
return 'Image/PTP';
332
case LIBUSB_CLASS_MASS_STORAGE:
333
return 'Mass Storage';
334
case LIBUSB_CLASS_HUB:
335
return 'Hub';
336
case LIBUSB_CLASS_DATA:
337
return 'Data';
338
case LIBUSB_CLASS_WIRELESS:
339
return 'Wireless';
340
case LIBUSB_CLASS_APPLICATION:
341
return 'Application';
342
case LIBUSB_CLASS_VENDOR_SPEC:
343
return 'Vendor Specific';
344
case LIBUSB_CLASS_PER_INTERFACE:
345
return 'Per Interface';
346
default:
347
return 'Unknown';
348
}
349
}
350
351
// Find specific device types
352
function findHIDDevices() {
353
const devices = getDeviceList();
354
return devices.filter(device =>
355
device.deviceDescriptor.bDeviceClass === LIBUSB_CLASS_HID
356
);
357
}
358
359
function findMassStorageDevices() {
360
const devices = getDeviceList();
361
return devices.filter(device =>
362
device.deviceDescriptor.bDeviceClass === LIBUSB_CLASS_MASS_STORAGE
363
);
364
}
365
```
366
367
### Transfer Type Constants
368
369
USB transfer type constants for endpoint configuration.
370
371
```typescript { .api }
372
/**
373
* Transfer Type Constants
374
*/
375
376
/** Control endpoint */
377
const LIBUSB_TRANSFER_TYPE_CONTROL: number;
378
379
/** Isochronous endpoint */
380
const LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: number;
381
382
/** Bulk endpoint */
383
const LIBUSB_TRANSFER_TYPE_BULK: number;
384
385
/** Interrupt endpoint */
386
const LIBUSB_TRANSFER_TYPE_INTERRUPT: number;
387
```
388
389
**Usage Examples:**
390
391
```typescript
392
import {
393
findByIds,
394
LIBUSB_TRANSFER_TYPE_CONTROL,
395
LIBUSB_TRANSFER_TYPE_BULK,
396
LIBUSB_TRANSFER_TYPE_INTERRUPT,
397
LIBUSB_TRANSFER_TYPE_ISOCHRONOUS
398
} from 'usb';
399
400
function analyzeEndpointTypes() {
401
const device = findByIds(0x1234, 0x5678);
402
if (!device) return;
403
404
device.open();
405
406
try {
407
const interface0 = device.interface(0);
408
interface0.claim();
409
410
console.log('Endpoint Analysis:');
411
interface0.endpoints.forEach((endpoint, index) => {
412
const transferType = endpoint.transferType;
413
const typeName = getTransferTypeName(transferType);
414
415
console.log(` Endpoint ${index} (0x${endpoint.address.toString(16)}):`);
416
console.log(` Transfer Type: ${typeName}`);
417
console.log(` Direction: ${endpoint.direction}`);
418
console.log(` Max Packet Size: ${endpoint.descriptor.wMaxPacketSize}`);
419
420
// Provide recommendations based on transfer type
421
switch (transferType) {
422
case LIBUSB_TRANSFER_TYPE_BULK:
423
console.log(` Recommended for: Large data transfers, file transfers`);
424
console.log(` Characteristics: Reliable, error correction, no guaranteed timing`);
425
break;
426
427
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
428
console.log(` Recommended for: Small, periodic data, HID reports`);
429
console.log(` Characteristics: Guaranteed timing, error correction`);
430
console.log(` Polling interval: ${endpoint.descriptor.bInterval}ms`);
431
break;
432
433
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
434
console.log(` Recommended for: Audio/video streaming`);
435
console.log(` Characteristics: Guaranteed timing, no error correction`);
436
break;
437
438
case LIBUSB_TRANSFER_TYPE_CONTROL:
439
console.log(` Recommended for: Device configuration, commands`);
440
console.log(` Characteristics: Reliable, structured format`);
441
break;
442
}
443
});
444
445
interface0.release(() => {});
446
} finally {
447
device.close();
448
}
449
}
450
451
function getTransferTypeName(transferType: number): string {
452
switch (transferType) {
453
case LIBUSB_TRANSFER_TYPE_CONTROL:
454
return 'Control';
455
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
456
return 'Isochronous';
457
case LIBUSB_TRANSFER_TYPE_BULK:
458
return 'Bulk';
459
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
460
return 'Interrupt';
461
default:
462
return 'Unknown';
463
}
464
}
465
```
466
467
### Transfer Status Constants
468
469
USB transfer completion status codes.
470
471
```typescript { .api }
472
/**
473
* Transfer Status Constants
474
*/
475
476
/** Transfer completed without error */
477
const LIBUSB_TRANSFER_COMPLETED: number;
478
479
/** Transfer failed */
480
const LIBUSB_TRANSFER_ERROR: number;
481
482
/** Transfer timed out */
483
const LIBUSB_TRANSFER_TIMED_OUT: number;
484
485
/** Transfer was cancelled */
486
const LIBUSB_TRANSFER_CANCELLED: number;
487
488
/** Halt condition detected (endpoint stalled) or control request not supported */
489
const LIBUSB_TRANSFER_STALL: number;
490
491
/** Device was disconnected */
492
const LIBUSB_TRANSFER_NO_DEVICE: number;
493
494
/** Device sent more data than requested */
495
const LIBUSB_TRANSFER_OVERFLOW: number;
496
```
497
498
**Usage Examples:**
499
500
```typescript
501
import {
502
findByIds,
503
LIBUSB_TRANSFER_COMPLETED,
504
LIBUSB_TRANSFER_ERROR,
505
LIBUSB_TRANSFER_TIMED_OUT,
506
LIBUSB_TRANSFER_CANCELLED,
507
LIBUSB_TRANSFER_STALL,
508
LIBUSB_TRANSFER_NO_DEVICE,
509
LIBUSB_TRANSFER_OVERFLOW
510
} from 'usb';
511
512
function handleTransferStatus() {
513
const device = findByIds(0x1234, 0x5678);
514
if (!device) return;
515
516
device.open();
517
518
try {
519
const interface0 = device.interface(0);
520
interface0.claim();
521
522
const inEndpoint = interface0.endpoints.find(ep => ep.direction === 'in');
523
if (inEndpoint) {
524
// Create transfer with detailed status handling
525
const transfer = inEndpoint.makeTransfer(5000, (error, buffer, actualLength) => {
526
if (error) {
527
console.error('Transfer failed:', error.message);
528
console.error('LibUSB Error Code:', error.errno);
529
530
// Handle transfer-specific errors
531
switch (error.errno) {
532
case LIBUSB_TRANSFER_TIMED_OUT:
533
console.error('Transfer timed out - device may be slow or unresponsive');
534
break;
535
536
case LIBUSB_TRANSFER_STALL:
537
console.error('Endpoint stalled - may need to clear halt');
538
// Clear halt and retry
539
inEndpoint.clearHalt((clearError) => {
540
if (!clearError) {
541
console.log('Halt cleared, can retry transfer');
542
}
543
});
544
break;
545
546
case LIBUSB_TRANSFER_NO_DEVICE:
547
console.error('Device disconnected during transfer');
548
break;
549
550
case LIBUSB_TRANSFER_OVERFLOW:
551
console.error('Device sent more data than expected');
552
break;
553
554
case LIBUSB_TRANSFER_CANCELLED:
555
console.log('Transfer was cancelled');
556
break;
557
558
default:
559
console.error('Unknown transfer error');
560
}
561
} else {
562
console.log(`Transfer completed successfully: ${actualLength} bytes`);
563
564
if (actualLength < buffer.length) {
565
console.log('Short transfer - received less data than buffer size');
566
}
567
568
console.log('Data:', buffer.slice(0, actualLength).toString('hex'));
569
}
570
});
571
572
// Submit transfer
573
const buffer = Buffer.alloc(64);
574
transfer.submit(buffer);
575
576
// Cancel transfer after 2 seconds for demonstration
577
setTimeout(() => {
578
const cancelled = transfer.cancel();
579
if (cancelled) {
580
console.log('Transfer cancellation requested');
581
}
582
}, 2000);
583
}
584
585
interface0.release(() => {});
586
} finally {
587
device.close();
588
}
589
}
590
```
591
592
### Endpoint Direction Constants
593
594
Endpoint direction constants for transfer operations.
595
596
```typescript { .api }
597
/**
598
* Endpoint Direction Constants
599
*/
600
601
/** IN: device-to-host */
602
const LIBUSB_ENDPOINT_IN: number;
603
604
/** OUT: host-to-device */
605
const LIBUSB_ENDPOINT_OUT: number;
606
```
607
608
**Usage Examples:**
609
610
```typescript
611
import {
612
findByIds,
613
LIBUSB_ENDPOINT_IN,
614
LIBUSB_ENDPOINT_OUT
615
} from 'usb';
616
617
function demonstrateEndpointDirections() {
618
const device = findByIds(0x1234, 0x5678);
619
if (!device) return;
620
621
device.open();
622
623
try {
624
const interface0 = device.interface(0);
625
interface0.claim();
626
627
// Find endpoints by direction
628
const inEndpoints = interface0.endpoints.filter(ep => ep.direction === 'in');
629
const outEndpoints = interface0.endpoints.filter(ep => ep.direction === 'out');
630
631
console.log(`Found ${inEndpoints.length} IN endpoints and ${outEndpoints.length} OUT endpoints`);
632
633
// Demonstrate control transfer with direction
634
const bmRequestTypeIn = LIBUSB_ENDPOINT_IN | 0x00 | 0x80; // Standard, device, IN
635
device.controlTransfer(bmRequestTypeIn, 0x06, 0x0100, 0x0000, 18, (error, data) => {
636
if (!error && data) {
637
console.log('IN control transfer successful');
638
}
639
});
640
641
const bmRequestTypeOut = LIBUSB_ENDPOINT_OUT | 0x00 | 0x00; // Standard, device, OUT
642
const outData = Buffer.from([0x01, 0x02, 0x03]);
643
device.controlTransfer(bmRequestTypeOut, 0x09, 0x0001, 0x0000, outData, (error, bytesWritten) => {
644
if (!error) {
645
console.log('OUT control transfer successful');
646
}
647
});
648
649
interface0.release(() => {});
650
} finally {
651
device.close();
652
}
653
}
654
655
// Helper function to determine endpoint direction from address
656
function getEndpointDirection(endpointAddress: number): 'in' | 'out' {
657
return (endpointAddress & LIBUSB_ENDPOINT_IN) ? 'in' : 'out';
658
}
659
660
// Create endpoint address with direction
661
function createEndpointAddress(endpointNumber: number, direction: 'in' | 'out'): number {
662
const directionBit = direction === 'in' ? LIBUSB_ENDPOINT_IN : LIBUSB_ENDPOINT_OUT;
663
return (endpointNumber & 0x7F) | directionBit;
664
}
665
```
666
667
### Request Type Constants
668
669
USB request type constants for control transfers.
670
671
```typescript { .api }
672
/**
673
* Request Type Constants
674
*/
675
676
/** Standard request */
677
const LIBUSB_REQUEST_TYPE_STANDARD: number;
678
679
/** Class-specific request */
680
const LIBUSB_REQUEST_TYPE_CLASS: number;
681
682
/** Vendor-specific request */
683
const LIBUSB_REQUEST_TYPE_VENDOR: number;
684
685
/** Reserved request type */
686
const LIBUSB_REQUEST_TYPE_RESERVED: number;
687
688
/**
689
* Request Recipient Constants
690
*/
691
692
/** Device recipient */
693
const LIBUSB_RECIPIENT_DEVICE: number;
694
695
/** Interface recipient */
696
const LIBUSB_RECIPIENT_INTERFACE: number;
697
698
/** Endpoint recipient */
699
const LIBUSB_RECIPIENT_ENDPOINT: number;
700
701
/** Other recipient */
702
const LIBUSB_RECIPIENT_OTHER: number;
703
```
704
705
**Usage Examples:**
706
707
```typescript
708
import {
709
findByIds,
710
LIBUSB_ENDPOINT_IN,
711
LIBUSB_ENDPOINT_OUT,
712
LIBUSB_REQUEST_TYPE_STANDARD,
713
LIBUSB_REQUEST_TYPE_CLASS,
714
LIBUSB_REQUEST_TYPE_VENDOR,
715
LIBUSB_RECIPIENT_DEVICE,
716
LIBUSB_RECIPIENT_INTERFACE,
717
LIBUSB_RECIPIENT_ENDPOINT
718
} from 'usb';
719
720
function demonstrateControlTransferTypes() {
721
const device = findByIds(0x1234, 0x5678);
722
if (!device) return;
723
724
device.open();
725
726
try {
727
// Standard device request - Get device descriptor
728
const standardRequest = LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE;
729
device.controlTransfer(standardRequest, 0x06, 0x0100, 0x0000, 18, (error, data) => {
730
if (!error && data) {
731
console.log('Standard device request successful');
732
console.log('Device descriptor received:', data.length, 'bytes');
733
}
734
});
735
736
// Vendor-specific request
737
const vendorRequest = LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE;
738
device.controlTransfer(vendorRequest, 0x01, 0x0000, 0x0000, 64, (error, data) => {
739
if (!error && data) {
740
console.log('Vendor-specific request successful');
741
} else if (error) {
742
console.log('Vendor request not supported (expected for most devices)');
743
}
744
});
745
746
// Class-specific interface request (example for HID)
747
const classRequest = LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE;
748
device.controlTransfer(classRequest, 0x01, 0x0000, 0x0000, 8, (error, data) => {
749
if (!error && data) {
750
console.log('Class-specific interface request successful');
751
} else if (error) {
752
console.log('Class request not applicable for this device');
753
}
754
});
755
756
// Endpoint-specific request - Clear halt
757
const endpointRequest = LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_ENDPOINT;
758
device.controlTransfer(endpointRequest, 0x01, 0x0000, 0x0081, 0, (error) => {
759
if (!error) {
760
console.log('Clear halt request successful');
761
} else {
762
console.log('Clear halt not needed or failed');
763
}
764
});
765
766
} finally {
767
device.close();
768
}
769
}
770
771
// Helper function to build request type byte
772
function buildRequestType(direction: 'in' | 'out', type: 'standard' | 'class' | 'vendor', recipient: 'device' | 'interface' | 'endpoint' | 'other'): number {
773
let requestType = 0;
774
775
// Direction
776
if (direction === 'in') {
777
requestType |= LIBUSB_ENDPOINT_IN;
778
}
779
780
// Type
781
switch (type) {
782
case 'standard':
783
requestType |= LIBUSB_REQUEST_TYPE_STANDARD;
784
break;
785
case 'class':
786
requestType |= LIBUSB_REQUEST_TYPE_CLASS;
787
break;
788
case 'vendor':
789
requestType |= LIBUSB_REQUEST_TYPE_VENDOR;
790
break;
791
}
792
793
// Recipient
794
switch (recipient) {
795
case 'device':
796
requestType |= LIBUSB_RECIPIENT_DEVICE;
797
break;
798
case 'interface':
799
requestType |= LIBUSB_RECIPIENT_INTERFACE;
800
break;
801
case 'endpoint':
802
requestType |= LIBUSB_RECIPIENT_ENDPOINT;
803
break;
804
case 'other':
805
requestType |= LIBUSB_RECIPIENT_OTHER;
806
break;
807
}
808
809
return requestType;
810
}
811
812
// Usage example
813
function sendVendorCommand() {
814
const device = findByIds(0x1234, 0x5678);
815
if (!device) return;
816
817
device.open();
818
819
try {
820
// Build vendor-specific device OUT request
821
const requestType = buildRequestType('out', 'vendor', 'device');
822
const commandData = Buffer.from([0x12, 0x34, 0x56, 0x78]);
823
824
device.controlTransfer(requestType, 0x42, 0x1234, 0x0000, commandData, (error, bytesWritten) => {
825
if (!error) {
826
console.log(`Vendor command sent: ${bytesWritten} bytes`);
827
} else {
828
console.error('Vendor command failed:', error.message);
829
}
830
});
831
832
} finally {
833
device.close();
834
}
835
}
836
```