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//! The `evdev` kernel system exposes input devices as character devices in `/dev/input`,
11//! typically `/dev/input/eventX` where `X` is an integer.
12//! Userspace applications can use `ioctl` system calls to interact with these devices.
13//! Libraries such as this one abstract away the low level calls to provide a high level
14//! interface.
15//!
16//! Applications can interact with `uinput` by writing to `/dev/uinput` to create virtual
17//! devices and send events to the virtual devices.
18//! Virtual devices are created in `/sys/devices/virtual/input`.
19//!
20//! # Devices
21//!
22//! Devices can be opened directly via their path:
23//! ```no_run
24//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
25//! use evdev::Device;
26//! let device = Device::open("/dev/input/event0")?;
27//! # Ok(())
28//! # }
29//! ```
30//! This approach requires the calling process to have the appropriate privileges to
31//! open the device node (typically this requires running as root user).
32//! Alternatively a device can be created from an already open file descriptor. This approach
33//! is useful where the file descriptor is provided by an external privileged process
34//! (e.g. systemd's logind):
35//!
36//! ```no_run
37//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
38//! use evdev::Device;
39//! use std::fs::File;
40//! use std::os::fd::OwnedFd;
41//! let f = File::open("/dev/input/event0")?;
42//! let fd = OwnedFd::from(f);
43//! let device = Device::from_fd(fd)?;
44//! # Ok(())
45//! # }
46//! ```
47//!
48//! # Input Events
49//!
50//! Devices emit events, represented by the [`InputEvent`] struct.
51//! A input event has three main fields: event [type](InputEvent::event_type), [code](InputEvent::code)
52//! and [value](InputEvent::value)
53//!
54//! The kernel documentation specifies different event types, reperesented by the [`EventType`] struct.
55//! Each device can support a subset of those types. See [`Device::supported_events()`].
56//! For each of the known event types there is a new-type wrapper around [`InputEvent`]
57//! in [`event_variants`] see the module documenation for more info about those.
58//!
59//! For most event types the kernel documentation also specifies a set of codes, represented by a new-type
60//! e.g. [`KeyCode`]. The individual codes of a [`EventType`] that a device supports can be retrieved
61//! through the `Device::supported_*()` methods, e.g. [`Device::supported_keys()`]:
62//! ```no_run
63//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
64//! use evdev::{Device, KeyCode};
65//! let device = Device::open("/dev/input/event0")?;
66//! // check if the device has an ENTER key
67//! if device.supported_keys().map_or(false, |keys| keys.contains(KeyCode::KEY_ENTER)) {
68//! println!("are you prepared to ENTER the world of evdev?");
69//! } else {
70//! println!(":(");
71//! }
72//! # Ok(())
73//! # }
74//! ```
75//! A [`InputEvent`] with a type of [`EventType::KEY`] a code of [`KeyCode::KEY_ENTER`] and a
76//! value of 1 is emitted when the Enter key is pressed.
77//!
78//! All events (even single events) are sent in batches followed by a synchronization event:
79//! `EV_SYN / SYN_REPORT / 0`.
80//! Events are grouped into batches based on if they are related and occur simultaneously,
81//! for example movement of a mouse triggers a movement event for the `X` and `Y` axes
82//! separately in a batch of 2 events.
83//!
84//! The evdev crate exposes functions to query the current state of a device from the kernel, as
85//! well as a function that can be called continuously to provide an iterator over update events
86//! as they arrive.
87//!
88//! ## Matching Events
89//!
90//! When reading from an input Device it is often useful to check which type/code or value
91//! the event has. This library provides the [`EventSummary`] enum which can be used to
92//! match specific events. Calling [`InputEvent::destructure`] will return that enum.
93//!
94//! ```no_run
95//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
96//! use evdev::*;
97//! let mut device = Device::open("/dev/input/event0")?;
98//! loop {
99//! for event in device.fetch_events().unwrap(){
100//! match event.destructure(){
101//! EventSummary::Key(ev, KeyCode::KEY_A, 1) => {
102//! println!("Key 'a' was pressed, got event: {:?}", ev);
103//! },
104//! EventSummary::Key(_, key_type, 0) => {
105//! println!("Key {:?} was released", key_type);
106//! },
107//! EventSummary::AbsoluteAxis(_, axis, value) => {
108//! println!("The Axis {:?} was moved to {}", axis, value);
109//! },
110//! _ => println!("got a different event!")
111//! }
112//! }
113//! }
114//! # unreachable!()
115//! # }
116//! ```
117//!
118//! # Synchronizing versus Raw modes
119//!
120//! This library can be used in either Raw or Synchronizing modes, which correspond roughly to
121//! evdev's `LIBEVDEV_READ_FLAG_NORMAL` and `LIBEVDEV_READ_FLAG_SYNC` modes, respectively.
122//! In both modes, calling `fetch_events` and driving the resulting iterator to completion
123//! will provide a stream of real-time events from the underlying kernel device state.
124//! As the state changes, the kernel will write events into a ring buffer. If the buffer becomes full, the
125//! kernel will *drop* events from the ring buffer and leave an event telling userspace that it
126//! did so. At this point, if the application were using the events it received to update its
127//! internal idea of what state the hardware device is in, it will be wrong: it is missing some
128//! events.
129//!
130//! In synchronous mode, this library tries to ease that pain by removing the corrupted events
131//! and injecting fake events as if the device had updated normally. Note that this is best-effort;
132//! events can never be recovered once lost. This synchronization comes at a performance cost: each
133//! set of input events read from the kernel in turn updates an internal state buffer, and events
134//! must be internally held back until the end of each frame. If this latency is unacceptable or
135//! for any reason you want to see every event directly, a raw stream reader is also provided.
136//!
137//! As an example of how synchronization behaves, if a switch is toggled twice there will be two switch events
138//! in the buffer. However, if the kernel needs to drop events, when the device goes to synchronize
139//! state with the kernel only one (or zero, if the switch is in the same state as it was before
140//! the sync) switch events will be visible in the stream.
141//!
142//! This cache can also be queried. For example, the [`DeviceState::led_vals`] method will tell you which
143//! LEDs are currently lit on the device. As calling code consumes each iterator, this state will be
144//! updated, and it will be fully re-synchronized with the kernel if the stream drops any events.
145//!
146//! It is recommended that you dedicate a thread to processing input events, or use epoll or an
147//! async runtime with the fd returned by `<Device as AsRawFd>::as_raw_fd` to process events when
148//! they are ready.
149//!
150//! For demonstrations of how to use this library in blocking, nonblocking, and async (tokio) modes,
151//! please reference the "examples" directory.
152
153// should really be cfg(target_os = "linux") and maybe also android?
154#![cfg(unix)]
155// Flag items' docs' with their required feature flags, but only on docsrs so
156// that local docs can still be built on stable toolchains.
157// As of the time of writing, the stabilization plan is such that:
158// - Once stabilized, this attribute should be replaced with #![doc(auto_cfg)]
159// - Then in edition 2024, doc(auto_cfg) will become the default and the
160// attribute can be removed entirely
161// (see https://github.com/rust-lang/rust/pull/100883#issuecomment-1264470491)
162#![cfg_attr(docsrs, feature(doc_auto_cfg))]
163
164// has to be first for its macro
165#[macro_use]
166mod attribute_set;
167
168mod compat;
169mod constants;
170mod device_state;
171pub mod event_variants;
172mod ff;
173mod inputid;
174pub mod raw_stream;
175mod scancodes;
176mod sync_stream;
177mod sys;
178#[cfg(test)]
179mod tests;
180pub mod uinput;
181
182use crate::compat::{input_absinfo, input_event, uinput_abs_setup};
183use std::fmt::{self, Display};
184use std::io;
185use std::os::fd::{AsFd, AsRawFd, OwnedFd};
186use std::path::PathBuf;
187use std::time::{Duration, SystemTime};
188
189pub use attribute_set::{AttributeSet, AttributeSetRef, EvdevEnum};
190pub use constants::*;
191pub use device_state::DeviceState;
192pub use event_variants::*;
193pub use ff::*;
194pub use inputid::*;
195pub use scancodes::*;
196pub use sync_stream::*;
197
198macro_rules! common_trait_impls {
199 ($raw:ty, $wrapper:ty) => {
200 impl From<$raw> for $wrapper {
201 fn from(raw: $raw) -> Self {
202 Self(raw)
203 }
204 }
205
206 impl From<$wrapper> for $raw {
207 fn from(wrapper: $wrapper) -> Self {
208 wrapper.0
209 }
210 }
211
212 impl AsRef<$raw> for $wrapper {
213 fn as_ref(&self) -> &$raw {
214 &self.0
215 }
216 }
217 };
218}
219
220const EVENT_BATCH_SIZE: usize = 32;
221
222/// A convenience mapping for matching a [`InputEvent`] while simultaniously checking its kind `(type, code)`
223/// and capturing the value
224///
225/// Note This enum can not enforce that `InputEvent.code() == ` enum variant(code).
226/// It is suggested to not construct this enum and instead use [`InputEvent::destructure`] to obtain instances.
227#[derive(Debug)]
228pub enum EventSummary {
229 Synchronization(SynchronizationEvent, SynchronizationCode, i32),
230 Key(KeyEvent, KeyCode, i32),
231 RelativeAxis(RelativeAxisEvent, RelativeAxisCode, i32),
232 AbsoluteAxis(AbsoluteAxisEvent, AbsoluteAxisCode, i32),
233 Misc(MiscEvent, MiscCode, i32),
234 Switch(SwitchEvent, SwitchCode, i32),
235 Led(LedEvent, LedCode, i32),
236 Sound(SoundEvent, SoundCode, i32),
237 Repeat(RepeatEvent, RepeatCode, i32),
238 ForceFeedback(FFEvent, FFEffectCode, i32),
239 Power(PowerEvent, PowerCode, i32),
240 ForceFeedbackStatus(FFStatusEvent, FFStatusCode, i32),
241 UInput(UInputEvent, UInputCode, i32),
242 Other(OtherEvent, OtherCode, i32),
243}
244
245impl From<InputEvent> for EventSummary {
246 fn from(value: InputEvent) -> Self {
247 match value.event_type() {
248 EventType::SYNCHRONIZATION => SynchronizationEvent::from_event(value).into(),
249 EventType::KEY => KeyEvent::from_event(value).into(),
250 EventType::RELATIVE => RelativeAxisEvent::from_event(value).into(),
251 EventType::ABSOLUTE => AbsoluteAxisEvent::from_event(value).into(),
252 EventType::MISC => MiscEvent::from_event(value).into(),
253 EventType::SWITCH => SwitchEvent::from_event(value).into(),
254 EventType::LED => LedEvent::from_event(value).into(),
255 EventType::SOUND => SoundEvent::from_event(value).into(),
256 EventType::REPEAT => RepeatEvent::from_event(value).into(),
257 EventType::FORCEFEEDBACK => FFEvent::from_event(value).into(),
258 EventType::POWER => PowerEvent::from_event(value).into(),
259 EventType::FORCEFEEDBACKSTATUS => FFStatusEvent::from_event(value).into(),
260 EventType::UINPUT => UInputEvent::from_event(value).into(),
261 _ => OtherEvent(value).into(),
262 }
263 }
264}
265
266/// A wrapped `input_absinfo` returned by EVIOCGABS and used with uinput to set up absolute
267/// axes
268///
269/// `input_absinfo` is a struct containing six fields:
270/// - `value: s32`
271/// - `minimum: s32`
272/// - `maximum: s32`
273/// - `fuzz: s32`
274/// - `flat: s32`
275/// - `resolution: s32`
276///
277#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
278#[repr(transparent)]
279pub struct AbsInfo(input_absinfo);
280
281impl AbsInfo {
282 #[inline]
283 pub fn value(&self) -> i32 {
284 self.0.value
285 }
286 #[inline]
287 pub fn minimum(&self) -> i32 {
288 self.0.minimum
289 }
290 #[inline]
291 pub fn maximum(&self) -> i32 {
292 self.0.maximum
293 }
294 #[inline]
295 pub fn fuzz(&self) -> i32 {
296 self.0.fuzz
297 }
298 #[inline]
299 pub fn flat(&self) -> i32 {
300 self.0.flat
301 }
302 #[inline]
303 pub fn resolution(&self) -> i32 {
304 self.0.resolution
305 }
306
307 /// Creates a new AbsInfo, particurarily useful for uinput
308 pub fn new(
309 value: i32,
310 minimum: i32,
311 maximum: i32,
312 fuzz: i32,
313 flat: i32,
314 resolution: i32,
315 ) -> Self {
316 AbsInfo(input_absinfo {
317 value,
318 minimum,
319 maximum,
320 fuzz,
321 flat,
322 resolution,
323 })
324 }
325}
326
327common_trait_impls!(input_absinfo, AbsInfo);
328
329/// A wrapped `uinput_abs_setup`, used to set up analogue axes with uinput
330///
331/// `uinput_abs_setup` is a struct containing two fields:
332/// - `code: u16`
333/// - `absinfo: input_absinfo`
334#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
335#[repr(transparent)]
336pub struct UinputAbsSetup(uinput_abs_setup);
337
338impl UinputAbsSetup {
339 #[inline]
340 pub fn code(&self) -> u16 {
341 self.0.code
342 }
343 #[inline]
344 pub fn absinfo(&self) -> AbsInfo {
345 AbsInfo(self.0.absinfo)
346 }
347 /// Creates new UinputAbsSetup
348 pub fn new(code: AbsoluteAxisCode, absinfo: AbsInfo) -> Self {
349 UinputAbsSetup(uinput_abs_setup {
350 code: code.0,
351 absinfo: absinfo.0,
352 })
353 }
354}
355
356common_trait_impls!(uinput_abs_setup, UinputAbsSetup);
357
358/// A wrapped `input_event` returned by the input device via the kernel.
359///
360/// `input_event` is a struct containing four fields:
361/// - `time: timeval`
362/// - `type_: u16`
363/// - `code: u16`
364/// - `value: s32`
365///
366/// The meaning of the "code" and "value" fields will depend on the underlying type of event.
367#[derive(Copy, Clone, Eq, PartialEq, Hash)]
368#[repr(transparent)]
369pub struct InputEvent(input_event);
370common_trait_impls!(input_event, InputEvent);
371
372impl InputEvent {
373 /// Returns the timestamp associated with the event.
374 #[inline]
375 pub fn timestamp(&self) -> SystemTime {
376 timeval_to_systime(&self.0.time)
377 }
378
379 /// Returns the type of event this describes, e.g. Key, Switch, etc.
380 #[inline]
381 pub fn event_type(&self) -> EventType {
382 EventType(self.0.type_)
383 }
384
385 /// Returns the raw "code" field directly from input_event.
386 #[inline]
387 pub fn code(&self) -> u16 {
388 self.0.code
389 }
390
391 /// Returns the raw "value" field directly from input_event.
392 ///
393 /// For keys and switches the values 0 and 1 map to pressed and not pressed respectively.
394 /// For axes, the values depend on the hardware and driver implementation.
395 #[inline]
396 pub fn value(&self) -> i32 {
397 self.0.value
398 }
399
400 /// A convenience function to destructure the InputEvent into a [`EventSummary`].
401 ///
402 /// # Example
403 /// ```
404 /// use evdev::*;
405 /// let event = InputEvent::new(1, KeyCode::KEY_A.0, 1);
406 /// match event.destructure() {
407 /// EventSummary::Key(KeyEvent, KeyCode::KEY_A, 1) => (),
408 /// _=> panic!(),
409 /// }
410 /// ```
411 pub fn destructure(self) -> EventSummary {
412 self.into()
413 }
414
415 /// Create a new InputEvent. Only really useful for emitting events on virtual devices.
416 pub fn new(type_: u16, code: u16, value: i32) -> Self {
417 let raw = input_event {
418 time: libc::timeval {
419 tv_sec: 0,
420 tv_usec: 0,
421 },
422 type_,
423 code,
424 value,
425 };
426 Self(raw)
427 }
428
429 /// Create a new InputEvent with the time field set to "now" on the system clock.
430 ///
431 /// Note that this isn't usually necessary simply for emitting events on a virtual device, as
432 /// even though [`InputEvent::new`] creates an `input_event` with the time field as zero,
433 /// the kernel will update `input_event.time` when it emits the events to any programs reading
434 /// the event "file".
435 pub fn new_now(type_: u16, code: u16, value: i32) -> Self {
436 let raw = input_event {
437 time: systime_to_timeval(&SystemTime::now()),
438 type_,
439 code,
440 value,
441 };
442 Self(raw)
443 }
444}
445
446impl fmt::Debug for InputEvent {
447 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
448 let summary = self.destructure();
449 let code: &dyn fmt::Debug = match &summary {
450 EventSummary::Synchronization(_, code, _) => code,
451 EventSummary::Key(_, code, _) => code,
452 EventSummary::RelativeAxis(_, code, _) => code,
453 EventSummary::AbsoluteAxis(_, code, _) => code,
454 EventSummary::Misc(_, code, _) => code,
455 EventSummary::Switch(_, code, _) => code,
456 EventSummary::Led(_, code, _) => code,
457 EventSummary::Sound(_, code, _) => code,
458 EventSummary::Repeat(_, code, _) => code,
459 EventSummary::ForceFeedback(_, code, _) => code,
460 EventSummary::Power(_, code, _) => code,
461 EventSummary::ForceFeedbackStatus(_, code, _) => code,
462 EventSummary::UInput(_, code, _) => code,
463 EventSummary::Other(_, code, _) => &code.1,
464 };
465 f.debug_struct("InputEvent")
466 .field("time", &self.timestamp())
467 .field("type", &self.event_type())
468 .field("code", code)
469 .field("value", &self.value())
470 .finish()
471 }
472}
473
474/// Crawls `/dev/input` for evdev devices.
475///
476/// Will not bubble up any errors in opening devices or traversing the directory. Instead returns
477/// an empty iterator or omits the devices that could not be opened.
478pub fn enumerate() -> EnumerateDevices {
479 EnumerateDevices {
480 inner: raw_stream::enumerate(),
481 }
482}
483
484/// An iterator over currently connected evdev devices.
485pub struct EnumerateDevices {
486 inner: raw_stream::EnumerateDevices,
487}
488impl Iterator for EnumerateDevices {
489 type Item = (PathBuf, Device);
490 fn next(&mut self) -> Option<(PathBuf, Device)> {
491 self.inner
492 .next()
493 .map(|(pb, dev)| (pb, Device::from_raw_device(dev)))
494 }
495}
496
497/// A safe Rust version of clock_gettime against CLOCK_REALTIME
498fn systime_to_timeval(time: &SystemTime) -> libc::timeval {
499 let (sign, dur) = match time.duration_since(SystemTime::UNIX_EPOCH) {
500 Ok(dur) => (1, dur),
501 Err(e) => (-1, e.duration()),
502 };
503
504 libc::timeval {
505 tv_sec: dur.as_secs() as libc::time_t * sign,
506 tv_usec: dur.subsec_micros() as libc::suseconds_t,
507 }
508}
509
510fn timeval_to_systime(tv: &libc::timeval) -> SystemTime {
511 let dur = Duration::new(tv.tv_sec as u64, tv.tv_usec as u32 * 1000);
512 if tv.tv_sec >= 0 {
513 SystemTime::UNIX_EPOCH + dur
514 } else {
515 SystemTime::UNIX_EPOCH - dur
516 }
517}
518
519/// SAFETY: T must not have any padding or otherwise uninitialized bytes inside of it
520pub(crate) unsafe fn cast_to_bytes<T: ?Sized>(mem: &T) -> &[u8] {
521 std::slice::from_raw_parts(mem as *const T as *const u8, std::mem::size_of_val(mem))
522}
523
524/// An error type for the `FromStr` implementation for enum-like types in this crate.
525#[derive(Debug, Clone, PartialEq, Eq, Hash)]
526pub struct EnumParseError(());
527
528impl Display for EnumParseError {
529 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
530 write!(f, "failed to parse Key from string")
531 }
532}
533
534impl std::error::Error for EnumParseError {}
535
536fn fd_write_all(fd: std::os::fd::BorrowedFd<'_>, mut data: &[u8]) -> nix::Result<()> {
537 loop {
538 match nix::unistd::write(fd, data) {
539 Ok(0) => return Ok(()),
540 Ok(n) => data = &data[n..],
541 Err(nix::Error::EINTR) => {}
542 Err(e) => return Err(e),
543 }
544 }
545}
546
547fn write_events(fd: std::os::fd::BorrowedFd<'_>, events: &[InputEvent]) -> nix::Result<()> {
548 let bytes = unsafe { cast_to_bytes(events) };
549 fd_write_all(fd, bytes)
550}
551
552/// Represents a force feedback effect that has been successfully uploaded to the device for
553/// playback.
554#[derive(Debug)]
555pub struct FFEffect {
556 fd: OwnedFd,
557 id: u16,
558}
559
560impl FFEffect {
561 /// Returns the effect ID.
562 pub fn id(&self) -> u16 {
563 self.id
564 }
565
566 /// Plays the force feedback effect with the `count` argument specifying how often the effect
567 /// should be played.
568 pub fn play(&mut self, count: i32) -> io::Result<()> {
569 let events = [*FFEvent::new(FFEffectCode(self.id), count)];
570 crate::write_events(self.fd.as_fd(), &events)?;
571
572 Ok(())
573 }
574
575 /// Stops playback of the force feedback effect.
576 pub fn stop(&mut self) -> io::Result<()> {
577 let events = [*FFEvent::new(FFEffectCode(self.id), 0)];
578 crate::write_events(self.fd.as_fd(), &events)?;
579
580 Ok(())
581 }
582
583 /// Updates the force feedback effect.
584 pub fn update(&mut self, data: FFEffectData) -> io::Result<()> {
585 let mut effect: sys::ff_effect = data.into();
586 effect.id = self.id as i16;
587
588 unsafe { sys::eviocsff(self.fd.as_raw_fd(), &effect)? };
589
590 Ok(())
591 }
592}
593
594impl Drop for FFEffect {
595 fn drop(&mut self) {
596 let _ = unsafe { sys::eviocrmff(self.fd.as_raw_fd(), self.id as _) };
597 }
598}
599
600/// Auto-repeat settings for a device.
601#[derive(Debug, Clone)]
602#[repr(C)]
603pub struct AutoRepeat {
604 /// The duration, in milliseconds, that a key needs to be held down before
605 /// it begins to auto-repeat.
606 pub delay: u32,
607 /// The duration, in milliseconds, between auto-repetitions of a held-down key.
608 pub period: u32,
609}