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