or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

constants-errors.mddata-transfers.mddescriptors.mddevice-communication.mddevice-management.mdevent-handling.mdindex.mdinterfaces-endpoints.mdwebusb-api.md

descriptors.mddocs/

0

# Descriptors and Metadata

1

2

Descriptors and metadata provide access to USB descriptors to understand device capabilities, configuration, and structure. This includes device descriptors, configuration descriptors, interface descriptors, endpoint descriptors, and Binary Object Store (BOS) descriptors.

3

4

## Capabilities

5

6

### Device Descriptors

7

8

Access device-level information and characteristics.

9

10

```typescript { .api }

11

/**

12

* USB Device Descriptor - describes device characteristics

13

*/

14

interface DeviceDescriptor {

15

/** Size of this descriptor (in bytes) */

16

bLength: number;

17

18

/** Descriptor type (should be LIBUSB_DT_DEVICE = 1) */

19

bDescriptorType: number;

20

21

/** USB specification release number in binary-coded decimal */

22

bcdUSB: number;

23

24

/** USB-IF class code for the device */

25

bDeviceClass: number;

26

27

/** USB-IF subclass code for the device, qualified by bDeviceClass */

28

bDeviceSubClass: number;

29

30

/** USB-IF protocol code for the device, qualified by bDeviceClass and bDeviceSubClass */

31

bDeviceProtocol: number;

32

33

/** Maximum packet size for endpoint 0 */

34

bMaxPacketSize0: number;

35

36

/** USB-IF vendor ID */

37

idVendor: number;

38

39

/** USB-IF product ID */

40

idProduct: number;

41

42

/** Device release number in binary-coded decimal */

43

bcdDevice: number;

44

45

/** Index of string descriptor describing manufacturer */

46

iManufacturer: number;

47

48

/** Index of string descriptor describing product */

49

iProduct: number;

50

51

/** Index of string descriptor containing device serial number */

52

iSerialNumber: number;

53

54

/** Number of possible configurations */

55

bNumConfigurations: number;

56

}

57

```

58

59

**Usage Examples:**

60

61

```typescript

62

import { getDeviceList } from 'usb';

63

64

// Analyze device descriptors

65

function analyzeDeviceDescriptors() {

66

const devices = getDeviceList();

67

68

devices.forEach((device, index) => {

69

const desc = device.deviceDescriptor;

70

71

console.log(`Device ${index}:`);

72

console.log(` Descriptor Length: ${desc.bLength}`);

73

console.log(` Descriptor Type: ${desc.bDescriptorType}`);

74

75

// Decode USB version

76

const usbMajor = (desc.bcdUSB >> 8) & 0xFF;

77

const usbMinor = (desc.bcdUSB >> 4) & 0x0F;

78

const usbSub = desc.bcdUSB & 0x0F;

79

console.log(` USB Version: ${usbMajor}.${usbMinor}.${usbSub}`);

80

81

console.log(` Device Class: ${desc.bDeviceClass} (${getDeviceClassName(desc.bDeviceClass)})`);

82

console.log(` Device Subclass: ${desc.bDeviceSubClass}`);

83

console.log(` Device Protocol: ${desc.bDeviceProtocol}`);

84

console.log(` Max Packet Size (EP0): ${desc.bMaxPacketSize0}`);

85

86

console.log(` Vendor ID: 0x${desc.idVendor.toString(16).padStart(4, '0')}`);

87

console.log(` Product ID: 0x${desc.idProduct.toString(16).padStart(4, '0')}`);

88

89

// Decode device version

90

const deviceMajor = (desc.bcdDevice >> 8) & 0xFF;

91

const deviceMinor = (desc.bcdDevice >> 4) & 0x0F;

92

const deviceSub = desc.bcdDevice & 0x0F;

93

console.log(` Device Version: ${deviceMajor}.${deviceMinor}.${deviceSub}`);

94

95

console.log(` Manufacturer String Index: ${desc.iManufacturer}`);

96

console.log(` Product String Index: ${desc.iProduct}`);

97

console.log(` Serial Number String Index: ${desc.iSerialNumber}`);

98

console.log(` Number of Configurations: ${desc.bNumConfigurations}`);

99

console.log('');

100

});

101

}

102

103

function getDeviceClassName(classCode: number): string {

104

const classNames: { [key: number]: string } = {

105

0: 'Per Interface',

106

1: 'Audio',

107

2: 'Communications',

108

3: 'HID',

109

5: 'Physical',

110

6: 'Image',

111

7: 'Printer',

112

8: 'Mass Storage',

113

9: 'Hub',

114

10: 'CDC Data',

115

11: 'Smart Card',

116

13: 'Content Security',

117

14: 'Video',

118

15: 'Personal Healthcare',

119

16: 'Audio/Video',

120

17: 'Billboard',

121

18: 'USB Type-C Bridge',

122

220: 'Diagnostic',

123

224: 'Wireless',

124

239: 'Miscellaneous',

125

254: 'Application Specific',

126

255: 'Vendor Specific'

127

};

128

129

return classNames[classCode] || 'Unknown';

130

}

131

132

// Get device strings from descriptor indices

133

async function getDeviceStrings(device: Device) {

134

const desc = device.deviceDescriptor;

135

const strings: any = {};

136

137

device.open();

138

139

try {

140

// Get manufacturer string

141

if (desc.iManufacturer > 0) {

142

strings.manufacturer = await new Promise<string>((resolve, reject) => {

143

device.getStringDescriptor(desc.iManufacturer, (error, value) => {

144

if (error) reject(error);

145

else resolve(value || '');

146

});

147

});

148

}

149

150

// Get product string

151

if (desc.iProduct > 0) {

152

strings.product = await new Promise<string>((resolve, reject) => {

153

device.getStringDescriptor(desc.iProduct, (error, value) => {

154

if (error) reject(error);

155

else resolve(value || '');

156

});

157

});

158

}

159

160

// Get serial number string

161

if (desc.iSerialNumber > 0) {

162

strings.serialNumber = await new Promise<string>((resolve, reject) => {

163

device.getStringDescriptor(desc.iSerialNumber, (error, value) => {

164

if (error) reject(error);

165

else resolve(value || '');

166

});

167

});

168

}

169

170

} catch (error) {

171

console.warn('Could not retrieve some string descriptors:', error);

172

} finally {

173

device.close();

174

}

175

176

return strings;

177

}

178

```

179

180

### Configuration Descriptors

181

182

Access device configuration information and interface layout.

183

184

```typescript { .api }

185

/**

186

* USB Configuration Descriptor - describes device configuration

187

*/

188

interface ConfigDescriptor {

189

/** Size of this descriptor (in bytes) */

190

bLength: number;

191

192

/** Descriptor type (should be LIBUSB_DT_CONFIG = 2) */

193

bDescriptorType: number;

194

195

/** Total length of data returned for this configuration */

196

wTotalLength: number;

197

198

/** Number of interfaces supported by this configuration */

199

bNumInterfaces: number;

200

201

/** Identifier value for this configuration */

202

bConfigurationValue: number;

203

204

/** Index of string descriptor describing this configuration */

205

iConfiguration: number;

206

207

/** Configuration characteristics */

208

bmAttributes: number;

209

210

/** Maximum power consumption from bus in this configuration (in 2mA units) */

211

bMaxPower: number;

212

213

/** Extra descriptors */

214

extra: Buffer;

215

216

/** Array of interfaces supported by this configuration */

217

interfaces: InterfaceDescriptor[][];

218

}

219

```

220

221

**Usage Examples:**

222

223

```typescript

224

import { findByIds } from 'usb';

225

226

async function analyzeConfiguration() {

227

const device = findByIds(0x1234, 0x5678);

228

if (!device) return;

229

230

device.open();

231

232

try {

233

// Get current configuration descriptor

234

const configDesc = device.configDescriptor;

235

if (configDesc) {

236

console.log('Configuration Descriptor:');

237

console.log(` Length: ${configDesc.bLength}`);

238

console.log(` Type: ${configDesc.bDescriptorType}`);

239

console.log(` Total Length: ${configDesc.wTotalLength}`);

240

console.log(` Number of Interfaces: ${configDesc.bNumInterfaces}`);

241

console.log(` Configuration Value: ${configDesc.bConfigurationValue}`);

242

console.log(` Configuration String Index: ${configDesc.iConfiguration}`);

243

244

// Decode attributes

245

const attributes = configDesc.bmAttributes;

246

console.log(` Attributes: 0x${attributes.toString(16)}`);

247

console.log(` Self Powered: ${(attributes & 0x40) ? 'Yes' : 'No'}`);

248

console.log(` Remote Wakeup: ${(attributes & 0x20) ? 'Yes' : 'No'}`);

249

250

console.log(` Max Power: ${configDesc.bMaxPower * 2}mA`);

251

console.log(` Extra Descriptors: ${configDesc.extra.length} bytes`);

252

253

// Analyze interfaces

254

configDesc.interfaces.forEach((interfaceGroup, groupIndex) => {

255

console.log(` Interface Group ${groupIndex}:`);

256

interfaceGroup.forEach((altSetting, altIndex) => {

257

console.log(` Alternate Setting ${altIndex}:`);

258

console.log(` Interface Number: ${altSetting.bInterfaceNumber}`);

259

console.log(` Alternate Setting: ${altSetting.bAlternateSetting}`);

260

console.log(` Interface Class: ${altSetting.bInterfaceClass}`);

261

console.log(` Interface Subclass: ${altSetting.bInterfaceSubClass}`);

262

console.log(` Interface Protocol: ${altSetting.bInterfaceProtocol}`);

263

console.log(` Number of Endpoints: ${altSetting.bNumEndpoints}`);

264

});

265

});

266

}

267

268

// Get all configuration descriptors

269

const allConfigs = device.allConfigDescriptors;

270

console.log(`\nDevice has ${allConfigs.length} configuration(s):`);

271

272

allConfigs.forEach((config, index) => {

273

console.log(`Configuration ${index}:`);

274

console.log(` Value: ${config.bConfigurationValue}`);

275

console.log(` Interfaces: ${config.bNumInterfaces}`);

276

console.log(` Power: ${config.bMaxPower * 2}mA`);

277

278

if (config.iConfiguration > 0) {

279

device.getStringDescriptor(config.iConfiguration, (error, configName) => {

280

if (!error && configName) {

281

console.log(` Name: ${configName}`);

282

}

283

});

284

}

285

});

286

287

} finally {

288

device.close();

289

}

290

}

291

292

// Find devices with specific configuration characteristics

293

function findDevicesByPowerRequirement(maxPowerMa: number) {

294

const devices = getDeviceList();

295

const matchingDevices: Device[] = [];

296

297

devices.forEach(device => {

298

try {

299

device.open();

300

const configDesc = device.configDescriptor;

301

302

if (configDesc && (configDesc.bMaxPower * 2) <= maxPowerMa) {

303

matchingDevices.push(device);

304

console.log(`Found low-power device: VID:PID = ${device.deviceDescriptor.idVendor.toString(16)}:${device.deviceDescriptor.idProduct.toString(16)}`);

305

console.log(` Power consumption: ${configDesc.bMaxPower * 2}mA`);

306

}

307

308

device.close();

309

} catch (error) {

310

// Skip devices that can't be opened

311

}

312

});

313

314

return matchingDevices;

315

}

316

```

317

318

### Interface Descriptors

319

320

Access interface-level information and endpoint configuration.

321

322

```typescript { .api }

323

/**

324

* USB Interface Descriptor - describes interface characteristics

325

*/

326

interface InterfaceDescriptor {

327

/** Size of this descriptor (in bytes) */

328

bLength: number;

329

330

/** Descriptor type (should be LIBUSB_DT_INTERFACE = 4) */

331

bDescriptorType: number;

332

333

/** Number of this interface */

334

bInterfaceNumber: number;

335

336

/** Value used to select this alternate setting for this interface */

337

bAlternateSetting: number;

338

339

/** Number of endpoints used by this interface (excluding control endpoint) */

340

bNumEndpoints: number;

341

342

/** USB-IF class code for this interface */

343

bInterfaceClass: number;

344

345

/** USB-IF subclass code for this interface, qualified by bInterfaceClass */

346

bInterfaceSubClass: number;

347

348

/** USB-IF protocol code for this interface, qualified by bInterfaceClass and bInterfaceSubClass */

349

bInterfaceProtocol: number;

350

351

/** Index of string descriptor describing this interface */

352

iInterface: number;

353

354

/** Extra descriptors */

355

extra: Buffer;

356

357

/** Array of endpoint descriptors */

358

endpoints: EndpointDescriptor[];

359

}

360

```

361

362

**Usage Examples:**

363

364

```typescript

365

import { findByIds } from 'usb';

366

367

function analyzeInterfaces() {

368

const device = findByIds(0x1234, 0x5678);

369

if (!device) return;

370

371

device.open();

372

373

try {

374

const configDesc = device.configDescriptor;

375

if (!configDesc) return;

376

377

configDesc.interfaces.forEach((interfaceGroup, groupIndex) => {

378

console.log(`Interface Group ${groupIndex}:`);

379

380

interfaceGroup.forEach((ifaceDesc, altIndex) => {

381

console.log(` Alternate Setting ${altIndex}:`);

382

console.log(` Length: ${ifaceDesc.bLength}`);

383

console.log(` Type: ${ifaceDesc.bDescriptorType}`);

384

console.log(` Interface Number: ${ifaceDesc.bInterfaceNumber}`);

385

console.log(` Alternate Setting: ${ifaceDesc.bAlternateSetting}`);

386

console.log(` Number of Endpoints: ${ifaceDesc.bNumEndpoints}`);

387

console.log(` Interface Class: ${ifaceDesc.bInterfaceClass} (${getInterfaceClassName(ifaceDesc.bInterfaceClass)})`);

388

console.log(` Interface Subclass: ${ifaceDesc.bInterfaceSubClass}`);

389

console.log(` Interface Protocol: ${ifaceDesc.bInterfaceProtocol}`);

390

console.log(` Interface String Index: ${ifaceDesc.iInterface}`);

391

console.log(` Extra Descriptors: ${ifaceDesc.extra.length} bytes`);

392

393

// Get interface string if available

394

if (ifaceDesc.iInterface > 0) {

395

device.getStringDescriptor(ifaceDesc.iInterface, (error, interfaceName) => {

396

if (!error && interfaceName) {

397

console.log(` Interface Name: ${interfaceName}`);

398

}

399

});

400

}

401

402

// Analyze endpoints

403

ifaceDesc.endpoints.forEach((endpoint, epIndex) => {

404

console.log(` Endpoint ${epIndex}:`);

405

analyzeEndpointDescriptor(endpoint);

406

});

407

408

console.log('');

409

});

410

});

411

412

} finally {

413

device.close();

414

}

415

}

416

417

function getInterfaceClassName(classCode: number): string {

418

const classNames: { [key: number]: string } = {

419

1: 'Audio',

420

2: 'Communications',

421

3: 'HID',

422

5: 'Physical',

423

6: 'Image',

424

7: 'Printer',

425

8: 'Mass Storage',

426

9: 'Hub',

427

10: 'CDC Data',

428

11: 'Smart Card',

429

13: 'Content Security',

430

14: 'Video',

431

15: 'Personal Healthcare',

432

255: 'Vendor Specific'

433

};

434

435

return classNames[classCode] || 'Unknown';

436

}

437

438

// Find interfaces by class

439

function findInterfacesByClass(targetClass: number) {

440

const devices = getDeviceList();

441

const matchingInterfaces: any[] = [];

442

443

devices.forEach(device => {

444

try {

445

device.open();

446

const configDesc = device.configDescriptor;

447

448

if (configDesc) {

449

configDesc.interfaces.forEach((interfaceGroup, groupIndex) => {

450

interfaceGroup.forEach((ifaceDesc, altIndex) => {

451

if (ifaceDesc.bInterfaceClass === targetClass) {

452

matchingInterfaces.push({

453

device: device,

454

interfaceNumber: ifaceDesc.bInterfaceNumber,

455

alternateSetting: ifaceDesc.bAlternateSetting,

456

descriptor: ifaceDesc

457

});

458

459

console.log(`Found ${getInterfaceClassName(targetClass)} interface:`);

460

console.log(` Device: VID:PID = ${device.deviceDescriptor.idVendor.toString(16)}:${device.deviceDescriptor.idProduct.toString(16)}`);

461

console.log(` Interface: ${ifaceDesc.bInterfaceNumber}, Alt: ${ifaceDesc.bAlternateSetting}`);

462

}

463

});

464

});

465

}

466

467

device.close();

468

} catch (error) {

469

// Skip devices that can't be opened

470

}

471

});

472

473

return matchingInterfaces;

474

}

475

```

476

477

### Endpoint Descriptors

478

479

Access endpoint-level information for data transfer configuration.

480

481

```typescript { .api }

482

/**

483

* USB Endpoint Descriptor - describes endpoint characteristics

484

*/

485

interface EndpointDescriptor {

486

/** Size of this descriptor (in bytes) */

487

bLength: number;

488

489

/** Descriptor type (should be LIBUSB_DT_ENDPOINT = 5) */

490

bDescriptorType: number;

491

492

/** The address of the endpoint described by this descriptor */

493

bEndpointAddress: number;

494

495

/** Attributes which apply to the endpoint when configured using bConfigurationValue */

496

bmAttributes: number;

497

498

/** Maximum packet size this endpoint is capable of sending/receiving */

499

wMaxPacketSize: number;

500

501

/** Interval for polling endpoint for data transfers */

502

bInterval: number;

503

504

/** For audio devices only: the rate at which synchronization feedback is provided */

505

bRefresh: number;

506

507

/** For audio devices only: the address of the synch endpoint */

508

bSynchAddress: number;

509

510

/** Extra descriptors */

511

extra: Buffer;

512

}

513

```

514

515

**Usage Examples:**

516

517

```typescript

518

import { findByIds, LIBUSB_ENDPOINT_IN } from 'usb';

519

520

function analyzeEndpointDescriptor(endpointDesc: EndpointDescriptor) {

521

console.log(` Length: ${endpointDesc.bLength}`);

522

console.log(` Type: ${endpointDesc.bDescriptorType}`);

523

console.log(` Address: 0x${endpointDesc.bEndpointAddress.toString(16)}`);

524

525

// Decode endpoint address

526

const endpointNumber = endpointDesc.bEndpointAddress & 0x7F;

527

const direction = (endpointDesc.bEndpointAddress & LIBUSB_ENDPOINT_IN) ? 'IN' : 'OUT';

528

console.log(` Endpoint Number: ${endpointNumber}`);

529

console.log(` Direction: ${direction}`);

530

531

// Decode attributes

532

const transferType = endpointDesc.bmAttributes & 0x03;

533

const syncType = (endpointDesc.bmAttributes >> 2) & 0x03;

534

const usageType = (endpointDesc.bmAttributes >> 4) & 0x03;

535

536

const transferTypes = ['Control', 'Isochronous', 'Bulk', 'Interrupt'];

537

const syncTypes = ['No Sync', 'Asynchronous', 'Adaptive', 'Synchronous'];

538

const usageTypes = ['Data', 'Feedback', 'Implicit Feedback', 'Reserved'];

539

540

console.log(` Transfer Type: ${transferTypes[transferType] || 'Unknown'}`);

541

if (transferType === 1) { // Isochronous

542

console.log(` Sync Type: ${syncTypes[syncType] || 'Unknown'}`);

543

console.log(` Usage Type: ${usageTypes[usageType] || 'Unknown'}`);

544

}

545

546

console.log(` Max Packet Size: ${endpointDesc.wMaxPacketSize}`);

547

console.log(` Polling Interval: ${endpointDesc.bInterval}`);

548

549

if (endpointDesc.bRefresh > 0) {

550

console.log(` Refresh: ${endpointDesc.bRefresh}`);

551

}

552

553

if (endpointDesc.bSynchAddress > 0) {

554

console.log(` Synch Address: 0x${endpointDesc.bSynchAddress.toString(16)}`);

555

}

556

557

console.log(` Extra Descriptors: ${endpointDesc.extra.length} bytes`);

558

}

559

560

function findEndpointsByType(transferType: number) {

561

const devices = getDeviceList();

562

const matchingEndpoints: any[] = [];

563

564

devices.forEach(device => {

565

try {

566

device.open();

567

const configDesc = device.configDescriptor;

568

569

if (configDesc) {

570

configDesc.interfaces.forEach((interfaceGroup) => {

571

interfaceGroup.forEach((ifaceDesc) => {

572

ifaceDesc.endpoints.forEach((endpoint) => {

573

if ((endpoint.bmAttributes & 0x03) === transferType) {

574

matchingEndpoints.push({

575

device: device,

576

interfaceNumber: ifaceDesc.bInterfaceNumber,

577

endpoint: endpoint

578

});

579

580

const transferTypes = ['Control', 'Isochronous', 'Bulk', 'Interrupt'];

581

console.log(`Found ${transferTypes[transferType]} endpoint:`);

582

console.log(` Device: VID:PID = ${device.deviceDescriptor.idVendor.toString(16)}:${device.deviceDescriptor.idProduct.toString(16)}`);

583

console.log(` Interface: ${ifaceDesc.bInterfaceNumber}`);

584

console.log(` Endpoint: 0x${endpoint.bEndpointAddress.toString(16)}`);

585

console.log(` Max Packet Size: ${endpoint.wMaxPacketSize}`);

586

}

587

});

588

});

589

});

590

}

591

592

device.close();

593

} catch (error) {

594

// Skip devices that can't be opened

595

}

596

});

597

598

return matchingEndpoints;

599

}

600

601

// Analyze endpoint capabilities for optimal transfer settings

602

function analyzeEndpointCapabilities(device: Device, interfaceNumber: number) {

603

device.open();

604

605

try {

606

const interface0 = device.interface(interfaceNumber);

607

const ifaceDesc = interface0.descriptor;

608

609

console.log(`Interface ${interfaceNumber} Endpoint Analysis:`);

610

611

interface0.endpoints.forEach((endpoint, index) => {

612

const desc = endpoint.descriptor;

613

console.log(` Endpoint ${index} (0x${desc.bEndpointAddress.toString(16)}):`);

614

console.log(` Max Packet Size: ${desc.wMaxPacketSize}`);

615

console.log(` Transfer Type: ${endpoint.transferType}`);

616

console.log(` Direction: ${endpoint.direction}`);

617

618

// Calculate optimal transfer settings

619

if (endpoint.direction === 'in') {

620

console.log(` Recommended read size: ${desc.wMaxPacketSize * 8} bytes`);

621

console.log(` Polling interval: ${desc.bInterval}ms`);

622

} else {

623

console.log(` Recommended write chunk: ${desc.wMaxPacketSize} bytes`);

624

}

625

626

// Check for high-speed capabilities

627

if (desc.wMaxPacketSize > 64) {

628

console.log(` High-speed capable (packet size > 64)`);

629

}

630

631

// Isochronous-specific analysis

632

if ((desc.bmAttributes & 0x03) === 1) {

633

const packetsPerFrame = ((desc.wMaxPacketSize >> 11) & 0x03) + 1;

634

const actualPacketSize = desc.wMaxPacketSize & 0x7FF;

635

console.log(` Packets per microframe: ${packetsPerFrame}`);

636

console.log(` Actual packet size: ${actualPacketSize}`);

637

console.log(` Max bandwidth: ${actualPacketSize * packetsPerFrame * 8000} bytes/sec`);

638

}

639

});

640

641

} finally {

642

device.close();

643

}

644

}

645

```

646

647

### Binary Object Store (BOS) Descriptors

648

649

Access advanced device capabilities through BOS descriptors.

650

651

```typescript { .api }

652

/**

653

* Binary Object Store (BOS) Descriptor - describes device capabilities

654

*/

655

interface BosDescriptor {

656

/** Size of this descriptor (in bytes) */

657

bLength: number;

658

659

/** Descriptor type (should be LIBUSB_DT_BOS = 15) */

660

bDescriptorType: number;

661

662

/** Length of this descriptor and all of its sub descriptors */

663

wTotalLength: number;

664

665

/** The number of separate device capability descriptors in the BOS */

666

bNumDeviceCaps: number;

667

668

/** Device Capability Descriptors */

669

capabilities: CapabilityDescriptor[];

670

}

671

672

/**

673

* Generic representation of a BOS Device Capability descriptor

674

*/

675

interface CapabilityDescriptor {

676

/** Size of this descriptor (in bytes) */

677

bLength: number;

678

679

/** Descriptor type (should be DEVICE_CAPABILITY = 16) */

680

bDescriptorType: number;

681

682

/** Device Capability type */

683

bDevCapabilityType: number;

684

685

/** Device Capability data (bLength - 3 bytes) */

686

dev_capability_data: Buffer;

687

}

688

689

/**

690

* Capability class for accessing BOS capabilities

691

*/

692

interface Capability {

693

/** Object with fields from the capability descriptor */

694

descriptor: CapabilityDescriptor;

695

696

/** Integer capability type */

697

type: number;

698

699

/** Buffer capability data */

700

data: Buffer;

701

}

702

```

703

704

**Usage Examples:**

705

706

```typescript

707

import { findByIds } from 'usb';

708

709

async function analyzeBOSDescriptor() {

710

const device = findByIds(0x1234, 0x5678);

711

if (!device) return;

712

713

device.open();

714

715

try {

716

// Get BOS descriptor

717

const bosDescriptor = await new Promise<BosDescriptor | undefined>((resolve, reject) => {

718

device.getBosDescriptor((error, descriptor) => {

719

if (error) reject(error);

720

else resolve(descriptor);

721

});

722

});

723

724

if (bosDescriptor) {

725

console.log('BOS Descriptor:');

726

console.log(` Length: ${bosDescriptor.bLength}`);

727

console.log(` Type: ${bosDescriptor.bDescriptorType}`);

728

console.log(` Total Length: ${bosDescriptor.wTotalLength}`);

729

console.log(` Number of Capabilities: ${bosDescriptor.bNumDeviceCaps}`);

730

731

// Analyze each capability

732

bosDescriptor.capabilities.forEach((capability, index) => {

733

console.log(` Capability ${index}:`);

734

console.log(` Length: ${capability.bLength}`);

735

console.log(` Type: ${capability.bDescriptorType}`);

736

console.log(` Capability Type: ${capability.bDevCapabilityType} (${getCapabilityTypeName(capability.bDevCapabilityType)})`);

737

console.log(` Data Length: ${capability.dev_capability_data.length} bytes`);

738

739

if (capability.dev_capability_data.length > 0) {

740

console.log(` Data: ${capability.dev_capability_data.toString('hex')}`);

741

}

742

});

743

} else {

744

console.log('Device does not have BOS descriptor (USB 2.0 or earlier)');

745

}

746

747

// Get capabilities using Capability class

748

const capabilities = await new Promise<Capability[]>((resolve, reject) => {

749

device.getCapabilities((error, capabilities) => {

750

if (error) reject(error);

751

else resolve(capabilities || []);

752

});

753

});

754

755

console.log(`\nFound ${capabilities.length} capabilities:`);

756

capabilities.forEach((capability, index) => {

757

console.log(`Capability ${index}:`);

758

console.log(` Type: ${capability.type}`);

759

console.log(` Data Length: ${capability.data.length}`);

760

console.log(` Data: ${capability.data.toString('hex')}`);

761

});

762

763

} catch (error) {

764

console.log('Could not retrieve BOS descriptor:', error.message);

765

} finally {

766

device.close();

767

}

768

}

769

770

function getCapabilityTypeName(capabilityType: number): string {

771

const capabilityTypes: { [key: number]: string } = {

772

1: 'Wireless USB',

773

2: 'USB 2.0 Extension',

774

3: 'SuperSpeed USB',

775

4: 'Container ID',

776

5: 'Platform',

777

6: 'Power Delivery Capability',

778

7: 'Battery Info Capability',

779

8: 'PD Consumer Port Capability',

780

9: 'PD Provider Port Capability',

781

10: 'SuperSpeed Plus',

782

11: 'Precision Time Measurement',

783

12: 'Wireless USB Ext'

784

};

785

786

return capabilityTypes[capabilityType] || 'Unknown';

787

}

788

789

// Analyze USB 3.0 SuperSpeed capabilities

790

function analyzeSuperspeedCapabilities(capability: Capability) {

791

if (capability.type === 3) { // SuperSpeed USB capability

792

const data = capability.data;

793

794

if (data.length >= 6) {

795

const bmAttributes = data.readUInt8(0);

796

const wSpeedsSupported = data.readUInt16LE(1);

797

const bFunctionalitySupport = data.readUInt8(3);

798

const bU1DevExitLat = data.readUInt8(4);

799

const bU2DevExitLat = data.readUInt16LE(5);

800

801

console.log('SuperSpeed USB Capability:');

802

console.log(` Attributes: 0x${bmAttributes.toString(16)}`);

803

console.log(` LTM Capable: ${(bmAttributes & 0x02) ? 'Yes' : 'No'}`);

804

console.log(` Speeds Supported: 0x${wSpeedsSupported.toString(16)}`);

805

console.log(` Low Speed: ${(wSpeedsSupported & 0x01) ? 'Yes' : 'No'}`);

806

console.log(` Full Speed: ${(wSpeedsSupported & 0x02) ? 'Yes' : 'No'}`);

807

console.log(` High Speed: ${(wSpeedsSupported & 0x04) ? 'Yes' : 'No'}`);

808

console.log(` SuperSpeed: ${(wSpeedsSupported & 0x08) ? 'Yes' : 'No'}`);

809

console.log(` Functionality Support: ${bFunctionalitySupport}`);

810

console.log(` U1 Device Exit Latency: ${bU1DevExitLat}μs`);

811

console.log(` U2 Device Exit Latency: ${bU2DevExitLat}μs`);

812

}

813

}

814

}

815

816

// Find USB 3.0 capable devices

817

async function findUSB3Devices() {

818

const devices = getDeviceList();

819

const usb3Devices: Device[] = [];

820

821

for (const device of devices) {

822

try {

823

device.open();

824

825

const capabilities = await new Promise<Capability[]>((resolve, reject) => {

826

device.getCapabilities((error, capabilities) => {

827

if (error) reject(error);

828

else resolve(capabilities || []);

829

});

830

});

831

832

const hasSuperspeed = capabilities.some(cap => cap.type === 3);

833

if (hasSuperspeed) {

834

usb3Devices.push(device);

835

console.log(`USB 3.0 device: VID:PID = ${device.deviceDescriptor.idVendor.toString(16)}:${device.deviceDescriptor.idProduct.toString(16)}`);

836

837

// Analyze SuperSpeed capability

838

const sspeedCap = capabilities.find(cap => cap.type === 3);

839

if (sspeedCap) {

840

analyzeSuperspeedCapabilities(sspeedCap);

841

}

842

}

843

844

device.close();

845

} catch (error) {

846

// Skip devices that can't be opened or don't have BOS

847

try { device.close(); } catch {}

848

}

849

}

850

851

return usb3Devices;

852

}

853

```