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(());