libusb1
libusb1 is a pure-Python wrapper for the `libusb-1.0` C library, providing low-level access to USB devices. It exposes both synchronous and asynchronous APIs, allowing access to all USB transfer types (control, bulk, interrupt, isochronous). Unlike PyUSB, which aims for a common subset across various USB libraries, libusb1 focuses on making the entire `libusb-1.0` API available. The project is actively maintained, with regular releases addressing bug fixes and improvements, such as the recent 3.3.1 release.
Warnings
- breaking Python 2.x support was dropped in `libusb1` version 3.0.0. Applications targeting Python versions older than 3.6 will not be compatible.
- deprecated Direct import from the `libusb1` module (e.g., `import libusb1`) is deprecated. All primary classes, functions, and constants are exposed through the `usb1` module.
- gotcha On Windows, while `libusb1` wheels bundle the `libusb-1.0` DLL, you still need to install appropriate USB drivers (e.g., WinUSB or libusbK) for your specific USB devices. The Python library does not handle driver installation.
- gotcha Older versions of `libusb1` (prior to 3.3.0) might have experienced 'finalizer registration errors,' which could manifest as warnings about USB devices being leaked or still referenced during application shutdown.
- gotcha On some macOS systems, the `select.poll` mechanism (used for asynchronous I/O) might be missing or have limitations, potentially affecting the reliability of asynchronous USB operations.
- gotcha Applications using `libusb1` (or `libusb-1.0` in general) often require elevated privileges (e.g., root or administrator) to access and interact with USB devices on the system, particularly on Linux.
Install
-
pip install libusb1
Imports
- USBContext
import usb1 # ... then use usb1.USBContext()
Quickstart
import usb1
import os
# Replace with your device's Vendor ID and Product ID
# You can often find these using 'lsusb' on Linux or device manager on Windows.
VENDOR_ID = os.environ.get('USB_DEVICE_VENDOR_ID', '0x1234') # Example vendor ID
PRODUCT_ID = os.environ.get('USB_DEVICE_PRODUCT_ID', '0x5678') # Example product ID
def list_all_devices():
with usb1.USBContext() as context:
print("Listing all USB devices:")
for device in context.get DeviceIterator():
print(f" Bus {device.getBusNumber():03d} Device {device.getDeviceAddress():03d}: ID {device.getVendorID():04x}:{device.getProductID():04x} {device.getManufacturerString() or 'N/A'} {device.getProductString() or 'N/A'}")
def find_and_access_device(vendor_id, product_id):
print(f"\nAttempting to find device with ID {int(vendor_id, 16):04x}:{int(product_id, 16):04x}")
try:
with usb1.USBContext() as context:
handle = context.openByVendorIDAndProductID(
int(vendor_id, 16),
int(product_id, 16),
skip_on_error=True,
)
if handle is None:
print("Device not found or access denied.")
return
with handle.claimInterface(0): # Claim interface 0 (adjust as needed)
print(f"Successfully found and claimed interface 0 of device {handle.getVendorID():04x}:{handle.getProductID():04x}")
# Example: Read from an endpoint (replace ENDPOINT_ADDRESS and BUFFER_SIZE)
# data = handle.bulkRead(0x81, 64)
# print(f"Read: {data.hex()}")
# Example: Write to an endpoint
# handle.bulkWrite(0x01, b'Hello USB')
except usb1.USBError as e:
print(f"USB Error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
if __name__ == "__main__":
list_all_devices()
find_and_access_device(VENDOR_ID, PRODUCT_ID)