When a real USB device stalls an endpoint, the VM sends
CLEAR_FEATURE(ENDPOINT_HALT) to recover. Previously this was a no-op,
leaving the endpoint permanently stalled and causing the guest to hang.
Now the CLEAR_FEATURE handler in device.rs finds the interface that owns
the stalled endpoint and calls clear_halt on its handler. For host
passthrough this forwards to nusb's new Interface::clear_halt; for
simulated devices it remains a no-op.
Fixes YubiKey (and other CCID devices) hanging after endpoint stall
during passthrough.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The client was passing devid=0 to vhci_hcd during attach, but the
server computes expected_devid from (bus_num << 16) | dev_num. This
caused the server's devid validation (added in 76f5134) to reject
every URB from the kernel client.
Three fixes for the UAC1 loopback test device:
- Add CS_ENDPOINT descriptors (type 0x25) after audio streaming isochronous
endpoints. The Linux snd-usb-audio driver requires these to recognize the
device. Added class_specific_descriptor field to UsbEndpoint (mirroring the
existing field on UsbInterface) and emit it in the config descriptor builder.
- Remove the 30s URB read timeout from handle_urb_loop. The connection lifetime
is managed by the kernel (vhci_hcd closes the socket on device detach). An
application-level timeout killed healthy idle devices. Fixed tests to properly
shutdown() write halves instead of relying on the timeout.
- Fix ISO packet descriptor byte order from big-endian to little-endian. The
USB/IP protocol uses big-endian for header fields but little-endian for ISO
descriptors (matching the kernel's usbip_pack_iso using cpu_to_le32). With
big-endian, field values like length=192 were byte-swapped to ~3GB, corrupting
isochronous audio streams.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a simulated USB Audio Class 1 loopback device for testing
isochronous transfers. Audio sent to the playback OUT endpoint
(48kHz/16-bit/stereo) is looped back to the capture IN endpoint.
- Add UsbEndpoint::transfer_type() masking bmAttributes to bits 0-1,
fixing dispatch for isochronous endpoints with sync-type sub-bits
- Update all endpoint attribute dispatch sites across the library
- Add UacLoopbackBuffer, UacControlHandler, UacStreamOutHandler,
UacStreamInHandler in lib/src/uac.rs
- Add build_uac_loopback_device() builder function
- Add `test_uac connect` CLI subcommand
- Add 10 unit tests covering buffer, descriptors, and handler behavior
- Add design spec and implementation plan docs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Support connecting to guests via Firecracker/Cloud-Hypervisor's Unix
domain socket vsock proxy. The host opens the VMM's socket file,
performs a CONNECT/OK text handshake, then uses the stream for USB/IP.
New address format: fc-vsock:/path/to/socket:<port>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update nusb to c1380673 which allows multiple IsoEndpoint instances per
address, enabling concurrent URB submission from separate threads.
Change UsbInterfaceHandler trait methods from &mut self to &self and
replace Arc<Mutex<Box<dyn Handler>>> with Arc<dyn Handler>. This
removes the serialization bottleneck where the handler mutex was held
for the entire USB transfer duration, causing ISO audio to play at
~67% speed.
Handlers needing interior mutability (HID, CDC) now use Mutex on
individual fields. Passthrough handlers already used Arc<Mutex<>>
internally and need no changes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three fixes for host device passthrough:
1. OUT transfers now report actual_length = transfer_buffer_length instead
of 0. The kernel needs to know how many bytes were consumed; returning 0
caused bulk writes (critical for mass storage) to appear as failures.
2. BCD version encoding (bcdUSB, bcdDevice) now properly reconstructs the
full 2-byte BCD value from the Version struct's nibble fields. Previously,
the minor field (a single nibble) was written as a full byte, corrupting
values like USB 1.1 (0x0110 → 0x0101).
3. USB transfer handlers (nusb) now propagate errors instead of silently
returning empty success responses. Failed control_in, bulk, and interrupt
transfers were falling through to Ok(UrbResponse::default()), making the
kernel think transfers succeeded with 0 bytes of data.
Also sets usb_version and dev_num from the actual device in build_usb_device.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add IsoPacketDescriptor, UrbRequest, and UrbResponse types to the
protocol layer. Rewrite handle_urb_loop to a concurrent architecture
with pipelining for improved throughput. Replace interfaces vec with
InterfaceState to track alternate settings.
Implement isochronous transfer support in the nusb host handler with
structured ISO packet descriptor parsing and serialization. Switch to
ISO-capable nusb fork. Add IsoLoopbackHandler test fixture and ISO
transfer tests.
Fix host device passthrough: detach kernel drivers before claiming
interfaces, use real EP0 max packet size, forward SET_CONFIGURATION
to device, map nusb Speed enum to Linux kernel values, and use
extend_from_slice for OUT transfer buffers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add TCP address types, parsing, and connect/listen functions alongside
the existing vsock transport. Update all CLI commands (client listen,
host connect, test_hid connect) to support both vsock: and tcp:
address prefixes. Add hostname resolution for TCP connections.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace all unimplemented!() panics with proper error returns across
URB, HID, and host handlers. Replace assert!() panics with error
returns in response serialization and string pool. Validate direction
field at runtime instead of only in debug builds.
Add allocation bounds checks to read_from_socket, read timeout to
URB loop, and clamp transfer_buffer_length to u16::MAX for control
transfers. Use correct USB/IP error status codes in submit failure
responses. Propagate control OUT transfer errors instead of swallowing
them. Fix compilation errors and doc comment copy-paste issues.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Convert to cargo workspace with lib/ and cli/ crates. Add Nix flake
for building and development. Extract handle_urb_loop and add
read_urb_command to the library for CLI consumption.
Implement the usbip-rs CLI binary with clap subcommands:
- client listen: accept incoming connections via vhci_hcd sysfs
- host connect: passthrough real USB devices via nusb
- test_hid connect: export a simulated HID keyboard for testing
Add vsock transport layer and vhci_hcd sysfs interaction module.
Apply rustfmt formatting project-wide and add rustfmt/clippy to devShell.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>