From dd66a5eb63d57731da5b72d18d6d1aad2abc48c4 Mon Sep 17 00:00:00 2001 From: lonsdaleite Date: Sun, 14 Jun 2026 17:54:48 +0200 Subject: [PATCH] fix(ROG Ally): invert gyro yaw for deck-uhid target ROG Ally devices report gyro yaw with the opposite sign from what hid-steam expects when using the deck-uhid target. Enable yaw inversion only on known Ally DMI board names (RC71L, RC72LA, RC73XA, RC73YA). --- src/input/target/steam_deck.rs | 5 +++++ src/input/target/steam_deck_uhid.rs | 29 ++++++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/input/target/steam_deck.rs b/src/input/target/steam_deck.rs index 071be6a9..bb4d475a 100644 --- a/src/input/target/steam_deck.rs +++ b/src/input/target/steam_deck.rs @@ -56,6 +56,10 @@ pub struct SteamDeckConfig { pub vendor: String, pub name: String, pub product_id: ProductId, + /// Invert gyro yaw written to the Deck HID report. Enabled only on ASUS ROG + /// Ally hardware (see `GYRO_YAW_INVERT_BOARD_NAMES` in steam_deck_uhid.rs) + /// when using the deck-uhid target. + pub invert_gyro_yaw: bool, } impl Default for SteamDeckConfig { @@ -64,6 +68,7 @@ impl Default for SteamDeckConfig { vendor: "InputPlumber".to_string(), name: "Generic Steam Controller".to_string(), product_id: ProductId::Generic, + invert_gyro_yaw: false, } } } diff --git a/src/input/target/steam_deck_uhid.rs b/src/input/target/steam_deck_uhid.rs index 3bf3f2a6..63b1ace2 100644 --- a/src/input/target/steam_deck_uhid.rs +++ b/src/input/target/steam_deck_uhid.rs @@ -16,6 +16,7 @@ use uhid_virt::{Bus, CreateParams, StreamError, UHIDDevice}; use crate::{ config::CompositeDeviceConfig, + dmi::get_dmi_data, drivers::steam_deck::{ hid_report::{ PackedHapticReport, PackedInputDataReport, PackedRumbleReport, ReportType, @@ -49,6 +50,11 @@ use super::{ // a button down event. const MIN_FRAME_TIME: Duration = Duration::from_millis(80); +/// DMI `board_name` values for ASUS ROG Ally hardware that need gyro yaw sign +/// correction when emulating via deck-uhid. See `matches.dmi_data.board_name` +/// in `/usr/share/inputplumber/devices/50-rog_*.yaml`. +const GYRO_YAW_INVERT_BOARD_NAMES: &[&str] = &["RC71L", "RC72LA", "RC73XA", "RC73YA"]; + pub struct SteamDeckUhidDevice { chip_id: [u8; 15], config: SteamDeckConfig, @@ -308,7 +314,10 @@ impl SteamDeckUhidDevice { self.state.pitch = Integer::from_primitive(x as i16); } if let Some(y) = y { - self.state.yaw = Integer::from_primitive(y as i16); + self.state.yaw = Integer::from_primitive(gyro_yaw_to_hid( + y, + self.config.invert_gyro_yaw, + )); } if let Some(z) = z { self.state.roll = Integer::from_primitive(z as i16); @@ -386,7 +395,10 @@ impl SteamDeckUhidDevice { self.state.pitch = Integer::from_primitive(x as i16); } if let Some(y) = y { - self.state.yaw = Integer::from_primitive(y as i16); + self.state.yaw = Integer::from_primitive(gyro_yaw_to_hid( + y, + self.config.invert_gyro_yaw, + )); } if let Some(z) = z { self.state.roll = Integer::from_primitive(z as i16); @@ -621,6 +633,7 @@ impl TargetInputDevice for SteamDeckUhidDevice { ) -> Result<(), InputError> { let (tx, rx) = channel(); let mut device_config = self.config.clone(); + let board_name = get_dmi_data().board_name; // Spawn a task to wait for the composite device config. This is done // to prevent potential deadlocks if the composite device and target @@ -706,11 +719,16 @@ impl TargetInputDevice for SteamDeckUhidDevice { _ => {} }; + device_config.invert_gyro_yaw = + GYRO_YAW_INVERT_BOARD_NAMES.contains(&board_name.as_str()); + log::debug!( - "Found Steam Deck target config: {} {} PID: {:?}", + "Found Steam Deck target config: {} {} PID: {:?} board_name: {} invert_gyro_yaw: {}", device_config.vendor, device_config.name, device_config.product_id.to_u16(), + board_name, + device_config.invert_gyro_yaw, ); if let Err(e) = tx.send(device_config) { @@ -989,3 +1007,8 @@ impl Debug for SteamDeckUhidDevice { .finish() } } + +fn gyro_yaw_to_hid(value: f64, invert: bool) -> i16 { + let value = if invert { -value } else { value }; + value as i16 +}