1use std::fmt;
2use std::str::FromStr;
3
4use crate::dsu::DSUFrame;
5use crate::errors::DeviceError;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
9pub enum DeviceFamily {
10 #[default]
12 Triton,
13 Legacy,
15}
16
17impl fmt::Display for DeviceFamily {
18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 match self {
20 Self::Triton => f.write_str("triton"),
21 Self::Legacy => f.write_str("legacy"),
22 }
23 }
24}
25
26impl FromStr for DeviceFamily {
27 type Err = DeviceError;
28
29 fn from_str(s: &str) -> Result<Self, Self::Err> {
30 match s {
31 "triton" => Ok(Self::Triton),
32 "legacy" => Ok(Self::Legacy),
33 _ => Err(DeviceError::InvalidDeviceFamily(s.to_string())),
34 }
35 }
36}
37
38pub trait Device {
40 fn initialize(&self) -> Result<(), DeviceError>;
42
43 fn read_frame(&self) -> Result<DSUFrame, DeviceError>;
45}
46
47impl<T> Device for Box<T>
48where
49 T: Device + ?Sized,
50{
51 fn initialize(&self) -> Result<(), DeviceError> {
52 (**self).initialize()
53 }
54
55 fn read_frame(&self) -> Result<DSUFrame, DeviceError> {
56 (**self).read_frame()
57 }
58}
59
60pub trait FrameDevice<F> {
62 fn to_dsu_frame(&self, frame: &F, gyro_disabled: bool) -> DSUFrame;
63 fn is_device_button_pressed(&self, button: &DeviceButton, frame: &F) -> bool;
65}
66
67#[derive(Debug, Clone)]
69pub enum DeviceButton {
70 DpadLeft,
72 DpadDown,
74 DpadRight,
76 DpadUp,
78 Start,
80 Select,
82 Guide,
84 Quaternary,
86 A,
88 B,
90 X,
92 Y,
94 L1,
96 R1,
98 L2,
100 R2,
102 L3,
104 R3,
106 L4,
108 L5,
110 R4,
112 R5,
114 LeftStickTouch,
116 RightStickTouch,
118 LeftPadTouch,
120 RightPadTouch,
122 LeftGrip,
124 RightGrip,
126 Unknown,
128}
129
130impl FromStr for DeviceButton {
131 type Err = DeviceError;
132
133 fn from_str(s: &str) -> Result<Self, Self::Err> {
134 match s {
135 "dpad_left" => Ok(Self::DpadLeft),
136 "dpad_down" => Ok(Self::DpadDown),
137 "dpad_right" => Ok(Self::DpadRight),
138 "dpad_up" => Ok(Self::DpadUp),
139 "start" => Ok(Self::Start),
140 "select" => Ok(Self::Select),
141 "guide" => Ok(Self::Guide),
142 "quaternary" => Ok(Self::Quaternary),
143 "a" => Ok(Self::A),
144 "b" => Ok(Self::B),
145 "x" => Ok(Self::X),
146 "y" => Ok(Self::Y),
147 "l1" => Ok(Self::L1),
148 "r1" => Ok(Self::R1),
149 "l2" => Ok(Self::L2),
150 "r2" => Ok(Self::R2),
151 "l3" => Ok(Self::L3),
152 "r3" => Ok(Self::R3),
153 "l4" => Ok(Self::L4),
154 "l5" => Ok(Self::L5),
155 "r4" => Ok(Self::R4),
156 "r5" => Ok(Self::R5),
157 "left_stick_touch" => Ok(Self::LeftStickTouch),
158 "right_stick_touch" => Ok(Self::RightStickTouch),
159 "left_pad_touch" => Ok(Self::LeftPadTouch),
160 "right_pad_touch" => Ok(Self::RightPadTouch),
161 "left_grip" => Ok(Self::LeftGrip),
162 "right_grip" => Ok(Self::RightGrip),
163 _ => Err(DeviceError::InvalidDeviceButton(s.to_string())),
164 }
165 }
166}
167
168impl std::fmt::Display for DeviceButton {
169 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
170 match self {
171 Self::DpadLeft => write!(f, "dpad_left"),
172 Self::DpadDown => write!(f, "dpad_down"),
173 Self::DpadRight => write!(f, "dpad_right"),
174 Self::DpadUp => write!(f, "dpad_up"),
175 Self::Start => write!(f, "start"),
176 Self::Select => write!(f, "select"),
177 Self::Guide => write!(f, "guide"),
178 Self::Quaternary => write!(f, "quaternary"),
179 Self::A => write!(f, "a"),
180 Self::B => write!(f, "b"),
181 Self::X => write!(f, "x"),
182 Self::Y => write!(f, "y"),
183 Self::L1 => write!(f, "l1"),
184 Self::R1 => write!(f, "r1"),
185 Self::L2 => write!(f, "l2"),
186 Self::R2 => write!(f, "r2"),
187 Self::L3 => write!(f, "l3"),
188 Self::R3 => write!(f, "r3"),
189 Self::L4 => write!(f, "l4"),
190 Self::L5 => write!(f, "l5"),
191 Self::R4 => write!(f, "r4"),
192 Self::R5 => write!(f, "r5"),
193 Self::LeftStickTouch => write!(f, "left_stick_touch"),
194 Self::RightStickTouch => write!(f, "right_stick_touch"),
195 Self::LeftPadTouch => write!(f, "left_pad_touch"),
196 Self::RightPadTouch => write!(f, "right_pad_touch"),
197 Self::LeftGrip => write!(f, "left_grip"),
198 Self::RightGrip => write!(f, "right_grip"),
199 Self::Unknown => write!(f, "unknown"),
200 }
201 }
202}
203
204#[derive(Default, Debug, Clone)]
210pub enum GyroActivationMode {
211 #[default]
212 Any,
213 All,
214}
215
216impl FromStr for GyroActivationMode {
217 type Err = DeviceError;
218
219 fn from_str(s: &str) -> Result<Self, Self::Err> {
220 match s {
221 "any" => Ok(Self::Any),
222 "all" => Ok(Self::All),
223 _ => Err(DeviceError::InvalidGyroActivationMode(s.to_string())),
224 }
225 }
226}
227
228impl std::fmt::Display for GyroActivationMode {
229 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
230 match self {
231 Self::Any => write!(f, "any"),
232 Self::All => write!(f, "all"),
233 }
234 }
235}
236
237#[derive(Debug, Clone)]
244pub struct DeviceConfig {
245 pub no_enable_lizard_mode_on_close: bool,
247 pub gyro_activation_inputs: Vec<DeviceButton>,
249 pub gyro_activation_mode: GyroActivationMode,
251 pub gyro_deadzone: f32,
253 pub gyro_pitch_scale: f32,
255 pub gyro_yaw_scale: f32,
257 pub gyro_roll_scale: f32,
259}
260
261impl Default for DeviceConfig {
262 fn default() -> Self {
263 Self {
264 no_enable_lizard_mode_on_close: false,
265 gyro_activation_inputs: Vec::new(),
266 gyro_activation_mode: GyroActivationMode::default(),
267 gyro_deadzone: 0.0,
268 gyro_pitch_scale: 1.0,
269 gyro_yaw_scale: 1.0,
270 gyro_roll_scale: 1.0,
271 }
272 }
273}