Easy USB access for Python with backend-neutral, cross-platform support
—
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.
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."""Legacy device enumeration following PyUSB 0.x patterns.
def busses():
"""
Return list of USB buses.
Returns:
list: Bus objects representing system USB buses
"""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 = 1import 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}")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")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)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}")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)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