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#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
93    pub struct ReadFlag: u32 {
94        /// Process data in sync mode
95        const SYNC = 1;
96        /// Process data in normal mode
97        const NORMAL = 2;
98        /// Pretend the next event is a SYN_DROPPED and require the
99        /// caller to sync
100        const FORCE_SYNC = 4;
101        /// The fd is not in O_NONBLOCK and a read may block
102        const BLOCKING = 8;
103    }
104}
105
106#[derive(PartialEq)]
107pub enum ReadStatus {
108    /// `next_event` has finished without an error and an event is available
109    /// for processing.
110    Success = raw::LIBEVDEV_READ_STATUS_SUCCESS as isize,
111    /// Depending on the `next_event` read flag:
112    /// libevdev received a SYN_DROPPED from the device, and the caller should
113    /// now resync the device, or, an event has been read in sync mode.
114    Sync = raw::LIBEVDEV_READ_STATUS_SYNC as isize,
115}
116
117pub enum LedState {
118    /// Turn the LED on
119    On = raw::LIBEVDEV_LED_ON as isize,
120    /// Turn the LED off
121    Off = raw::LIBEVDEV_LED_OFF as isize,
122}
123
124#[derive(Debug)]
125pub struct DeviceId {
126    pub bustype: BusType,
127    pub vendor: u16,
128    pub product: u16,
129    pub version: u16,
130}
131
132#[derive(Clone, Copy, Debug)]
133/// used by EVIOCGABS/EVIOCSABS ioctls
134pub struct AbsInfo {
135    /// latest reported value for the axis
136    pub value: i32,
137    /// specifies minimum value for the axis
138    pub minimum: i32,
139    /// specifies maximum value for the axis
140    pub maximum: i32,
141    /// specifies fuzz value that is used to filter noise from
142    /// the event stream
143    pub fuzz: i32,
144    /// values that are within this value will be discarded by
145    /// joydev interface and reported as 0 instead
146    pub flat: i32,
147    /// specifies resolution for the values reported for
148    /// the axis
149    pub resolution: i32,
150}
151
152impl AbsInfo {
153    pub const fn from_raw(absinfo: libc::input_absinfo) -> AbsInfo {
154        AbsInfo {
155            value: absinfo.value,
156            minimum: absinfo.minimum,
157            maximum: absinfo.maximum,
158            fuzz: absinfo.fuzz,
159            flat: absinfo.flat,
160            resolution: absinfo.resolution,
161        }
162    }
163
164    pub const fn as_raw(&self) -> libc::input_absinfo {
165        libc::input_absinfo {
166            value: self.value,
167            minimum: self.minimum,
168            maximum: self.maximum,
169            fuzz: self.fuzz,
170            flat: self.flat,
171            resolution: self.resolution,
172        }
173    }
174}
175
176#[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))]
177#[derive(Copy, Clone, Eq, Hash, PartialOrd, Ord, Debug, PartialEq)]
178pub struct TimeVal {
179    pub tv_sec: time_t,
180    pub tv_usec: suseconds_t,
181}
182
183impl TryFrom<SystemTime> for TimeVal {
184    type Error = SystemTimeError;
185    fn try_from(system_time: SystemTime) -> Result<Self, Self::Error> {
186        let d = system_time.duration_since(UNIX_EPOCH)?;
187        Ok(TimeVal {
188            tv_sec: d.as_secs() as time_t,
189            tv_usec: d.subsec_micros() as suseconds_t,
190        })
191    }
192}
193
194impl TryInto<SystemTime> for TimeVal {
195    type Error = ();
196    /// Fails if TimeVal.tv_usec is >= 10^6 or if the TimeVal is outside
197    /// the range of SystemTime
198    fn try_into(self) -> Result<SystemTime, Self::Error> {
199        let secs = self.tv_sec.try_into().map_err(|_| ())?;
200        let nanos = (self.tv_usec * 1000).try_into().map_err(|_| ())?;
201        let duration = Duration::new(secs, nanos);
202        UNIX_EPOCH.checked_add(duration).ok_or(())
203    }
204}
205
206impl TimeVal {
207    pub const fn new(tv_sec: time_t, tv_usec: suseconds_t) -> TimeVal {
208        const MICROS_PER_SEC: suseconds_t = 1_000_000;
209        TimeVal {
210            tv_sec: tv_sec + tv_usec / MICROS_PER_SEC,
211            tv_usec: tv_usec % MICROS_PER_SEC,
212        }
213    }
214
215    pub const fn from_raw(timeval: &libc::timeval) -> TimeVal {
216        TimeVal {
217            tv_sec: timeval.tv_sec,
218            tv_usec: timeval.tv_usec,
219        }
220    }
221
222    pub const fn as_raw(&self) -> libc::timeval {
223        libc::timeval {
224            tv_sec: self.tv_sec,
225            tv_usec: self.tv_usec,
226        }
227    }
228}
229
230/// The event structure itself
231#[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))]
232#[derive(Clone, Debug, PartialEq, Eq, Hash)]
233pub struct InputEvent {
234    /// The time at which event occured
235    pub time: TimeVal,
236    pub event_code: EventCode,
237    pub value: i32,
238}
239
240impl InputEvent {
241    pub const fn new(timeval: &TimeVal, code: &EventCode, value: i32) -> InputEvent {
242        InputEvent {
243            time: *timeval,
244            event_code: *code,
245            value,
246        }
247    }
248
249    pub fn event_type(&self) -> Option<EventType> {
250        int_to_event_type(event_code_to_int(&self.event_code).0)
251    }
252
253    pub fn from_raw(event: &libc::input_event) -> InputEvent {
254        let ev_type = event.type_ as u32;
255        let event_code = int_to_event_code(ev_type, event.code as u32);
256        InputEvent {
257            time: TimeVal::from_raw(&event.time),
258            event_code,
259            value: event.value,
260        }
261    }
262
263    pub fn as_raw(&self) -> libc::input_event {
264        let (ev_type, ev_code) = event_code_to_int(&self.event_code);
265        libc::input_event {
266            time: self.time.as_raw(),
267            type_: ev_type as u16,
268            code: ev_code as u16,
269            value: self.value,
270        }
271    }
272
273    pub fn is_type(&self, ev_type: &EventType) -> bool {
274        unsafe { raw::libevdev_event_is_type(&self.as_raw(), *ev_type as c_uint) == 1 }
275    }
276
277    pub fn is_code(&self, code: &EventCode) -> bool {
278        let (ev_type, ev_code) = event_code_to_int(code);
279
280        unsafe { raw::libevdev_event_is_code(&self.as_raw(), ev_type, ev_code) == 1 }
281    }
282}