sweetacid_evdev/
lib.rs

1//! Linux event device handling.
2//!
3//! The Linux kernel's "evdev" subsystem exposes input devices to userspace in a generic,
4//! consistent way. I'll try to explain the device model as completely as possible. The upstream
5//! kernel documentation is split across two files:
6//!
7//! - https://www.kernel.org/doc/Documentation/input/event-codes.txt
8//! - https://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt
9//!
10//! Devices emit events, represented by the [`InputEvent`] type. Each device supports a few different
11//! kinds of events, specified by the [`EventType`] struct and the [`Device::supported_events()`]
12//! method. Most event types also have a "subtype", e.g. a `KEY` event with a `KEY_ENTER` code. This
13//! type+subtype combo is represented by [`InputEventKind`]/[`InputEvent::kind()`]. The individual
14//! subtypes of a type that a device supports can be retrieved through the `Device::supported_*()`
15//! methods, e.g. [`Device::supported_keys()`]:
16//!
17//! ```no_run
18//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
19//! use evdev::{Device, Key};
20//! let device = Device::open("/dev/input/event0")?;
21//! // check if the device has an ENTER key
22//! if device.supported_keys().map_or(false, |keys| keys.contains(Key::KEY_ENTER)) {
23//!     println!("are you prepared to ENTER the world of evdev?");
24//! } else {
25//!     println!(":(");
26//! }
27//! # Ok(())
28//! # }
29//! ```
30//!
31//! The evdev crate exposes functions to query the current state of a device from the kernel, as
32//! well as a function that can be called continuously to provide an iterator over update events
33//! as they arrive.
34//!
35//! # Synchronizing versus Raw modes
36//!
37//! This library can be used in either Raw or Synchronizing modes, which correspond roughly to
38//! evdev's `LIBEVDEV_READ_FLAG_NORMAL` and `LIBEVDEV_READ_FLAG_SYNC` modes, respectively.
39//! In both modes, calling `fetch_events` and driving the resulting iterator to completion
40//! will provide a stream of real-time events from the underlying kernel device state.
41//! As the state changes, the kernel will write events into a ring buffer. If the buffer becomes full, the
42//! kernel will *drop* events from the ring buffer and leave an event telling userspace that it
43//! did so. At this point, if the application were using the events it received to update its
44//! internal idea of what state the hardware device is in, it will be wrong: it is missing some
45//! events.
46//!
47//! In synchronous mode, this library tries to ease that pain by removing the corrupted events
48//! and injecting fake events as if the device had updated normally. Note that this is best-effort;
49//! events can never be recovered once lost. This synchronization comes at a performance cost: each
50//! set of input events read from the kernel in turn updates an internal state buffer, and events
51//! must be internally held back until the end of each frame. If this latency is unacceptable or
52//! for any reason you want to see every event directly, a raw stream reader is also provided.
53//!
54//! As an example of how synchronization behaves, if a switch is toggled twice there will be two switch events
55//! in the buffer. However, if the kernel needs to drop events, when the device goes to synchronize
56//! state with the kernel only one (or zero, if the switch is in the same state as it was before
57//! the sync) switch events will be visible in the stream.
58//!
59//! This cache can also be queried. For example, the [`DeviceState::led_vals`] method will tell you which
60//! LEDs are currently lit on the device. As calling code consumes each iterator, this state will be
61//! updated, and it will be fully re-synchronized with the kernel if the stream drops any events.
62//!
63//! It is recommended that you dedicate a thread to processing input events, or use epoll or an
64//! async runtime with the fd returned by `<Device as AsRawFd>::as_raw_fd` to process events when
65//! they are ready.
66//!
67//! For demonstrations of how to use this library in blocking, nonblocking, and async (tokio) modes,
68//! please reference the "examples" directory.
69
70// should really be cfg(target_os = "linux") and maybe also android?
71#![cfg(unix)]
72
73// has to be first for its macro
74#[macro_use]
75mod attribute_set;
76
77mod constants;
78mod device_state;
79mod inputid;
80pub mod raw_stream;
81mod scancodes;
82mod sync_stream;
83mod sys;
84pub mod uinput;
85
86#[cfg(feature = "tokio")]
87mod tokio_stream;
88
89use std::fmt;
90use std::time::{Duration, SystemTime};
91
92// pub use crate::constants::FFEffect::*;
93pub use attribute_set::{AttributeSet, AttributeSetRef};
94pub use constants::*;
95pub use device_state::DeviceState;
96pub use inputid::*;
97pub use raw_stream::AutoRepeat;
98pub use scancodes::*;
99pub use sync_stream::*;
100
101const EVENT_BATCH_SIZE: usize = 32;
102
103/// A convenience mapping from an event `(type, code)` to an enumeration.
104///
105/// Note that this does not capture an event's value, just the type and code.
106#[derive(Debug, Copy, Clone, PartialEq, Eq)]
107pub enum InputEventKind {
108    Synchronization(Synchronization),
109    Key(Key),
110    RelAxis(RelativeAxisType),
111    AbsAxis(AbsoluteAxisType),
112    Misc(MiscType),
113    Switch(SwitchType),
114    Led(LedType),
115    Sound(SoundType),
116    Other,
117}
118
119/// A wrapped `libc::input_event` returned by the input device via the kernel.
120///
121/// `input_event` is a struct containing four fields:
122/// - `time: timeval`
123/// - `type_: u16`
124/// - `code: u16`
125/// - `value: s32`
126///
127/// The meaning of the "code" and "value" fields will depend on the underlying type of event.
128#[derive(Copy, Clone)]
129#[repr(transparent)]
130pub struct InputEvent(libc::input_event);
131
132impl InputEvent {
133    /// Returns the timestamp associated with the event.
134    #[inline]
135    pub fn timestamp(&self) -> SystemTime {
136        timeval_to_systime(&self.0.time)
137    }
138
139    /// Returns the type of event this describes, e.g. Key, Switch, etc.
140    #[inline]
141    pub fn event_type(&self) -> EventType {
142        EventType(self.0.type_)
143    }
144
145    /// Returns the raw "code" field directly from input_event.
146    #[inline]
147    pub fn code(&self) -> u16 {
148        self.0.code
149    }
150
151    /// A convenience function to return `self.code()` wrapped in a certain newtype determined by
152    /// the type of this event.
153    ///
154    /// This is useful if you want to match events by specific key codes or axes. Note that this
155    /// does not capture the event value, just the type and code.
156    #[inline]
157    pub fn kind(&self) -> InputEventKind {
158        let code = self.code();
159        match self.event_type() {
160            EventType::SYNCHRONIZATION => InputEventKind::Synchronization(Synchronization(code)),
161            EventType::KEY => InputEventKind::Key(Key::new(code)),
162            EventType::RELATIVE => InputEventKind::RelAxis(RelativeAxisType(code)),
163            EventType::ABSOLUTE => InputEventKind::AbsAxis(AbsoluteAxisType(code)),
164            EventType::MISC => InputEventKind::Misc(MiscType(code)),
165            EventType::SWITCH => InputEventKind::Switch(SwitchType(code)),
166            EventType::LED => InputEventKind::Led(LedType(code)),
167            EventType::SOUND => InputEventKind::Sound(SoundType(code)),
168            _ => InputEventKind::Other,
169        }
170    }
171
172    /// Returns the raw "value" field directly from input_event.
173    ///
174    /// For keys and switches the values 0 and 1 map to pressed and not pressed respectively.
175    /// For axes, the values depend on the hardware and driver implementation.
176    #[inline]
177    pub fn value(&self) -> i32 {
178        self.0.value
179    }
180
181    /// Create a new InputEvent. Only really useful for emitting events on virtual devices.
182    pub fn new(type_: EventType, code: u16, value: i32) -> Self {
183        InputEvent(libc::input_event {
184            time: libc::timeval {
185                tv_sec: 0,
186                tv_usec: 0,
187            },
188            type_: type_.0,
189            code,
190            value,
191        })
192    }
193
194    /// Create a new InputEvent with the time field set to "now" on the system clock.
195    ///
196    /// Note that this isn't usually necessary simply for emitting events on a virtual device, as
197    /// even though [`InputEvent::new`] creates an `input_event` with the time field as zero,
198    /// the kernel will update `input_event.time` when it emits the events to any programs reading
199    /// the event "file".
200    pub fn new_now(type_: EventType, code: u16, value: i32) -> Self {
201        InputEvent(libc::input_event {
202            time: systime_to_timeval(&SystemTime::now()),
203            type_: type_.0,
204            code,
205            value,
206        })
207    }
208}
209
210impl From<libc::input_event> for InputEvent {
211    fn from(raw: libc::input_event) -> Self {
212        Self(raw)
213    }
214}
215
216impl AsRef<libc::input_event> for InputEvent {
217    fn as_ref(&self) -> &libc::input_event {
218        &self.0
219    }
220}
221
222impl fmt::Debug for InputEvent {
223    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
224        let mut debug = f.debug_struct("InputEvent");
225        debug.field("time", &self.timestamp());
226        let kind = self.kind();
227        if let InputEventKind::Other = kind {
228            debug
229                .field("type", &self.event_type())
230                .field("code", &self.code());
231        } else {
232            debug.field("kind", &kind);
233        }
234        debug.field("value", &self.value()).finish()
235    }
236}
237
238/// Crawls `/dev/input` for evdev devices.
239///
240/// Will not bubble up any errors in opening devices or traversing the directory. Instead returns
241/// an empty iterator or omits the devices that could not be opened.
242pub fn enumerate() -> EnumerateDevices {
243    EnumerateDevices {
244        inner: raw_stream::enumerate(),
245    }
246}
247
248pub struct EnumerateDevices {
249    inner: raw_stream::EnumerateDevices,
250}
251impl Iterator for EnumerateDevices {
252    type Item = Device;
253    fn next(&mut self) -> Option<Device> {
254        self.inner.next().map(Device::from_raw_device)
255    }
256}
257
258/// A safe Rust version of clock_gettime against CLOCK_REALTIME
259fn systime_to_timeval(time: &SystemTime) -> libc::timeval {
260    let (sign, dur) = match time.duration_since(SystemTime::UNIX_EPOCH) {
261        Ok(dur) => (1, dur),
262        Err(e) => (-1, e.duration()),
263    };
264
265    libc::timeval {
266        tv_sec: dur.as_secs() as libc::time_t * sign,
267        tv_usec: dur.subsec_micros() as libc::suseconds_t,
268    }
269}
270
271fn timeval_to_systime(tv: &libc::timeval) -> SystemTime {
272    let dur = Duration::new(tv.tv_sec.abs() as u64, tv.tv_usec as u32 * 1000);
273    if tv.tv_sec >= 0 {
274        SystemTime::UNIX_EPOCH + dur
275    } else {
276        SystemTime::UNIX_EPOCH - dur
277    }
278}
279
280/// SAFETY: T must not have any padding or otherwise uninitialized bytes inside of it
281pub(crate) unsafe fn cast_to_bytes<T: ?Sized>(mem: &T) -> &[u8] {
282    std::slice::from_raw_parts(mem as *const T as *const u8, std::mem::size_of_val(mem))
283}
284
285#[derive(Debug, Clone, PartialEq, Eq)]
286pub struct EnumParseError(());