docs(steam): gadget PoC — interface 2 PROVEN (Steam opens + XInput-reserves it)
On the Deck (which ships dummy_hcd + raw_gadget + configfs f_hid), a pure-shell configfs gadget stood up a real 3-interface USB Deck (kbd=0/mouse=1/controller=2, 28de:1205) on a dummy_hcd loopback UDC. hid-steam bound all 3 interfaces, and crucially Steam PROMOTED the interface-2 controller: "Local Device Found ... Interface: 2 ... Steam controller device opened for index 14 ... Steam Controller reserving XInput slot 1" — exactly where the interface -1 UHID Deck was filtered. It then failed only at feature-report exchange (f_hid can't serve HID GET_REPORT: "steam_send_report: error -32", "couldn't get controller details ... zombie controller"), and no gamepad evdev formed for the same reason. So interface 2 is necessary AND sufficient for Steam to open+XInput-reserve the Deck; the remaining piece is serving feature/output reports, which raw_gadget can (full control, like UHID). Next: a raw_gadget 3-interface Deck emulator. Doc §11. Not pushed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -732,3 +732,29 @@ configfs) or a kernel USB bus driver — a much larger, less portable lift, and
|
||||
1. A **live SDL/non-Steam game** on a Linux host actually consuming the virtual Deck's grips/trackpads
|
||||
(the path that *does* work) — needs a real Deck/SC client + a Steam-Input-disabled consumer.
|
||||
2. The **Moonlight paddle regression** from the M3 xpad-map change (stock paddle client → host).
|
||||
|
||||
### Gadget PoC — interface 2 is PROVEN on the Deck (2026-06-29)
|
||||
|
||||
SteamOS ships every primitive (`CONFIG_USB_DUMMY_HCD=m`, `CONFIG_USB_RAW_GADGET=m`,
|
||||
`CONFIG_USB_CONFIGFS_F_HID=y`), so the gadget path is testable on the Deck itself with no
|
||||
module-building. A pure-shell **configfs gadget** (`deck_gadget_up.sh`) stood up a real 3-interface
|
||||
USB Deck on a `dummy_hcd` loopback UDC — keyboard = interface 0, mouse = 1, **controller = interface
|
||||
2** (`STEAMDECK_RDESC`), `28DE:1205`. Result:
|
||||
|
||||
- It enumerates as a real USB device (`lsusb: 28de:1205 Valve Software Steam Deck Controller`) and
|
||||
`hid-steam` binds **all three** interfaces — the controller on `bInterfaceNumber=02`.
|
||||
- **Steam promoted it:** `Local Device Found … Interface: 2 … !! Steam controller device opened for
|
||||
index 14 … Steam Controller reserving XInput slot 1`. *This is the proof: a device on interface 2
|
||||
IS opened + XInput-reserved by Steam, where the interface-`-1` UHID device was filtered out.*
|
||||
- It then failed at the next step — `f_hid` can't serve HID **feature reports** (`hid-steam:
|
||||
steam_send_report: error -32 (ae 16 01)` → serial `XXXXXXXXXX`; Steam: `couldn't get controller
|
||||
details … GetControllerInfo failed … Disconnecting zombie controller`). No gamepad evdev was
|
||||
created either, for the same reason (hid-steam can't complete Deck init without the feature/output
|
||||
channel).
|
||||
|
||||
**Conclusion: the wall is fully characterised and climbable.** Interface 2 is necessary *and*
|
||||
sufficient for Steam to open + XInput-reserve the Deck; the only remaining piece is serving the
|
||||
HID feature/output reports, which `f_hid` can't but **`raw_gadget` can** (userspace handles every
|
||||
control transfer, exactly like the UHID path). Next: a `raw_gadget` userspace emulator of the
|
||||
3-interface Deck (controller on interface 2) that answers the serial/attribute/settings feature
|
||||
reports + streams the 64-byte state report — then re-test hid-steam gamepad evdev + Steam promotion.
|
||||
|
||||
Reference in New Issue
Block a user