Skip to main content

usehid_core/
gamepad.rs

1//! Virtual Gamepad implementation
2
3use crate::error::{Error, Result};
4use crate::hid::GamepadReport;
5use crate::platform::HidBackend;
6use crate::Device;
7use bitflags::bitflags;
8use serde::{Deserialize, Serialize};
9
10bitflags! {
11    /// Gamepad button flags
12    #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
13    pub struct GamepadButton: u16 {
14        const A = 0x0001;
15        const B = 0x0002;
16        const X = 0x0004;
17        const Y = 0x0008;
18        const LB = 0x0010;
19        const RB = 0x0020;
20        const BACK = 0x0040;
21        const START = 0x0080;
22        const GUIDE = 0x0100;
23        const LEFT_STICK = 0x0200;
24        const RIGHT_STICK = 0x0400;
25        const DPAD_UP = 0x0800;
26        const DPAD_DOWN = 0x1000;
27        const DPAD_LEFT = 0x2000;
28        const DPAD_RIGHT = 0x4000;
29    }
30}
31
32/// Virtual gamepad device
33pub struct Gamepad {
34    backend: Option<Box<dyn HidBackend>>,
35    report: GamepadReport,
36    name: String,
37}
38
39impl Gamepad {
40    /// Create a new virtual gamepad
41    pub fn new() -> Self {
42        Self::with_name("useHID Virtual Gamepad")
43    }
44    
45    /// Create a new virtual gamepad with custom name
46    pub fn with_name(name: &str) -> Self {
47        let mut gamepad = Self {
48            backend: None,
49            report: GamepadReport::default(),
50            name: name.to_string(),
51        };
52        // Center sticks
53        gamepad.report.left_x = 128;
54        gamepad.report.left_y = 128;
55        gamepad.report.right_x = 128;
56        gamepad.report.right_y = 128;
57        gamepad
58    }
59    
60    /// Press button(s)
61    pub fn press(&mut self, button: GamepadButton) -> Result<()> {
62        self.report.buttons |= button.bits();
63        self.send_report()
64    }
65    
66    /// Release button(s)
67    pub fn release(&mut self, button: GamepadButton) -> Result<()> {
68        self.report.buttons &= !button.bits();
69        self.send_report()
70    }
71    
72    /// Tap button (press and release)
73    pub fn tap(&mut self, button: GamepadButton) -> Result<()> {
74        self.press(button)?;
75        std::thread::sleep(std::time::Duration::from_millis(50));
76        self.release(button)
77    }
78    
79    /// Set left stick position (0-255, 128 = center)
80    pub fn set_left_stick(&mut self, x: u8, y: u8) -> Result<()> {
81        self.report.left_x = x;
82        self.report.left_y = y;
83        self.send_report()
84    }
85    
86    /// Set right stick position (0-255, 128 = center)
87    pub fn set_right_stick(&mut self, x: u8, y: u8) -> Result<()> {
88        self.report.right_x = x;
89        self.report.right_y = y;
90        self.send_report()
91    }
92    
93    /// Set left trigger (0-255)
94    pub fn set_left_trigger(&mut self, value: u8) -> Result<()> {
95        self.report.left_trigger = value;
96        self.send_report()
97    }
98    
99    /// Set right trigger (0-255)
100    pub fn set_right_trigger(&mut self, value: u8) -> Result<()> {
101        self.report.right_trigger = value;
102        self.send_report()
103    }
104    
105    /// Reset all to default (center sticks, no buttons)
106    pub fn reset(&mut self) -> Result<()> {
107        self.report.buttons = 0;
108        self.report.left_x = 128;
109        self.report.left_y = 128;
110        self.report.right_x = 128;
111        self.report.right_y = 128;
112        self.report.left_trigger = 0;
113        self.report.right_trigger = 0;
114        self.send_report()
115    }
116    
117    fn send_report(&self) -> Result<()> {
118        if let Some(backend) = &self.backend {
119            backend.send_report(self.report.as_bytes())
120        } else {
121            Err(Error::DeviceNotCreated)
122        }
123    }
124}
125
126impl Default for Gamepad {
127    fn default() -> Self {
128        Self::new()
129    }
130}
131
132impl Device for Gamepad {
133    fn create(&mut self) -> Result<()> {
134        if self.backend.is_some() {
135            return Err(Error::DeviceAlreadyExists);
136        }
137        
138        let backend = crate::platform::create_gamepad_backend(&self.name)?;
139        self.backend = Some(backend);
140        Ok(())
141    }
142    
143    fn destroy(&mut self) -> Result<()> {
144        if let Some(backend) = self.backend.take() {
145            backend.destroy()
146        } else {
147            Err(Error::DeviceNotCreated)
148        }
149    }
150    
151    fn is_created(&self) -> bool {
152        self.backend.is_some()
153    }
154}