From 429fef5b0d07d8eba3986ff1f9003964c3887f32 Mon Sep 17 00:00:00 2001 From: honjow Date: Fri, 27 Feb 2026 04:44:49 +0800 Subject: [PATCH 1/3] fix(horipad_steam): reply to GET_REPORT requests to prevent UHID timeout Without a reply, each GET_REPORT request times out after ~5 seconds, causing significant delays when Steam probes the device during controller enumeration. --- src/input/target/horipad_steam.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/input/target/horipad_steam.rs b/src/input/target/horipad_steam.rs index c291c42f..d127f2c0 100644 --- a/src/input/target/horipad_steam.rs +++ b/src/input/target/horipad_steam.rs @@ -304,13 +304,22 @@ impl HoripadSteamDevice { Ok(vec![]) } - /// Handle [OutputEvent::GetReport] events from the HIDRAW device + /// Handle [OutputEvent::GetReport] events from the HIDRAW device. + /// Reply immediately to prevent UHID GET_REPORT timeout (~5s per request) + /// which would cause long delays when consumers like Steam probe the device. fn handle_get_report( &mut self, - _id: u32, - _report_number: u8, + id: u32, + report_number: u8, _report_type: uhid_virt::ReportType, ) -> Result<(), Box> { + log::debug!( + "Received GetReport request: id: {id}, report_number: {report_number}" + ); + if let Err(e) = self.device.write_get_report_reply(id, 1, vec![]) { + log::warn!("Failed to write get report reply: {:?}", e); + return Err(e.to_string().into()); + } Ok(()) } } From 9927346e3a00de718caaa45e4cf3898a5d616d47 Mon Sep 17 00:00:00 2001 From: honjow Date: Fri, 6 Mar 2026 17:33:42 +0800 Subject: [PATCH 2/3] fix(horipad-steam): swap yaw/roll field names in HID report struct According to SDL_hidapi_steam_hori.c lines 329-330, bytes 12-13 are read as yaw (imu_data[1]) and bytes 14-15 are read as roll (imu_data[2]). The previous field names had them reversed. https://github.com/libsdl-org/SDL/blob/main/src/joystick/hidapi/SDL_hidapi_steam_hori.c#L329-L330 --- src/drivers/horipad_steam/hid_report.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/drivers/horipad_steam/hid_report.rs b/src/drivers/horipad_steam/hid_report.rs index 7692b4ac..58588e55 100644 --- a/src/drivers/horipad_steam/hid_report.rs +++ b/src/drivers/horipad_steam/hid_report.rs @@ -135,9 +135,9 @@ pub struct PackedInputDataReport { // bytes 12-17 // Gyro #[packed_field(bytes = "12..=13", endian = "lsb")] - pub roll: Integer>, - #[packed_field(bytes = "14..=15", endian = "lsb")] pub yaw: Integer>, + #[packed_field(bytes = "14..=15", endian = "lsb")] + pub roll: Integer>, #[packed_field(bytes = "16..=17", endian = "lsb")] pub pitch: Integer>, // bytes 18-23 // Accelerometer @@ -187,8 +187,8 @@ impl Default for PackedInputDataReport { rt_analog: 0, lt_analog: 0, tick: Integer::from_primitive(0), - roll: Integer::from_primitive(0), yaw: Integer::from_primitive(0), + roll: Integer::from_primitive(0), pitch: Integer::from_primitive(0), accel_z: Integer::from_primitive(0), accel_y: Integer::from_primitive(0), From 8511ed3237efb17cf8476b87ef90fe4e1f2ed474 Mon Sep 17 00:00:00 2001 From: honjow Date: Fri, 27 Feb 2026 04:44:33 +0800 Subject: [PATCH 3/3] fix(horipad_steam): negate gyroscope values to match SDL sign convention SDL negates all three gyro axes when reading from this device, so we pre-negate the values here to produce the correct orientation after SDL's correction. https://github.com/libsdl-org/SDL/blob/main/src/joystick/hidapi/SDL_hidapi_steam_hori.c#L329-L331 --- src/input/target/horipad_steam.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/input/target/horipad_steam.rs b/src/input/target/horipad_steam.rs index d127f2c0..009d284e 100644 --- a/src/input/target/horipad_steam.rs +++ b/src/input/target/horipad_steam.rs @@ -531,9 +531,11 @@ fn denormalize_accel_value(value_meters_sec: f64) -> i16 { value as i16 } -/// Horipad gyro values are measured in units of degrees per second. -/// InputPlumber gyro values are also measured in degrees per second. +/// SDL negates all gyro axes when reading from this device (SDL_hidapi_steam_hori.c L329-331): +/// imu_data[N] = -1.0f * LOAD16(data[...]) +/// We invert here so that SDL produces the correct sign after its negation. +/// https://github.com/libsdl-org/SDL/blob/main/src/joystick/hidapi/SDL_hidapi_steam_hori.c#L329-L331 fn denormalize_gyro_value(value_degrees_sec: f64) -> i16 { - let value = value_degrees_sec; + let value = -value_degrees_sec; value as i16 }