USBIP - Python library
Create virtual USB devices and write USB host drivers for them, in pure Python.
USB/IP is a protocol born in the Linux kernel. Its intended job is to export a computer's real USB devices, so another machine can use them over the network. It has been in the mainline kernel for years.
But the protocol has a second, unintended power: the traffic on the wire is just USB requests over TCP, so an ordinary program can answer those requests and become a USB device - no hardware, no kernel code. The kernel side always existed; a standard library for this side did not. This library fills that gap:
- Device API (
usbip.device,usbip.function) - your program is a USB device: keyboard, serial port, disk, webcam, sound card, or anything you define yourself. - Host API (
usbip.open,usbip.attach) - your program talks to such a device, shaped like libusb, with no kernel driver and no root.
See API reference and guide for more details.
Use cases
- Test automation - exercise a host application against a scripted USB device in CI, with no hardware on the runner.
- AI in the loop - an agent can build, plug, probe and fix a USB device or a host application entirely in software.
- Reverse engineering - re-create a device from a captured trace and refine it until the original driver accepts it.
- Develop before the hardware exists - write and test the host software against a virtual model of the device.
- Emulate old or discontinued hardware whose driver you still need to run.
- Learn USB by building devices and watching every transfer in Wireshark
(set
USBIP_PCAPNG=1on any program using this library).
Setup
pip install usbip
Requires Python 3.8+ and nothing else. The import name is usbip.
Creating a virtual device
A complete device - one vendor interface, two bulk endpoints, echoing back whatever the host sends. WinUSB is advertised so Windows binds a driver automatically:
from usbip import In, Interface, Out, USBDevice
from usbip.transport import USBIP
class VendorBulk(Interface):
bInterfaceClass = 0xFF # vendor-specific
bulk_out = Out(0x01, "bulk", mps=64) # host -> device
bulk_in = In(0x81, "bulk", mps=64) # device -> host
dev = USBDevice(0x1209, 0x0004, manufacturer="USB over IP", product="My 1st Device", serial="0004")
fn = dev.add(VendorBulk())
dev.enable_winusb() # Skip driver install on Windows
transport = USBIP("0.0.0.0", 3240)
dev.plug(via=transport) # serve and return
while True: # echo everything back
data = fn.bulk_out.read(timeout=1.0)
if data:
fn.bulk_in.write(data)
Run it with python3 my_device.py.
Attaching it
The script now serves the device on TCP port 3240 and waits. Nothing appears yet: your program is the USB/IP server, and the operating system is the client that imports the device. That import step is the only part that differs per OS.
On Linux, the client is already in the kernel:
sudo modprobe vhci-hcd # once per boot
sudo usbip attach -r 127.0.0.1 -b 1-1
lsusb # Check if your device is listed
(Detach with sudo usbip detach -p 00.)
On Windows, install usbip-win2 and attach with its GUI:
or from a terminal: usbip.exe attach -r <ip> -b 1-1. Because the device above
advertises WinUSB, no driver hunt follows - it is immediately usable from libusb apps.
On an OS without a USB/IP client (macOS has none in-box), use USBIP for microcontrollers: a small board that attaches over the network and re-presents the device on a real USB port, which any machine sees as plain USB.
A COM port in a few lines
Device classes are built in, so common devices take almost no code. A serial port that echoes what you type:
import time
from usbip.classes.device import CDCACM
from usbip.device import USBDevice
def on_rx(port, data):
port.write(bytes(data)) # echo back to the host
dev = USBDevice(0x1209, 0x0001, product="My Serial Port")
dev.add(CDCACM(on_rx=on_rx))
dev.plug() # local USB/IP by default
while True:
time.sleep(3600) # the class handles everything
Attach it and a serial port appears - /dev/ttyACM0 on Linux, a COMx port on
Windows; open it with any terminal program. The other built-in classes are HID
(keyboard/mouse/raw), MSC (disk), UVC (webcam), UAC (sound card), DFU
(firmware upgrade), MTP (file transfer) and Bluetooth (HCI dongle) - see
examples/ for a runnable program per class (some need
pip install "usbip[examples]"), and the
guide for what each one turns into
per OS.
Writing a host driver
The host API is shaped like libusb, so the learning curve is minimal. It imports a device and drives it from your own process - no kernel client, no root, works on any OS including macOS:
import usbip
with usbip.open(0x1209, 0x0004) as dev: # local server; usbip.attach() for remote
dev.bulk_out(0x01, b"hello")
print(dev.bulk_in(0x81, 64)) # -> b"hello" (the echo device above)
usbip.use(usbip.Loopback()) runs a device and a driver in the same process with no
network at all - handy for tests.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file usbip-0.7.0.tar.gz.
File metadata
- Download URL: usbip-0.7.0.tar.gz
- Upload date:
- Size: 92.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e3454896f19442b0942c84cec48ff7f8a02a4486c4aa73d03732ab105e928951
|
|
| MD5 |
aefe5e5a631b109c2da50a49fdfd2bd7
|
|
| BLAKE2b-256 |
a01af05bc94f6c080d43fc56a4483a745b2ae843766981a63344685e2f1c0b1f
|
Provenance
The following attestation bundles were made for usbip-0.7.0.tar.gz:
Publisher:
publish.yml on jabezwinston/usbip-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
usbip-0.7.0.tar.gz -
Subject digest:
e3454896f19442b0942c84cec48ff7f8a02a4486c4aa73d03732ab105e928951 - Sigstore transparency entry: 2489422080
- Sigstore integration time:
-
Permalink:
jabezwinston/usbip-python@34d6fac0eb369e4a6238b4719036ab39743a9a93 -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/jabezwinston
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@34d6fac0eb369e4a6238b4719036ab39743a9a93 -
Trigger Event:
push
-
Statement type:
File details
Details for the file usbip-0.7.0-py3-none-any.whl.
File metadata
- Download URL: usbip-0.7.0-py3-none-any.whl
- Upload date:
- Size: 103.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
79aeff1cce47dc79b20d434266a0c80c7111a7e352af753cc81a203c4d439ef2
|
|
| MD5 |
a2d882106b20767bf0436351727a0cbd
|
|
| BLAKE2b-256 |
50417255559f6e0f4823294095a364bd2c962b1d8aeccf7e72940dc29695c38a
|
Provenance
The following attestation bundles were made for usbip-0.7.0-py3-none-any.whl:
Publisher:
publish.yml on jabezwinston/usbip-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
usbip-0.7.0-py3-none-any.whl -
Subject digest:
79aeff1cce47dc79b20d434266a0c80c7111a7e352af753cc81a203c4d439ef2 - Sigstore transparency entry: 2489422214
- Sigstore integration time:
-
Permalink:
jabezwinston/usbip-python@34d6fac0eb369e4a6238b4719036ab39743a9a93 -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/jabezwinston
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@34d6fac0eb369e4a6238b4719036ab39743a9a93 -
Trigger Event:
push
-
Statement type: