0
# USB Context Management
1
2
The USBContext class provides the entry point for all USB operations, managing system resources, device enumeration, and global USB settings. All USB operations require an active context, which handles low-level libusb-1.0 initialization and cleanup.
3
4
## Capabilities
5
6
### Context Creation and Lifecycle
7
8
Create and manage USB contexts with optional configuration for logging, Windows backend selection, and device discovery behavior.
9
10
```python { .api }
11
class USBContext:
12
def __init__(self, log_level=None, use_usbdk=False, with_device_discovery=True, log_callback=None):
13
"""
14
Create a new USB context.
15
16
Args:
17
log_level: Log level constant (LOG_LEVEL_NONE, LOG_LEVEL_ERROR, etc.)
18
use_usbdk (bool): Windows only - use UsbDk backend if available
19
with_device_discovery (bool): Linux only - enable device scan during init
20
log_callback: Function accepting (context, level, message) for log messages
21
"""
22
23
def __enter__(self):
24
"""Context manager entry - initializes the context."""
25
26
def __exit__(self, exc_type, exc_val, exc_tb):
27
"""Context manager exit - closes the context."""
28
29
def open(self):
30
"""
31
Finish context initialization manually.
32
33
Returns:
34
USBContext: Self for method chaining
35
"""
36
37
def close(self):
38
"""Close and destroy the USB context, releasing all resources."""
39
```
40
41
### Device Enumeration
42
43
Discover and iterate over USB devices connected to the system with flexible filtering and error handling options.
44
45
```python { .api }
46
def getDeviceIterator(self, skip_on_error=False):
47
"""
48
Return iterator over all USB devices currently connected.
49
50
Args:
51
skip_on_error (bool): If True, ignore devices that raise USBError
52
53
Yields:
54
USBDevice: Device instances for each connected device
55
"""
56
57
def getDeviceList(self, skip_on_access_error=False, skip_on_error=False):
58
"""
59
Return list of all USB devices currently connected.
60
61
Args:
62
skip_on_error (bool): If True, ignore devices that raise USBError
63
skip_on_access_error (bool): Deprecated alias for skip_on_error
64
65
Returns:
66
list[USBDevice]: List of device instances
67
"""
68
69
def getByVendorIDAndProductID(self, vendor_id, product_id, skip_on_access_error=False, skip_on_error=False):
70
"""
71
Find first device matching vendor and product IDs.
72
73
Args:
74
vendor_id (int): USB vendor ID (16-bit)
75
product_id (int): USB product ID (16-bit)
76
skip_on_error (bool): If True, ignore devices that raise USBError
77
skip_on_access_error (bool): Deprecated alias for skip_on_error
78
79
Returns:
80
USBDevice or None: Device instance or None if not found
81
"""
82
83
def openByVendorIDAndProductID(self, vendor_id, product_id, skip_on_access_error=False, skip_on_error=False):
84
"""
85
Find and open first device matching vendor and product IDs.
86
87
Args:
88
vendor_id (int): USB vendor ID (16-bit)
89
product_id (int): USB product ID (16-bit)
90
skip_on_error (bool): If True, ignore devices that raise USBError
91
skip_on_access_error (bool): Deprecated alias for skip_on_error
92
93
Returns:
94
USBDeviceHandle or None: Opened device handle or None if not found
95
"""
96
```
97
98
### Event Handling
99
100
Handle USB events for asynchronous operations with timeout control and interrupt capabilities.
101
102
```python { .api }
103
def handleEvents(self):
104
"""Handle pending USB events (blocking with internal timeout)."""
105
106
def handleEventsTimeout(self, tv=0):
107
"""
108
Handle pending USB events with specified timeout.
109
110
Args:
111
tv (float): Timeout in seconds, 0 for immediate return
112
"""
113
114
def interruptEventHandler(self):
115
"""Interrupt active event handling thread."""
116
117
def getNextTimeout(self):
118
"""
119
Get next internal timeout libusb needs to handle.
120
121
Returns:
122
float or None: Timeout in seconds or None if no timeout needed
123
"""
124
```
125
126
### Hotplug Device Detection
127
128
Register callbacks for USB device connection and disconnection events with flexible filtering options.
129
130
```python { .api }
131
def hotplugRegisterCallback(self, callback, events=HOTPLUG_EVENT_DEVICE_ARRIVED | HOTPLUG_EVENT_DEVICE_LEFT,
132
flags=HOTPLUG_ENUMERATE, vendor_id=HOTPLUG_MATCH_ANY,
133
product_id=HOTPLUG_MATCH_ANY, dev_class=HOTPLUG_MATCH_ANY):
134
"""
135
Register hotplug callback for device arrival/departure events.
136
137
Args:
138
callback: Function accepting (context, device, event) returning bool
139
events (int): Event mask (HOTPLUG_EVENT_DEVICE_ARRIVED | HOTPLUG_EVENT_DEVICE_LEFT)
140
flags (int): Callback flags (HOTPLUG_ENUMERATE to get existing devices)
141
vendor_id (int): Vendor ID filter or HOTPLUG_MATCH_ANY
142
product_id (int): Product ID filter or HOTPLUG_MATCH_ANY
143
dev_class (int): Device class filter or HOTPLUG_MATCH_ANY
144
145
Returns:
146
int: Opaque handle for hotplugDeregisterCallback
147
148
Note:
149
Callback must return True to unregister, False to stay registered.
150
Callback cannot call synchronous libusb functions.
151
"""
152
153
def hotplugDeregisterCallback(self, handle):
154
"""
155
Deregister hotplug callback.
156
157
Args:
158
handle (int): Handle returned by hotplugRegisterCallback
159
"""
160
```
161
162
### System Device Wrapping
163
164
Wrap existing system device file descriptors for USB communication without device enumeration.
165
166
```python { .api }
167
def wrapSysDevice(self, sys_device):
168
"""
169
Wrap system device file descriptor as USBDeviceHandle.
170
171
Args:
172
sys_device: File object or file descriptor of sys device node
173
174
Returns:
175
USBDeviceHandle: Handle for wrapped device
176
177
Note:
178
Keep the file open while using the device handle.
179
"""
180
```
181
182
### Advanced Event Loop Integration
183
184
Low-level file descriptor polling support for integration with select/poll-based event loops.
185
186
```python { .api }
187
def getPollFDList(self):
188
"""
189
Get file descriptors for USB event polling.
190
191
Returns:
192
list[tuple]: List of (fd, events) tuples for polling
193
194
Raises:
195
NotImplementedError: If libusb doesn't support pollable FDs
196
"""
197
198
def setPollFDNotifiers(self, added_cb=None, removed_cb=None, user_data=None):
199
"""
200
Set callbacks for file descriptor addition/removal.
201
202
Args:
203
added_cb: Function called when FD is added: (fd, events, user_data)
204
removed_cb: Function called when FD is removed: (fd, user_data)
205
user_data: User data passed to callbacks
206
"""
207
```
208
209
### Logging and Debugging
210
211
Configure context-specific logging and debug output for troubleshooting USB operations.
212
213
```python { .api }
214
def setLogCallback(self, log_callback):
215
"""
216
Set context-specific log callback.
217
218
Args:
219
log_callback: Function accepting (context, level, message) or None to disable
220
"""
221
222
def setDebug(self, level):
223
"""
224
Set debug level for this context.
225
226
Args:
227
level (int): Log level constant (LOG_LEVEL_NONE through LOG_LEVEL_DEBUG)
228
"""
229
```
230
231
## Usage Examples
232
233
### Basic Context Usage
234
235
```python
236
import usb1
237
238
# Simple context manager usage
239
with usb1.USBContext() as context:
240
devices = context.getDeviceList()
241
print(f"Found {len(devices)} USB devices")
242
243
# Manual context management
244
context = usb1.USBContext()
245
context.open()
246
try:
247
device = context.getByVendorIDAndProductID(0x1234, 0x5678)
248
if device:
249
print(f"Found device: {device}")
250
finally:
251
context.close()
252
```
253
254
### Device Enumeration with Error Handling
255
256
```python
257
import usb1
258
259
with usb1.USBContext() as context:
260
# Iterate with automatic error skipping
261
for device in context.getDeviceIterator(skip_on_error=True):
262
try:
263
print(f"Device {device.getVendorID():04x}:{device.getProductID():04x}")
264
print(f" Manufacturer: {device.getManufacturer()}")
265
print(f" Product: {device.getProduct()}")
266
except usb1.USBError as e:
267
print(f" Error accessing device: {e}")
268
```
269
270
### Hotplug Event Monitoring
271
272
```python
273
import usb1
274
import threading
275
import time
276
277
def hotplug_callback(context, device, event):
278
if event == usb1.HOTPLUG_EVENT_DEVICE_ARRIVED:
279
print(f"Device connected: {device.getVendorID():04x}:{device.getProductID():04x}")
280
elif event == usb1.HOTPLUG_EVENT_DEVICE_LEFT:
281
print(f"Device disconnected: {device.getVendorID():04x}:{device.getProductID():04x}")
282
return False # Keep callback registered
283
284
with usb1.USBContext() as context:
285
# Register hotplug callback
286
handle = context.hotplugRegisterCallback(hotplug_callback)
287
288
# Event handling loop
289
try:
290
while True:
291
context.handleEventsTimeout(1.0) # 1 second timeout
292
except KeyboardInterrupt:
293
print("Stopping...")
294
finally:
295
context.hotplugDeregisterCallback(handle)
296
```
297
298
### Event Loop Integration
299
300
```python
301
import usb1
302
import select
303
304
with usb1.USBContext() as context:
305
# Get file descriptors for polling
306
try:
307
poll_fds = context.getPollFDList()
308
print(f"Monitoring {len(poll_fds)} file descriptors")
309
310
# Integration with select
311
read_fds = [fd for fd, events in poll_fds if events & select.POLLIN]
312
write_fds = [fd for fd, events in poll_fds if events & select.POLLOUT]
313
314
# Poll with timeout
315
ready_read, ready_write, _ = select.select(read_fds, write_fds, [], 1.0)
316
317
if ready_read or ready_write:
318
context.handleEventsTimeout(0) # Process immediately
319
320
except NotImplementedError:
321
print("Platform doesn't support pollable file descriptors")
322
# Fall back to timeout-based event handling
323
context.handleEventsTimeout(1.0)
324
```