1use serde::{Deserialize, Serialize};
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
4pub enum GlyphStyle {
5 PlayStation,
6 Standard,
7}
8
9impl GlyphStyle {
10 pub const ALL: [GlyphStyle; 2] = [GlyphStyle::PlayStation, GlyphStyle::Standard];
11
12 pub fn family(self) -> Family {
13 match self {
14 GlyphStyle::PlayStation => Family::DualSense,
15 GlyphStyle::Standard => Family::Xbox,
16 }
17 }
18
19 pub fn name(self) -> &'static str {
20 match self {
21 GlyphStyle::PlayStation => "PlayStation",
22 GlyphStyle::Standard => "Standard",
23 }
24 }
25}
26
27#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
28pub enum Family {
29 DualSense,
30 DualShock4,
31 Xbox,
32 SteamController,
33 SteamDeck,
34 SwitchPro,
35 Generic,
36}
37
38impl Family {
39 pub const ALL: [Family; 7] = [
40 Family::DualSense,
41 Family::DualShock4,
42 Family::Xbox,
43 Family::SteamController,
44 Family::SteamDeck,
45 Family::SwitchPro,
46 Family::Generic,
47 ];
48
49 pub fn from_ids(vendor: u16, product: u16) -> Family {
50 if let Some(entry) = PADS
51 .iter()
52 .find(|entry| entry.vendor == vendor && entry.product == product)
53 {
54 return entry.family;
55 }
56 match vendor {
57 SONY => Family::DualShock4,
58 MICROSOFT => Family::Xbox,
59 VALVE => Family::SteamController,
60 NINTENDO => Family::SwitchPro,
61 _ => Family::Generic,
62 }
63 }
64
65 pub fn from_steam_input_type(kind: i32) -> Family {
66 match kind {
67 STEAM_INPUT_STEAM_CONTROLLER => Family::SteamController,
68 STEAM_INPUT_XBOX_360 | STEAM_INPUT_XBOX_ONE => Family::Xbox,
69 STEAM_INPUT_PS4 | STEAM_INPUT_PS3 => Family::DualShock4,
70 STEAM_INPUT_PS5 => Family::DualSense,
71 STEAM_INPUT_SWITCH_JOYCON_PAIR
72 | STEAM_INPUT_SWITCH_JOYCON_SINGLE
73 | STEAM_INPUT_SWITCH_PRO => Family::SwitchPro,
74 STEAM_INPUT_STEAM_DECK => Family::SteamDeck,
75 _ => Family::Generic,
76 }
77 }
78
79 pub fn name(self) -> &'static str {
80 match self {
81 Family::DualSense => "DualSense",
82 Family::DualShock4 => "DualShock 4",
83 Family::Xbox => "Xbox",
84 Family::SteamController => "Steam Controller",
85 Family::SteamDeck => "Steam Deck",
86 Family::SwitchPro => "Switch Pro",
87 Family::Generic => "Generic",
88 }
89 }
90
91 pub fn style(self) -> GlyphStyle {
92 match self {
93 Family::DualSense | Family::DualShock4 => GlyphStyle::PlayStation,
94 _ => GlyphStyle::Standard,
95 }
96 }
97
98 pub fn has_grips(self) -> bool {
99 matches!(self, Family::SteamController | Family::SteamDeck)
100 }
101}
102
103pub const SONY: u16 = 0x054c;
104pub const MICROSOFT: u16 = 0x045e;
105pub const VALVE: u16 = 0x28de;
106pub const NINTENDO: u16 = 0x057e;
107
108pub const STEAM_INPUT_UNKNOWN: i32 = 0;
109pub const STEAM_INPUT_STEAM_CONTROLLER: i32 = 1;
110pub const STEAM_INPUT_XBOX_360: i32 = 2;
111pub const STEAM_INPUT_XBOX_ONE: i32 = 3;
112pub const STEAM_INPUT_GENERIC: i32 = 4;
113pub const STEAM_INPUT_PS4: i32 = 5;
114pub const STEAM_INPUT_APPLE_MFI: i32 = 6;
115pub const STEAM_INPUT_ANDROID: i32 = 7;
116pub const STEAM_INPUT_SWITCH_JOYCON_PAIR: i32 = 8;
117pub const STEAM_INPUT_SWITCH_JOYCON_SINGLE: i32 = 9;
118pub const STEAM_INPUT_SWITCH_PRO: i32 = 10;
119pub const STEAM_INPUT_MOBILE_TOUCH: i32 = 11;
120pub const STEAM_INPUT_PS3: i32 = 12;
121pub const STEAM_INPUT_PS5: i32 = 13;
122pub const STEAM_INPUT_STEAM_DECK: i32 = 14;
123
124#[derive(Clone, Copy, Debug, PartialEq, Eq)]
125pub struct PadEntry {
126 pub vendor: u16,
127 pub product: u16,
128 pub family: Family,
129 pub model: &'static str,
130}
131
132const fn pad(vendor: u16, product: u16, family: Family, model: &'static str) -> PadEntry {
133 PadEntry {
134 vendor,
135 product,
136 family,
137 model,
138 }
139}
140
141pub const PADS: &[PadEntry] = &[
142 pad(SONY, 0x0ce6, Family::DualSense, "DualSense"),
143 pad(SONY, 0x0df2, Family::DualSense, "DualSense Edge"),
144 pad(SONY, 0x05c4, Family::DualShock4, "DualShock 4"),
145 pad(
146 SONY,
147 0x09cc,
148 Family::DualShock4,
149 "DualShock 4 (second revision)",
150 ),
151 pad(
152 SONY,
153 0x0ba0,
154 Family::DualShock4,
155 "DualShock 4 wireless adapter",
156 ),
157 pad(SONY, 0x0268, Family::DualShock4, "DualShock 3"),
158 pad(MICROSOFT, 0x028e, Family::Xbox, "Xbox 360"),
159 pad(MICROSOFT, 0x028f, Family::Xbox, "Xbox 360 wireless"),
160 pad(
161 MICROSOFT,
162 0x0719,
163 Family::Xbox,
164 "Xbox 360 wireless receiver",
165 ),
166 pad(MICROSOFT, 0x02d1, Family::Xbox, "Xbox One"),
167 pad(MICROSOFT, 0x02dd, Family::Xbox, "Xbox One (2015)"),
168 pad(MICROSOFT, 0x02e0, Family::Xbox, "Xbox One S wireless"),
169 pad(MICROSOFT, 0x02e3, Family::Xbox, "Xbox One Elite"),
170 pad(MICROSOFT, 0x02ea, Family::Xbox, "Xbox One S"),
171 pad(MICROSOFT, 0x02fd, Family::Xbox, "Xbox One S Bluetooth"),
172 pad(MICROSOFT, 0x0b00, Family::Xbox, "Xbox Elite Series 2"),
173 pad(
174 MICROSOFT,
175 0x0b05,
176 Family::Xbox,
177 "Xbox Elite Series 2 Bluetooth",
178 ),
179 pad(MICROSOFT, 0x0b12, Family::Xbox, "Xbox Series X|S"),
180 pad(MICROSOFT, 0x0b13, Family::Xbox, "Xbox Series X|S Bluetooth"),
181 pad(
182 MICROSOFT,
183 0x0b20,
184 Family::Xbox,
185 "Xbox One S Bluetooth (2021)",
186 ),
187 pad(
188 MICROSOFT,
189 0x0b22,
190 Family::Xbox,
191 "Xbox Elite Series 2 Bluetooth (2021)",
192 ),
193 pad(VALVE, 0x1102, Family::SteamController, "Steam Controller"),
194 pad(
195 VALVE,
196 0x1142,
197 Family::SteamController,
198 "Steam Controller dongle",
199 ),
200 pad(VALVE, 0x1205, Family::SteamDeck, "Steam Deck"),
201 pad(
202 VALVE,
203 0x11ff,
204 Family::Generic,
205 "Steam Input virtual gamepad",
206 ),
207 pad(NINTENDO, 0x2009, Family::SwitchPro, "Switch Pro"),
208 pad(NINTENDO, 0x2006, Family::SwitchPro, "Joy-Con (L)"),
209 pad(NINTENDO, 0x2007, Family::SwitchPro, "Joy-Con (R)"),
210 pad(NINTENDO, 0x200e, Family::SwitchPro, "Joy-Con charging grip"),
211];
212
213pub fn model(vendor: u16, product: u16) -> Option<&'static str> {
214 PADS.iter()
215 .find(|entry| entry.vendor == vendor && entry.product == product)
216 .map(|entry| entry.model)
217}