gcrecomp_runtime/input/
switch_pro.rs1use anyhow::Result;
3use hidapi::HidApi;
4use std::time::Duration;
5
6pub struct SwitchProController {
7 device: Option<hidapi::HidDevice>,
8 connected: bool,
9}
10
11impl SwitchProController {
12 pub fn new() -> Result<Self> {
13 let api = HidApi::new()?;
14
15 const NINTENDO_VENDOR_ID: u16 = 0x057e;
17 const PRO_CONTROLLER_PRODUCT_ID: u16 = 0x2009;
18
19 let device = api.open(NINTENDO_VENDOR_ID, PRO_CONTROLLER_PRODUCT_ID).ok();
20 let connected = device.is_some();
21
22 Ok(Self {
23 device,
24 connected,
25 })
26 }
27
28 pub fn is_connected(&self) -> bool {
29 self.connected
30 }
31
32 pub fn read_input(&mut self) -> Result<SwitchProInput> {
33 if let Some(ref device) = self.device {
34 let mut buf = [0u8; 64];
35 let len = device.read_timeout(&mut buf, 16)?;
36
37 if len > 0 {
38 return Self::parse_input(&buf[..len]);
39 }
40 }
41
42 Ok(SwitchProInput::default())
43 }
44
45 fn parse_input(data: &[u8]) -> Result<SwitchProInput> {
46 if data.len() < 10 {
47 return Ok(SwitchProInput::default());
48 }
49
50 let buttons = u16::from_le_bytes([data[3], data[4]]);
51
52 Ok(SwitchProInput {
53 a: (buttons & 0x0001) != 0,
54 b: (buttons & 0x0002) != 0,
55 x: (buttons & 0x0004) != 0,
56 y: (buttons & 0x0008) != 0,
57 minus: (buttons & 0x0010) != 0,
58 plus: (buttons & 0x0020) != 0,
59 l: (buttons & 0x0040) != 0,
60 r: (buttons & 0x0080) != 0,
61 zl: (buttons & 0x0100) != 0,
62 zr: (buttons & 0x0200) != 0,
63 left_stick_x: data[6] as f32 / 128.0 - 1.0,
64 left_stick_y: data[7] as f32 / 128.0 - 1.0,
65 right_stick_x: data[8] as f32 / 128.0 - 1.0,
66 right_stick_y: data[9] as f32 / 128.0 - 1.0,
67 })
68 }
69
70 pub fn set_rumble(&mut self, low_freq: u8, high_freq: u8) -> Result<()> {
71 if let Some(ref device) = self.device {
72 let mut buf = [0u8; 10];
73 buf[0] = 0x10; buf[1] = 0x80;
75 buf[3] = low_freq;
76 buf[4] = high_freq;
77 device.write(&buf)?;
78 }
79 Ok(())
80 }
81}
82
83#[derive(Debug, Clone, Default)]
84pub struct SwitchProInput {
85 pub a: bool,
86 pub b: bool,
87 pub x: bool,
88 pub y: bool,
89 pub minus: bool,
90 pub plus: bool,
91 pub l: bool,
92 pub r: bool,
93 pub zl: bool,
94 pub zr: bool,
95 pub left_stick_x: f32,
96 pub left_stick_y: f32,
97 pub right_stick_x: f32,
98 pub right_stick_y: f32,
99}