0
# Backends
1
2
Pluggable backend architecture supporting multiple USB libraries with automatic backend detection and configuration. PyUSB's backend system provides abstraction over different USB implementations while maintaining consistent API behavior.
3
4
## Capabilities
5
6
### Backend Interface
7
8
Abstract base class defining the backend interface that all USB backends must implement.
9
10
```python { .api }
11
class IBackend:
12
"""
13
Abstract backend interface for USB operations.
14
15
All USB backends must implement this interface to provide
16
USB device access through different underlying libraries.
17
"""
18
19
def enumerate_devices(self):
20
"""Enumerate available USB devices."""
21
22
def open_device(self, device):
23
"""Open device for communication."""
24
25
def close_device(self, device_handle):
26
"""Close device handle."""
27
28
def set_configuration(self, device_handle, config_value):
29
"""Set device configuration."""
30
31
def claim_interface(self, device_handle, interface_number):
32
"""Claim interface for exclusive access."""
33
34
def release_interface(self, device_handle, interface_number):
35
"""Release interface."""
36
```
37
38
### libusb 1.x Backend
39
40
Modern libusb 1.x backend providing comprehensive USB support with advanced features.
41
42
```python { .api }
43
def get_backend():
44
"""
45
Get libusb 1.x backend instance.
46
47
Returns:
48
Backend object for libusb 1.x operations
49
50
Raises:
51
- NoBackendError: libusb 1.x not available
52
"""
53
54
# libusb 1.x error codes
55
LIBUSB_SUCCESS = 0
56
LIBUSB_ERROR_IO = -1
57
LIBUSB_ERROR_INVALID_PARAM = -2
58
LIBUSB_ERROR_ACCESS = -3
59
LIBUSB_ERROR_NO_DEVICE = -4
60
LIBUSB_ERROR_NOT_FOUND = -5
61
LIBUSB_ERROR_BUSY = -6
62
LIBUSB_ERROR_TIMEOUT = -7
63
LIBUSB_ERROR_OVERFLOW = -8
64
LIBUSB_ERROR_PIPE = -9
65
LIBUSB_ERROR_INTERRUPTED = -10
66
LIBUSB_ERROR_NO_MEM = -11
67
LIBUSB_ERROR_NOT_SUPPORTED = -12
68
LIBUSB_ERROR_OTHER = -99
69
```
70
71
### libusb 0.1 Backend
72
73
Legacy libusb 0.1 backend for compatibility with older systems.
74
75
```python { .api }
76
def get_backend():
77
"""
78
Get libusb 0.1 backend instance.
79
80
Returns:
81
Backend object for libusb 0.1 operations
82
83
Raises:
84
- NoBackendError: libusb 0.1 not available
85
"""
86
```
87
88
### OpenUSB Backend
89
90
OpenUSB backend providing alternative USB library support.
91
92
```python { .api }
93
def get_backend():
94
"""
95
Get OpenUSB backend instance.
96
97
Returns:
98
Backend object for OpenUSB operations
99
100
Raises:
101
- NoBackendError: OpenUSB not available
102
"""
103
104
# OpenUSB result codes
105
OPENUSB_SUCCESS = 0
106
OPENUSB_PLATFORM_FAILURE = -1
107
OPENUSB_NO_RESOURCES = -2
108
OPENUSB_NO_BANDWIDTH = -3
109
OPENUSB_NOT_SUPPORTED = -4
110
OPENUSB_HC_HARDWARE_ERROR = -5
111
OPENUSB_INVALID_PERM = -6
112
OPENUSB_BUSY = -7
113
OPENUSB_BADARG = -8
114
OPENUSB_NOACCESS = -9
115
OPENUSB_PARSE_ERROR = -10
116
OPENUSB_UNKNOWN_DEVICE = -11
117
OPENUSB_INVALID_HANDLE = -12
118
OPENUSB_IO_TIMEOUT = -13
119
OPENUSB_IO_CANCELLED = -14
120
OPENUSB_IO_OVERFLOW = -15
121
OPENUSB_CB_CONTINUE = -16
122
```
123
124
### Backend Selection
125
126
Automatic backend selection and access to specific backend modules.
127
128
```python { .api }
129
def get_backend():
130
"""
131
Get best available backend automatically.
132
133
Attempts to load backends in order of preference:
134
1. libusb 1.x (most modern and capable)
135
2. libusb 0.1 (legacy compatibility)
136
3. OpenUSB (alternative implementation)
137
138
Returns:
139
Backend object for the first available backend
140
141
Raises:
142
- NoBackendError: No USB backend available
143
"""
144
145
import usb.backend.libusb1 # Modern libusb 1.x backend
146
import usb.backend.libusb0 # Legacy libusb 0.1 backend
147
import usb.backend.openusb # OpenUSB backend
148
```
149
150
### Library Loading (libloader module)
151
152
Helper functions for loading USB backend libraries with error handling and library location.
153
154
```python { .api }
155
def locate_library(candidates, find_library=None):
156
"""
157
Locate library from candidate list.
158
159
Parameters:
160
- candidates: list, candidate library names
161
- find_library: callable, library finder function
162
163
Returns:
164
str: path to library or None if not found
165
"""
166
167
def load_library(lib, name=None, lib_cls=None):
168
"""
169
Load library from path.
170
171
Parameters:
172
- lib: str, library path
173
- name: str, library name for error messages
174
- lib_cls: class, library wrapper class
175
176
Returns:
177
Library object
178
179
Raises:
180
- LibraryException: Library loading failed
181
"""
182
183
class LibraryException(Exception):
184
"""Base exception for library loading errors."""
185
186
class LibraryNotFoundException(LibraryException):
187
"""Library not found exception."""
188
189
class NoLibraryCandidatesException(LibraryException):
190
"""No library candidates available exception."""
191
```
192
193
## Usage Examples
194
195
### Automatic Backend Selection
196
197
```python
198
import usb.core
199
200
# PyUSB automatically selects the best available backend
201
device = usb.core.find(idVendor=0x1234, idProduct=0x5678)
202
203
if device:
204
print(f"Device found using automatic backend selection")
205
print(f"Backend: {device._ctx.backend.__class__.__module__}")
206
else:
207
print("No device found or no backend available")
208
```
209
210
### Explicit Backend Selection
211
212
```python
213
import usb.core
214
import usb.backend.libusb1
215
216
# Use specific backend
217
try:
218
backend = usb.backend.libusb1.get_backend()
219
device = usb.core.find(idVendor=0x1234, idProduct=0x5678, backend=backend)
220
221
if device:
222
print("Device found using libusb1 backend")
223
else:
224
print("Device not found")
225
226
except usb.core.NoBackendError:
227
print("libusb1 backend not available")
228
```
229
230
### Backend Availability Check
231
232
```python
233
import usb.backend.libusb1
234
import usb.backend.libusb0
235
import usb.backend.openusb
236
import usb.core
237
238
def check_backends():
239
"""Check which backends are available."""
240
backends = {
241
'libusb1': usb.backend.libusb1,
242
'libusb0': usb.backend.libusb0,
243
'openusb': usb.backend.openusb
244
}
245
246
available = []
247
for name, backend_module in backends.items():
248
try:
249
backend = backend_module.get_backend()
250
if backend:
251
available.append(name)
252
print(f"{name}: Available")
253
except usb.core.NoBackendError:
254
print(f"{name}: Not available")
255
256
return available
257
258
print("Backend availability:")
259
available_backends = check_backends()
260
print(f"Available backends: {available_backends}")
261
```
262
263
### Backend-Specific Error Handling
264
265
```python
266
import usb.core
267
import usb.backend.libusb1
268
269
try:
270
backend = usb.backend.libusb1.get_backend()
271
device = usb.core.find(idVendor=0x1234, idProduct=0x5678, backend=backend)
272
273
if device:
274
# Perform operations that might fail
275
try:
276
device.set_configuration()
277
data = device.read(0x81, 64, timeout=1000)
278
279
except usb.core.USBError as e:
280
# Check for libusb1-specific error codes
281
if hasattr(e, 'backend_error_code'):
282
error_code = e.backend_error_code
283
if error_code == usb.backend.libusb1.LIBUSB_ERROR_TIMEOUT:
284
print("Operation timed out")
285
elif error_code == usb.backend.libusb1.LIBUSB_ERROR_NO_DEVICE:
286
print("Device disconnected")
287
elif error_code == usb.backend.libusb1.LIBUSB_ERROR_ACCESS:
288
print("Access denied - check permissions")
289
else:
290
print(f"USB error with backend code: {error_code}")
291
else:
292
print(f"USB error: {e}")
293
294
except usb.core.NoBackendError:
295
print("libusb1 backend not available")
296
```
297
298
### Multi-Backend Device Search
299
300
```python
301
import usb.core
302
import usb.backend.libusb1
303
import usb.backend.libusb0
304
305
def find_device_any_backend(vendor_id, product_id):
306
"""Try to find device using any available backend."""
307
308
backends_to_try = [
309
('libusb1', usb.backend.libusb1),
310
('libusb0', usb.backend.libusb0),
311
]
312
313
for backend_name, backend_module in backends_to_try:
314
try:
315
backend = backend_module.get_backend()
316
device = usb.core.find(
317
idVendor=vendor_id,
318
idProduct=product_id,
319
backend=backend
320
)
321
322
if device:
323
print(f"Device found using {backend_name} backend")
324
return device, backend_name
325
326
except usb.core.NoBackendError:
327
print(f"{backend_name} backend not available")
328
continue
329
330
return None, None
331
332
# Search for device
333
device, backend_used = find_device_any_backend(0x1234, 0x5678)
334
335
if device:
336
print(f"Successfully found device using {backend_used}")
337
else:
338
print("Device not found with any backend")
339
```
340
341
### Backend Configuration
342
343
```python
344
import usb.core
345
import usb.backend.libusb1
346
import os
347
348
# Some backends may support configuration through environment variables
349
# For example, libusb debug output:
350
os.environ['LIBUSB_DEBUG'] = '3' # Enable verbose libusb debugging
351
352
try:
353
backend = usb.backend.libusb1.get_backend()
354
print("libusb1 backend initialized with debug output")
355
356
# Find device with debugging enabled
357
device = usb.core.find(idVendor=0x1234, idProduct=0x5678, backend=backend)
358
359
except usb.core.NoBackendError:
360
print("libusb1 backend not available")
361
```
362
363
### Backend Performance Comparison
364
365
```python
366
import usb.core
367
import usb.backend.libusb1
368
import usb.backend.libusb0
369
import time
370
371
def benchmark_backend(backend_module, backend_name):
372
"""Benchmark device enumeration with specific backend."""
373
try:
374
backend = backend_module.get_backend()
375
376
start_time = time.time()
377
devices = usb.core.find(find_all=True, backend=backend)
378
end_time = time.time()
379
380
device_count = len(devices) if devices else 0
381
elapsed = end_time - start_time
382
383
print(f"{backend_name}: Found {device_count} devices in {elapsed:.3f}s")
384
return elapsed
385
386
except usb.core.NoBackendError:
387
print(f"{backend_name}: Not available")
388
return None
389
390
print("Backend performance comparison:")
391
libusb1_time = benchmark_backend(usb.backend.libusb1, "libusb1")
392
libusb0_time = benchmark_backend(usb.backend.libusb0, "libusb0")
393
394
if libusb1_time and libusb0_time:
395
if libusb1_time < libusb0_time:
396
print("libusb1 is faster for device enumeration")
397
else:
398
print("libusb0 is faster for device enumeration")
399
```
400
401
### Custom Backend Integration
402
403
```python
404
import usb.core
405
from usb.backend import IBackend
406
407
class CustomBackend(IBackend):
408
"""Example custom backend implementation."""
409
410
def enumerate_devices(self):
411
"""Custom device enumeration logic."""
412
# Implement custom device discovery
413
pass
414
415
def open_device(self, device):
416
"""Custom device opening logic."""
417
# Implement custom device access
418
pass
419
420
# Implement other required methods...
421
422
# Use custom backend
423
custom_backend = CustomBackend()
424
425
try:
426
device = usb.core.find(
427
idVendor=0x1234,
428
idProduct=0x5678,
429
backend=custom_backend
430
)
431
432
if device:
433
print("Device found using custom backend")
434
435
except Exception as e:
436
print(f"Custom backend error: {e}")
437
```