evdev_rs_tokio/
lib.rs

1//! Rust bindings to libevdev, a wrapper for evdev devices.
2//!
3//! This library intends to provide a safe interface to the libevdev library. It
4//! will look for the library on the local system, and link to the installed copy.
5//!
6//! # Examples
7//!
8//! ## Intializing a evdev device
9//!
10//! ```rust,no_run
11//! use evdev_rs::Device;
12//! use std::fs::File;
13//!
14//! let file = File::open("/dev/input/event0").unwrap();
15//! let mut d = Device::new_from_file(file).unwrap();
16//! ```
17//!
18//! ## Getting the next event
19//!
20//! ```rust,no_run
21//! use evdev_rs::Device;
22//! use std::fs::File;
23//! use evdev_rs::ReadFlag;
24//!
25//! let file = File::open("/dev/input/event0").unwrap();
26//! let mut d = Device::new_from_file(file).unwrap();
27//!
28//! loop {
29//!     let ev = d.next_event(ReadFlag::NORMAL | ReadFlag::BLOCKING).map(|val| val.1);
30//!     match ev {
31//!         Ok(ev) => println!("Event: time {}.{}, ++++++++++++++++++++ {} +++++++++++++++",
32//!                           ev.time.tv_sec,
33//!                           ev.time.tv_usec,
34//!                           ev.event_type().map(|ev_type| format!("{}", ev_type)).unwrap_or("".to_owned())),
35//!         Err(e) => (),
36//!     }
37//! }
38//! ```
39//!
40//! ## Serialization
41//! to use serialization, you muse enable the `serde` feature.
42//! ```toml
43//! # Cargo.toml
44//! [dependencies]
45//! evdev-rs = { version = "0.4.0", features = ["serde"] }
46//! ```
47
48#[macro_use]
49mod macros;
50pub mod device;
51pub mod enums;
52pub mod logging;
53pub mod uinput;
54pub mod util;
55
56use bitflags::bitflags;
57use libc::{c_uint, suseconds_t, time_t};
58use std::convert::{TryFrom, TryInto};
59use std::time::{Duration, SystemTime, SystemTimeError, UNIX_EPOCH};
60
61use enums::*;
62use util::*;
63
64use evdev_sys as raw;
65
66#[doc(inline)]
67pub use device::Device;
68#[doc(inline)]
69pub use device::DeviceWrapper;
70#[doc(inline)]
71pub use device::UninitDevice;
72#[doc(inline)]
73pub use uinput::UInputDevice;
74
75#[cfg(feature = "serde")]
76use serde::{Deserialize, Serialize};
77
78pub enum GrabMode {
79    /// Grab the device if not currently grabbed
80    Grab = raw::LIBEVDEV_GRAB as isize,
81    /// Ungrab the device if currently grabbed
82    Ungrab = raw::LIBEVDEV_UNGRAB as isize,
83}
84
85bitflags! {
86    pub struct ReadFlag: u32 {
87        /// Process data in sync mode
88        const SYNC = 1;
89        /// Process data in normal mode
90        const NORMAL = 2;
91        /// Pretend the next event is a SYN_DROPPED and require the
92        /// caller to sync
93        const FORCE_SYNC = 4;
94        /// The fd is not in O_NONBLOCK and a read may block
95        const BLOCKING = 8;
96    }
97}
98
99#[derive(PartialEq)]
100pub enum ReadStatus {
101    /// `next_event` has finished without an error and an event is available
102    /// for processing.
103    Success = raw::LIBEVDEV_READ_STATUS_SUCCESS as isize,
104    /// Depending on the `next_event` read flag:
105    /// libevdev received a SYN_DROPPED from the device, and the caller should
106    /// now resync the device, or, an event has been read in sync mode.
107    Sync = raw::LIBEVDEV_READ_STATUS_SYNC as isize,
108}
109
110pub enum LedState {
111    /// Turn the LED on
112    On = raw::LIBEVDEV_LED_ON as isize,
113    /// Turn the LED off
114    Off = raw::LIBEVDEV_LED_OFF as isize,
115}
116
117pub struct DeviceId {
118    pub bustype: BusType,
119    pub vendor: u16,
120    pub product: u16,
121    pub version: u16,
122}
123
124/// used by EVIOCGABS/EVIOCSABS ioctls
125pub struct AbsInfo {
126    /// latest reported value for the axis
127    pub value: i32,
128    /// specifies minimum value for the axis
129    pub minimum: i32,
130    /// specifies maximum value for the axis
131    pub maximum: i32,
132    /// specifies fuzz value that is used to filter noise from
133    /// the event stream
134    pub fuzz: i32,
135    /// values that are within this value will be discarded by
136    /// joydev interface and reported as 0 instead
137    pub flat: i32,
138    /// specifies resolution for the values reported for
139    /// the axis
140    pub resolution: i32,
141}
142
143impl AbsInfo {
144    pub fn from_raw(absinfo: libc::input_absinfo) -> AbsInfo {
145        AbsInfo {
146            value: absinfo.value,
147            minimum: absinfo.minimum,
148            maximum: absinfo.maximum,
149            fuzz: absinfo.fuzz,
150            flat: absinfo.flat,
151            resolution: absinfo.resolution,
152        }
153    }
154
155    pub fn as_raw(&self) -> libc::input_absinfo {
156        libc::input_absinfo {
157            value: self.value,
158            minimum: self.minimum,
159            maximum: self.maximum,
160            fuzz: self.fuzz,
161            flat: self.flat,
162            resolution: self.resolution,
163        }
164    }
165}
166
167#[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))]
168#[derive(Copy, Clone, Eq, Hash, PartialOrd, Ord, Debug, PartialEq)]
169pub struct TimeVal {
170    pub tv_sec: time_t,
171    pub tv_usec: suseconds_t,
172}
173
174impl TryFrom<SystemTime> for TimeVal {
175    type Error = SystemTimeError;
176    fn try_from(system_time: SystemTime) -> Result<Self, Self::Error> {
177        let d = system_time.duration_since(UNIX_EPOCH)?;
178        Ok(TimeVal {
179            tv_sec: d.as_secs() as time_t,
180            tv_usec: d.subsec_micros() as suseconds_t,
181        })
182    }
183}
184
185impl TryInto<SystemTime> for TimeVal {
186    type Error = ();
187    /// Fails if TimeVal.tv_usec is >= 10^6 or if the TimeVal is outside
188    /// the range of SystemTime
189    fn try_into(self) -> Result<SystemTime, Self::Error> {
190        let secs = self.tv_sec.try_into().map_err(|_| ())?;
191        let nanos = (self.tv_usec * 1000).try_into().map_err(|_| ())?;
192        let duration = Duration::new(secs, nanos);
193        UNIX_EPOCH.checked_add(duration).ok_or(())
194    }
195}
196
197impl TimeVal {
198    pub fn new(tv_sec: time_t, tv_usec: suseconds_t) -> TimeVal {
199        const MICROS_PER_SEC: suseconds_t = 1_000_000;
200        TimeVal {
201            tv_sec: tv_sec + tv_usec / MICROS_PER_SEC,
202            tv_usec: tv_usec % MICROS_PER_SEC,
203        }
204    }
205
206    pub fn from_raw(timeval: &libc::timeval) -> TimeVal {
207        TimeVal {
208            tv_sec: timeval.tv_sec,
209            tv_usec: timeval.tv_usec,
210        }
211    }
212
213    pub fn as_raw(&self) -> libc::timeval {
214        libc::timeval {
215            tv_sec: self.tv_sec,
216            tv_usec: self.tv_usec,
217        }
218    }
219}
220
221/// The event structure itself
222#[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))]
223#[derive(Clone, Debug, PartialEq, Eq, Hash)]
224pub struct InputEvent {
225    /// The time at which event occured
226    pub time: TimeVal,
227    pub event_code: EventCode,
228    pub value: i32,
229}
230
231impl InputEvent {
232    pub fn new(timeval: &TimeVal, code: &EventCode, value: i32) -> InputEvent {
233        InputEvent {
234            time: *timeval,
235            event_code: *code,
236            value,
237        }
238    }
239
240    pub fn event_type(&self) -> Option<EventType> {
241        int_to_event_type(event_code_to_int(&self.event_code).0)
242    }
243
244    pub fn from_raw(event: &libc::input_event) -> InputEvent {
245        let ev_type = event.type_ as u32;
246        let event_code = int_to_event_code(ev_type, event.code as u32);
247        InputEvent {
248            time: TimeVal::from_raw(&event.time),
249            event_code,
250            value: event.value,
251        }
252    }
253
254    pub fn as_raw(&self) -> libc::input_event {
255        let (ev_type, ev_code) = event_code_to_int(&self.event_code);
256        libc::input_event {
257            time: self.time.as_raw(),
258            type_: ev_type as u16,
259            code: ev_code as u16,
260            value: self.value,
261        }
262    }
263
264    pub fn is_type(&self, ev_type: &EventType) -> bool {
265        unsafe { raw::libevdev_event_is_type(&self.as_raw(), *ev_type as c_uint) == 1 }
266    }
267
268    pub fn is_code(&self, code: &EventCode) -> bool {
269        let (ev_type, ev_code) = event_code_to_int(code);
270
271        unsafe { raw::libevdev_event_is_code(&self.as_raw(), ev_type, ev_code) == 1 }
272    }
273}