From 165a42fcc9a472bba40cc91b63170bab80adf0c2 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Sat, 15 Aug 2026 20:10:53 +0200 Subject: [PATCH] fix(host/udev): the virtual Steam Controller 2's hidraw node was root-only, so Steam never saw it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Field report: the Android client captures a wired SC2 and says so ("captured — streams as-is"), the host attaches the virtual pad over usbip cleanly, and Steam's Settings → Controller → Connected Controllers is empty. Nothing works in game mode. The host's own log names the culprit by what is missing from it. Every kernel control transfer is there — device/config/string descriptors, SET_CONFIGURATION, SET_IDLE, and a GET of the 372-byte report descriptor — and there is not one SET_REPORT and not one `answering feature GET`. The kernel enumerated the controller; Steam never opened it. 60-punktfunk.rules grants hidraw access per product id, and it lists what the host used to mint: the Sony pads, the Switch Pro, the Deck (28DE:1205) and the classic Steam Controller (28DE:1102). The SC2 identities `steam_backend_product` mints — wired 28DE:1302 and Puck 28DE:1304 — were never added, so their nodes stayed root-only while the host runs as a user service. For any other pad that would be a degradation. For this one it is total: no kernel driver claims the PID (mainline hid-steam stops at the Deck) and the state reports ride a vendor collection, so there is no evdev node either. Steam is the only consumer there is, and a hidraw node it cannot open is not a degraded controller, it is no controller. Leaning on the distro's steam-devices rules doesn't save it — those lists are per-PID and the SC2 shipped in 2026, so a host whose copy predates it grants nothing. Add both identities in the same two forms the Deck uses (KERNELS for the UHID shape, ATTRS for the usbip/gadget one), and document the symptom in troubleshooting with the hand-rollable rule for hosts on an older package, the one-line-plus-one-absence log signature, and a note that the trackpads needing Steam to act as a mouse is lizard mode being off on purpose, not a fault. Single source of truth: every distro installs this file (the NixOS module takes it from the package via services.udev.packages), so no per-packaging change is needed. --- docs-site/content/docs/troubleshooting.md | 40 +++++++++++++++++++++++ scripts/60-punktfunk.rules | 13 ++++++++ 2 files changed, 53 insertions(+) diff --git a/docs-site/content/docs/troubleshooting.md b/docs-site/content/docs/troubleshooting.md index 9c5fa696..b7995a16 100644 --- a/docs-site/content/docs/troubleshooting.md +++ b/docs-site/content/docs/troubleshooting.md @@ -350,6 +350,46 @@ It is not only the pad, though: the same group authorizes the helper that stops for a managed **Gaming Mode** takeover, so on a box that autologins into Game Mode, skipping it also costs you [the takeover](#game-mode-black-screen-on-connect-or-the-stream-is-stuck-at-the-boxs-resolution). +## A Steam Controller 2 is captured, but Steam's controller list stays empty + +The client says everything is fine — the Controllers screen shows **Steam Controller 2, captured, +streams as-is** — and on the host Steam's **Settings → Controller → Connected Controllers** has +nothing in it. Buttons do nothing in games, and the trackpads don't move the pointer. + +Unlike every other pad Punktfunk presents, the Steam Controller 2 has exactly one consumer: +**Steam**. No kernel driver claims its product id — mainline `hid-steam` stops at the Deck — and its +state reports ride a vendor collection, so the pad produces no evdev node for anything else to read. +If Steam can't open its `hidraw` node, you don't get a degraded controller, you get no controller. + +The node is root-only until a udev rule says otherwise, and distro `steam-devices` rule sets are +per-product-id: a host whose copy predates the SC2 (it shipped in 2026) never grants it. Punktfunk +ships the rule itself from 0.30.0 on. On an older host, add it by hand: + +```sh +sudo tee /etc/udev/rules.d/61-punktfunk-sc2.rules >/dev/null <<'EOF' +KERNEL=="hidraw*", KERNELS=="*28DE:1302*", GROUP="input", MODE="0660", TAG+="uaccess" +KERNEL=="hidraw*", KERNELS=="*28DE:1304*", GROUP="input", MODE="0660", TAG+="uaccess" +KERNEL=="hidraw*", ATTRS{idVendor}=="28de", ATTRS{idProduct}=="1302", GROUP="input", MODE="0660", TAG+="uaccess" +KERNEL=="hidraw*", ATTRS{idVendor}=="28de", ATTRS{idProduct}=="1304", GROUP="input", MODE="0660", TAG+="uaccess" +EOF +sudo udevadm control --reload-rules && sudo udevadm trigger +``` + +Then end the session and reconnect, so the pad re-enumerates under the new rule. `1302` is the wired +controller and `1304` the Puck dongle — the two identities the host presents. + +To confirm this is what you're hitting, look at the host log for one line and one absence: the pad +attaching (`attached via usbip`), and **no** `answering feature GET` afterwards. That pair means the +kernel enumerated the controller and Steam never opened it. The everything-else checks — the +`punktfunk` group, `vhci_hcd`, the `attach` node — are in +[the virtual Steam Deck section](#the-pad-works-but-arrives-as-an-xbox-360-controller-instead-of-a-steam-deck) +above; if `attached via usbip` is missing from the log entirely, start there instead. + +One more thing that is *not* a bug: with Punktfunk capturing, the trackpads stop working as a mouse +whenever Steam isn't running. Punktfunk turns the controller's built-in mouse-and-keyboard emulation +("lizard mode") off so it can read the full report stream, so on this pad Steam is what makes the +trackpads a pointer — exactly as on a Steam Deck in desktop mode. + ## Copy and paste between host and client does nothing The shared clipboard needs **two** separate switches on, and turning on only one looks exactly like diff --git a/scripts/60-punktfunk.rules b/scripts/60-punktfunk.rules index de9a8595..8259b5d2 100644 --- a/scripts/60-punktfunk.rules +++ b/scripts/60-punktfunk.rules @@ -48,3 +48,16 @@ KERNEL=="hidraw*", KERNELS=="*28DE:1205*", GROUP="input", MODE="0660", TAG+="uac KERNEL=="hidraw*", KERNELS=="*28DE:1102*", GROUP="input", MODE="0660", TAG+="uaccess" KERNEL=="hidraw*", ATTRS{idVendor}=="28de", ATTRS{idProduct}=="1205", GROUP="input", MODE="0660", TAG+="uaccess" KERNEL=="hidraw*", ATTRS{idVendor}=="28de", ATTRS{idProduct}=="1102", GROUP="input", MODE="0660", TAG+="uaccess" +# Steam Controller 2 (Triton): wired 28DE:1302 and the Puck dongle 28DE:1304 — the two identities +# `steam_backend_product` mints. Steam is the ONLY consumer of this pad: no kernel driver claims +# the PID (mainline hid-steam stops at the Deck), so its state reports ride a vendor collection +# that yields no evdev node at all. A hidraw node Steam cannot open is therefore not a degraded +# controller, it is no controller — the pad enumerates, the kernel reads its report descriptor, +# and Steam's own device list stays empty (field report 2026-08-15: usbip attached cleanly, the +# log showed every kernel control transfer and not one SET_REPORT from Steam). +# Relying on the distro's steam-devices rules is not enough for a pad that shipped in 2026: those +# lists are per-PID and a host whose copy predates the SC2 leaves the node root-only. +KERNEL=="hidraw*", KERNELS=="*28DE:1302*", GROUP="input", MODE="0660", TAG+="uaccess" +KERNEL=="hidraw*", KERNELS=="*28DE:1304*", GROUP="input", MODE="0660", TAG+="uaccess" +KERNEL=="hidraw*", ATTRS{idVendor}=="28de", ATTRS{idProduct}=="1302", GROUP="input", MODE="0660", TAG+="uaccess" +KERNEL=="hidraw*", ATTRS{idVendor}=="28de", ATTRS{idProduct}=="1304", GROUP="input", MODE="0660", TAG+="uaccess" -- 2.54.0