Skip to main content

pfx_input/
family.rs

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}