CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pyusb

Easy USB access for Python with backend-neutral, cross-platform support

Pending
Overview
Eval results
Files

backends.mddocs/

Backends

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.

Capabilities

Backend Interface

Abstract base class defining the backend interface that all USB backends must implement.

class IBackend:
    """
    Abstract backend interface for USB operations.
    
    All USB backends must implement this interface to provide
    USB device access through different underlying libraries.
    """
    
    def enumerate_devices(self):
        """Enumerate available USB devices."""
        
    def open_device(self, device):
        """Open device for communication."""
        
    def close_device(self, device_handle):
        """Close device handle."""
        
    def set_configuration(self, device_handle, config_value):
        """Set device configuration."""
        
    def claim_interface(self, device_handle, interface_number):
        """Claim interface for exclusive access."""
        
    def release_interface(self, device_handle, interface_number):
        """Release interface."""

libusb 1.x Backend

Modern libusb 1.x backend providing comprehensive USB support with advanced features.

def get_backend():
    """
    Get libusb 1.x backend instance.
    
    Returns:
    Backend object for libusb 1.x operations
    
    Raises:
    - NoBackendError: libusb 1.x not available
    """

# libusb 1.x error codes
LIBUSB_SUCCESS = 0
LIBUSB_ERROR_IO = -1
LIBUSB_ERROR_INVALID_PARAM = -2
LIBUSB_ERROR_ACCESS = -3
LIBUSB_ERROR_NO_DEVICE = -4
LIBUSB_ERROR_NOT_FOUND = -5
LIBUSB_ERROR_BUSY = -6
LIBUSB_ERROR_TIMEOUT = -7
LIBUSB_ERROR_OVERFLOW = -8
LIBUSB_ERROR_PIPE = -9
LIBUSB_ERROR_INTERRUPTED = -10
LIBUSB_ERROR_NO_MEM = -11
LIBUSB_ERROR_NOT_SUPPORTED = -12
LIBUSB_ERROR_OTHER = -99

libusb 0.1 Backend

Legacy libusb 0.1 backend for compatibility with older systems.

def get_backend():
    """
    Get libusb 0.1 backend instance.
    
    Returns:
    Backend object for libusb 0.1 operations
    
    Raises:
    - NoBackendError: libusb 0.1 not available
    """

OpenUSB Backend

OpenUSB backend providing alternative USB library support.

def get_backend():
    """
    Get OpenUSB backend instance.
    
    Returns:
    Backend object for OpenUSB operations
    
    Raises:
    - NoBackendError: OpenUSB not available
    """

# OpenUSB result codes
OPENUSB_SUCCESS = 0
OPENUSB_PLATFORM_FAILURE = -1
OPENUSB_NO_RESOURCES = -2
OPENUSB_NO_BANDWIDTH = -3
OPENUSB_NOT_SUPPORTED = -4
OPENUSB_HC_HARDWARE_ERROR = -5
OPENUSB_INVALID_PERM = -6
OPENUSB_BUSY = -7
OPENUSB_BADARG = -8
OPENUSB_NOACCESS = -9
OPENUSB_PARSE_ERROR = -10
OPENUSB_UNKNOWN_DEVICE = -11
OPENUSB_INVALID_HANDLE = -12
OPENUSB_IO_TIMEOUT = -13
OPENUSB_IO_CANCELLED = -14
OPENUSB_IO_OVERFLOW = -15
OPENUSB_CB_CONTINUE = -16

Backend Selection

Automatic backend selection and access to specific backend modules.

def get_backend():
    """
    Get best available backend automatically.
    
    Attempts to load backends in order of preference:
    1. libusb 1.x (most modern and capable)
    2. libusb 0.1 (legacy compatibility)
    3. OpenUSB (alternative implementation)
    
    Returns:
    Backend object for the first available backend
    
    Raises:
    - NoBackendError: No USB backend available
    """

import usb.backend.libusb1    # Modern libusb 1.x backend
import usb.backend.libusb0    # Legacy libusb 0.1 backend  
import usb.backend.openusb    # OpenUSB backend

Library Loading (libloader module)

Helper functions for loading USB backend libraries with error handling and library location.

def locate_library(candidates, find_library=None):
    """
    Locate library from candidate list.
    
    Parameters:
    - candidates: list, candidate library names
    - find_library: callable, library finder function
    
    Returns:
    str: path to library or None if not found
    """

def load_library(lib, name=None, lib_cls=None):
    """
    Load library from path.
    
    Parameters:
    - lib: str, library path
    - name: str, library name for error messages
    - lib_cls: class, library wrapper class
    
    Returns:
    Library object
    
    Raises:
    - LibraryException: Library loading failed
    """

class LibraryException(Exception):
    """Base exception for library loading errors."""

class LibraryNotFoundException(LibraryException):
    """Library not found exception."""
    
class NoLibraryCandidatesException(LibraryException):
    """No library candidates available exception."""

Usage Examples

Automatic Backend Selection

import usb.core

# PyUSB automatically selects the best available backend
device = usb.core.find(idVendor=0x1234, idProduct=0x5678)

if device:
    print(f"Device found using automatic backend selection")
    print(f"Backend: {device._ctx.backend.__class__.__module__}")
else:
    print("No device found or no backend available")

Explicit Backend Selection

import usb.core
import usb.backend.libusb1

# Use specific backend
try:
    backend = usb.backend.libusb1.get_backend()
    device = usb.core.find(idVendor=0x1234, idProduct=0x5678, backend=backend)
    
    if device:
        print("Device found using libusb1 backend")
    else:
        print("Device not found")
        
except usb.core.NoBackendError:
    print("libusb1 backend not available")

Backend Availability Check

import usb.backend.libusb1
import usb.backend.libusb0
import usb.backend.openusb
import usb.core

def check_backends():
    """Check which backends are available."""
    backends = {
        'libusb1': usb.backend.libusb1,
        'libusb0': usb.backend.libusb0,
        'openusb': usb.backend.openusb
    }
    
    available = []
    for name, backend_module in backends.items():
        try:
            backend = backend_module.get_backend()
            if backend:
                available.append(name)
                print(f"{name}: Available")
        except usb.core.NoBackendError:
            print(f"{name}: Not available")
    
    return available

print("Backend availability:")
available_backends = check_backends()
print(f"Available backends: {available_backends}")

Backend-Specific Error Handling

import usb.core
import usb.backend.libusb1

try:
    backend = usb.backend.libusb1.get_backend()
    device = usb.core.find(idVendor=0x1234, idProduct=0x5678, backend=backend)
    
    if device:
        # Perform operations that might fail
        try:
            device.set_configuration()
            data = device.read(0x81, 64, timeout=1000)
            
        except usb.core.USBError as e:
            # Check for libusb1-specific error codes
            if hasattr(e, 'backend_error_code'):
                error_code = e.backend_error_code
                if error_code == usb.backend.libusb1.LIBUSB_ERROR_TIMEOUT:
                    print("Operation timed out")
                elif error_code == usb.backend.libusb1.LIBUSB_ERROR_NO_DEVICE:
                    print("Device disconnected")
                elif error_code == usb.backend.libusb1.LIBUSB_ERROR_ACCESS:
                    print("Access denied - check permissions")
                else:
                    print(f"USB error with backend code: {error_code}")
            else:
                print(f"USB error: {e}")
                
except usb.core.NoBackendError:
    print("libusb1 backend not available")

Multi-Backend Device Search

import usb.core
import usb.backend.libusb1
import usb.backend.libusb0

def find_device_any_backend(vendor_id, product_id):
    """Try to find device using any available backend."""
    
    backends_to_try = [
        ('libusb1', usb.backend.libusb1),
        ('libusb0', usb.backend.libusb0),
    ]
    
    for backend_name, backend_module in backends_to_try:
        try:
            backend = backend_module.get_backend()
            device = usb.core.find(
                idVendor=vendor_id, 
                idProduct=product_id, 
                backend=backend
            )
            
            if device:
                print(f"Device found using {backend_name} backend")
                return device, backend_name
                
        except usb.core.NoBackendError:
            print(f"{backend_name} backend not available")
            continue
    
    return None, None

# Search for device
device, backend_used = find_device_any_backend(0x1234, 0x5678)

if device:
    print(f"Successfully found device using {backend_used}")
else:
    print("Device not found with any backend")

Backend Configuration

import usb.core
import usb.backend.libusb1
import os

# Some backends may support configuration through environment variables
# For example, libusb debug output:
os.environ['LIBUSB_DEBUG'] = '3'  # Enable verbose libusb debugging

try:
    backend = usb.backend.libusb1.get_backend()
    print("libusb1 backend initialized with debug output")
    
    # Find device with debugging enabled
    device = usb.core.find(idVendor=0x1234, idProduct=0x5678, backend=backend)
    
except usb.core.NoBackendError:
    print("libusb1 backend not available")

Backend Performance Comparison

import usb.core
import usb.backend.libusb1
import usb.backend.libusb0
import time

def benchmark_backend(backend_module, backend_name):
    """Benchmark device enumeration with specific backend."""
    try:
        backend = backend_module.get_backend()
        
        start_time = time.time()
        devices = usb.core.find(find_all=True, backend=backend)
        end_time = time.time()
        
        device_count = len(devices) if devices else 0
        elapsed = end_time - start_time
        
        print(f"{backend_name}: Found {device_count} devices in {elapsed:.3f}s")
        return elapsed
        
    except usb.core.NoBackendError:
        print(f"{backend_name}: Not available")
        return None

print("Backend performance comparison:")
libusb1_time = benchmark_backend(usb.backend.libusb1, "libusb1")
libusb0_time = benchmark_backend(usb.backend.libusb0, "libusb0")

if libusb1_time and libusb0_time:
    if libusb1_time < libusb0_time:
        print("libusb1 is faster for device enumeration")
    else:
        print("libusb0 is faster for device enumeration")

Custom Backend Integration

import usb.core
from usb.backend import IBackend

class CustomBackend(IBackend):
    """Example custom backend implementation."""
    
    def enumerate_devices(self):
        """Custom device enumeration logic."""
        # Implement custom device discovery
        pass
    
    def open_device(self, device):
        """Custom device opening logic."""
        # Implement custom device access
        pass
    
    # Implement other required methods...

# Use custom backend
custom_backend = CustomBackend()

try:
    device = usb.core.find(
        idVendor=0x1234, 
        idProduct=0x5678, 
        backend=custom_backend
    )
    
    if device:
        print("Device found using custom backend")
        
except Exception as e:
    print(f"Custom backend error: {e}")

Install with Tessl CLI

npx tessl i tessl/pypi-pyusb

docs

backends.md

control-requests.md

device-communication.md

device-discovery.md

index.md

legacy-api.md

utilities.md

tile.json