Easy USB access for Python with backend-neutral, cross-platform support
—
Helper functions for endpoint handling, interface management, descriptor parsing, and resource cleanup. The util module provides essential utilities for USB device operations and data interpretation.
Parse and interpret endpoint addresses and attributes for proper communication setup.
def endpoint_address(address):
"""
Return endpoint absolute address.
Parameters:
- address: int, endpoint address from descriptor
Returns:
int: absolute endpoint address (0-15)
"""
def endpoint_direction(address):
"""
Return endpoint transfer direction.
Parameters:
- address: int, endpoint address from descriptor
Returns:
int: ENDPOINT_OUT (0) or ENDPOINT_IN (128)
"""
def endpoint_type(bmAttributes):
"""
Return endpoint type from attributes.
Parameters:
- bmAttributes: int, endpoint attributes from descriptor
Returns:
int: endpoint type (ENDPOINT_TYPE_CTRL, ENDPOINT_TYPE_ISO,
ENDPOINT_TYPE_BULK, ENDPOINT_TYPE_INTR)
"""Build control transfer parameters and interpret transfer directions.
def ctrl_direction(bmRequestType):
"""
Return direction of control transfer.
Parameters:
- bmRequestType: int, request type field
Returns:
int: CTRL_OUT (0) or CTRL_IN (128)
"""
def build_request_type(direction, type, recipient):
"""
Build bmRequestType field for control transfer.
Parameters:
- direction: int, transfer direction (CTRL_OUT or CTRL_IN)
- type: int, request type (CTRL_TYPE_STANDARD, CTRL_TYPE_CLASS, CTRL_TYPE_VENDOR)
- recipient: int, recipient (CTRL_RECIPIENT_DEVICE, CTRL_RECIPIENT_INTERFACE, etc.)
Returns:
int: bmRequestType value
"""Create and manage buffers for USB data operations.
def create_buffer(length):
"""
Create buffer for USB operations.
Parameters:
- length: int, buffer size in bytes
Returns:
array.array: buffer suitable for USB operations
"""Find specific descriptors within device configuration hierarchies.
def find_descriptor(desc, find_all=False, custom_match=None, **args):
"""
Find inner descriptor within a configuration/interface/endpoint hierarchy.
Parameters:
- desc: descriptor object to search within
- find_all: bool, return all matches instead of first match
- custom_match: callable taking descriptor as argument, return True for matches
- **args: descriptor fields to match
Returns:
Descriptor object or list of descriptors, None if not found
"""Claim and release interfaces for exclusive device access.
def claim_interface(device, interface):
"""
Explicitly claim an interface.
Parameters:
- device: Device object
- interface: int or Interface object, interface to claim
Raises:
- USBError: Interface claim failed
"""
def release_interface(device, interface):
"""
Explicitly release an interface.
Parameters:
- device: Device object
- interface: int or Interface object, interface to release
Raises:
- USBError: Interface release failed
"""Clean up device resources and handle proper disposal.
def dispose_resources(device):
"""
Release internal resources allocated by the device object.
Parameters:
- device: Device object to clean up
"""Retrieve and decode string descriptors with language support.
def get_langids(dev):
"""
Retrieve list of supported string languages from device.
Parameters:
- dev: Device object
Returns:
list: language ID codes supported by device
Raises:
- USBError: Language ID retrieval failed
"""
def get_string(dev, index, langid=None):
"""
Retrieve string descriptor from device.
Parameters:
- dev: Device object
- index: int, string descriptor index
- langid: int, language ID (default: first supported language)
Returns:
str: decoded string descriptor
Raises:
- USBError: String retrieval failed
"""Direction and type constants for endpoint and control operations.
# Descriptor types
DESC_TYPE_DEVICE = 0x01
DESC_TYPE_CONFIG = 0x02
DESC_TYPE_STRING = 0x03
DESC_TYPE_INTERFACE = 0x04
DESC_TYPE_ENDPOINT = 0x05
# Endpoint directions
ENDPOINT_IN = 0x80
ENDPOINT_OUT = 0x00
# Endpoint types
ENDPOINT_TYPE_CTRL = 0x00
ENDPOINT_TYPE_ISO = 0x01
ENDPOINT_TYPE_BULK = 0x02
ENDPOINT_TYPE_INTR = 0x03
# Control transfer directions
CTRL_OUT = 0x00
CTRL_IN = 0x80
# Control transfer types
CTRL_TYPE_STANDARD = 0x00
CTRL_TYPE_CLASS = 0x20
CTRL_TYPE_VENDOR = 0x40
CTRL_TYPE_RESERVED = 0x60
# Control transfer recipients
CTRL_RECIPIENT_DEVICE = 0x00
CTRL_RECIPIENT_INTERFACE = 0x01
CTRL_RECIPIENT_ENDPOINT = 0x02
CTRL_RECIPIENT_OTHER = 0x03
# USB speeds
SPEED_UNKNOWN = 0
SPEED_LOW = 1
SPEED_FULL = 2
SPEED_HIGH = 3
SPEED_SUPER = 4import usb.core
import usb.util
device = usb.core.find(idVendor=0x1234, idProduct=0x5678)
device.set_configuration()
config = device.get_active_configuration()
interface = config.interfaces()[0]
for endpoint in interface.endpoints():
addr = endpoint.bEndpointAddress
attrs = endpoint.bmAttributes
print(f"Endpoint address: 0x{addr:02x}")
print(f" Absolute address: {usb.util.endpoint_address(addr)}")
direction = usb.util.endpoint_direction(addr)
if direction == usb.util.ENDPOINT_IN:
print(" Direction: IN")
else:
print(" Direction: OUT")
ep_type = usb.util.endpoint_type(attrs)
type_names = {
usb.util.ENDPOINT_TYPE_CTRL: "Control",
usb.util.ENDPOINT_TYPE_ISO: "Isochronous",
usb.util.ENDPOINT_TYPE_BULK: "Bulk",
usb.util.ENDPOINT_TYPE_INTR: "Interrupt"
}
print(f" Type: {type_names[ep_type]}")
print(f" Max packet size: {endpoint.wMaxPacketSize}")import usb.core
import usb.util
device = usb.core.find(idVendor=0x1234, idProduct=0x5678)
device.set_configuration()
interface_num = 0
try:
# Claim interface for exclusive access
usb.util.claim_interface(device, interface_num)
print(f"Interface {interface_num} claimed")
# Perform device operations...
finally:
# Always release interface when done
usb.util.release_interface(device, interface_num)
print(f"Interface {interface_num} released")import usb.core
import usb.util
device = usb.core.find(idVendor=0x1234, idProduct=0x5678)
try:
# Get supported languages
langids = usb.util.get_langids(device)
print(f"Supported languages: {[hex(lid) for lid in langids]}")
# Get device strings in first supported language
if langids and device.iManufacturer:
manufacturer = usb.util.get_string(device, device.iManufacturer, langids[0])
print(f"Manufacturer: {manufacturer}")
if langids and device.iProduct:
product = usb.util.get_string(device, device.iProduct, langids[0])
print(f"Product: {product}")
if langids and device.iSerialNumber:
serial = usb.util.get_string(device, device.iSerialNumber, langids[0])
print(f"Serial number: {serial}")
except usb.core.USBError as e:
print(f"String access failed: {e}")import usb.core
import usb.util
device = usb.core.find(idVendor=0x1234, idProduct=0x5678)
device.set_configuration()
config = device.get_active_configuration()
# Find all bulk endpoints
bulk_endpoints = usb.util.find_descriptor(
config,
find_all=True,
custom_match=lambda e: usb.util.endpoint_type(e.bmAttributes) == usb.util.ENDPOINT_TYPE_BULK
)
print(f"Found {len(bulk_endpoints)} bulk endpoints:")
for ep in bulk_endpoints:
direction = "IN" if usb.util.endpoint_direction(ep.bEndpointAddress) == usb.util.ENDPOINT_IN else "OUT"
print(f" Endpoint 0x{ep.bEndpointAddress:02x} ({direction})")
# Find specific interface by class
hid_interface = usb.util.find_descriptor(
config,
bInterfaceClass=3 # HID class
)
if hid_interface:
print(f"Found HID interface: {hid_interface.bInterfaceNumber}")import usb.core
import usb.util
device = usb.core.find(idVendor=0x1234, idProduct=0x5678)
# Build request type for vendor-specific IN request to device
request_type = usb.util.build_request_type(
usb.util.CTRL_IN,
usb.util.CTRL_TYPE_VENDOR,
usb.util.CTRL_RECIPIENT_DEVICE
)
print(f"Request type: 0x{request_type:02x}")
# Perform control transfer
try:
result = device.ctrl_transfer(
request_type,
0x01, # Vendor-specific request
0x0000, # wValue
0x0000, # wIndex
64 # Read 64 bytes
)
print(f"Control transfer result: {result}")
except usb.core.USBError as e:
print(f"Control transfer failed: {e}")import usb.core
import usb.util
device = usb.core.find(idVendor=0x1234, idProduct=0x5678)
device.set_configuration()
# Create buffer for reading data
buffer = usb.util.create_buffer(1024)
print(f"Created buffer of size {len(buffer)}")
# Use buffer with read operation
endpoint_addr = 0x81 # IN endpoint
try:
bytes_read = device.read(endpoint_addr, buffer, timeout=1000)
print(f"Read {bytes_read} bytes into buffer")
print(f"Data: {buffer[:bytes_read]}")
except usb.core.USBTimeoutError:
print("Read operation timed out")import usb.core
import usb.util
device = usb.core.find(idVendor=0x1234, idProduct=0x5678)
try:
# Perform device operations
device.set_configuration()
# ... communication ...
finally:
# Clean up device resources
usb.util.dispose_resources(device)
print("Device resources disposed")Install with Tessl CLI
npx tessl i tessl/pypi-pyusb