Skip to content

Commit

Permalink
feat: EvdevHandle::read_input_event{,s}
Browse files Browse the repository at this point in the history
  • Loading branch information
arcnmx committed Jul 19, 2024
1 parent 9a2d768 commit 8d45b1d
Showing 1 changed file with 39 additions and 1 deletion.
40 changes: 39 additions & 1 deletion src/evdev.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! An interface to the Linux kernel's event devices (`/dev/input/*`).
use std::io;
use std::mem::{MaybeUninit, size_of};
use std::mem::{MaybeUninit, size_of, transmute};
use std::slice::from_raw_parts_mut;
use std::os::unix::io::{RawFd, AsRawFd, IntoRawFd, FromRawFd};
use std::os::fd::{AsFd, BorrowedFd, OwnedFd};
Expand All @@ -11,6 +11,7 @@ use crate::{
AbsoluteAxis, AbsoluteInfo, AutorepeatKind, EventKind, InputId,
InputProperty, Key, LedKind, MiscKind, RelativeAxis, SoundKind, SwitchKind,
ForceFeedbackKind,
InputEvent,
};
use crate::macros::convert_error;
use crate::bitmask::Bitmask;
Expand Down Expand Up @@ -88,6 +89,43 @@ impl<F: AsRawFd> EvdevHandle<F> {
.map(|len| len / size_of::<sys::input_event>()).map_err(convert_error)
}

/// Read events from the input device
pub fn read_input_events(&self, events: &mut [MaybeUninit<InputEvent>]) -> io::Result<&mut [InputEvent]> {
let res = {
let events = unsafe { from_raw_parts_mut(events.as_mut_ptr() as *mut _, events.len() * size_of::<InputEvent>()) };
nix::unistd::read(self.fd(), events)
}.map_err(convert_error);
res.and_then(|len| {
let count = len as usize / size_of::<InputEvent>();
let events = &mut events[..count];
for event in events.iter() {
let event = event.as_ptr() as *const sys::input_event;
let _ = InputEvent::from_raw(unsafe { &*event })?;
}
Ok(unsafe {
transmute(events)
})
})
}

/// Read a single event from the input device
pub fn read_input_event(&self) -> io::Result<InputEvent> {
let mut events = [MaybeUninit::<InputEvent>::uninit()];
self.read_input_events(&mut events)
.and_then(|read| match read.is_empty() {
true => Err(io::Error::new(io::ErrorKind::UnexpectedEof, "empty evdev read")),
false => Ok(unsafe {
events[0].assume_init()
}),
})
}

/// Read a single event from the input device
pub fn read_event(&self) -> io::Result<crate::Event> {
self.read_input_event()
.map(From::from)
}

/// Write events to the input device
pub fn write(&self, events: &[sys::input_event]) -> io::Result<usize> {
let events = unsafe { from_raw_parts_mut(events.as_ptr() as *mut u8, size_of::<sys::input_event>() * events.len()) };
Expand Down

0 comments on commit 8d45b1d

Please sign in to comment.