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}