Add raw_stream::enumerate() -> Iterator<RawDevice>

This commit is contained in:
Noah 2021-03-22 12:17:26 -05:00 committed by Jeff Hiner
parent be24cc15be
commit 9f63c9a0eb
3 changed files with 42 additions and 18 deletions

View file

@ -86,7 +86,6 @@ pub mod uinput;
#[cfg(feature = "tokio")]
mod tokio_stream;
use std::os::unix::ffi::OsStrExt;
use std::time::{Duration, SystemTime};
use std::{fmt, io};
@ -241,28 +240,17 @@ impl fmt::Debug for InputEvent {
/// an empty iterator or omits the devices that could not be opened.
pub fn enumerate() -> EnumerateDevices {
EnumerateDevices {
readdir: std::fs::read_dir("/dev/input").ok(),
inner: raw_stream::enumerate(),
}
}
pub struct EnumerateDevices {
readdir: Option<std::fs::ReadDir>,
inner: raw_stream::EnumerateDevices,
}
impl Iterator for EnumerateDevices {
type Item = Device;
fn next(&mut self) -> Option<Device> {
let readdir = self.readdir.as_mut()?;
loop {
if let Ok(entry) = readdir.next()? {
let path = entry.path();
let fname = path.file_name().unwrap();
if fname.as_bytes().starts_with(b"event") {
if let Ok(dev) = Device::open(&path) {
return Some(dev);
}
}
}
}
self.inner.next().map(Device::from_raw_device)
}
}

View file

@ -518,6 +518,38 @@ fn vec_spare_capacity_mut<T>(v: &mut Vec<T>) -> &mut [mem::MaybeUninit<T>] {
}
}
/// Crawls `/dev/input` for evdev devices.
///
/// Will not bubble up any errors in opening devices or traversing the directory. Instead returns
/// an empty iterator or omits the devices that could not be opened.
pub fn enumerate() -> EnumerateDevices {
EnumerateDevices {
readdir: std::fs::read_dir("/dev/input").ok(),
}
}
pub struct EnumerateDevices {
readdir: Option<std::fs::ReadDir>,
}
impl Iterator for EnumerateDevices {
type Item = RawDevice;
fn next(&mut self) -> Option<RawDevice> {
use std::os::unix::ffi::OsStrExt;
let readdir = self.readdir.as_mut()?;
loop {
if let Ok(entry) = readdir.next()? {
let path = entry.path();
let fname = path.file_name().unwrap();
if fname.as_bytes().starts_with(b"event") {
if let Ok(dev) = RawDevice::open(&path) {
return Some(dev);
}
}
}
}
}
}
#[cfg(feature = "tokio")]
mod tokio_stream {
use super::*;

View file

@ -35,18 +35,22 @@ impl Device {
Self::_open(path.as_ref())
}
#[inline]
fn _open(path: &Path) -> io::Result<Device> {
let raw = RawDevice::open(path)?;
RawDevice::open(path).map(Self::from_raw_device)
}
// TODO: should this be public?
pub(crate) fn from_raw_device(raw: RawDevice) -> Device {
let state = DeviceState::new(&raw);
let prev_state = state.clone();
Ok(Device {
Device {
raw,
prev_state,
state,
block_dropped: false,
})
}
}
/// Returns the synchronization engine's current understanding (cache) of the device state.