hidg_core/
lib.rs

1#![forbid(future_incompatible)]
2#![deny(bad_style, missing_docs)]
3#![doc = include_str!("../README.md")]
4
5#[cfg(not(target_os = "linux"))]
6compile_error!("This crate support Linux only");
7
8#[cfg(feature = "serde")]
9use serde::{Deserialize, Serialize};
10
11#[macro_use]
12mod macros;
13
14#[cfg(feature = "either")]
15mod either_report;
16
17#[cfg(feature = "keyboard")]
18mod keyboard;
19
20#[cfg(feature = "mouse")]
21mod mouse;
22
23#[cfg(feature = "keyboard")]
24pub use keyboard::{
25    Key, KeyStateChanges, Keyboard, KeyboardInput, KeyboardOutput, Led, LedStateChanges, Leds,
26    Modifiers,
27};
28
29#[cfg(feature = "mouse")]
30pub use mouse::{
31    Button, Buttons, Mouse, MouseInput, MouseInputChange, MouseInputChanges, MouseOutput,
32};
33
34use std::{
35    io::ErrorKind,
36    path::{Path, PathBuf},
37};
38
39pub use std::io::{Error, Result};
40
41/// Unknown error
42#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
43pub struct Unknown;
44
45impl std::error::Error for Unknown {}
46
47impl core::fmt::Display for Unknown {
48    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
49        f.write_str("Unknown")
50    }
51}
52
53/// Key/button/LED state change event
54#[derive(Clone, Copy, Debug, PartialEq, Eq)]
55#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
56pub struct StateChange<T> {
57    data: T,
58    state: bool,
59}
60
61impl<T> StateChange<T> {
62    /// Create new state change event
63    pub fn new(data: T, state: bool) -> Self {
64        Self { data, state }
65    }
66
67    /// Create new press event
68    pub fn press(data: T) -> Self {
69        Self::new(data, true)
70    }
71
72    /// Create new on event
73    pub fn on(data: T) -> Self {
74        Self::new(data, true)
75    }
76
77    /// Create new release event
78    pub fn release(data: T) -> Self {
79        Self::new(data, false)
80    }
81
82    /// Create new off event
83    pub fn off(data: T) -> Self {
84        Self::new(data, false)
85    }
86
87    /// Get data
88    pub fn data(&self) -> T
89    where
90        T: Copy,
91    {
92        self.data
93    }
94
95    /// Get state
96    pub fn state(&self) -> bool {
97        self.state
98    }
99
100    /// Is key/button press event
101    pub fn is_press(&self) -> bool {
102        self.state
103    }
104
105    /// Is LED on event
106    pub fn is_on(&self) -> bool {
107        self.state
108    }
109
110    /// Is key/button release event
111    pub fn is_release(&self) -> bool {
112        !self.state
113    }
114
115    /// Is LED off event
116    pub fn is_off(&self) -> bool {
117        !self.state
118    }
119}
120
121impl<T> From<(T, bool)> for StateChange<T> {
122    fn from((data, state): (T, bool)) -> Self {
123        Self { data, state }
124    }
125}
126
127impl<T> From<StateChange<T>> for (T, bool) {
128    fn from(StateChange { data, state }: StateChange<T>) -> Self {
129        (data, state)
130    }
131}
132
133/// Pointer/cursor position change event
134#[derive(Clone, Copy, Debug, PartialEq, Eq)]
135#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
136pub struct ValueChange<T> {
137    data: T,
138    #[cfg_attr(feature = "serde", serde(rename = "rel"))]
139    relative: bool,
140}
141
142impl<T> ValueChange<T> {
143    /// Create new value change event
144    pub fn new(data: T, relative: bool) -> Self {
145        Self { data, relative }
146    }
147
148    /// Get underlying data
149    pub fn data(&self) -> T
150    where
151        T: Copy,
152    {
153        self.data
154    }
155
156    /// Create new absolute value change event
157    pub fn absolute(data: T) -> Self {
158        Self::new(data, false)
159    }
160
161    /// Create new relative value change event
162    pub fn relative(data: T) -> Self {
163        Self::new(data, true)
164    }
165
166    /// Is value change relative
167    pub fn is_relative(&self) -> bool {
168        self.relative
169    }
170
171    /// Is value change absolute
172    pub fn is_absolute(&self) -> bool {
173        !self.relative
174    }
175}
176
177impl<T> From<(T, bool)> for ValueChange<T> {
178    fn from((data, relative): (T, bool)) -> Self {
179        Self { data, relative }
180    }
181}
182
183impl<T> From<ValueChange<T>> for (T, bool) {
184    fn from(ValueChange { data, relative }: ValueChange<T>) -> Self {
185        (data, relative)
186    }
187}
188
189deref_impl! {
190    StateChange<T> => data: T,
191    ValueChange<T> => data: T,
192}
193
194/// Device class trait
195pub trait Class {
196    /// Input report type
197    type Input;
198
199    /// Output report type
200    type Output;
201
202    /// Create input report
203    fn input(&self) -> Self::Input;
204
205    /// Create output report
206    fn output(&self) -> Self::Output;
207}
208
209/// Device path trait
210pub trait AsDevicePath {
211    /// Get absolute device path
212    fn as_device_path(&self) -> PathBuf;
213}
214
215impl AsDevicePath for Path {
216    fn as_device_path(&self) -> PathBuf {
217        if self.is_absolute() {
218            self.to_path_buf()
219        } else {
220            Path::new("/dev").join(self)
221        }
222    }
223}
224
225impl AsDevicePath for &Path {
226    fn as_device_path(&self) -> PathBuf {
227        if self.is_absolute() {
228            self.to_path_buf()
229        } else {
230            Path::new("/dev").join(self)
231        }
232    }
233}
234
235impl AsDevicePath for PathBuf {
236    fn as_device_path(&self) -> PathBuf {
237        let path: &Path = self;
238        path.as_device_path()
239    }
240}
241
242impl AsDevicePath for &PathBuf {
243    fn as_device_path(&self) -> PathBuf {
244        let path: &Path = self;
245        path.as_device_path()
246    }
247}
248
249impl AsDevicePath for &str {
250    fn as_device_path(&self) -> PathBuf {
251        Path::new(self).as_device_path()
252    }
253}
254
255impl AsDevicePath for String {
256    fn as_device_path(&self) -> PathBuf {
257        let s: &str = self;
258        s.as_device_path()
259    }
260}
261
262impl AsDevicePath for &String {
263    fn as_device_path(&self) -> PathBuf {
264        let s: &str = self;
265        s.as_device_path()
266    }
267}
268
269impl AsDevicePath for usize {
270    fn as_device_path(&self) -> PathBuf {
271        format!("/dev/hidg{self}").as_device_path()
272    }
273}
274
275macro_rules! as_device_path {
276    ($($type:ty),*) => {
277        $(
278            impl AsDevicePath for $type {
279                fn as_device_path(&self) -> PathBuf {
280                    (*self as usize).as_device_path()
281                }
282            }
283        )*
284    };
285}
286
287as_device_path!(u8, u16, u32, u64, i8, i16, i32, i64, isize);
288
289/// Wrapper to hide internals
290#[derive(Clone, Copy, Default)]
291pub struct Internal<T>(T);
292
293impl<T> core::ops::Deref for Internal<T> {
294    type Target = T;
295
296    fn deref(&self) -> &Self::Target {
297        &self.0
298    }
299}
300
301impl<T> core::ops::DerefMut for Internal<T> {
302    fn deref_mut(&mut self) -> &mut Self::Target {
303        &mut self.0
304    }
305}
306
307/// Check write report length
308pub fn check_write(actual: usize, expected: usize) -> Result<()> {
309    if actual == expected {
310        Ok(())
311    } else {
312        Err(Error::new(ErrorKind::Other, "Error when writing report"))
313    }
314}
315
316/// Check read report length
317pub fn check_read(actual: usize, expected: usize) -> Result<()> {
318    if actual == expected {
319        Ok(())
320    } else {
321        Err(Error::new(ErrorKind::Other, "Error when reading report"))
322    }
323}