Skip to main content

scdsu_core/devices/
device.rs

1use std::str::FromStr;
2
3use crate::dsu::DSUFrame;
4use crate::errors::DeviceError;
5
6/// A trait defining shared behavior between compatible devices.
7pub trait Device {
8    /// Run any initialization logic the device requires.
9    fn initialize(&self) -> Result<(), DeviceError>;
10
11    /// Read a DSU frame from the device.
12    fn read_frame(&self) -> Result<DSUFrame, DeviceError>;
13}
14
15/// A trait defining shared behavior dependant on the frame type `F` between compatible devices.
16pub trait FrameDevice<F> {
17    fn to_dsu_frame(&self, frame: &F, gyro_disabled: bool) -> DSUFrame;
18    /// Test if a [`DeviceButton`](crate::devices::DeviceButton) is pressed.
19    fn is_device_button_pressed(&self, button: &DeviceButton, frame: &F) -> bool;
20}
21
22/// Device buttons not specific to any one device.
23#[derive(Debug, Clone)]
24pub enum DeviceButton {
25    /// Directional pad Left
26    DpadLeft,
27    /// Directional pad Down
28    DpadDown,
29    /// Directional pad Right
30    DpadRight,
31    /// Directional pad Up
32    DpadUp,
33    /// Start, options, etc.
34    Start,
35    /// Select, share, etc.
36    Select,
37    /// PS button, steam button, etc.
38    Guide,
39    /// QAM, Mic, etc.
40    Quaternary,
41    /// XB layout A
42    A,
43    /// XB layout B
44    B,
45    /// XB layout X
46    X,
47    /// XB layout Y
48    Y,
49    /// L1, Left Bumper
50    L1,
51    /// R1, Right Bumper
52    R1,
53    /// L2, Left Trigger
54    L2,
55    /// R2, Right Trigger
56    R2,
57    /// L3, Left stick click
58    L3,
59    /// R3, Right stick click
60    R3,
61    /// Triton only
62    L4,
63    /// Triton only
64    L5,
65    /// Triton only
66    R4,
67    /// Triton only
68    R5,
69    /// Triton only
70    LeftStickTouch,
71    /// Triton only
72    RightStickTouch,
73    /// Triton only
74    LeftPadTouch,
75    /// Triton only
76    RightPadTouch,
77    /// Triton only
78    LeftGrip,
79    /// Triton only
80    RightGrip,
81    /// Unknown button
82    Unknown,
83}
84
85impl FromStr for DeviceButton {
86    type Err = DeviceError;
87
88    fn from_str(s: &str) -> Result<Self, Self::Err> {
89        match s {
90            "dpad_left" => Ok(Self::DpadLeft),
91            "dpad_down" => Ok(Self::DpadDown),
92            "dpad_right" => Ok(Self::DpadRight),
93            "dpad_up" => Ok(Self::DpadUp),
94            "start" => Ok(Self::Start),
95            "select" => Ok(Self::Select),
96            "guide" => Ok(Self::Guide),
97            "quaternary" => Ok(Self::Quaternary),
98            "a" => Ok(Self::A),
99            "b" => Ok(Self::B),
100            "x" => Ok(Self::X),
101            "y" => Ok(Self::Y),
102            "l1" => Ok(Self::L1),
103            "r1" => Ok(Self::R1),
104            "l2" => Ok(Self::L2),
105            "r2" => Ok(Self::R2),
106            "l3" => Ok(Self::L3),
107            "r3" => Ok(Self::R3),
108            "l4" => Ok(Self::L4),
109            "l5" => Ok(Self::L5),
110            "r4" => Ok(Self::R4),
111            "r5" => Ok(Self::R5),
112            "left_stick_touch" => Ok(Self::LeftStickTouch),
113            "right_stick_touch" => Ok(Self::RightStickTouch),
114            "left_pad_touch" => Ok(Self::LeftPadTouch),
115            "right_pad_touch" => Ok(Self::RightPadTouch),
116            "left_grip" => Ok(Self::LeftGrip),
117            "right_grip" => Ok(Self::RightGrip),
118            _ => Err(DeviceError::InvalidDeviceButton(s.to_string())),
119        }
120    }
121}
122
123impl std::fmt::Display for DeviceButton {
124    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
125        match self {
126            Self::DpadLeft => write!(f, "dpad_left"),
127            Self::DpadDown => write!(f, "dpad_down"),
128            Self::DpadRight => write!(f, "dpad_right"),
129            Self::DpadUp => write!(f, "dpad_up"),
130            Self::Start => write!(f, "start"),
131            Self::Select => write!(f, "select"),
132            Self::Guide => write!(f, "guide"),
133            Self::Quaternary => write!(f, "quaternary"),
134            Self::A => write!(f, "a"),
135            Self::B => write!(f, "b"),
136            Self::X => write!(f, "x"),
137            Self::Y => write!(f, "y"),
138            Self::L1 => write!(f, "l1"),
139            Self::R1 => write!(f, "r1"),
140            Self::L2 => write!(f, "l2"),
141            Self::R2 => write!(f, "r2"),
142            Self::L3 => write!(f, "l3"),
143            Self::R3 => write!(f, "r3"),
144            Self::L4 => write!(f, "l4"),
145            Self::L5 => write!(f, "l5"),
146            Self::R4 => write!(f, "r4"),
147            Self::R5 => write!(f, "r5"),
148            Self::LeftStickTouch => write!(f, "left_stick_touch"),
149            Self::RightStickTouch => write!(f, "right_stick_touch"),
150            Self::LeftPadTouch => write!(f, "left_pad_touch"),
151            Self::RightPadTouch => write!(f, "right_pad_touch"),
152            Self::LeftGrip => write!(f, "left_grip"),
153            Self::RightGrip => write!(f, "right_grip"),
154            Self::Unknown => write!(f, "unknown"),
155        }
156    }
157}
158
159/// Gyro activation toggle mode.
160///
161/// Any => At least one button must be pressed to activate gyro.
162///
163/// All => All buttons must be pressed to activate gyro.
164#[derive(Default, Debug, Clone)]
165pub enum GyroActivationMode {
166    #[default]
167    Any,
168    All,
169}
170
171impl FromStr for GyroActivationMode {
172    type Err = DeviceError;
173
174    fn from_str(s: &str) -> Result<Self, Self::Err> {
175        match s {
176            "any" => Ok(Self::Any),
177            "all" => Ok(Self::All),
178            _ => Err(DeviceError::InvalidGyroActivationMode(s.to_string())),
179        }
180    }
181}
182
183impl std::fmt::Display for GyroActivationMode {
184    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
185        match self {
186            Self::Any => write!(f, "any"),
187            Self::All => write!(f, "all"),
188        }
189    }
190}
191
192/// Device configuration.
193///
194/// Defines configurable behavior within device adapters themselves.
195///
196/// For configuration affecting the behavior of the DSU server,
197/// see ['ServerConfig'](crate::server::ServerConfig)
198#[derive(Debug, Clone)]
199pub struct DeviceConfig {
200    /// Don't enable lizard mode when the device is dropped (Triton)
201    pub no_enable_lizard_mode_on_close: bool,
202    /// Inputs that must be pressed to send gyro data through the DSU server.
203    pub gyro_activation_inputs: Vec<DeviceButton>,
204    /// See ['GyroActivationMode'](crate::devices::GyroActivationMode)
205    pub gyro_activation_mode: GyroActivationMode,
206    /// Gyro deadzone in degrees per second. Values below this threshold are reported as zero.
207    pub gyro_deadzone: f32,
208    /// Scale factor applied to the pitch gyro axis.
209    pub gyro_pitch_scale: f32,
210    /// Scale factor applied to the yaw gyro axis.
211    pub gyro_yaw_scale: f32,
212    /// Scale factor applied to the roll gyro axis.
213    pub gyro_roll_scale: f32,
214}
215
216impl Default for DeviceConfig {
217    fn default() -> Self {
218        Self {
219            no_enable_lizard_mode_on_close: false,
220            gyro_activation_inputs: Vec::new(),
221            gyro_activation_mode: GyroActivationMode::default(),
222            gyro_deadzone: 0.0,
223            gyro_pitch_scale: 1.0,
224            gyro_yaw_scale: 1.0,
225            gyro_roll_scale: 1.0,
226        }
227    }
228}