evdev/
evdev.rs

1use libc::{input_event, timeval};
2use poller::{EventContext, Events, Poller};
3use std::fs::File;
4use std::io::Read;
5use std::os::unix::io::AsRawFd;
6use std::sync::Arc;
7
8#[derive(Clone, Copy)]
9#[repr(C)]
10pub struct InputEvent {
11    inner: input_event,
12}
13
14impl std::fmt::Debug for InputEvent {
15    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16        f.debug_struct("InputEvent")
17            .field("time", &TimeVal::from(self.inner.time))
18            .field("type", &self.inner.type_)
19            .field("code", &self.inner.code)
20            .field("value", &self.inner.value)
21            .finish()
22    }
23}
24impl std::fmt::Display for InputEvent {
25    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26        write!(
27            f,
28            "InputEvent {{ time: {}, type: {}, code: {}, value: {} }}",
29            TimeVal::from(self.inner.time),
30            self.inner.type_,
31            self.inner.code,
32            self.inner.value
33        )
34    }
35}
36
37#[derive(Clone, Copy)]
38#[repr(C)]
39pub struct TimeVal {
40    inner: timeval,
41}
42
43impl From<timeval> for TimeVal {
44    fn from(val: timeval) -> Self {
45        Self { inner: val }
46    }
47}
48
49impl Into<timeval> for TimeVal {
50    fn into(self) -> timeval {
51        self.inner
52    }
53}
54
55impl Into<(u32, u32)> for TimeVal {
56    fn into(self) -> (u32, u32) {
57        (self.inner.tv_sec as u32, self.inner.tv_usec as u32)
58    }
59}
60
61impl Into<u64> for TimeVal {
62    fn into(self) -> u64 {
63        self.inner.tv_sec as u64 * 1_000_000u64 + self.inner.tv_usec as u64
64    }
65}
66
67impl std::fmt::Debug for TimeVal {
68    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69        f.debug_struct("TimeVal")
70            .field("sec", &self.inner.tv_sec)
71            .field("usec", &self.inner.tv_usec)
72            .finish()
73    }
74}
75
76impl std::fmt::Display for TimeVal {
77    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78        write!(
79            f,
80            "{}.{number:>0width$}",
81            self.inner.tv_sec,
82            number = self.inner.tv_usec,
83            width = 6
84        )
85    }
86}
87
88fn main() -> Result<(), Box<dyn std::error::Error>> {
89    // Open the linux evdev.
90    let evdev = Arc::new(File::open("/dev/input/event0")?);
91    // Create the Poller.
92    let mut poller = Poller::new()?;
93    // Add stdin to the watching list of the Poller.
94    poller.add(0, Events::new().read(), None)?;
95    // Add evdev to the watching list of the Poller.
96    poller.add(
97        evdev.as_raw_fd(),
98        Events::new().read(),
99        Some(Arc::clone(&evdev) as EventContext),
100    )?;
101    // Buffer to read one InputEvent data from evdev.
102    const N: usize = std::mem::size_of::<input_event>();
103    let mut buf: [u8; N] = [0; N];
104
105    println!("Press any key to exit ...");
106
107    'outer: loop {
108        // Pull all events with 1 seconds timeout.
109        let events = poller.pull_events(1000)?;
110        for (_fd, _events, _ctx) in events.iter() {
111            // Exit loop if press any key.
112            if _fd == &0 {
113                break 'outer;
114            }
115            // Use EventContext to processing the event.
116            if let Some(x) = _ctx {
117                if let Some(mut f) = x.downcast_ref::<File>() {
118                    f.read_exact(&mut buf)?;
119                }
120            }
121            // Cast the buffer to &InputEvent.
122            let a = unsafe { std::mem::transmute::<&[u8; N], &InputEvent>(&buf) };
123            // Display the InputEvent.
124            println!("{}", a);
125        }
126    }
127
128    Ok(())
129}