feat(host/steam): shippable usbip/vhci_hcd virtual Deck + client leave-shortcuts
apple / screenshots (push) Has been cancelled
android / android (push) Has been cancelled
apple / swift (push) Has been cancelled
audit / cargo-audit (push) Has been cancelled
ci / web (push) Has been cancelled
ci / docs-site (push) Has been cancelled
ci / bench (push) Has been cancelled
ci / rust (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
flatpak / build-publish (push) Has been cancelled
release / apple (push) Has been cancelled
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
windows-host / package (push) Has been cancelled
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Has been cancelled
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Has been cancelled
windows / build (aarch64-pc-windows-msvc) (push) Has been cancelled
windows / build (x86_64-pc-windows-msvc) (push) Has been cancelled

Steam Deck pass-through (design/steam-deck-passthrough-plan.md), code-complete +
all CI checks green on Linux + adversarially reviewed; on-glass validation pending:

- usbip/`vhci_hcd` virtual Deck transport (inject/linux/steam_usbip.rs) for
  non-SteamOS hosts (Bazzite/generic) — presents a real interface-2 USB Deck so
  Steam Input promotes it. In-process vhci attach (loopback OP_REQ_IMPORT handshake
  → sysfs attach) with a bounded `usbip`-CLI fallback; detach on drop.
- Backed by a vendored, libusb-free trim of the `usbip` crate
  (crates/punktfunk-host/vendor/usbip-sim, MIT + NOTICE; host/cdc/hid + rusb/nusb
  removed; interrupt-IN paced by bInterval).
- Selection ladder raw_gadget (SteamOS fast-path) → usbip (universal) → UHID,
  with PUNKTFUNK_STEAM_USBIP / PUNKTFUNK_USBIP_ATTACH knobs.
- Shared Deck descriptors + the 0x83/0xAE feature contract + a Steam-accepted
  serial consolidated into steam_proto.rs; the raw_gadget backend reuses them.
- Linux client leave-shortcuts: Ctrl+Alt+Shift+D + holding the escape chord
  (L1+R1+Start+Select) >=1.5s end the session (short press still exits
  fullscreen); the chord state resets across sessions.

Also bundles in-progress work already staged in the tree:
- host(kwin): xdg-output logical-geometry mapping so the KWin fake_input backend
  places absolute coordinates correctly under display scaling.
- docs: design/README index entries + design/controller-only-mode.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-29 19:17:00 +00:00
parent 831b37b4b7
commit 580b1ea7a7
26 changed files with 3292 additions and 145 deletions
+26 -5
View File
@@ -1,12 +1,33 @@
# Plan: production-ready Steam Deck pass-through (client) + shippable virtual Deck on any Linux host
> **Status (2026-06-29):** architecture validated end-to-end on hardware; this is the build plan to
> ship it. Companion doc: [`steam-controller-deck-support.md`](steam-controller-deck-support.md)
> **Status (2026-06-29): BUILT — code-complete, all CI checks green on Linux (build · `clippy
> -D warnings` · `fmt` · ~270 tests), adversarially reviewed; NOT yet on-glass validated, NOT pushed.**
> Implemented in one pass:
> - **usbip/`vhci_hcd` transport** (`crates/punktfunk-host/src/inject/linux/steam_usbip.rs`) presenting
> a real interface-2 USB Deck, with **in-process vhci attach** (sysfs `OP_REQ_IMPORT` handshake) and a
> bounded `usbip`-CLI fallback. Backed by a **vendored, libusb-free trim** of the `usbip` crate
> (`crates/punktfunk-host/vendor/usbip-sim/`, MIT, see its NOTICE).
> - **Selection ladder** `raw_gadget` (SteamOS) → `usbip` (`vhci_hcd`, universal) → UHID
> (`steam_controller.rs::open_transport`); `PUNKTFUNK_STEAM_USBIP=0/1`, `PUNKTFUNK_USBIP_ATTACH=inproc|cli`.
> - **Shared Deck device contract** (captured descriptors + `0x83`/`0xAE` `feature_reply` + a
> Steam-accepted serial) consolidated into `steam_proto.rs`; the gadget now reuses it.
> - **Client leave-shortcuts**: keyboard **Ctrl+Alt+Shift+D** + controller **hold the escape chord
> (L1+R1+Start+Select) ≥1.5 s** → disconnect (short press still leaves fullscreen). Steam/QAM are NOT
> in the chord. Linux client only for now (windows/apple/android mirror is future work).
>
> **Decisions taken** (the plan's open questions): vendor-trim the crate (no libusb) ✓; in-process
> attach primary + CLI fallback ✓; escalate the existing escape chord (long-hold) ✓; keep BOTH
> `raw_gadget` (SteamOS fast-path) and usbip (universal) behind the transport ladder ✓.
>
> **Remaining = §6 on-glass validation** (Bazzite `192.168.1.41` + Deck `192.168.1.253`): confirm the
> in-process usbip attach promotes the Deck in game mode (Steam + QAM reach the game-mode UI), the
> raw_gadget path still works on SteamOS (regression), and the leave-shortcuts fire. The dev box has no
> Steam + no root, so this could not be run here.
>
> Companion doc: [`steam-controller-deck-support.md`](steam-controller-deck-support.md)
> (the virtual-Deck design + §11 the interface-2 / gadget story). The virtual Steam Deck that Steam
> Input promotes is **already built, hardware-validated, and default-on for SteamOS**
> (`raw_gadget`/`dummy_hcd`, glass-confirmed in-game on a real Deck). What remains is (a) exact
> Deck pass-through from the Linux *client* incl. the Steam + QAM buttons, (b) a **shippable** virtual
> Deck on non-SteamOS Linux hosts (Bazzite etc.) via **usbip/`vhci_hcd`**, and (c) a leave-shortcut.
> (`raw_gadget`/`dummy_hcd`, glass-confirmed in-game on a real Deck).
## Goal