or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-transfers.mddescriptors.mddevice-access.mdindex.mdsync-transfers.mdusb-context.md

device-access.mddocs/

0

# Device Access and Configuration

1

2

USB device access involves two main classes: USBDevice for device enumeration and descriptor access, and USBDeviceHandle for actual communication and configuration. This separation allows efficient device discovery without claiming system resources until communication is needed.

3

4

## Capabilities

5

6

### Device Information and Properties

7

8

Access device identification, location, and capability information without opening the device for communication.

9

10

```python { .api }

11

class USBDevice:

12

def getBusNumber(self):

13

"""

14

Get device's bus number.

15

16

Returns:

17

int: Bus number

18

"""

19

20

def getPortNumber(self):

21

"""

22

Get device's port number.

23

24

Returns:

25

int: Port number

26

"""

27

28

def getPortNumberList(self):

29

"""

30

Get list of port numbers from root hub to device.

31

32

Returns:

33

list[int]: Port numbers along the path

34

"""

35

36

def getDeviceAddress(self):

37

"""

38

Get device's address on the bus.

39

40

Returns:

41

int: Device address (1-127)

42

"""

43

44

def getVendorID(self):

45

"""

46

Get device's vendor ID.

47

48

Returns:

49

int: 16-bit vendor ID

50

"""

51

52

def getProductID(self):

53

"""

54

Get device's product ID.

55

56

Returns:

57

int: 16-bit product ID

58

"""

59

60

def getbcdUSB(self):

61

"""

62

Get USB specification version in BCD format.

63

64

Returns:

65

int: USB version (e.g. 0x0200 for USB 2.0)

66

"""

67

68

def getbcdDevice(self):

69

"""

70

Get device release number in BCD format.

71

72

Returns:

73

int: Device release number

74

"""

75

76

def getDeviceClass(self):

77

"""

78

Get device class code.

79

80

Returns:

81

int: Device class (0 if specified at interface level)

82

"""

83

84

def getDeviceSubClass(self):

85

"""

86

Get device subclass code.

87

88

Returns:

89

int: Device subclass

90

"""

91

92

def getDeviceProtocol(self):

93

"""

94

Get device protocol code.

95

96

Returns:

97

int: Device protocol

98

"""

99

100

def getDeviceSpeed(self):

101

"""

102

Get device operating speed.

103

104

Returns:

105

int: Speed constant (SPEED_LOW, SPEED_FULL, SPEED_HIGH, SPEED_SUPER, SPEED_SUPER_PLUS)

106

"""

107

108

def getMaxPacketSize0(self):

109

"""

110

Get maximum packet size for endpoint 0 (control endpoint).

111

112

Returns:

113

int: Maximum packet size in bytes

114

"""

115

116

def getMaxPacketSize(self, endpoint):

117

"""

118

Get maximum packet size for specified endpoint.

119

120

Args:

121

endpoint (int): Endpoint address

122

123

Returns:

124

int: Maximum packet size in bytes

125

126

Warning:

127

May not always give expected results. Consult endpoint descriptor instead.

128

"""

129

130

def getMaxISOPacketSize(self, endpoint):

131

"""

132

Get maximum isochronous packet size for endpoint.

133

134

Args:

135

endpoint (int): Endpoint address

136

137

Returns:

138

int: Maximum ISO packet size in bytes

139

140

Warning:

141

May not always give expected results. Consult endpoint descriptor instead.

142

"""

143

144

def getNumConfigurations(self):

145

"""

146

Get number of possible configurations.

147

148

Returns:

149

int: Number of configurations

150

"""

151

```

152

153

### Device Opening and Closing

154

155

Open devices for communication and manage device handle lifecycle.

156

157

```python { .api }

158

class USBDevice:

159

def open(self):

160

"""

161

Open device for communication.

162

163

Returns:

164

USBDeviceHandle: Handle for device communication

165

166

Raises:

167

USBError: If device cannot be opened

168

"""

169

170

def close(self):

171

"""Close device and release resources."""

172

173

class USBDeviceHandle:

174

def close(self):

175

"""

176

Close device handle and release resources.

177

178

Note:

179

Cancels any in-flight transfers. May block until transfers complete.

180

"""

181

182

def getDevice(self):

183

"""

184

Get USBDevice instance for this handle.

185

186

Returns:

187

USBDevice: Associated device instance

188

"""

189

```

190

191

### String Descriptor Access

192

193

Retrieve human-readable device information including manufacturer, product name, and serial number.

194

195

```python { .api }

196

class USBDevice:

197

def getManufacturer(self):

198

"""

199

Get manufacturer string (opens device temporarily).

200

201

Returns:

202

str or None: Manufacturer name or None if not available

203

"""

204

205

def getProduct(self):

206

"""

207

Get product string (opens device temporarily).

208

209

Returns:

210

str or None: Product name or None if not available

211

"""

212

213

def getSerialNumber(self):

214

"""

215

Get serial number string (opens device temporarily).

216

217

Returns:

218

str or None: Serial number or None if not available

219

"""

220

221

def getSupportedLanguageList(self):

222

"""

223

Get list of supported language IDs (opens device temporarily).

224

225

Returns:

226

list[int]: List of language IDs

227

"""

228

229

class USBDeviceHandle:

230

def getManufacturer(self):

231

"""

232

Get manufacturer string.

233

234

Returns:

235

str or None: Manufacturer name or None if not available

236

"""

237

238

def getProduct(self):

239

"""

240

Get product string.

241

242

Returns:

243

str or None: Product name or None if not available

244

"""

245

246

def getSerialNumber(self):

247

"""

248

Get serial number string.

249

250

Returns:

251

str or None: Serial number or None if not available

252

"""

253

254

def getSupportedLanguageList(self):

255

"""

256

Get list of supported language IDs.

257

258

Returns:

259

list[int]: List of USB language identifiers

260

"""

261

262

def getStringDescriptor(self, descriptor, lang_id, errors='strict'):

263

"""

264

Get string descriptor in specified language.

265

266

Args:

267

descriptor (int): String descriptor index

268

lang_id (int): Language ID

269

errors (str): Error handling mode ('strict', 'ignore', 'replace')

270

271

Returns:

272

str or None: String content or None if not found

273

"""

274

275

def getASCIIStringDescriptor(self, descriptor, errors='strict'):

276

"""

277

Get string descriptor in first available language as ASCII.

278

279

Args:

280

descriptor (int): String descriptor index

281

errors (str): Error handling mode ('strict', 'ignore', 'replace')

282

283

Returns:

284

str or None: String content or None if not found

285

"""

286

```

287

288

### Configuration Management

289

290

Get and set device configuration, the top-level organizational unit for device functionality.

291

292

```python { .api }

293

class USBDeviceHandle:

294

def getConfiguration(self):

295

"""

296

Get current configuration number.

297

298

Returns:

299

int: Configuration value (1-based, 0 = unconfigured)

300

"""

301

302

def setConfiguration(self, configuration):

303

"""

304

Set device configuration.

305

306

Args:

307

configuration (int): Configuration value (1-based, 0 = unconfigure)

308

309

Raises:

310

USBError: If configuration cannot be set

311

"""

312

```

313

314

### Interface Management

315

316

Claim and release interfaces for exclusive access, and manage alternate settings within interfaces.

317

318

```python { .api }

319

class USBDeviceHandle:

320

def claimInterface(self, interface):

321

"""

322

Claim interface for exclusive access.

323

324

Args:

325

interface (int): Interface number

326

327

Returns:

328

_ReleaseInterface: Context manager that auto-releases on exit

329

330

Raises:

331

USBError: If interface cannot be claimed

332

333

Usage:

334

with handle.claimInterface(0):

335

# perform operations

336

pass

337

# interface automatically released

338

"""

339

340

def releaseInterface(self, interface):

341

"""

342

Release interface, allowing other processes to claim it.

343

344

Args:

345

interface (int): Interface number

346

347

Raises:

348

USBError: If interface cannot be released

349

"""

350

351

def setInterfaceAltSetting(self, interface, alt_setting):

352

"""

353

Set alternate setting for interface.

354

355

Args:

356

interface (int): Interface number

357

alt_setting (int): Alternate setting number

358

359

Raises:

360

USBError: If alternate setting cannot be set

361

"""

362

```

363

364

### Endpoint Management

365

366

Manage endpoint states and clear error conditions.

367

368

```python { .api }

369

class USBDeviceHandle:

370

def clearHalt(self, endpoint):

371

"""

372

Clear halt/stall condition on endpoint.

373

374

Args:

375

endpoint (int): Endpoint address

376

377

Raises:

378

USBError: If halt cannot be cleared

379

"""

380

```

381

382

### Device Reset

383

384

Reset device to initial state, potentially causing disconnection and reconnection.

385

386

```python { .api }

387

class USBDeviceHandle:

388

def resetDevice(self):

389

"""

390

Reset device to initial state.

391

392

Raises:

393

USBErrorNotFound: If device disconnects and must be rediscovered

394

USBError: If reset fails

395

396

Note:

397

May cause device to disconnect and reconnect with new address.

398

"""

399

```

400

401

### Kernel Driver Management

402

403

Manage kernel driver attachment and detachment for interface access on Linux and similar systems.

404

405

```python { .api }

406

class USBDeviceHandle:

407

def kernelDriverActive(self, interface):

408

"""

409

Check if kernel driver is active on interface.

410

411

Args:

412

interface (int): Interface number

413

414

Returns:

415

bool: True if kernel driver is active

416

"""

417

418

def detachKernelDriver(self, interface):

419

"""

420

Detach kernel driver from interface.

421

422

Args:

423

interface (int): Interface number

424

425

Raises:

426

USBError: If driver cannot be detached

427

428

Note:

429

Required on Linux before claiming some interfaces.

430

"""

431

432

def attachKernelDriver(self, interface):

433

"""

434

Re-attach kernel driver to interface.

435

436

Args:

437

interface (int): Interface number

438

439

Raises:

440

USBError: If driver cannot be attached

441

"""

442

443

def setAutoDetachKernelDriver(self, enable):

444

"""

445

Enable/disable automatic kernel driver detachment.

446

447

Args:

448

enable (bool): True to enable auto-detach

449

450

Raises:

451

USBError: If auto-detach cannot be configured

452

"""

453

```

454

455

### Asynchronous Transfer Creation

456

457

Create transfer objects for asynchronous operations.

458

459

```python { .api }

460

class USBDeviceHandle:

461

def getTransfer(self, iso_packets=0, short_is_error=False, add_zero_packet=False):

462

"""

463

Create transfer object for asynchronous operations.

464

465

Args:

466

iso_packets (int): Number of isochronous packet descriptors

467

short_is_error (bool): Treat short transfers as errors

468

add_zero_packet (bool): Add zero-length packet for transfers that are multiples of endpoint size

469

470

Returns:

471

USBTransfer: Transfer object for async operations

472

"""

473

```

474

475

## Usage Examples

476

477

### Basic Device Access

478

479

```python

480

import usb1

481

482

with usb1.USBContext() as context:

483

# Find device by vendor/product ID

484

device = context.getByVendorIDAndProductID(0x1234, 0x5678)

485

if not device:

486

print("Device not found")

487

return

488

489

# Display device information

490

print(f"Device: {device.getVendorID():04x}:{device.getProductID():04x}")

491

print(f"Bus {device.getBusNumber():03d}, Address {device.getDeviceAddress():03d}")

492

print(f"USB {device.getbcdUSB() >> 8}.{(device.getbcdUSB() >> 4) & 0xf}")

493

print(f"Speed: {device.getDeviceSpeed()}")

494

print(f"Class: {device.getDeviceClass()}")

495

496

# Access string descriptors

497

try:

498

print(f"Manufacturer: {device.getManufacturer()}")

499

print(f"Product: {device.getProduct()}")

500

print(f"Serial: {device.getSerialNumber()}")

501

except usb1.USBError as e:

502

print(f"Error reading strings: {e}")

503

```

504

505

### Device Configuration and Interface Claiming

506

507

```python

508

import usb1

509

510

with usb1.USBContext() as context:

511

device = context.getByVendorIDAndProductID(0x1234, 0x5678)

512

if device:

513

with device.open() as handle:

514

# Check current configuration

515

current_config = handle.getConfiguration()

516

print(f"Current configuration: {current_config}")

517

518

# Set configuration if needed

519

if current_config != 1:

520

handle.setConfiguration(1)

521

print("Set configuration to 1")

522

523

# Check for kernel driver and detach if necessary

524

interface_num = 0

525

if handle.kernelDriverActive(interface_num):

526

print("Detaching kernel driver")

527

handle.detachKernelDriver(interface_num)

528

529

# Claim interface with automatic release

530

with handle.claimInterface(interface_num):

531

print(f"Claimed interface {interface_num}")

532

533

# Set alternate setting if needed

534

handle.setInterfaceAltSetting(interface_num, 0)

535

print("Set alternate setting 0")

536

537

# Perform operations here

538

# ...

539

540

print("Interface automatically released")

541

```

542

543

### Comprehensive Device Information

544

545

```python

546

import usb1

547

548

def print_device_info(device):

549

"""Print comprehensive device information."""

550

print(f"\nDevice {device.getVendorID():04x}:{device.getProductID():04x}")

551

print(f" Bus: {device.getBusNumber():03d}")

552

print(f" Address: {device.getDeviceAddress():03d}")

553

print(f" Port path: {' -> '.join(map(str, device.getPortNumberList()))}")

554

print(f" USB version: {device.getbcdUSB() >> 8}.{(device.getbcdUSB() >> 4) & 0xf}")

555

print(f" Device version: {device.getbcdDevice() >> 8}.{(device.getbcdDevice() >> 4) & 0xf}")

556

print(f" Speed: {device.getDeviceSpeed()}")

557

print(f" Class: {device.getDeviceClass()}")

558

print(f" Subclass: {device.getDeviceSubClass()}")

559

print(f" Protocol: {device.getDeviceProtocol()}")

560

print(f" Max packet size (EP0): {device.getMaxPacketSize0()}")

561

print(f" Configurations: {device.getNumConfigurations()}")

562

563

# Try to get string descriptors

564

try:

565

manufacturer = device.getManufacturer()

566

product = device.getProduct()

567

serial = device.getSerialNumber()

568

languages = device.getSupportedLanguageList()

569

570

if manufacturer:

571

print(f" Manufacturer: {manufacturer}")

572

if product:

573

print(f" Product: {product}")

574

if serial:

575

print(f" Serial: {serial}")

576

if languages:

577

print(f" Languages: {[hex(lang) for lang in languages]}")

578

579

except usb1.USBError as e:

580

print(f" Error reading strings: {e}")

581

582

with usb1.USBContext() as context:

583

for device in context.getDeviceIterator(skip_on_error=True):

584

print_device_info(device)

585

```

586

587

### Error Handling and Resource Management

588

589

```python

590

import usb1

591

592

def safe_device_operation(vendor_id, product_id):

593

"""Demonstrate safe device operation with proper error handling."""

594

context = None

595

device = None

596

handle = None

597

598

try:

599

# Create context

600

context = usb1.USBContext()

601

context.open()

602

603

# Find device

604

device = context.getByVendorIDAndProductID(vendor_id, product_id)

605

if not device:

606

print("Device not found")

607

return False

608

609

# Open device

610

handle = device.open()

611

612

# Detach kernel driver if needed

613

interface_num = 0

614

kernel_attached = False

615

616

try:

617

if handle.kernelDriverActive(interface_num):

618

handle.detachKernelDriver(interface_num)

619

kernel_attached = True

620

print("Detached kernel driver")

621

except usb1.USBErrorNotSupported:

622

print("Kernel driver operations not supported")

623

624

# Claim interface

625

interface_claimed = False

626

try:

627

handle.claimInterface(interface_num)

628

interface_claimed = True

629

print("Claimed interface")

630

631

# Perform operations here

632

print("Performing device operations...")

633

634

return True

635

636

except usb1.USBError as e:

637

print(f"Error claiming interface: {e}")

638

return False

639

640

finally:

641

# Clean up in reverse order

642

if interface_claimed:

643

try:

644

handle.releaseInterface(interface_num)

645

print("Released interface")

646

except usb1.USBError as e:

647

print(f"Error releasing interface: {e}")

648

649

if kernel_attached:

650

try:

651

handle.attachKernelDriver(interface_num)

652

print("Re-attached kernel driver")

653

except usb1.USBError as e:

654

print(f"Error re-attaching kernel driver: {e}")

655

656

except usb1.USBError as e:

657

print(f"USB error: {e}")

658

return False

659

660

finally:

661

# Clean up resources

662

if handle:

663

handle.close()

664

if device:

665

device.close()

666

if context:

667

context.close()

668

669

# Usage

670

safe_device_operation(0x1234, 0x5678)

671

```