From 1d0f2aef4751577a4f915fb16bbb32138b778be3 Mon Sep 17 00:00:00 2001 From: William Edwards Date: Sun, 13 Jul 2025 00:07:21 -0700 Subject: [PATCH] feat(Output Events): add native output events --- src/input/output_event/mod.rs | 7 ++++ src/input/output_event/native.rs | 20 ++++++++++++ src/input/output_event/value.rs | 55 ++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 src/input/output_event/native.rs create mode 100644 src/input/output_event/value.rs diff --git a/src/input/output_event/mod.rs b/src/input/output_event/mod.rs index 046a1e30..e65c59c9 100644 --- a/src/input/output_event/mod.rs +++ b/src/input/output_event/mod.rs @@ -1,6 +1,10 @@ +pub mod native; +pub mod value; + use std::sync::mpsc::Sender; use ::evdev::{FFEffectData, InputEvent}; +use native::NativeOutputEvent; use crate::drivers::{ dualsense::hid_report::SetStatePackedOutputData, @@ -10,8 +14,10 @@ use crate::drivers::{ use super::output_capability::{Haptic, OutputCapability}; /// Output events are events that flow from target devices back to source devices +/// TODO: Remove this in favor of directly using NativeOutputEvent #[derive(Debug, Clone)] pub enum OutputEvent { + Native(NativeOutputEvent), Evdev(InputEvent), Uinput(UinputOutputEvent), DualSense(SetStatePackedOutputData), @@ -23,6 +29,7 @@ impl OutputEvent { /// Returns the capability of the output event fn as_capability(&self) -> Vec { match self { + OutputEvent::Native(event) => todo!(), OutputEvent::Evdev(event) => match event.destructure() { evdev::EventSummary::Synchronization(_, _, _) => { vec![OutputCapability::NotImplemented] diff --git a/src/input/output_event/native.rs b/src/input/output_event/native.rs new file mode 100644 index 00000000..9ae524cb --- /dev/null +++ b/src/input/output_event/native.rs @@ -0,0 +1,20 @@ +use crate::input::output_capability::OutputCapability; + +use super::value::OutputValue; + +#[derive(Debug, Clone)] +pub struct NativeOutputEvent { + capability: OutputCapability, + value: OutputValue, +} + +impl NativeOutputEvent { + pub fn new(capability: OutputCapability, value: OutputValue) -> Self { + Self { capability, value } + } + + /// Returns the value of this event + pub fn get_value(&self) -> &OutputValue { + &self.value + } +} diff --git a/src/input/output_event/value.rs b/src/input/output_event/value.rs new file mode 100644 index 00000000..912c6f4e --- /dev/null +++ b/src/input/output_event/value.rs @@ -0,0 +1,55 @@ +use packed_struct::types::SizedInteger; + +use crate::{ + drivers::steam_deck::hid_report::PackedRumbleReport, input::output_capability::OutputCapability, +}; + +use super::native::NativeOutputEvent; + +#[derive(Debug, Clone)] +pub enum OutputValue { + ForceFeedback(ForceFeedbackValue), + Led, +} + +#[derive(Debug, Clone)] +pub enum ForceFeedbackValue { + Magnitude { strong: f64, weak: f64 }, + SuperSpecialMegaRumble { x: f64, y: f64, z: f64 }, +} + +/// Deck -> Native +impl From for NativeOutputEvent { + fn from(value: PackedRumbleReport) -> Self { + let capability = OutputCapability::ForceFeedback; + let value = OutputValue::ForceFeedback(ForceFeedbackValue::Magnitude { + strong: value.left_speed.to_primitive() as f64, + weak: value.right_speed.to_primitive() as f64, + }); + + Self::new(capability, value) + } +} + +/// Native -> Deck +impl From for PackedRumbleReport { + fn from(event: NativeOutputEvent) -> Self { + // TODO: this conversion + let OutputValue::ForceFeedback(value) = event.get_value() else { + // NOTE: UNABLE TO TRANSLATE! + return Self::default(); + }; + + match value { + ForceFeedbackValue::Magnitude { strong, weak } => todo!(), + ForceFeedbackValue::SuperSpecialMegaRumble { x, y, z } => todo!(), + } + + Self { + intensity: 0, + left_speed: Default::default(), + right_speed: Default::default(), + ..Default::default() + } + } +}