Jiajie Chen d5774284bf host: fix nusb transfers and pass through SuperSpeed descriptors
The nusb host path panicked on every non-empty bulk/interrupt OUT transfer:
endpoint.allocate() returns a Buffer whose len is 0, so copy_from_slice()
wrote into an empty slice. Use extend_from_slice() instead.

nusb also rejects IN transfers whose length is not a multiple of the endpoint
max packet size; a 36-byte SCSI INQUIRY on a 512-byte bulk endpoint made
usb-storage repeat resets. Round the request up and truncate the completion
back to the requested length.

While here, fix descriptor passthrough for USB 3 devices:
- encode bcdUSB/bcdDevice and the device qualifier as real BCD, keeping the
  sub-minor digit
- pass through endpoint extra descriptors (SuperSpeed endpoint companion, UAS
  pipe usage) so the client sees the real endpoint capabilities
- pass through the BOS descriptor so the SuperSpeed capability and its LPM
  latencies are not lost
- claim interfaces in the rusb backend; usbfs logged "did not claim interface"

Extend the QEMU passthrough test with a SuperSpeed bulk-only device
(usb-bot) for the data path, in addition to the SuperSpeed UAS device (which
can only be enumerated because vhci-hcd lacks streams) and the high-speed
usb-storage device. The test now writes and reads back a block through both
bulk-only devices with the nusb and rusb backends, and fails if the client
reports missing endpoint companions or LPM information.

Fixes #66
2026-11-09 15:47:13 +08:00
2026-08-13 09:28:02 +08:00
2025-12-25 20:58:48 +08:00
2022-12-05 17:39:37 +08:00

usbip

Coverage Status crates.io

A Rust library to run a USB/IP server to simulate USB devices and share real USB devices over a network.

What is USB/IP?

USB/IP is a network protocol that allows USB devices to be shared between computers over a network. It enables:

  • Device simulation: Create virtual USB devices that can be accessed remotely
  • Device sharing: Share physical USB devices from one machine to another
  • Cross-platform: Works across different operating systems (Linux, etc.)

Installation

Prerequisites

Install Rust from the official documentation.

Building from source

git clone https://github.com/jiegec/usbip.git
cd usbip
cargo build --release

How to use

Examples

The examples/ directory contains four example programs:

  1. hid_keyboard: Simulate a HID keyboard that types something every second
  2. cdc_acm_serial: Simulate a CDC ACM serial device that receives a character every second
  3. host: Act as a USB/IP server, sharing physical devices from the host machine to remote clients
  4. demo: Simulate a HID keyboard and a CDC ACM serial device together (used by the QEMU test)

Running an example

cargo run --example hid_keyboard

Connecting from a USB/IP client

On the client machine (e.g. Linux with USB/IP support):

# List available devices
usbip list -r $remote_ip

# Attach to a device
usbip attach -r $remote_ip -b $bus_id

QEMU end-to-end test

The simulated devices can be verified against a real Linux kernel booted under QEMU. The test assembles a minimal initramfs (busybox + usbip tool + the demo server + the kernel's usbip/vhci/cdc/hid modules), boots it, then uses vhci-hcd to attach the simulated keyboard and serial device. Inside the guest it confirms the serial port emits 'a' and that the keyboard generates a KEY_1 input event.

Run it locally (requires qemu-system-x86, a static busybox, cpio, and the usbip tool):

./scripts/qemu/run-qemu-test.sh --build --dump-log

It runs under KVM when available and falls back to QEMU TCG otherwise. The kernel, vmlinuz and module tree used can be overridden via the KERNEL, VMLINUZ and MODTREE environment variables (useful to reproduce a CI kernel locally).

In CI (scripts/qemu + .github/workflows/qemu.yml) the Ubuntu generic kernel is installed and booted. This matters because the GitHub runner's Azure kernel has CONFIG_USB_HID disabled, so it cannot enumerate a simulated USB keyboard; the generic kernel ships the hid/hid-generic/usbhid modules which are loaded in the guest so both the serial device and the keyboard are verified.

QEMU host-passthrough test

The host example is tested the same way, with emulated devices: a SuperSpeed UAS device (usb-uas) and a SuperSpeed bulk-only device (usb-bot) on an emulated xHCI controller, plus a high-speed usb-storage device on an emulated EHCI controller. Inside the guest the example exports them over USB/IP -- first with the nusb backend, then with libusb/rusb -- and the guest attaches them back through vhci-hcd. The test checks that each virtual copy enumerates at the same speed, with the same bMaxPacketSize0 (the exponent 9, i.e. 512 bytes, at SuperSpeed) and the same bcdUSB as the real device, and it writes and reads back a block through both bulk-only devices, exercising bulk IN/OUT and the SuperSpeed endpoint companion descriptors. The UAS device is only enumerated: vhci-hcd does not support streams, which the Linux UAS driver requires at SuperSpeed.

./scripts/qemu/run-qemu-passthrough-test.sh --build --dump-log

License

MIT License - see LICENSE file for details.

Description
A Rust library to run a USB/IP server
Readme MIT 512 KiB
Languages
Rust 82.9%
Shell 17.1%