Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/input/target/steam_deck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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,
}
}
}
Expand Down
29 changes: 26 additions & 3 deletions src/input/target/steam_deck_uhid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
}