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}