From 8c1e4c2f8761102ac9ad49aad029b66ae29f5af3 Mon Sep 17 00:00:00 2001 From: William Edwards Date: Mon, 18 Nov 2024 16:33:44 -0800 Subject: [PATCH] fix(SourceSteamDeck): configure trackpads when disabling lizard mode --- src/drivers/steam_deck/driver.rs | 62 ++++++++++++--- src/drivers/steam_deck/hid_report.rs | 104 +++++++++++++++++++++++++- src/input/source/hidraw/steam_deck.rs | 10 ++- 3 files changed, 163 insertions(+), 13 deletions(-) diff --git a/src/drivers/steam_deck/driver.rs b/src/drivers/steam_deck/driver.rs index fe73a63e..464d5c09 100644 --- a/src/drivers/steam_deck/driver.rs +++ b/src/drivers/steam_deck/driver.rs @@ -12,7 +12,7 @@ use super::{ AccelerometerEvent, AccelerometerInput, AxisEvent, AxisInput, BinaryInput, ButtonEvent, Event, TouchAxisInput, TriggerEvent, TriggerInput, }, - hid_report::{PackedMappingsReport, PackedRumbleReport, ReportType}, + hid_report::{PackedMappingsReport, PackedRumbleReport, Register, ReportType, TrackpadMode}, }; /// Vendor ID @@ -93,18 +93,62 @@ impl Driver { /// Set lizard mode, which will automatically try to emulate mouse/keyboard /// if enabled. pub fn set_lizard_mode(&self, enabled: bool) -> Result<(), Box> { - // Initialize the report to send - let report = match enabled { - true => PackedMappingsReport { + // Lizard mode enabled + if enabled { + // Enable keyboard emulation + let report = PackedMappingsReport { report_id: ReportType::DefaultMappings as u8, - }, - false => PackedMappingsReport { + }; + let buf = report.pack()?; + let _bytes_written = self.device.write(&buf)?; + + // Enable mouse emulation on the right pad + let report = PackedMappingsReport { + report_id: ReportType::DefaultMouse as u8, + }; + let buf = report.pack()?; + let _bytes_written = self.device.write(&buf)?; + + // Enable smoothing + self.write_register(Register::SmoothAbsoluteMouse, 0x01)?; + } + // Lizard mode disabled + else { + // Disable keyboard emulation (for a few seconds) + let report = PackedMappingsReport { report_id: ReportType::ClearMappings as u8, - }, - }; + }; + let buf = report.pack()?; + let _bytes_written = self.device.write(&buf)?; + + // Disable mouse emulation on the right pad + self.write_register(Register::RPadMode, TrackpadMode::None as u16)?; + + // Disable smoothing + self.write_register(Register::SmoothAbsoluteMouse, 0x00)?; + } + + Ok(()) + } + + /// Write the given register value to the gamepad device + pub fn write_register( + &self, + register: Register, + value: u16, + ) -> Result<(), Box> { + // Create a buffer for the report + let mut buf = [0; 64]; + buf[0] = ReportType::WriteRegister as u8; + // Only allow writing one register at a time (size: 3 bytes) + buf[1] = 3; + // Register is 8 bits + buf[2] = register as u8; + // Value is 16 bits, with the low bits first + buf[3] = (value & 0xff) as u8; + buf[4] = (value >> 8) as u8; // Write the report to the device - let buf = report.pack()?; let _bytes_written = self.device.write(&buf)?; Ok(()) diff --git a/src/drivers/steam_deck/hid_report.rs b/src/drivers/steam_deck/hid_report.rs index f3c089e5..703c748f 100644 --- a/src/drivers/steam_deck/hid_report.rs +++ b/src/drivers/steam_deck/hid_report.rs @@ -88,11 +88,111 @@ impl TryFrom for ReportType { } } +/// Register settings pub enum Register { + MouseSensitivity = 0x00, + MouseAcceleration = 0x01, + TrackballRotationAngle = 0x02, + HapticIntensityUnused = 0x03, + LeftGamepadStickEnabled = 0x04, + RightGamepadStickEnabled = 0x05, + UsbDebugMode = 0x06, LPadMode = 0x07, RPadMode = 0x08, - RPadMargin = 0x18, - GyroMode = 0x30, + MousePointerEnabled = 0x09, + + DPadDeadzone, + MinimumMomentumVel, + MomentumDecayAmmount, + TrackpadRelativeModeTicksPerPixel, + HapticIncrement, + DPadAngleSin, + DPadAngleCos, + MomentumVerticalDivisor, + MomentumMaximumVelocity, + TrackpadZOn, + + TrackpadZOff, + SensitivyScaleAmmount, + LeftTrackpadSecondaryMode, + RightTrackpadSecondaryMode, + SmoothAbsoluteMouse, + SteamButtonPowerOffTime, + Unused1, + TrackpadOuterRadius, + TrackpadZOnLeft, + TrackpadZOffLeft, + + TrackpadOuterSpinVel, + TrackpadOuterSpinRadius, + TrackpadOuterSpinHorizontalOnly, + TrackpadRelativeModeDeadzone, + TrackpadRelativeModeMaxVel, + TrackpadRelativeModeInvertY, + TrackpadDoubleTapBeepEnabled, + TrackpadDoubleTapBeepPeriod, + TrackpadDoubleTapBeepCount, + TrackpadOuterRadiusReleaseOnTransition, + + RadialModeAngle, + HapticIntensityMouseMode, + LeftDPadRequiresClick, + RightDPadRequiresClick, + LedBaselineBrightness, + LedUserBrightness, + EnableRawJoystick, + EnableFastScan, + ImuMode, + WirelessPacketVersion, + + SleepInactivityTimeout, + TrackpadNoiseThreshold, + LeftTrackpadClickPressure, + RightTrackpadClickPressure, + LeftBumperClickPressure, + RightBumperClickPressure, + LeftGripClickPressure, + RightGripClickPressure, + LeftGrip2ClickPressure, + RightGrip2ClickPressure, + + PressureMode, + ControllerTestMode, + TriggerMode, + TrackpadZThreshold, + FrameRate, + TrackpadFiltCtrl, + TrackpadClip, + DebugOutputSelect, + TriggerThresholdPercent, + TrackpadFrequencyHopping, + + HapticsEnabled, + SteamWatchdogEnable, + TimpTouchThresholdOn, + TimpTouchThresholdOff, + FreqHopping, + TestControl, + HapticMasterGainDb, + ThumbTouchThresh, + DevicePowerStatus, + HapticIntensity, + + StabilizerEnabled, + TimpModeMte, +} + +/// Trackpad modes +pub enum TrackpadMode { + AbsoluteMouse = 0x00, + RelativeMouse = 0x01, + DPadFourWayDiscrete = 0x02, + DPadFourWayOverlap = 0x03, + DPadEightWay = 0x04, + RadialMode = 0x05, + AbsoluteDPad = 0x06, + None = 0x07, + GestureKeyboard = 0x08, } #[derive(PackedStruct, Debug, Copy, Clone, PartialEq)] diff --git a/src/input/source/hidraw/steam_deck.rs b/src/input/source/hidraw/steam_deck.rs index 5b6d50af..27621a61 100644 --- a/src/input/source/hidraw/steam_deck.rs +++ b/src/input/source/hidraw/steam_deck.rs @@ -334,12 +334,15 @@ fn normalize_axis_value(event: steam_deck::event::AxisEvent) -> InputValue { let min = steam_deck::hid_report::PAD_X_MIN; let max = steam_deck::hid_report::PAD_X_MAX; let x = normalize_signed_value(value.x as f64, min, max); + let x = (x + 1.0) / 2.0; // Convert from -1.0 - 1.0 range to 0.0 - 1.0 range let x = Some(x); let min = steam_deck::hid_report::PAD_Y_MAX; // uses inverted Y-axis let max = steam_deck::hid_report::PAD_Y_MIN; let y = normalize_signed_value(value.y as f64, min, max); - let y = Some(-y); // Y-Axis is inverted + let y = -y; // Y-axis is inverted + let y = (y + 1.0) / 2.0; // Convert from -1.0 - 1.0 range to 0.0 - 1.0 range + let y = Some(y); InputValue::Touch { index: value.index, @@ -353,12 +356,15 @@ fn normalize_axis_value(event: steam_deck::event::AxisEvent) -> InputValue { let min = steam_deck::hid_report::PAD_X_MIN; let max = steam_deck::hid_report::PAD_X_MAX; let x = normalize_signed_value(value.x as f64, min, max); + let x = (x + 1.0) / 2.0; // Convert from -1.0 - 1.0 range to 0.0 - 1.0 range let x = Some(x); let min = steam_deck::hid_report::PAD_Y_MAX; // uses inverted Y-axis let max = steam_deck::hid_report::PAD_Y_MIN; let y = normalize_signed_value(value.y as f64, min, max); - let y = Some(-y); // Y-Axis is inverted + let y = -y; // Y-axis is inverted + let y = (y + 1.0) / 2.0; // Convert from -1.0 - 1.0 range to 0.0 - 1.0 range + let y = Some(y); InputValue::Touch { index: value.index,