evdevil/
lib.rs

1#![doc = include_str!("../README.md")]
2#![warn(missing_debug_implementations)]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4
5#[macro_use]
6mod macros;
7
8#[cfg(test)]
9mod test;
10
11mod abs_info;
12mod batch;
13pub mod bits;
14mod drop;
15pub mod enumerate;
16mod evdev;
17pub mod event;
18pub mod ff;
19pub mod hotplug;
20mod input_id;
21mod key_repeat;
22mod keymap_entry;
23mod raw;
24pub mod reader;
25mod slot;
26pub mod uinput;
27mod util;
28mod version;
29
30use std::{
31    fs::File,
32    io::{self, Read, Write},
33    slice,
34};
35
36pub use abs_info::AbsInfo;
37#[doc(inline)]
38pub use enumerate::{enumerate, enumerate_hotplug};
39pub use evdev::*;
40pub use event::codes::{InputProp, UnknownVariant};
41pub use input_id::{Bus, InputId};
42pub use key_repeat::KeyRepeat;
43pub use keymap_entry::{KeymapEntry, Scancode};
44#[doc(inline)]
45pub use reader::EventReader;
46pub use slot::Slot;
47pub use version::Version;
48
49use crate::event::InputEvent;
50
51/// Reads raw events from an `Evdev` or a `UinputDevice` (`file`) into `dest`.
52///
53/// Returns the number of events that were read.
54fn read_raw(mut file: &File, dest: &mut [InputEvent]) -> io::Result<usize> {
55    let bptr = dest.as_mut_ptr().cast::<u8>();
56    // Safety: this requires that `InputEvent` contains no padding, which is tested where `input_event` is defined.
57    let byte_buf = unsafe { slice::from_raw_parts_mut(bptr, size_of::<InputEvent>() * dest.len()) };
58    let bytes = file.read(byte_buf)?;
59    debug_assert_eq!(bytes % size_of::<InputEvent>(), 0);
60    Ok(bytes / size_of::<InputEvent>())
61}
62
63/// Writes all events from `events` to an `Evdev` or a `UinputDevice` represented by `File`.
64fn write_raw(mut file: &File, events: &[InputEvent]) -> io::Result<()> {
65    let bptr = events.as_ptr().cast::<u8>();
66    // Safety: this requires that `InputEvent` contains no padding, which is tested where `input_event` is defined.
67    let bytes = unsafe { slice::from_raw_parts(bptr, size_of::<InputEvent>() * events.len()) };
68    file.write_all(bytes)?;
69    Ok(())
70}
71
72#[cfg(test)]
73mod tests {
74    use crate::{hotplug::HotplugMonitor, uinput::UinputDevice};
75
76    use super::*;
77
78    #[test]
79    fn send_sync() {
80        fn assert<T: Send + Sync>() {}
81
82        assert::<Evdev>();
83        assert::<EventReader>();
84        assert::<UinputDevice>();
85        assert::<HotplugMonitor>();
86    }
87}