Files
punktfunk/packaging/linux/steam-deck-gadget/usbip-poc/README.md
T
enricobuehler 4f0b4aa68f docs(steam): production plan for Deck client pass-through + shippable usbip host
Write design/steam-deck-passthrough-plan.md — the build plan to ship exact Steam
Deck pass-through from the Linux client (incl. the Steam + QAM buttons) plus a
virtual Deck on any Linux host. Key validated facts captured so the next session
doesn't re-investigate:

- Client capture is ALREADY correct: SDL3 maps Steam->Guide, QAM->Misc1; the
  client forwards BTN_GUIDE/BTN_MISC1; the host maps them to btn::STEAM/btn::QAM.
  Only precondition: Steam Input disabled on the client (the Decky UX).
- Shippable host transport = usbip + vhci_hcd (in-tree + signed everywhere, no
  module build, no MOK) — PROVEN on Bazzite: Steam promotes the usbip interface-2
  Deck (XInput slot + X-Box pad), identical to raw_gadget on SteamOS.
- Build steps: refactor steam_gadget.rs into shared Deck-logic + a transport
  trait; add the usbip transport (vendor-trim the usbip crate to drop rusb/libusb,
  in-process vhci attach); transport-select raw_gadget->usbip->UHID/DualSense;
  client leave-shortcut (controller chord + Ctrl+Alt+Shift+D); serial polish.

Also checks in the working usbip Deck PoC (packaging/linux/steam-deck-gadget/
usbip-poc/) for the next session to build on. Not pushed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 19:17:37 +00:00

1.6 KiB

usbip Deck PoC — the shippable virtual Deck for non-SteamOS Linux hosts

Presents a real 3-interface USB Steam Deck (28DE:1205, controller on interface 2) over the usbip protocol via the usbip crate, so vhci_hcd can attach it locally — the Secure-Boot-clean, universal alternative to dummy_hcd+raw_gadget (which Bazzite/Fedora don't ship). Reuses the exact captured descriptors + feature contract from crates/punktfunk-host/src/inject/linux/steam_gadget.rs.

Validated live on Bazzite (2026-06-29): vhci_hcd enumerates it, hid-steam binds it + reads the serial + makes the Steam Deck evdevs, stable (1 connect / 0 disconnect), and Steam promotes it (Interface: 2 … reserving XInput slot 1, X-Box pad emitted) — identical to the gadget on SteamOS.

cargo build --release           # glibc; needs GLIBC_2.34 (Bazzite has 2.42), libusb present/vendored
# on the host (root for the last two):
sudo modprobe vhci_hcd
./usbip-deck-poc pressa &        # the usbip server (runs as a normal user, TCP 127.0.0.1:3240)
sudo usbip attach -r 127.0.0.1 -b 0-0-0

See design/steam-deck-passthrough-plan.md for the production build plan (vendor-trim the crate to drop the rusb/libusb dep; in-process vhci_hcd attach to avoid the usbip CLI; transport-select raw_gadgetusbip→UHID). usbip crate API: a custom UsbInterfaceHandlerget_class_specific_descriptor() = the 9-byte HID descriptor; handle_urb() dispatches EP0 GET_DESCRIPTOR(report) / HID GET_REPORT(=feature_reply) / SET_REPORT, and returns the 64-byte state report on the interrupt-IN endpoint.