This release is a pre-release and may not be stable for production use.
python-can-busmust
Alpha release: 0.1.0a1. Not yet validated on physical hardware. The software tests use simulated USB devices. APIs and firmware compatibility may change as real-adapter testing proceeds. This is an independent project, not an official BUSMUST release.
A native Python/PyUSB driver for BUSMUST USB CAN and CAN FD adapters. It talks directly to the device protocol described by the bmsocketcan reference; it does not load the BMAPI shared library or require SocketCAN.
The installed package registers interface="busmust" with python-can using
its plugin interface.
Standard can.Message, software filters, Notifier, logging, asynchronous
listeners, ThreadSafeBus, and software periodic transmission are supported.
Libraries accepting a can.BusABC, such as can-isotp and cantools, can use this
bus directly. See the protocol analysis for implementation
details and differences from the kernel driver.
Install
Python 3.9 or newer and a libusb backend are required:
# macOS
brew install libusb
# Debian/Ubuntu
sudo apt install libusb-1.0-0
# Install the alpha from PyPI, in your Python environment
python -m pip install --pre python-can-busmust
# Or pin this release
python -m pip install python-can-busmust==0.1.0a1
On Windows, install a libusb-compatible driver (usually WinUSB via Zadig) for the adapter's CAN interface 0 and make libusb available to PyUSB. For a composite device, keep the other interfaces intact. Switching to WinUSB may prevent the vendor application's driver from opening that interface. Consult the PyUSB installation guide for backend setup.
On Linux, grant your user access to the adapter, for example with a udev rule
SUBSYSTEM=="usb", ATTR{idVendor}=="0810", MODE="0660", TAG+="uaccess".
Reload udev rules and reconnect the adapter. Stop applications using its kernel
CAN interfaces before opening it with detach_kernel_driver=True. The default
refuses to detach an active kernel driver; an explicitly detached driver is
reattached when the last bus on that adapter shuts down.
Send and receive
import can
with can.Bus(interface="busmust", channel=0, bitrate=500_000,
fd=True, data_bitrate=2_000_000, termination=120) as bus:
bus.send(can.Message(arbitration_id=0x123, is_extended_id=False,
data=[0xDE, 0xAD, 0xBE, 0xEF]), timeout=0.5)
message = bus.recv(timeout=1.0)
print(message)
Channels are zero-based. Set bitrates, sample points, and termination to
match the physical bus. termination=None preserves the device setting;
use 0 to disable or 120 to enable its resistor.
configs = can.detect_available_configs(interfaces=["busmust"])
print(configs)
# Select an adapter explicitly when more than one is attached.
bus = can.Bus(interface="busmust", channel=0, serial="YOUR_SERIAL",
bitrate=500_000)
try:
bus.set_filters([{"can_id": 0x700, "can_mask": 0x700, "extended": False}])
print(bus.get_status())
finally:
bus.shutdown()
Separate channels on the same adapter share a USB reader and have independent receive queues. Open each channel once per process; different processes cannot share the adapter. Closing one channel leaves the others running.
with can.Bus(interface="busmust", channel=0) as first, \
can.Bus(interface="busmust", channel=1) as second:
listener = can.BufferedReader()
notifier = can.Notifier(second, [listener])
try:
task = first.send_periodic(
can.Message(arbitration_id=0x123, is_extended_id=False, data=[1]),
period=0.1,
)
print(listener.get_message(timeout=1.0))
task.stop()
finally:
notifier.stop()
This example requires a two-channel adapter and a correctly wired bus between
the channels. examples/loopback.py provides a single-channel firmware loopback
smoke test. No hardware transmissions are needed to run the automated tests.
Options
| Argument | Default | Meaning |
|---|---|---|
channel |
0 |
Zero-based physical CAN port; numeric strings accepted |
bitrate |
500_000 |
Arbitration bitrate in bit/s; whole kbit/s |
fd |
False |
Enable CAN FD alongside Classical CAN |
data_bitrate |
2_000_000 |
CAN FD data bitrate in bit/s |
sample_point |
87.5 |
Arbitration sample point in percent |
data_sample_point |
80.0 |
Data sample point in percent |
termination |
None |
Preserve, disable (0), or enable (120) termination |
serial |
None |
Exact USB serial number |
product_id |
None |
Integer USB product ID |
usb_bus, usb_address |
None |
USB location selectors returned by discovery |
listen_only |
False |
Receive without acknowledging; sending rejected |
loopback |
False |
Internal firmware loopback |
receive_own_messages |
False |
Request and deliver firmware TX echoes as is_rx=False |
non_iso |
False |
Non-ISO CAN FD mode; requires fd=True |
one_shot |
False |
Disable firmware automatic retransmission |
can_filters |
None |
Standard python-can software filters |
rx_queue_size |
10_000 |
Maximum buffered frames per channel |
detach_kernel_driver |
False |
Explicitly allow temporary USB interface detachment |
The reference protocol encodes sample points as integer percentages, so 87.5
is sent as 87. Explicit can.BitTiming/BitTimingFd configuration is unsupported.
Validation checks the wire format's range; firmware determines supported rates.
Supported device IDs
All use USB vendor ID 0810. These are the reference implementation's mappings;
listing an ID is not a claim of hardware validation.
| Generation | Product | Product ID | CAN channels |
|---|---|---|---|
| 2 | X1 / X1 Pro | F012 / F112 | 1 |
| 2 | X2 / X4 / X8 Pi | F122 / F142 / F182 | 2 / 4 / 8 |
| 2.5 | X2R / X4R | E122 / E142 | 2 / 4 |
| 3 | X1 / X2 / X4 | F013 / F023 / F043 | 1 / 2 / 4 |
| 3 | XL2 / XL4 | 0043 / 0083 | 2 / 4 |
Behavior and limits
send()waits for USB submission, not a CAN-bus acknowledgment.timeoutis in seconds;Noneuses a 1-second USB transfer timeout, and0uses a minimum 1 ms because libusb interprets zero as infinite. Partial writes are reported and never retried automatically. A timed-out transfer may have sent data; avoid blind retries for commands with side effects.- CAN FD payloads between legal DLC lengths are zero-padded to the next legal length. Receiving reports the on-wire length, e.g. 9 transmitted bytes become a 12-byte frame. RTR messages retain their requested DLC and have empty data.
- Gen3 timestamp tails provide UTC microseconds. Older devices' wrapping microsecond clocks are anchored to host epoch time on the first received frame; absolute accuracy includes USB latency. Echoes do not advance the receive timestamp tracker. Clock reset requires reopening the adapter.
- USB disconnects, malformed CAN envelopes, and queue overflow raise
can.CanOperationError. Overflow fails the affected channel rather than silently dropping frames. Reopen failed channels; reconnect all channels after a USB session failure. StopNotifierbefore shutting down its bus. - Status flags/counters are available through
get_status()andbus.state. This driver does not synthesize SocketCAN error frames or implement the kernel driver's firmware-specific bus-off recovery procedures. - Hardware TX tasks, routes, offline logging/replay, persistent configuration, PTP synchronization, and hardware acceptance-filter optimization are outside this implementation. Periodic sending and filtering run in Python.
- No physical adapter validation or throughput guarantees are claimed. Firmware echo behavior and cross-platform backend setup need hardware verification.
Development and hardware feedback
Clone the repository before running the development commands:
git clone https://github.com/madprogrammer/python-can-busmust.git
cd python-can-busmust
python -m pip install -e '.[test]'
python -m pytest
python -m build
Tests use the real python-can and PyUSB packages with a simulated USB device.
They cover protocol vectors, shared-channel lifecycle, transfer failures,
timestamps, plugin discovery, and python-can listener/periodic APIs.
For hardware reports, include the model/product ID, firmware version, OS,
Python version, bitrate/sample-point settings, and a minimal reproduction in
a GitHub issue.
Start with python examples/loopback.py, then test a correctly terminated
two-node bus. Internal loopback alone does not establish physical-bus operation.
License and provenance
GPL-2.0-or-later, see LICENSE. Protocol behavior was derived from
the GPL-licensed bmsocketcan/src/bmcan_proto.c, bmcan_usb.c,
bmcan_netdev.c, and inc/bmcan_core.h (BUSMUST, 2026), at upstream commit
70919fbc2a1be146498ca0df941d1d8a0a93c74b. A local reference clone may be kept
in the ignored bmsocketcan/ directory. Its separately licensed vendor headers are not
copied into or required by this Python distribution.
Metadata
Release files for python-can-busmust 0.1.0a1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| python_can_busmust-0.1.0a1.tar.gz | 33.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| python_can_busmust-0.1.0a1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 55.7 kB
Release files / python_can_busmust-0.1.0a1.tar.gz
| Download URL | python_can_busmust-0.1.0a1.tar.gz |
|---|---|
| Size | 33.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4d1842de50472d1c544496e82cd2f97923de0c0190aa6ec6723afa99cbae2bca
|
|
BLAKE2b-256 checksum How to use checksums |
735e2822b58d721b6ab53105e8c4f4f5a3c73b06e6ea3908ae1288c584fd13bf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / python_can_busmust-0.1.0a1-py3-none-any.whl
| Download URL | python_can_busmust-0.1.0a1-py3-none-any.whl |
|---|---|
| Size | 21.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fbcafb1464fd74791bd85b10c5e004ed3fe1b8ef212d024153aaa0b0f68d4170
|
|
BLAKE2b-256 checksum How to use checksums |
ed15771a823924bb7281e86128a230b4c74cb9f9bd73d80256b11b5988d1417e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|