0
# Utilities
1
2
Helper functions for endpoint handling, interface management, descriptor parsing, and resource cleanup. The util module provides essential utilities for USB device operations and data interpretation.
3
4
## Capabilities
5
6
### Endpoint Operations
7
8
Parse and interpret endpoint addresses and attributes for proper communication setup.
9
10
```python { .api }
11
def endpoint_address(address):
12
"""
13
Return endpoint absolute address.
14
15
Parameters:
16
- address: int, endpoint address from descriptor
17
18
Returns:
19
int: absolute endpoint address (0-15)
20
"""
21
22
def endpoint_direction(address):
23
"""
24
Return endpoint transfer direction.
25
26
Parameters:
27
- address: int, endpoint address from descriptor
28
29
Returns:
30
int: ENDPOINT_OUT (0) or ENDPOINT_IN (128)
31
"""
32
33
def endpoint_type(bmAttributes):
34
"""
35
Return endpoint type from attributes.
36
37
Parameters:
38
- bmAttributes: int, endpoint attributes from descriptor
39
40
Returns:
41
int: endpoint type (ENDPOINT_TYPE_CTRL, ENDPOINT_TYPE_ISO,
42
ENDPOINT_TYPE_BULK, ENDPOINT_TYPE_INTR)
43
"""
44
```
45
46
### Control Transfer Utilities
47
48
Build control transfer parameters and interpret transfer directions.
49
50
```python { .api }
51
def ctrl_direction(bmRequestType):
52
"""
53
Return direction of control transfer.
54
55
Parameters:
56
- bmRequestType: int, request type field
57
58
Returns:
59
int: CTRL_OUT (0) or CTRL_IN (128)
60
"""
61
62
def build_request_type(direction, type, recipient):
63
"""
64
Build bmRequestType field for control transfer.
65
66
Parameters:
67
- direction: int, transfer direction (CTRL_OUT or CTRL_IN)
68
- type: int, request type (CTRL_TYPE_STANDARD, CTRL_TYPE_CLASS, CTRL_TYPE_VENDOR)
69
- recipient: int, recipient (CTRL_RECIPIENT_DEVICE, CTRL_RECIPIENT_INTERFACE, etc.)
70
71
Returns:
72
int: bmRequestType value
73
"""
74
```
75
76
### Buffer Management
77
78
Create and manage buffers for USB data operations.
79
80
```python { .api }
81
def create_buffer(length):
82
"""
83
Create buffer for USB operations.
84
85
Parameters:
86
- length: int, buffer size in bytes
87
88
Returns:
89
array.array: buffer suitable for USB operations
90
"""
91
```
92
93
### Descriptor Search
94
95
Find specific descriptors within device configuration hierarchies.
96
97
```python { .api }
98
def find_descriptor(desc, find_all=False, custom_match=None, **args):
99
"""
100
Find inner descriptor within a configuration/interface/endpoint hierarchy.
101
102
Parameters:
103
- desc: descriptor object to search within
104
- find_all: bool, return all matches instead of first match
105
- custom_match: callable taking descriptor as argument, return True for matches
106
- **args: descriptor fields to match
107
108
Returns:
109
Descriptor object or list of descriptors, None if not found
110
"""
111
```
112
113
### Interface Management
114
115
Claim and release interfaces for exclusive device access.
116
117
```python { .api }
118
def claim_interface(device, interface):
119
"""
120
Explicitly claim an interface.
121
122
Parameters:
123
- device: Device object
124
- interface: int or Interface object, interface to claim
125
126
Raises:
127
- USBError: Interface claim failed
128
"""
129
130
def release_interface(device, interface):
131
"""
132
Explicitly release an interface.
133
134
Parameters:
135
- device: Device object
136
- interface: int or Interface object, interface to release
137
138
Raises:
139
- USBError: Interface release failed
140
"""
141
```
142
143
### Resource Management
144
145
Clean up device resources and handle proper disposal.
146
147
```python { .api }
148
def dispose_resources(device):
149
"""
150
Release internal resources allocated by the device object.
151
152
Parameters:
153
- device: Device object to clean up
154
"""
155
```
156
157
### String Descriptors
158
159
Retrieve and decode string descriptors with language support.
160
161
```python { .api }
162
def get_langids(dev):
163
"""
164
Retrieve list of supported string languages from device.
165
166
Parameters:
167
- dev: Device object
168
169
Returns:
170
list: language ID codes supported by device
171
172
Raises:
173
- USBError: Language ID retrieval failed
174
"""
175
176
def get_string(dev, index, langid=None):
177
"""
178
Retrieve string descriptor from device.
179
180
Parameters:
181
- dev: Device object
182
- index: int, string descriptor index
183
- langid: int, language ID (default: first supported language)
184
185
Returns:
186
str: decoded string descriptor
187
188
Raises:
189
- USBError: String retrieval failed
190
"""
191
```
192
193
### USB Constants
194
195
Direction and type constants for endpoint and control operations.
196
197
```python { .api }
198
# Descriptor types
199
DESC_TYPE_DEVICE = 0x01
200
DESC_TYPE_CONFIG = 0x02
201
DESC_TYPE_STRING = 0x03
202
DESC_TYPE_INTERFACE = 0x04
203
DESC_TYPE_ENDPOINT = 0x05
204
205
# Endpoint directions
206
ENDPOINT_IN = 0x80
207
ENDPOINT_OUT = 0x00
208
209
# Endpoint types
210
ENDPOINT_TYPE_CTRL = 0x00
211
ENDPOINT_TYPE_ISO = 0x01
212
ENDPOINT_TYPE_BULK = 0x02
213
ENDPOINT_TYPE_INTR = 0x03
214
215
# Control transfer directions
216
CTRL_OUT = 0x00
217
CTRL_IN = 0x80
218
219
# Control transfer types
220
CTRL_TYPE_STANDARD = 0x00
221
CTRL_TYPE_CLASS = 0x20
222
CTRL_TYPE_VENDOR = 0x40
223
CTRL_TYPE_RESERVED = 0x60
224
225
# Control transfer recipients
226
CTRL_RECIPIENT_DEVICE = 0x00
227
CTRL_RECIPIENT_INTERFACE = 0x01
228
CTRL_RECIPIENT_ENDPOINT = 0x02
229
CTRL_RECIPIENT_OTHER = 0x03
230
231
# USB speeds
232
SPEED_UNKNOWN = 0
233
SPEED_LOW = 1
234
SPEED_FULL = 2
235
SPEED_HIGH = 3
236
SPEED_SUPER = 4
237
```
238
239
## Usage Examples
240
241
### Endpoint Analysis
242
243
```python
244
import usb.core
245
import usb.util
246
247
device = usb.core.find(idVendor=0x1234, idProduct=0x5678)
248
device.set_configuration()
249
250
config = device.get_active_configuration()
251
interface = config.interfaces()[0]
252
253
for endpoint in interface.endpoints():
254
addr = endpoint.bEndpointAddress
255
attrs = endpoint.bmAttributes
256
257
print(f"Endpoint address: 0x{addr:02x}")
258
print(f" Absolute address: {usb.util.endpoint_address(addr)}")
259
260
direction = usb.util.endpoint_direction(addr)
261
if direction == usb.util.ENDPOINT_IN:
262
print(" Direction: IN")
263
else:
264
print(" Direction: OUT")
265
266
ep_type = usb.util.endpoint_type(attrs)
267
type_names = {
268
usb.util.ENDPOINT_TYPE_CTRL: "Control",
269
usb.util.ENDPOINT_TYPE_ISO: "Isochronous",
270
usb.util.ENDPOINT_TYPE_BULK: "Bulk",
271
usb.util.ENDPOINT_TYPE_INTR: "Interrupt"
272
}
273
print(f" Type: {type_names[ep_type]}")
274
print(f" Max packet size: {endpoint.wMaxPacketSize}")
275
```
276
277
### Interface Management
278
279
```python
280
import usb.core
281
import usb.util
282
283
device = usb.core.find(idVendor=0x1234, idProduct=0x5678)
284
device.set_configuration()
285
286
interface_num = 0
287
288
try:
289
# Claim interface for exclusive access
290
usb.util.claim_interface(device, interface_num)
291
print(f"Interface {interface_num} claimed")
292
293
# Perform device operations...
294
295
finally:
296
# Always release interface when done
297
usb.util.release_interface(device, interface_num)
298
print(f"Interface {interface_num} released")
299
```
300
301
### String Descriptor Access
302
303
```python
304
import usb.core
305
import usb.util
306
307
device = usb.core.find(idVendor=0x1234, idProduct=0x5678)
308
309
try:
310
# Get supported languages
311
langids = usb.util.get_langids(device)
312
print(f"Supported languages: {[hex(lid) for lid in langids]}")
313
314
# Get device strings in first supported language
315
if langids and device.iManufacturer:
316
manufacturer = usb.util.get_string(device, device.iManufacturer, langids[0])
317
print(f"Manufacturer: {manufacturer}")
318
319
if langids and device.iProduct:
320
product = usb.util.get_string(device, device.iProduct, langids[0])
321
print(f"Product: {product}")
322
323
if langids and device.iSerialNumber:
324
serial = usb.util.get_string(device, device.iSerialNumber, langids[0])
325
print(f"Serial number: {serial}")
326
327
except usb.core.USBError as e:
328
print(f"String access failed: {e}")
329
```
330
331
### Descriptor Search
332
333
```python
334
import usb.core
335
import usb.util
336
337
device = usb.core.find(idVendor=0x1234, idProduct=0x5678)
338
device.set_configuration()
339
340
config = device.get_active_configuration()
341
342
# Find all bulk endpoints
343
bulk_endpoints = usb.util.find_descriptor(
344
config,
345
find_all=True,
346
custom_match=lambda e: usb.util.endpoint_type(e.bmAttributes) == usb.util.ENDPOINT_TYPE_BULK
347
)
348
349
print(f"Found {len(bulk_endpoints)} bulk endpoints:")
350
for ep in bulk_endpoints:
351
direction = "IN" if usb.util.endpoint_direction(ep.bEndpointAddress) == usb.util.ENDPOINT_IN else "OUT"
352
print(f" Endpoint 0x{ep.bEndpointAddress:02x} ({direction})")
353
354
# Find specific interface by class
355
hid_interface = usb.util.find_descriptor(
356
config,
357
bInterfaceClass=3 # HID class
358
)
359
360
if hid_interface:
361
print(f"Found HID interface: {hid_interface.bInterfaceNumber}")
362
```
363
364
### Control Transfer Setup
365
366
```python
367
import usb.core
368
import usb.util
369
370
device = usb.core.find(idVendor=0x1234, idProduct=0x5678)
371
372
# Build request type for vendor-specific IN request to device
373
request_type = usb.util.build_request_type(
374
usb.util.CTRL_IN,
375
usb.util.CTRL_TYPE_VENDOR,
376
usb.util.CTRL_RECIPIENT_DEVICE
377
)
378
379
print(f"Request type: 0x{request_type:02x}")
380
381
# Perform control transfer
382
try:
383
result = device.ctrl_transfer(
384
request_type,
385
0x01, # Vendor-specific request
386
0x0000, # wValue
387
0x0000, # wIndex
388
64 # Read 64 bytes
389
)
390
print(f"Control transfer result: {result}")
391
392
except usb.core.USBError as e:
393
print(f"Control transfer failed: {e}")
394
```
395
396
### Buffer Management
397
398
```python
399
import usb.core
400
import usb.util
401
402
device = usb.core.find(idVendor=0x1234, idProduct=0x5678)
403
device.set_configuration()
404
405
# Create buffer for reading data
406
buffer = usb.util.create_buffer(1024)
407
print(f"Created buffer of size {len(buffer)}")
408
409
# Use buffer with read operation
410
endpoint_addr = 0x81 # IN endpoint
411
try:
412
bytes_read = device.read(endpoint_addr, buffer, timeout=1000)
413
print(f"Read {bytes_read} bytes into buffer")
414
print(f"Data: {buffer[:bytes_read]}")
415
416
except usb.core.USBTimeoutError:
417
print("Read operation timed out")
418
```
419
420
### Resource Cleanup
421
422
```python
423
import usb.core
424
import usb.util
425
426
device = usb.core.find(idVendor=0x1234, idProduct=0x5678)
427
428
try:
429
# Perform device operations
430
device.set_configuration()
431
# ... communication ...
432
433
finally:
434
# Clean up device resources
435
usb.util.dispose_resources(device)
436
print("Device resources disposed")
437
```