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;
178pub mod uinput;
179
180use crate::compat::{input_absinfo, input_event, uinput_abs_setup};
181use std::fmt::{self, Display};
182use std::io;
183use std::os::fd::{AsFd, AsRawFd, OwnedFd};
184use std::path::PathBuf;
185use std::time::{Duration, SystemTime};
186
187pub use attribute_set::{AttributeSet, AttributeSetRef, EvdevEnum};
188pub use constants::*;
189pub use device_state::DeviceState;
190pub use event_variants::*;
191pub use ff::*;
192pub use inputid::*;
193pub use scancodes::*;
194pub use sync_stream::*;
195
196macro_rules! common_trait_impls {
197    ($raw:ty, $wrapper:ty) => {
198        impl From<$raw> for $wrapper {
199            fn from(raw: $raw) -> Self {
200                Self(raw)
201            }
202        }
203
204        impl From<$wrapper> for $raw {
205            fn from(wrapper: $wrapper) -> Self {
206                wrapper.0
207            }
208        }
209
210        impl AsRef<$raw> for $wrapper {
211            fn as_ref(&self) -> &$raw {
212                &self.0
213            }
214        }
215    };
216}
217
218const EVENT_BATCH_SIZE: usize = 32;
219
220/// A convenience mapping for matching a [`InputEvent`] while simultaniously checking its kind `(type, code)`
221/// and capturing the value
222///
223/// Note This enum can not enforce that `InputEvent.code() == ` enum variant(code).
224/// It is suggested to not construct this enum and instead use [`InputEvent::destructure`] to obtain instances.
225#[derive(Debug)]
226pub enum EventSummary {
227    Synchronization(SynchronizationEvent, SynchronizationCode, i32),
228    Key(KeyEvent, KeyCode, i32),
229    RelativeAxis(RelativeAxisEvent, RelativeAxisCode, i32),
230    AbsoluteAxis(AbsoluteAxisEvent, AbsoluteAxisCode, i32),
231    Misc(MiscEvent, MiscCode, i32),
232    Switch(SwitchEvent, SwitchCode, i32),
233    Led(LedEvent, LedCode, i32),
234    Sound(SoundEvent, SoundCode, i32),
235    Repeat(RepeatEvent, RepeatCode, i32),
236    ForceFeedback(FFEvent, FFEffectCode, i32),
237    Power(PowerEvent, PowerCode, i32),
238    ForceFeedbackStatus(FFStatusEvent, FFStatusCode, i32),
239    UInput(UInputEvent, UInputCode, i32),
240    Other(OtherEvent, OtherCode, i32),
241}
242
243impl From<InputEvent> for EventSummary {
244    fn from(value: InputEvent) -> Self {
245        match value.event_type() {
246            EventType::SYNCHRONIZATION => SynchronizationEvent::from_event(value).into(),
247            EventType::KEY => KeyEvent::from_event(value).into(),
248            EventType::RELATIVE => RelativeAxisEvent::from_event(value).into(),
249            EventType::ABSOLUTE => AbsoluteAxisEvent::from_event(value).into(),
250            EventType::MISC => MiscEvent::from_event(value).into(),
251            EventType::SWITCH => SwitchEvent::from_event(value).into(),
252            EventType::LED => LedEvent::from_event(value).into(),
253            EventType::SOUND => SoundEvent::from_event(value).into(),
254            EventType::REPEAT => RepeatEvent::from_event(value).into(),
255            EventType::FORCEFEEDBACK => FFEvent::from_event(value).into(),
256            EventType::POWER => PowerEvent::from_event(value).into(),
257            EventType::FORCEFEEDBACKSTATUS => FFStatusEvent::from_event(value).into(),
258            EventType::UINPUT => UInputEvent::from_event(value).into(),
259            _ => OtherEvent(value).into(),
260        }
261    }
262}
263
264/// A wrapped `input_absinfo` returned by EVIOCGABS and used with uinput to set up absolute
265/// axes
266///
267/// `input_absinfo` is a struct containing six fields:
268/// - `value: s32`
269/// - `minimum: s32`
270/// - `maximum: s32`
271/// - `fuzz: s32`
272/// - `flat: s32`
273/// - `resolution: s32`
274///
275#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
276#[repr(transparent)]
277pub struct AbsInfo(input_absinfo);
278
279impl AbsInfo {
280    #[inline]
281    pub fn value(&self) -> i32 {
282        self.0.value
283    }
284    #[inline]
285    pub fn minimum(&self) -> i32 {
286        self.0.minimum
287    }
288    #[inline]
289    pub fn maximum(&self) -> i32 {
290        self.0.maximum
291    }
292    #[inline]
293    pub fn fuzz(&self) -> i32 {
294        self.0.fuzz
295    }
296    #[inline]
297    pub fn flat(&self) -> i32 {
298        self.0.flat
299    }
300    #[inline]
301    pub fn resolution(&self) -> i32 {
302        self.0.resolution
303    }
304
305    /// Creates a new AbsInfo, particurarily useful for uinput
306    pub fn new(
307        value: i32,
308        minimum: i32,
309        maximum: i32,
310        fuzz: i32,
311        flat: i32,
312        resolution: i32,
313    ) -> Self {
314        AbsInfo(input_absinfo {
315            value,
316            minimum,
317            maximum,
318            fuzz,
319            flat,
320            resolution,
321        })
322    }
323}
324
325common_trait_impls!(input_absinfo, AbsInfo);
326
327/// A wrapped `uinput_abs_setup`, used to set up analogue axes with uinput
328///
329/// `uinput_abs_setup` is a struct containing two fields:
330/// - `code: u16`
331/// - `absinfo: input_absinfo`
332#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
333#[repr(transparent)]
334pub struct UinputAbsSetup(uinput_abs_setup);
335
336impl UinputAbsSetup {
337    #[inline]
338    pub fn code(&self) -> u16 {
339        self.0.code
340    }
341    #[inline]
342    pub fn absinfo(&self) -> AbsInfo {
343        AbsInfo(self.0.absinfo)
344    }
345    /// Creates new UinputAbsSetup
346    pub fn new(code: AbsoluteAxisCode, absinfo: AbsInfo) -> Self {
347        UinputAbsSetup(uinput_abs_setup {
348            code: code.0,
349            absinfo: absinfo.0,
350        })
351    }
352}
353
354common_trait_impls!(uinput_abs_setup, UinputAbsSetup);
355
356/// A wrapped `input_event` returned by the input device via the kernel.
357///
358/// `input_event` is a struct containing four fields:
359/// - `time: timeval`
360/// - `type_: u16`
361/// - `code: u16`
362/// - `value: s32`
363///
364/// The meaning of the "code" and "value" fields will depend on the underlying type of event.
365#[derive(Copy, Clone, Eq, PartialEq, Hash)]
366#[repr(transparent)]
367pub struct InputEvent(input_event);
368common_trait_impls!(input_event, InputEvent);
369
370impl InputEvent {
371    /// Returns the timestamp associated with the event.
372    #[inline]
373    pub fn timestamp(&self) -> SystemTime {
374        timeval_to_systime(&self.0.time)
375    }
376
377    /// Returns the type of event this describes, e.g. Key, Switch, etc.
378    #[inline]
379    pub fn event_type(&self) -> EventType {
380        EventType(self.0.type_)
381    }
382
383    /// Returns the raw "code" field directly from input_event.
384    #[inline]
385    pub fn code(&self) -> u16 {
386        self.0.code
387    }
388
389    /// Returns the raw "value" field directly from input_event.
390    ///
391    /// For keys and switches the values 0 and 1 map to pressed and not pressed respectively.
392    /// For axes, the values depend on the hardware and driver implementation.
393    #[inline]
394    pub fn value(&self) -> i32 {
395        self.0.value
396    }
397
398    /// A convenience function to destructure the InputEvent into a [`EventSummary`].
399    ///
400    /// # Example
401    /// ```
402    /// use evdev::*;
403    /// let event =  InputEvent::new(1, KeyCode::KEY_A.0, 1);
404    /// match event.destructure() {
405    ///     EventSummary::Key(KeyEvent, KeyCode::KEY_A, 1) => (),
406    ///     _=> panic!(),
407    /// }
408    /// ```
409    pub fn destructure(self) -> EventSummary {
410        self.into()
411    }
412
413    /// Create a new InputEvent. Only really useful for emitting events on virtual devices.
414    pub fn new(type_: u16, code: u16, value: i32) -> Self {
415        let raw = input_event {
416            time: libc::timeval {
417                tv_sec: 0,
418                tv_usec: 0,
419            },
420            type_,
421            code,
422            value,
423        };
424        Self(raw)
425    }
426
427    /// Create a new InputEvent with the time field set to "now" on the system clock.
428    ///
429    /// Note that this isn't usually necessary simply for emitting events on a virtual device, as
430    /// even though [`InputEvent::new`] creates an `input_event` with the time field as zero,
431    /// the kernel will update `input_event.time` when it emits the events to any programs reading
432    /// the event "file".
433    pub fn new_now(type_: u16, code: u16, value: i32) -> Self {
434        let raw = input_event {
435            time: systime_to_timeval(&SystemTime::now()),
436            type_,
437            code,
438            value,
439        };
440        Self(raw)
441    }
442}
443
444impl fmt::Debug for InputEvent {
445    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
446        let summary = self.destructure();
447        let code: &dyn fmt::Debug = match &summary {
448            EventSummary::Synchronization(_, code, _) => code,
449            EventSummary::Key(_, code, _) => code,
450            EventSummary::RelativeAxis(_, code, _) => code,
451            EventSummary::AbsoluteAxis(_, code, _) => code,
452            EventSummary::Misc(_, code, _) => code,
453            EventSummary::Switch(_, code, _) => code,
454            EventSummary::Led(_, code, _) => code,
455            EventSummary::Sound(_, code, _) => code,
456            EventSummary::Repeat(_, code, _) => code,
457            EventSummary::ForceFeedback(_, code, _) => code,
458            EventSummary::Power(_, code, _) => code,
459            EventSummary::ForceFeedbackStatus(_, code, _) => code,
460            EventSummary::UInput(_, code, _) => code,
461            EventSummary::Other(_, code, _) => &code.1,
462        };
463        f.debug_struct("InputEvent")
464            .field("time", &self.timestamp())
465            .field("type", &self.event_type())
466            .field("code", code)
467            .field("value", &self.value())
468            .finish()
469    }
470}
471
472/// Crawls `/dev/input` for evdev devices.
473///
474/// Will not bubble up any errors in opening devices or traversing the directory. Instead returns
475/// an empty iterator or omits the devices that could not be opened.
476pub fn enumerate() -> EnumerateDevices {
477    EnumerateDevices {
478        inner: raw_stream::enumerate(),
479    }
480}
481
482/// An iterator over currently connected evdev devices.
483pub struct EnumerateDevices {
484    inner: raw_stream::EnumerateDevices,
485}
486impl Iterator for EnumerateDevices {
487    type Item = (PathBuf, Device);
488    fn next(&mut self) -> Option<(PathBuf, Device)> {
489        self.inner
490            .next()
491            .map(|(pb, dev)| (pb, Device::from_raw_device(dev)))
492    }
493}
494
495/// A safe Rust version of clock_gettime against CLOCK_REALTIME
496fn systime_to_timeval(time: &SystemTime) -> libc::timeval {
497    let (sign, dur) = match time.duration_since(SystemTime::UNIX_EPOCH) {
498        Ok(dur) => (1, dur),
499        Err(e) => (-1, e.duration()),
500    };
501
502    libc::timeval {
503        tv_sec: dur.as_secs() as libc::time_t * sign,
504        tv_usec: dur.subsec_micros() as libc::suseconds_t,
505    }
506}
507
508fn timeval_to_systime(tv: &libc::timeval) -> SystemTime {
509    let dur = Duration::new(tv.tv_sec as u64, tv.tv_usec as u32 * 1000);
510    if tv.tv_sec >= 0 {
511        SystemTime::UNIX_EPOCH + dur
512    } else {
513        SystemTime::UNIX_EPOCH - dur
514    }
515}
516
517/// SAFETY: T must not have any padding or otherwise uninitialized bytes inside of it
518pub(crate) unsafe fn cast_to_bytes<T: ?Sized>(mem: &T) -> &[u8] {
519    std::slice::from_raw_parts(mem as *const T as *const u8, std::mem::size_of_val(mem))
520}
521
522/// An error type for the `FromStr` implementation for enum-like types in this crate.
523#[derive(Debug, Clone, PartialEq, Eq, Hash)]
524pub struct EnumParseError(());
525
526impl Display for EnumParseError {
527    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
528        write!(f, "failed to parse Key from string")
529    }
530}
531
532impl std::error::Error for EnumParseError {}
533
534fn fd_write_all(fd: std::os::fd::BorrowedFd<'_>, mut data: &[u8]) -> nix::Result<()> {
535    loop {
536        match nix::unistd::write(fd, data) {
537            Ok(0) => return Ok(()),
538            Ok(n) => data = &data[n..],
539            Err(nix::Error::EINTR) => {}
540            Err(e) => return Err(e),
541        }
542    }
543}
544
545fn write_events(fd: std::os::fd::BorrowedFd<'_>, events: &[InputEvent]) -> nix::Result<()> {
546    let bytes = unsafe { cast_to_bytes(events) };
547    fd_write_all(fd, bytes)
548}
549
550/// Represents a force feedback effect that has been successfully uploaded to the device for
551/// playback.
552#[derive(Debug)]
553pub struct FFEffect {
554    fd: OwnedFd,
555    id: u16,
556}
557
558impl FFEffect {
559    /// Returns the effect ID.
560    pub fn id(&self) -> u16 {
561        self.id
562    }
563
564    /// Plays the force feedback effect with the `count` argument specifying how often the effect
565    /// should be played.
566    pub fn play(&mut self, count: i32) -> io::Result<()> {
567        let events = [*FFEvent::new(FFEffectCode(self.id), count)];
568        crate::write_events(self.fd.as_fd(), &events)?;
569
570        Ok(())
571    }
572
573    /// Stops playback of the force feedback effect.
574    pub fn stop(&mut self) -> io::Result<()> {
575        let events = [*FFEvent::new(FFEffectCode(self.id), 0)];
576        crate::write_events(self.fd.as_fd(), &events)?;
577
578        Ok(())
579    }
580
581    /// Updates the force feedback effect.
582    pub fn update(&mut self, data: FFEffectData) -> io::Result<()> {
583        let mut effect: sys::ff_effect = data.into();
584        effect.id = self.id as i16;
585
586        unsafe { sys::eviocsff(self.fd.as_raw_fd(), &effect)? };
587
588        Ok(())
589    }
590}
591
592impl Drop for FFEffect {
593    fn drop(&mut self) {
594        let _ = unsafe { sys::eviocrmff(self.fd.as_raw_fd(), self.id as _) };
595    }
596}
597
598/// Auto-repeat settings for a device.
599#[derive(Debug, Clone)]
600#[repr(C)]
601pub struct AutoRepeat {
602    /// The duration, in milliseconds, that a key needs to be held down before
603    /// it begins to auto-repeat.
604    pub delay: u32,
605    /// The duration, in milliseconds, between auto-repetitions of a held-down key.
606    pub period: u32,
607}