feat(host/steam): M5 — fallback remap, motion rescale, degrade ladder
Keep the rich Steam inputs from silently dropping when the resolved backend
isn't the virtual hid-steam device, and fix a cross-device motion-scale bug.
- inject/proto/steam_remap.rs (new, pure + unit-tested):
* motion_wire_to_deck — the wire carries DualSense-convention units (20 LSB/
deg.s gyro, 10000 LSB/g accel — what every client capture emits), but the
Deck's hid-steam report wants 16 LSB/deg.s + 16384 LSB/g. The Deck backend
now rescales (gyro x16/20, accel x16384/10000): a real Deck<->Deck gyro/
accel correctness fix (the DualSense/DS4 backends consume the wire 1:1).
* fold_paddles + RemapConfig (PUNKTFUNK_STEAM_REMAP=paddles=drop|stickclicks|
shoulders, default drop) — the DualSense + DS4 managers fold a client's back
grips onto standard buttons rather than dropping them (those pads have no
back-button HID slot; the uinput Xbox pad already exposes them as Elite
paddles BTN_TRIGGER_HAPPY5-8).
- resolve_gamepad: a runtime degrade ladder — a UHID backend (DualSense / DS4 /
Steam Deck) on a host where /dev/uhid isn't writable now falls back to the
uinput Xbox 360 pad instead of a dead controller (the device-create would
just fail). Separate from pick_gamepad's compile-time platform check, so the
existing pick_gamepad tests are untouched.
- Delete the throwaway M0/M1 spike (src/bin/steam_uhid_spike.rs) — M2's
#[ignore]d backend test subsumes its validation, and removing it frees
steam_proto to reference steam_remap cleanly.
On-box backend test still green; workspace clippy/fmt/test green (incl. the new
steam_remap tests). Deferred as optional RemapConfig growth: gyro->mouse /
trackpad->stick synthesis on an Xbox target (no slot — documented drop today).
Not pushed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -245,8 +245,11 @@ impl SteamState {
|
||||
self.rpad_y = ((y as i32) - 32768) as i16;
|
||||
}
|
||||
RichInput::Motion { gyro, accel, .. } => {
|
||||
self.gyro = gyro;
|
||||
self.accel = accel;
|
||||
// The wire carries DualSense-convention units (what every client capture emits); the
|
||||
// Deck's hid-steam report wants 16 LSB/°·s + 16384 LSB/g, so rescale here.
|
||||
let (g, a) = super::steam_remap::motion_wire_to_deck(gyro, accel);
|
||||
self.gyro = g;
|
||||
self.accel = a;
|
||||
}
|
||||
RichInput::TouchpadEx {
|
||||
surface,
|
||||
@@ -444,13 +447,15 @@ mod tests {
|
||||
assert_ne!(s.buttons & btn::RPAD_TOUCH, 0);
|
||||
assert_eq!(s.rpad_x, 32767); // 65535-32768
|
||||
assert_eq!(s.rpad_y, -32768); // 0-32768
|
||||
// Motion is rescaled from the wire (DualSense) convention into Deck units (gyro ×16/20,
|
||||
// accel ×16384/10000) — see steam_remap::motion_wire_to_deck.
|
||||
s.apply_rich(RichInput::Motion {
|
||||
pad: 0,
|
||||
gyro: [1, 2, 3],
|
||||
accel: [4, 5, 6],
|
||||
gyro: [1000, -2000, 0],
|
||||
accel: [10000, -5000, 0],
|
||||
});
|
||||
assert_eq!(s.gyro, [1, 2, 3]);
|
||||
assert_eq!(s.accel, [4, 5, 6]);
|
||||
assert_eq!(s.gyro, [800, -1600, 0]);
|
||||
assert_eq!(s.accel, [16384, -8192, 0]);
|
||||
}
|
||||
|
||||
/// M3: the wire back-button bits map to the four Deck grips + QAM, and `TouchpadEx` routes the
|
||||
|
||||
Reference in New Issue
Block a user