gilrs_core/
lib.rs
1#[macro_use]
2extern crate log;
3
4use std::fmt;
5use std::fmt::Display;
6use std::fmt::Formatter;
7
8use std::error;
9use std::time::Duration;
10use std::time::SystemTime;
11
12mod platform;
13pub mod utils;
14
15pub const IS_Y_AXIS_REVERSED: bool = platform::IS_Y_AXIS_REVERSED;
17
18#[derive(Debug)]
20pub struct FfDevice {
21 inner: platform::FfDevice,
22}
23
24impl FfDevice {
25 pub fn set_ff_state(&mut self, strong: u16, weak: u16, min_duration: Duration) {
27 self.inner.set_ff_state(strong, weak, min_duration)
28 }
29}
30
31#[derive(Copy, Clone, PartialEq, Eq, Debug)]
33#[non_exhaustive]
34pub struct Event {
35 pub id: usize,
37 pub event: EventType,
39 pub time: SystemTime,
41}
42
43impl Event {
44 pub fn new(id: usize, event: EventType) -> Self {
46 let time = utils::time_now();
47 Event { id, event, time }
48 }
49}
50
51#[derive(Debug, Clone, Copy, PartialEq, Eq)]
52#[non_exhaustive]
54pub enum EventType {
55 ButtonPressed(EvCode),
56 ButtonReleased(EvCode),
57 AxisValueChanged(i32, EvCode),
58 Connected,
59 Disconnected,
60}
61
62#[derive(Copy, Clone, Debug)]
64pub struct AxisInfo {
65 pub min: i32,
66 pub max: i32,
67 pub deadzone: Option<u32>,
68}
69
70#[derive(Debug, Copy, Clone, PartialEq, Eq)]
87pub enum PowerInfo {
88 Unknown,
90 Wired,
92 Discharging(u8),
94 Charging(u8),
96 Charged,
98}
99
100#[derive(Debug)]
102pub struct Gilrs {
103 inner: platform::Gilrs,
104}
105
106impl Gilrs {
107 pub fn new() -> Result<Self, Error> {
108 let inner = platform::Gilrs::new().map_err(|e| match e {
109 PlatformError::NotImplemented(inner) => Error::NotImplemented(Gilrs { inner }),
110 PlatformError::Other(e) => Error::Other(e),
111 })?;
112
113 Ok(Gilrs { inner })
114 }
115
116 pub fn next_event(&mut self) -> Option<Event> {
118 self.inner.next_event()
119 }
120
121 pub fn next_event_blocking(&mut self, timeout: Option<Duration>) -> Option<Event> {
123 self.inner.next_event_blocking(timeout)
124 }
125
126 pub fn gamepad(&self, id: usize) -> Option<&Gamepad> {
128 unsafe {
129 let gp: Option<&platform::Gamepad> = self.inner.gamepad(id);
130
131 gp.map(|gp| &*(gp as *const _ as *const Gamepad))
132 }
133 }
134
135 pub fn last_gamepad_hint(&self) -> usize {
142 self.inner.last_gamepad_hint()
143 }
144}
145
146#[derive(Debug)]
148#[repr(transparent)]
149pub struct Gamepad {
150 inner: platform::Gamepad,
151}
152
153impl Gamepad {
154 pub fn name(&self) -> &str {
156 self.inner.name()
157 }
158
159 pub fn is_connected(&self) -> bool {
161 self.inner.is_connected()
162 }
163
164 pub fn uuid(&self) -> [u8; 16] {
172 *self.inner.uuid().as_bytes()
173 }
174
175 pub fn vendor_id(&self) -> Option<u16> {
177 self.inner.vendor_id()
178 }
179
180 pub fn product_id(&self) -> Option<u16> {
182 self.inner.product_id()
183 }
184
185 pub fn power_info(&self) -> PowerInfo {
187 self.inner.power_info()
188 }
189
190 pub fn is_ff_supported(&self) -> bool {
192 self.inner.is_ff_supported()
193 }
194
195 pub fn ff_device(&self) -> Option<FfDevice> {
197 self.inner.ff_device().map(|inner| FfDevice { inner })
198 }
199
200 pub fn buttons(&self) -> &[EvCode] {
202 unsafe {
203 let bt: &[platform::EvCode] = self.inner.buttons();
204
205 &*(bt as *const _ as *const [EvCode])
206 }
207 }
208
209 pub fn axes(&self) -> &[EvCode] {
211 unsafe {
212 let ax: &[platform::EvCode] = self.inner.axes();
213
214 &*(ax as *const _ as *const [EvCode])
215 }
216 }
217
218 pub fn axis_info(&self, nec: EvCode) -> Option<&AxisInfo> {
221 self.inner.axis_info(nec.0)
222 }
223}
224
225#[cfg(feature = "serde-serialize")]
226use serde::{Deserialize, Serialize};
227
228#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
230#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
231#[repr(transparent)]
232pub struct EvCode(platform::EvCode);
233
234impl EvCode {
235 pub fn into_u32(self) -> u32 {
236 self.0.into_u32()
237 }
238}
239
240impl Display for EvCode {
241 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
242 self.0.fmt(f)
243 }
244}
245
246#[derive(Debug)]
250enum PlatformError {
251 #[allow(dead_code)]
254 NotImplemented(platform::Gilrs),
255 #[allow(dead_code)]
257 Other(Box<dyn error::Error + Send + Sync>),
258}
259
260impl Display for PlatformError {
261 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
262 match *self {
263 PlatformError::NotImplemented(_) => {
264 f.write_str("Gilrs does not support current platform.")
265 }
266 PlatformError::Other(ref e) => e.fmt(f),
267 }
268 }
269}
270
271impl error::Error for PlatformError {
272 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
273 match self {
274 PlatformError::Other(e) => Some(e.as_ref()),
275 _ => None,
276 }
277 }
278}
279
280#[non_exhaustive]
282#[derive(Debug)]
283pub enum Error {
284 NotImplemented(Gilrs),
287 Other(Box<dyn error::Error + Send + Sync + 'static>),
289}
290
291impl Display for Error {
292 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
293 match *self {
294 Error::NotImplemented(_) => f.write_str("Gilrs does not support current platform."),
295 Error::Other(ref e) => e.fmt(f),
296 }
297 }
298}
299
300impl error::Error for Error {
301 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
302 match self {
303 Error::Other(e) => Some(e.as_ref()),
304 _ => None,
305 }
306 }
307}
308
309pub mod native_ev_codes {
312 use super::EvCode;
313 use crate::platform::native_ev_codes as nec;
314
315 pub const AXIS_LSTICKX: EvCode = EvCode(nec::AXIS_LSTICKX);
316 pub const AXIS_LSTICKY: EvCode = EvCode(nec::AXIS_LSTICKY);
317 pub const AXIS_LEFTZ: EvCode = EvCode(nec::AXIS_LEFTZ);
318 pub const AXIS_RSTICKX: EvCode = EvCode(nec::AXIS_RSTICKX);
319 pub const AXIS_RSTICKY: EvCode = EvCode(nec::AXIS_RSTICKY);
320 pub const AXIS_RIGHTZ: EvCode = EvCode(nec::AXIS_RIGHTZ);
321 pub const AXIS_DPADX: EvCode = EvCode(nec::AXIS_DPADX);
322 pub const AXIS_DPADY: EvCode = EvCode(nec::AXIS_DPADY);
323 pub const AXIS_RT: EvCode = EvCode(nec::AXIS_RT);
324 pub const AXIS_LT: EvCode = EvCode(nec::AXIS_LT);
325 pub const AXIS_RT2: EvCode = EvCode(nec::AXIS_RT2);
326 pub const AXIS_LT2: EvCode = EvCode(nec::AXIS_LT2);
327
328 pub const BTN_SOUTH: EvCode = EvCode(nec::BTN_SOUTH);
329 pub const BTN_EAST: EvCode = EvCode(nec::BTN_EAST);
330 pub const BTN_C: EvCode = EvCode(nec::BTN_C);
331 pub const BTN_NORTH: EvCode = EvCode(nec::BTN_NORTH);
332 pub const BTN_WEST: EvCode = EvCode(nec::BTN_WEST);
333 pub const BTN_Z: EvCode = EvCode(nec::BTN_Z);
334 pub const BTN_LT: EvCode = EvCode(nec::BTN_LT);
335 pub const BTN_RT: EvCode = EvCode(nec::BTN_RT);
336 pub const BTN_LT2: EvCode = EvCode(nec::BTN_LT2);
337 pub const BTN_RT2: EvCode = EvCode(nec::BTN_RT2);
338 pub const BTN_SELECT: EvCode = EvCode(nec::BTN_SELECT);
339 pub const BTN_START: EvCode = EvCode(nec::BTN_START);
340 pub const BTN_MODE: EvCode = EvCode(nec::BTN_MODE);
341 pub const BTN_LTHUMB: EvCode = EvCode(nec::BTN_LTHUMB);
342 pub const BTN_RTHUMB: EvCode = EvCode(nec::BTN_RTHUMB);
343
344 pub const BTN_DPAD_UP: EvCode = EvCode(nec::BTN_DPAD_UP);
345 pub const BTN_DPAD_DOWN: EvCode = EvCode(nec::BTN_DPAD_DOWN);
346 pub const BTN_DPAD_LEFT: EvCode = EvCode(nec::BTN_DPAD_LEFT);
347 pub const BTN_DPAD_RIGHT: EvCode = EvCode(nec::BTN_DPAD_RIGHT);
348}