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

legacy-api.mddocs/

Legacy API

Backward-compatible API matching PyUSB 0.x interface patterns with extensive USB constants and legacy device handling. This module provides compatibility for applications written against PyUSB 0.x versions.

Capabilities

Device Hierarchy

Legacy device representation using bus/device hierarchy similar to PyUSB 0.x.

class Bus:
    """Legacy bus representation."""
    dirname: str          # Bus directory name
    location: int         # Bus location
    
    def devices(self):
        """Return list of devices on this bus."""

class Device:
    """Legacy device representation."""
    deviceClass: int      # Device class
    deviceSubClass: int   # Device sub-class  
    deviceProtocol: int   # Device protocol
    maxPacketSize: int    # Maximum packet size
    idVendor: int         # Vendor ID
    idProduct: int        # Product ID
    bcdDevice: int        # Device version
    iManufacturer: int    # Manufacturer string index
    iProduct: int         # Product string index
    iSerialNumber: int    # Serial number string index
    
    def configurations(self):
        """Return list of configurations."""
        
    def open(self):
        """Open device and return DeviceHandle."""

class Configuration:
    """Legacy configuration representation."""
    value: int            # Configuration value
    iConfiguration: int   # Configuration string index
    attributes: int       # Configuration attributes
    maxPower: int         # Maximum power consumption
    
    def interfaces(self):
        """Return list of interfaces."""

class Interface:
    """Legacy interface representation."""
    interfaceNumber: int     # Interface number
    alternateSetting: int    # Alternate setting
    interfaceClass: int      # Interface class
    interfaceSubClass: int   # Interface sub-class
    interfaceProtocol: int   # Interface protocol
    iInterface: int          # Interface string index
    
    def endpoints(self):
        """Return list of endpoints."""

class Endpoint:
    """Legacy endpoint representation."""
    address: int          # Endpoint address
    type: int            # Endpoint type
    maxPacketSize: int   # Maximum packet size
    interval: int        # Polling interval

class DeviceHandle:
    """Legacy device handle for communication."""
    
    def bulkWrite(self, endpoint, buffer, timeout=100):
        """Write data via bulk transfer."""
        
    def bulkRead(self, endpoint, size, timeout=100):
        """Read data via bulk transfer."""
        
    def interruptWrite(self, endpoint, buffer, timeout=100):
        """Write data via interrupt transfer."""
        
    def interruptRead(self, endpoint, size, timeout=100):
        """Read data via interrupt transfer."""
        
    def controlMsg(self, requestType, request, buffer, value=0, index=0, timeout=100):
        """Send control message."""
        
    def setConfiguration(self, configuration):
        """Set device configuration."""
        
    def claimInterface(self, interface):
        """Claim interface."""
        
    def releaseInterface(self, interface):
        """Release interface."""
        
    def setAltInterface(self, alt):
        """Set alternate interface."""

Device Enumeration

Legacy device enumeration following PyUSB 0.x patterns.

def busses():
    """
    Return list of USB buses.
    
    Returns:
    list: Bus objects representing system USB buses
    """

USB Constants

Comprehensive set of USB constants for device classes, descriptor types, endpoints, and requests.

# Device Classes
CLASS_AUDIO = 1
CLASS_COMM = 2
CLASS_HID = 3
CLASS_PRINTER = 7
CLASS_MASS_STORAGE = 8
CLASS_HUB = 9
CLASS_DATA = 10
CLASS_WIRELESS_CONTROLLER = 224
CLASS_VENDOR_SPEC = 255
CLASS_PER_INTERFACE = 0

# Descriptor Types
DT_DEVICE = 1
DT_CONFIG = 2
DT_STRING = 3
DT_INTERFACE = 4
DT_ENDPOINT = 5
DT_HID = 33
DT_HUB = 41
DT_PHYSICAL = 35
DT_REPORT = 34

# Descriptor Sizes
DT_DEVICE_SIZE = 18
DT_CONFIG_SIZE = 9
DT_INTERFACE_SIZE = 9
DT_ENDPOINT_SIZE = 7
DT_ENDPOINT_AUDIO_SIZE = 9
DT_HUB_NONVAR_SIZE = 7

# Endpoint Directions
ENDPOINT_IN = 128
ENDPOINT_OUT = 0
ENDPOINT_ADDRESS_MASK = 15
ENDPOINT_DIR_MASK = 128

# Endpoint Types
ENDPOINT_TYPE_CONTROL = 0
ENDPOINT_TYPE_ISOCHRONOUS = 1
ENDPOINT_TYPE_BULK = 2
ENDPOINT_TYPE_INTERRUPT = 3
ENDPOINT_TYPE_MASK = 3

# Request Types
TYPE_STANDARD = 0
TYPE_CLASS = 32
TYPE_VENDOR = 64
TYPE_RESERVED = 96

# Recipients
RECIP_DEVICE = 0
RECIP_INTERFACE = 1
RECIP_ENDPOINT = 2
RECIP_OTHER = 3

# Standard Requests
REQ_GET_STATUS = 0
REQ_CLEAR_FEATURE = 1
REQ_SET_FEATURE = 3
REQ_SET_ADDRESS = 5
REQ_GET_DESCRIPTOR = 6    
REQ_SET_DESCRIPTOR = 7
REQ_GET_CONFIGURATION = 8
REQ_SET_CONFIGURATION = 9
REQ_GET_INTERFACE = 10
REQ_SET_INTERFACE = 11
REQ_SYNCH_FRAME = 12

# Configuration Limits
MAXCONFIG = 8
MAXINTERFACES = 32
MAXALTSETTING = 128
MAXENDPOINTS = 32

# Error Codes
ERROR_BEGIN = 500000

# Protocol Codes
PROTOCOL_BLUETOOTH_PRIMARY_CONTROLLER = 1
SUBCLASS_RF_CONTROLLER = 1

Usage Examples

Legacy Device Enumeration

import usb

# Get all USB buses
buses = usb.busses()
print(f"Found {len(buses)} USB buses")

# Enumerate all devices
for bus in buses:
    devices = bus.devices()
    print(f"Bus {bus.dirname}: {len(devices)} devices")
    
    for device in devices:
        print(f"  Device {device.idVendor:04x}:{device.idProduct:04x}")
        print(f"    Class: {device.deviceClass}")
        print(f"    Max packet size: {device.maxPacketSize}")

Legacy Device Communication

import usb

# Find device (legacy style)
def find_device(vendor_id, product_id):
    """Find device using legacy enumeration."""
    for bus in usb.busses():
        for device in bus.devices():
            if device.idVendor == vendor_id and device.idProduct == product_id:
                return device
    return None

device = find_device(0x1234, 0x5678)

if device:
    print("Device found!")
    
    # Open device handle
    handle = device.open()
    
    try:
        # Set configuration
        handle.setConfiguration(1)
        
        # Claim interface
        handle.claimInterface(0)
        
        # Bulk write
        data = b"Hello USB device!"
        bytes_written = handle.bulkWrite(0x01, data, timeout=1000)
        print(f"Wrote {bytes_written} bytes")
        
        # Bulk read
        read_data = handle.bulkRead(0x81, 64, timeout=1000)
        print(f"Read {len(read_data)} bytes: {read_data}")
        
    finally:
        # Clean up
        handle.releaseInterface(0)
        
else:
    print("Device not found")

Legacy Control Messages

import usb

device = find_device(0x1234, 0x5678)  # From previous example
handle = device.open()

try:
    # Control message for getting device status
    request_type = usb.TYPE_STANDARD | usb.RECIP_DEVICE | usb.ENDPOINT_IN
    result = handle.controlMsg(
        requestType=request_type,
        request=usb.REQ_GET_STATUS,
        buffer=2,  # 2 bytes for status
        value=0,
        index=0,
        timeout=1000
    )
    
    print(f"Device status: {result}")
    
    # Vendor-specific control message
    vendor_request_type = usb.TYPE_VENDOR | usb.RECIP_DEVICE | usb.ENDPOINT_IN
    vendor_result = handle.controlMsg(
        requestType=vendor_request_type,
        request=0x01,  # Vendor-specific request
        buffer=64,
        value=0x1234,
        index=0x5678,
        timeout=1000
    )
    
    print(f"Vendor response: {vendor_result}")
    
finally:
    handle.releaseInterface(0)

Legacy Configuration Inspection

import usb

device = find_device(0x1234, 0x5678)  # From previous example

print(f"Device {device.idVendor:04x}:{device.idProduct:04x}")
print(f"Device class: {device.deviceClass}")
print(f"Device sub-class: {device.deviceSubClass}")
print(f"Device protocol: {device.deviceProtocol}")

# Enumerate configurations
configurations = device.configurations()
print(f"Configurations: {len(configurations)}")

for config in configurations:
    print(f"  Configuration {config.value}:")
    print(f"    Max power: {config.maxPower * 2}mA")  # maxPower is in 2mA units
    print(f"    Attributes: 0x{config.attributes:02x}")
    
    # Enumerate interfaces
    interfaces = config.interfaces()
    print(f"    Interfaces: {len(interfaces)}")
    
    for interface in interfaces:
        print(f"      Interface {interface.interfaceNumber}:")
        print(f"        Class: {interface.interfaceClass}")
        print(f"        Sub-class: {interface.interfaceSubClass}")
        print(f"        Protocol: {interface.interfaceProtocol}")
        
        # Enumerate endpoints
        endpoints = interface.endpoints()
        print(f"        Endpoints: {len(endpoints)}")
        
        for endpoint in endpoints:
            direction = "IN" if endpoint.address & usb.ENDPOINT_IN else "OUT"
            ep_type = endpoint.type & usb.ENDPOINT_TYPE_MASK
            
            type_names = {
                usb.ENDPOINT_TYPE_CONTROL: "Control",
                usb.ENDPOINT_TYPE_ISOCHRONOUS: "Isochronous",
                usb.ENDPOINT_TYPE_BULK: "Bulk", 
                usb.ENDPOINT_TYPE_INTERRUPT: "Interrupt"
            }
            
            print(f"          Endpoint 0x{endpoint.address:02x} ({direction} {type_names[ep_type]})")
            print(f"            Max packet: {endpoint.maxPacketSize}")
            print(f"            Interval: {endpoint.interval}")

Legacy Interrupt Transfers

import usb
import time

device = find_device(0x1234, 0x5678)  # From previous example
handle = device.open()

try:
    handle.setConfiguration(1)
    handle.claimInterface(0)
    
    # Interrupt read loop
    interrupt_endpoint = 0x83  # IN endpoint 3
    
    print("Starting interrupt read loop...")
    for i in range(10):
        try:
            data = handle.interruptRead(interrupt_endpoint, 8, timeout=1000)
            print(f"Interrupt data [{i}]: {data}")
            
        except usb.USBError as e:
            print(f"Interrupt read error: {e}")
            break
            
        time.sleep(0.1)
    
    # Interrupt write (if supported)
    interrupt_out_endpoint = 0x03  # OUT endpoint 3
    try:
        bytes_written = handle.interruptWrite(
            interrupt_out_endpoint, 
            b'\x01\x02\x03\x04', 
            timeout=1000
        )
        print(f"Interrupt write: {bytes_written} bytes")
        
    except usb.USBError as e:
        print(f"Interrupt write not supported: {e}")
    
finally:
    handle.releaseInterface(0)

Legacy Error Handling

import usb

try:
    device = find_device(0x1234, 0x5678)
    
    if device is None:
        raise usb.USBError("Device not found")
    
    handle = device.open()
    
    try:
        handle.setConfiguration(1)
        handle.claimInterface(0)
        
        # Operations that might fail
        data = handle.bulkRead(0x81, 64, timeout=100)
        
    except usb.USBError as e:
        print(f"USB operation failed: {e}")
        # Handle specific error conditions based on error message or code
        
    finally:
        # Always clean up
        try:
            handle.releaseInterface(0)
        except:
            pass  # Ignore cleanup errors
            
except usb.USBError as e:
    print(f"USB error: {e}")
except Exception as e:
    print(f"Unexpected 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