CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-libusb1

Pure-python wrapper for libusb-1.0 providing comprehensive USB device access with support for all transfer types

Pending
Overview
Eval results
Files

device-access.mddocs/

Device Access and Configuration

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.

Capabilities

Device Information and Properties

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

class USBDevice:
    def getBusNumber(self):
        """
        Get device's bus number.
        
        Returns:
            int: Bus number
        """

    def getPortNumber(self):
        """
        Get device's port number.
        
        Returns:
            int: Port number
        """

    def getPortNumberList(self):
        """
        Get list of port numbers from root hub to device.
        
        Returns:
            list[int]: Port numbers along the path
        """

    def getDeviceAddress(self):
        """
        Get device's address on the bus.
        
        Returns:
            int: Device address (1-127)
        """

    def getVendorID(self):
        """
        Get device's vendor ID.
        
        Returns:
            int: 16-bit vendor ID
        """

    def getProductID(self):
        """
        Get device's product ID.
        
        Returns:
            int: 16-bit product ID
        """

    def getbcdUSB(self):
        """
        Get USB specification version in BCD format.
        
        Returns:
            int: USB version (e.g. 0x0200 for USB 2.0)
        """

    def getbcdDevice(self):
        """
        Get device release number in BCD format.
        
        Returns:
            int: Device release number
        """

    def getDeviceClass(self):
        """
        Get device class code.
        
        Returns:
            int: Device class (0 if specified at interface level)
        """

    def getDeviceSubClass(self):
        """
        Get device subclass code.
        
        Returns:
            int: Device subclass
        """

    def getDeviceProtocol(self):
        """
        Get device protocol code.
        
        Returns:
            int: Device protocol
        """

    def getDeviceSpeed(self):
        """
        Get device operating speed.
        
        Returns:
            int: Speed constant (SPEED_LOW, SPEED_FULL, SPEED_HIGH, SPEED_SUPER, SPEED_SUPER_PLUS)
        """

    def getMaxPacketSize0(self):
        """
        Get maximum packet size for endpoint 0 (control endpoint).
        
        Returns:
            int: Maximum packet size in bytes
        """

    def getMaxPacketSize(self, endpoint):
        """
        Get maximum packet size for specified endpoint.
        
        Args:
            endpoint (int): Endpoint address
            
        Returns:
            int: Maximum packet size in bytes
            
        Warning:
            May not always give expected results. Consult endpoint descriptor instead.
        """

    def getMaxISOPacketSize(self, endpoint):
        """
        Get maximum isochronous packet size for endpoint.
        
        Args:
            endpoint (int): Endpoint address
            
        Returns:
            int: Maximum ISO packet size in bytes
            
        Warning:
            May not always give expected results. Consult endpoint descriptor instead.
        """

    def getNumConfigurations(self):
        """
        Get number of possible configurations.
        
        Returns:
            int: Number of configurations
        """

Device Opening and Closing

Open devices for communication and manage device handle lifecycle.

class USBDevice:
    def open(self):
        """
        Open device for communication.
        
        Returns:
            USBDeviceHandle: Handle for device communication
            
        Raises:
            USBError: If device cannot be opened
        """

    def close(self):
        """Close device and release resources."""

class USBDeviceHandle:
    def close(self):
        """
        Close device handle and release resources.
        
        Note:
            Cancels any in-flight transfers. May block until transfers complete.
        """

    def getDevice(self):
        """
        Get USBDevice instance for this handle.
        
        Returns:
            USBDevice: Associated device instance
        """

String Descriptor Access

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

class USBDevice:
    def getManufacturer(self):
        """
        Get manufacturer string (opens device temporarily).
        
        Returns:
            str or None: Manufacturer name or None if not available
        """

    def getProduct(self):
        """
        Get product string (opens device temporarily).
        
        Returns:
            str or None: Product name or None if not available
        """

    def getSerialNumber(self):
        """
        Get serial number string (opens device temporarily).
        
        Returns:
            str or None: Serial number or None if not available
        """

    def getSupportedLanguageList(self):
        """
        Get list of supported language IDs (opens device temporarily).
        
        Returns:
            list[int]: List of language IDs
        """

class USBDeviceHandle:
    def getManufacturer(self):
        """
        Get manufacturer string.
        
        Returns:
            str or None: Manufacturer name or None if not available
        """

    def getProduct(self):
        """
        Get product string.
        
        Returns:
            str or None: Product name or None if not available
        """

    def getSerialNumber(self):
        """
        Get serial number string.
        
        Returns:
            str or None: Serial number or None if not available
        """

    def getSupportedLanguageList(self):
        """
        Get list of supported language IDs.
        
        Returns:
            list[int]: List of USB language identifiers
        """

    def getStringDescriptor(self, descriptor, lang_id, errors='strict'):
        """
        Get string descriptor in specified language.
        
        Args:
            descriptor (int): String descriptor index
            lang_id (int): Language ID
            errors (str): Error handling mode ('strict', 'ignore', 'replace')
            
        Returns:
            str or None: String content or None if not found
        """

    def getASCIIStringDescriptor(self, descriptor, errors='strict'):
        """
        Get string descriptor in first available language as ASCII.
        
        Args:
            descriptor (int): String descriptor index
            errors (str): Error handling mode ('strict', 'ignore', 'replace')
            
        Returns:
            str or None: String content or None if not found
        """

Configuration Management

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

class USBDeviceHandle:
    def getConfiguration(self):
        """
        Get current configuration number.
        
        Returns:
            int: Configuration value (1-based, 0 = unconfigured)
        """

    def setConfiguration(self, configuration):
        """
        Set device configuration.
        
        Args:
            configuration (int): Configuration value (1-based, 0 = unconfigure)
            
        Raises:
            USBError: If configuration cannot be set
        """

Interface Management

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

class USBDeviceHandle:
    def claimInterface(self, interface):
        """
        Claim interface for exclusive access.
        
        Args:
            interface (int): Interface number
            
        Returns:
            _ReleaseInterface: Context manager that auto-releases on exit
            
        Raises:
            USBError: If interface cannot be claimed
            
        Usage:
            with handle.claimInterface(0):
                # perform operations
                pass
            # interface automatically released
        """

    def releaseInterface(self, interface):
        """
        Release interface, allowing other processes to claim it.
        
        Args:
            interface (int): Interface number
            
        Raises:
            USBError: If interface cannot be released
        """

    def setInterfaceAltSetting(self, interface, alt_setting):
        """
        Set alternate setting for interface.
        
        Args:
            interface (int): Interface number
            alt_setting (int): Alternate setting number
            
        Raises:
            USBError: If alternate setting cannot be set
        """

Endpoint Management

Manage endpoint states and clear error conditions.

class USBDeviceHandle:
    def clearHalt(self, endpoint):
        """
        Clear halt/stall condition on endpoint.
        
        Args:
            endpoint (int): Endpoint address
            
        Raises:
            USBError: If halt cannot be cleared
        """

Device Reset

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

class USBDeviceHandle:
    def resetDevice(self):
        """
        Reset device to initial state.
        
        Raises:
            USBErrorNotFound: If device disconnects and must be rediscovered
            USBError: If reset fails
            
        Note:
            May cause device to disconnect and reconnect with new address.
        """

Kernel Driver Management

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

class USBDeviceHandle:
    def kernelDriverActive(self, interface):
        """
        Check if kernel driver is active on interface.
        
        Args:
            interface (int): Interface number
            
        Returns:
            bool: True if kernel driver is active
        """

    def detachKernelDriver(self, interface):
        """
        Detach kernel driver from interface.
        
        Args:
            interface (int): Interface number
            
        Raises:
            USBError: If driver cannot be detached
            
        Note:
            Required on Linux before claiming some interfaces.
        """

    def attachKernelDriver(self, interface):
        """
        Re-attach kernel driver to interface.
        
        Args:
            interface (int): Interface number
            
        Raises:
            USBError: If driver cannot be attached
        """

    def setAutoDetachKernelDriver(self, enable):
        """
        Enable/disable automatic kernel driver detachment.
        
        Args:
            enable (bool): True to enable auto-detach
            
        Raises:
            USBError: If auto-detach cannot be configured
        """

Asynchronous Transfer Creation

Create transfer objects for asynchronous operations.

class USBDeviceHandle:
    def getTransfer(self, iso_packets=0, short_is_error=False, add_zero_packet=False):
        """
        Create transfer object for asynchronous operations.
        
        Args:
            iso_packets (int): Number of isochronous packet descriptors
            short_is_error (bool): Treat short transfers as errors
            add_zero_packet (bool): Add zero-length packet for transfers that are multiples of endpoint size
            
        Returns:
            USBTransfer: Transfer object for async operations
        """

Usage Examples

Basic Device Access

import usb1

with usb1.USBContext() as context:
    # Find device by vendor/product ID
    device = context.getByVendorIDAndProductID(0x1234, 0x5678)
    if not device:
        print("Device not found")
        return
    
    # Display device information
    print(f"Device: {device.getVendorID():04x}:{device.getProductID():04x}")
    print(f"Bus {device.getBusNumber():03d}, Address {device.getDeviceAddress():03d}")
    print(f"USB {device.getbcdUSB() >> 8}.{(device.getbcdUSB() >> 4) & 0xf}")
    print(f"Speed: {device.getDeviceSpeed()}")
    print(f"Class: {device.getDeviceClass()}")
    
    # Access string descriptors
    try:
        print(f"Manufacturer: {device.getManufacturer()}")
        print(f"Product: {device.getProduct()}")
        print(f"Serial: {device.getSerialNumber()}")
    except usb1.USBError as e:
        print(f"Error reading strings: {e}")

Device Configuration and Interface Claiming

import usb1

with usb1.USBContext() as context:
    device = context.getByVendorIDAndProductID(0x1234, 0x5678)
    if device:
        with device.open() as handle:
            # Check current configuration
            current_config = handle.getConfiguration()
            print(f"Current configuration: {current_config}")
            
            # Set configuration if needed
            if current_config != 1:
                handle.setConfiguration(1)
                print("Set configuration to 1")
            
            # Check for kernel driver and detach if necessary
            interface_num = 0
            if handle.kernelDriverActive(interface_num):
                print("Detaching kernel driver")
                handle.detachKernelDriver(interface_num)
            
            # Claim interface with automatic release
            with handle.claimInterface(interface_num):
                print(f"Claimed interface {interface_num}")
                
                # Set alternate setting if needed
                handle.setInterfaceAltSetting(interface_num, 0)
                print("Set alternate setting 0")
                
                # Perform operations here
                # ...
                
            print("Interface automatically released")

Comprehensive Device Information

import usb1

def print_device_info(device):
    """Print comprehensive device information."""
    print(f"\nDevice {device.getVendorID():04x}:{device.getProductID():04x}")
    print(f"  Bus: {device.getBusNumber():03d}")
    print(f"  Address: {device.getDeviceAddress():03d}")
    print(f"  Port path: {' -> '.join(map(str, device.getPortNumberList()))}")
    print(f"  USB version: {device.getbcdUSB() >> 8}.{(device.getbcdUSB() >> 4) & 0xf}")
    print(f"  Device version: {device.getbcdDevice() >> 8}.{(device.getbcdDevice() >> 4) & 0xf}")
    print(f"  Speed: {device.getDeviceSpeed()}")
    print(f"  Class: {device.getDeviceClass()}")
    print(f"  Subclass: {device.getDeviceSubClass()}")
    print(f"  Protocol: {device.getDeviceProtocol()}")
    print(f"  Max packet size (EP0): {device.getMaxPacketSize0()}")
    print(f"  Configurations: {device.getNumConfigurations()}")
    
    # Try to get string descriptors
    try:
        manufacturer = device.getManufacturer()
        product = device.getProduct()
        serial = device.getSerialNumber()
        languages = device.getSupportedLanguageList()
        
        if manufacturer:
            print(f"  Manufacturer: {manufacturer}")
        if product:
            print(f"  Product: {product}")
        if serial:
            print(f"  Serial: {serial}")
        if languages:
            print(f"  Languages: {[hex(lang) for lang in languages]}")
            
    except usb1.USBError as e:
        print(f"  Error reading strings: {e}")

with usb1.USBContext() as context:
    for device in context.getDeviceIterator(skip_on_error=True):
        print_device_info(device)

Error Handling and Resource Management

import usb1

def safe_device_operation(vendor_id, product_id):
    """Demonstrate safe device operation with proper error handling."""
    context = None
    device = None
    handle = None
    
    try:
        # Create context
        context = usb1.USBContext()
        context.open()
        
        # Find device
        device = context.getByVendorIDAndProductID(vendor_id, product_id)
        if not device:
            print("Device not found")
            return False
        
        # Open device  
        handle = device.open()
        
        # Detach kernel driver if needed
        interface_num = 0
        kernel_attached = False
        
        try:
            if handle.kernelDriverActive(interface_num):
                handle.detachKernelDriver(interface_num)
                kernel_attached = True
                print("Detached kernel driver")
        except usb1.USBErrorNotSupported:
            print("Kernel driver operations not supported")
        
        # Claim interface
        interface_claimed = False
        try:
            handle.claimInterface(interface_num)
            interface_claimed = True
            print("Claimed interface")
            
            # Perform operations here
            print("Performing device operations...")
            
            return True
            
        except usb1.USBError as e:
            print(f"Error claiming interface: {e}")
            return False
            
        finally:
            # Clean up in reverse order
            if interface_claimed:
                try:
                    handle.releaseInterface(interface_num)
                    print("Released interface")
                except usb1.USBError as e:
                    print(f"Error releasing interface: {e}")
            
            if kernel_attached:
                try:
                    handle.attachKernelDriver(interface_num)
                    print("Re-attached kernel driver")
                except usb1.USBError as e:
                    print(f"Error re-attaching kernel driver: {e}")
                    
    except usb1.USBError as e:
        print(f"USB error: {e}")
        return False
        
    finally:
        # Clean up resources
        if handle:
            handle.close()
        if device:
            device.close()
        if context:
            context.close()

# Usage
safe_device_operation(0x1234, 0x5678)

Install with Tessl CLI

npx tessl i tessl/pypi-libusb1

docs

async-transfers.md

descriptors.md

device-access.md

index.md

sync-transfers.md

usb-context.md

tile.json