Skip to content

About

Cross-platform Python client and CLI for Silicon Labs USBXpress devices (C8051F32x/34x/38x) — works without the vendor driver.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pyusbxpress

Cross-platform Python client for Silicon Labs USBXpress devices (C8051F32x / C8051F34x / C8051F38x) — without the vendor driver.

Silicon Labs' USBXpress host driver (SiUSBXp.sys / SiUSBXp.dll) is Windows-only and version-fragile, and Silicon Labs does not document the wire protocol between the host driver and the device firmware library. This project documents that protocol — independently re-derived here and consistent with earlier community implementations (see Related projects) — and provides a small Python client that talks to USBXpress devices directly over libusb/WinUSB, so the same code runs on Windows, Linux and macOS.

Disclaimer — this is an unofficial project based on interoperability research. It is not affiliated with or endorsed by Silicon Labs. It contains no Silicon Labs code or binaries; the protocol description was derived from black-box observation and analysis of the behaviour of the device firmware library. "USBXpress" and "Silicon Labs" are trademarks of Silicon Labs, used here only to describe compatibility.

Status

Alpha (v0.1.x). Verified on Windows 10/11 with a C8051F380 target (see docs/DEVICES.md); Linux/macOS are supported by design (libusb backend) and reports are welcome.

Install

pip install pyusbxpress

or from a checkout:

pip install -e .

The libusb backend needs a USB driver that lets user space claim the device:

Platform Requirement
Windows Bind the device to WinUSB (e.g. with Zadig) — or keep the SiLabs driver and use --backend siusbxp
Linux A udev rule so the device is accessible without root — see docs/LINUX.md
macOS Usually nothing: vendor-specific devices are not claimed by a kernel driver, libusb can use them directly

Quick start

usbxpress list                       # list matching devices
usbxpress info                       # USB info + optional command exchange
usbxpress info --send "01"           # send one 64-byte packet, print the answer
usbxpress monitor                    # print every packet the device sends
usbxpress write --hex "01 55"        # send a single packet

As a library:

from usbxpress import UsbXpressDevice

with UsbXpressDevice() as dev:               # VID 10C4 / PID EA61 by default
    reply = dev.command(b"\x01")             # send one packet, wait for a
    print(reply.hex(" "))                    # packet that starts with 0x01

UsbXpressDevice is deliberately thin: one 64-byte packet per call, plus a command() helper that skips unsolicited packets (some firmwares emit periodic heartbeats). The meaning of the packets is up to your device firmware — see examples/ for a minimal ping and for a complete bootloader flashing example.

How it works (short version)

USBXpress is a vendor-specific USB device (interface class 0xFF) with two bulk endpoints (64-byte packets) and a small set of vendor control requests. The data path stays disabled until the host sends the DEVICE_OPEN control request — this handshake is the piece that Silicon Labs' documentation does not describe, and the reason "enumeration works but no data ever arrives" is a common complaint.

Direction Transport
host → device bulk OUT endpoint, 64-byte packets
device → host bulk IN endpoint, 64-byte packets
enable/disable data path vendor control bmRequestType=0x40, bRequest=0x02 with wValue=0x0002 (open) / 0x0004 (close)
flush device buffers same request with wValue=0x0001

Full details, including the device-side event bits and the recommended host sequence, are in docs/PROTOCOL.md. The method used to derive the protocol is described in docs/INTERNALS.md.

Backends

Backend Platforms Driver needed Notes
libusb (default) Windows, Linux, macOS WinUSB on Windows; udev rule on Linux Uses pyusb + libusb-package; no vendor software
siusbxp Windows only SiLabs USBXpress driver Uses SiUSBXp.dll through ctypes; the driver performs the open/close handshake itself

--backend auto (the default) uses libusb when a WinUSB-bound device is present, and falls back to the SiLabs driver on Windows when it is not.

CLI reference

usbxpress [-h] [--version] {list,info,monitor,write,flush,reset} ...

common options:
  --vid HEX      vendor ID (default 10c4)
  --pid HEX      product ID (default ea61)
  --index N      device index when several are attached
  --serial S     select by serial string
  --backend      auto | libusb | siusbxp
  --dll PATH     SiUSBXp.dll location (siusbxp backend only)
  --timeout SEC  per-transfer timeout (default 1.0)

list      show matching devices and the backend that can see them
info      open the device, print USB info; --send HEX performs one exchange
monitor   print incoming packets with timestamps; --send HEX [--interval S] repeats a packet
write     send one packet: --hex "01 55" | --text "hello" | --file image.bin
flush     purge the device's USB buffers and drop pending input packets
reset     reset the USB device (port reset) and reopen it

Documentation

File Contents
docs/PROTOCOL.md The USBXpress wire protocol (requests, endpoints, events, host sequence)
docs/INTERNALS.md How the protocol was derived (reproducible method)
docs/LINUX.md udev rules, permissions, WSL2/usbipd testing recipe
docs/DEVICES.md Devices verified so far, and how to report a new one

Examples

File Contents
examples/ping.py Minimal command/response exchange
examples/flash_demo.py Complete example: flash an Intel HEX image through a bootloader that implements the reference command set (query/erase/write/read/go + validity record)

Tests

python -m unittest discover -s tests -v

The tests cover the protocol helpers and the packet/response logic with a fake backend; no hardware is required.

API coverage (compared with the SiUSBXp API)

pyusbxpress is not an API clone — it is a small Pythonic layer over the same protocol — but for porting purposes it covers the calls that matter:

SiUSBXp function pyusbxpress Notes
SI_GetNumDevices list_devices(), usbxpress list filters by VID/PID (and optional serial)
SI_GetProductString info (manufacturer/product/serial), --serial reads the USB descriptors
SI_Open / SI_Close open() / close() sends DEVICE_OPEN / DEVICE_CLOSE
SI_Read / SI_Write read(), command() / write() one 64-byte packet per call
SI_SetTimeouts timeout= argument per call; there is no global set/get
SI_FlushBuffers flush(), usbxpress flush sends FIFO_PURGE and drops pending input
SI_ResetDevice reset(), usbxpress reset USB port reset, then reopen
SI_CheckRXQueue not provided read() returning None means "nothing pending"; there is no local ring buffer to inspect
SI_DeviceIOControl not applicable CP21xx register IOCTLs, unrelated to the C8051 firmware protocol

Related projects

The USBXpress wire protocol has been implemented in the open before. It was re-derived independently for this project (device firmware library disassembly plus live device tests) and the results match:

  • SiUSBXp_Linux_Driver — Craig Shelley's open-source C implementation (2010, GPL-2, libusb 0.1); its SI_Open sends the same DEVICE_OPEN request and moves data over the bulk endpoints.
  • fMeow/silabs_usb_xpress — a Rust port of that driver (2020, GPL-3, published on crates.io).

pyusbxpress differs by targeting modern libusb 1.0 from Python, being maintained and documented, and shipping a CLI with tested examples.

License

MIT — see LICENSE.

About

Cross-platform Python client and CLI for Silicon Labs USBXpress devices (C8051F32x/34x/38x) — works without the vendor driver.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages