Add more rustdoc; reorder pub fns for clarity

This commit is contained in:
Jeff Hiner 2021-03-01 14:27:03 -07:00
parent fa4838e5f8
commit 6b13fd3d45
4 changed files with 94 additions and 51 deletions

View file

@ -1,6 +1,11 @@
use bitvec::prelude::*; use bitvec::prelude::*;
use std::fmt; use std::fmt;
/// A collection of bits representing either device capability or state.
///
/// This can be used to iterate across all keys supported by a keyboard, or all buttons supported
/// by a joystick. You can also query directly whether a specific bit is set (corresponding to
/// whether a key or button is depressed).
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct AttributeSet<'a, T> { pub struct AttributeSet<'a, T> {
bitslice: &'a BitSlice<Lsb0, u8>, bitslice: &'a BitSlice<Lsb0, u8>,
@ -17,11 +22,13 @@ impl<'a, T: EvdevEnum> AttributeSet<'a, T> {
} }
#[inline] #[inline]
/// Returns `true` if this AttributeSet contains the passed T.
pub fn contains(&self, attr: T) -> bool { pub fn contains(&self, attr: T) -> bool {
self.bitslice.get(attr.to_index()).map_or(false, |b| *b) self.bitslice.get(attr.to_index()).map_or(false, |b| *b)
} }
#[inline] #[inline]
/// Provides an iterator over all "set" bits in the collection.
pub fn iter(&self) -> impl Iterator<Item = T> + 'a { pub fn iter(&self) -> impl Iterator<Item = T> + 'a {
self.bitslice.iter_ones().map(T::from_index) self.bitslice.iter_ones().map(T::from_index)
} }

View file

@ -1,4 +1,6 @@
/// Event types supported by the device. /// Event types supported by the device.
///
/// This is implemented as a newtype around the u16 "type" field of `libc::input_event`.
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
pub struct EventType(pub u16); pub struct EventType(pub u16);
@ -44,11 +46,12 @@ impl EventType {
} }
/// A "synchronization" message type published by the kernel into the events stream.
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
pub struct Synchronization(pub u16); pub struct Synchronization(pub u16);
impl Synchronization { impl Synchronization {
/// Terminates a packet of events from the device. /// Used to mark the end of a single atomic "reading" from the device.
pub const SYN_REPORT: u16 = 0; pub const SYN_REPORT: u16 = 0;
/// Appears to be unused. /// Appears to be unused.
pub const SYN_CONFIG: u16 = 1; pub const SYN_CONFIG: u16 = 1;
@ -97,6 +100,7 @@ impl PropType {
pub(crate) const COUNT: usize = 0x20; pub(crate) const COUNT: usize = 0x20;
} }
/// A type of relative axis measurement, typically produced by mice.
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
pub struct RelativeAxisType(pub u16); pub struct RelativeAxisType(pub u16);
@ -121,6 +125,7 @@ impl RelativeAxisType {
pub(crate) const COUNT: usize = 0x10; pub(crate) const COUNT: usize = 0x10;
} }
/// A type of absolute axis measurement, typically used for touch events and joysticks.
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
pub struct AbsoluteAxisType(pub u16); pub struct AbsoluteAxisType(pub u16);
@ -188,6 +193,7 @@ impl AbsoluteAxisType {
pub(crate) const COUNT: usize = 0x40; pub(crate) const COUNT: usize = 0x40;
} }
/// An event type corresponding to a physical or virtual switch.
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
pub struct SwitchType(pub u16); pub struct SwitchType(pub u16);
@ -260,7 +266,7 @@ impl LedType {
pub(crate) const COUNT: usize = 0x10; pub(crate) const COUNT: usize = 0x10;
} }
/// Various miscellaneous event types. Current as of kernel 4.1. /// Various miscellaneous event types.
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
pub struct MiscType(pub u16); pub struct MiscType(pub u16);
@ -323,6 +329,7 @@ impl MiscType {
// pub(crate) const COUNT: usize = 0x02; // pub(crate) const COUNT: usize = 0x02;
// } // }
/// A type associated with simple sounds, such as beeps or tones.
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
pub struct SoundType(pub u16); pub struct SoundType(pub u16);

View file

@ -81,6 +81,8 @@ use std::{ffi::CString, mem::MaybeUninit};
pub use crate::attribute_set::AttributeSet; pub use crate::attribute_set::AttributeSet;
pub use crate::constants::*; pub use crate::constants::*;
pub use crate::scancodes::*; pub use crate::scancodes::*;
#[cfg(feature = "tokio")]
pub use crate::tokio_stream::EventStream;
fn ioctl_get_cstring( fn ioctl_get_cstring(
f: unsafe fn(RawFd, &mut [u8]) -> nix::Result<libc::c_int>, f: unsafe fn(RawFd, &mut [u8]) -> nix::Result<libc::c_int>,
@ -350,12 +352,45 @@ impl fmt::Display for Device {
const DEFAULT_EVENT_COUNT: usize = 32; const DEFAULT_EVENT_COUNT: usize = 32;
impl Device { impl Device {
/// Returns a set of the event types supported by this device (Key, Switch, etc) #[inline(always)]
/// Opens a device, given its system path.
/// ///
/// If you're interested in the individual keys or switches supported, it's probably easier /// Paths are typically something like `/dev/input/event0`.
/// to just call the appropriate `supported_*` function instead. pub fn open(path: impl AsRef<Path>) -> io::Result<Device> {
pub fn supported_events(&self) -> AttributeSet<'_, EventType> { Self::_open(path.as_ref())
AttributeSet::new(&self.ty) }
/// Fetches and returns events from the kernel ring buffer without doing synchronization on
/// SYN_DROPPED.
///
/// By default this will block until events are available. Typically, users will want to call
/// this in a tight loop within a thread.
pub fn fetch_events_no_sync(&mut self) -> io::Result<impl Iterator<Item = InputEvent> + '_> {
self.fill_events(DEFAULT_EVENT_COUNT)?;
Ok(self.pending_events.drain(..).map(InputEvent))
}
/// Fetches and returns events from the kernel ring buffer, doing synchronization on SYN_DROPPED.
///
/// By default this will block until events are available. Typically, users will want to call
/// this in a tight loop within a thread.
/// Will insert "fake" events.
pub fn fetch_events(&mut self) -> io::Result<impl Iterator<Item = InputEvent> + '_> {
self.fill_events(DEFAULT_EVENT_COUNT)?;
self.compensate_dropped()?;
Ok(self.pending_events.drain(..).map(InputEvent))
}
#[cfg(feature = "tokio")]
/// Return a `futures::stream` asynchronous stream of `InputEvent` compatible with Tokio.
///
/// The stream does NOT compensate for SYN_DROPPED events and will not update internal cached
/// state.
/// The Tokio runtime is expected to keep up with typical event rates.
/// This operation consumes the Device.
pub fn into_event_stream_no_sync(self) -> io::Result<tokio_stream::EventStream> {
tokio_stream::EventStream::new(self)
} }
/// Returns the device's name as read from the kernel. /// Returns the device's name as read from the kernel.
@ -388,6 +423,14 @@ impl Device {
self.driver_version self.driver_version
} }
/// Returns a set of the event types supported by this device (Key, Switch, etc)
///
/// If you're interested in the individual keys or switches supported, it's probably easier
/// to just call the appropriate `supported_*` function instead.
pub fn supported_events(&self) -> AttributeSet<'_, EventType> {
AttributeSet::new(&self.ty)
}
/// Returns the set of supported keys reported by the device. /// Returns the set of supported keys reported by the device.
/// ///
/// For keyboards, this is the set of all possible keycodes the keyboard may emit. Controllers, /// For keyboards, this is the set of all possible keycodes the keyboard may emit. Controllers,
@ -513,14 +556,6 @@ impl Device {
&self.state &self.state
} }
#[inline(always)]
/// Opens a device, given its system path.
///
/// Paths are typically something like `/dev/input/event0`.
pub fn open(path: impl AsRef<Path>) -> io::Result<Device> {
Self::_open(path.as_ref())
}
fn _open(path: &Path) -> io::Result<Device> { fn _open(path: &Path) -> io::Result<Device> {
let mut options = OpenOptions::new(); let mut options = OpenOptions::new();
@ -826,7 +861,7 @@ impl Device {
/// O_NONBLOCK, this will block. /// O_NONBLOCK, this will block.
/// ///
/// Returns the number of events that were read, or an error. /// Returns the number of events that were read, or an error.
pub fn fill_events(&mut self, num: usize) -> io::Result<usize> { fn fill_events(&mut self, num: usize) -> io::Result<usize> {
let fd = self.as_raw_fd(); let fd = self.as_raw_fd();
self.read_buf.clear(); self.read_buf.clear();
self.read_buf.reserve_exact(num); self.read_buf.reserve_exact(num);
@ -851,42 +886,12 @@ impl Device {
fn pop_event(&mut self) -> Option<InputEvent> { fn pop_event(&mut self) -> Option<InputEvent> {
self.pending_events.pop_front().map(InputEvent) self.pending_events.pop_front().map(InputEvent)
} }
/// Fetches and returns events from the kernel ring buffer without doing synchronization on
/// SYN_DROPPED.
///
/// By default this will block until events are available. Typically, users will want to call
/// this in a tight loop within a thread.
pub fn fetch_events_no_sync(&mut self) -> io::Result<impl Iterator<Item = InputEvent> + '_> {
self.fill_events(DEFAULT_EVENT_COUNT)?;
Ok(self.pending_events.drain(..).map(InputEvent))
}
/// Fetches and returns events from the kernel ring buffer, doing synchronization on SYN_DROPPED.
///
/// By default this will block until events are available. Typically, users will want to call
/// this in a tight loop within a thread.
/// Will insert "fake" events.
pub fn fetch_events(&mut self) -> io::Result<impl Iterator<Item = InputEvent> + '_> {
self.fill_events(DEFAULT_EVENT_COUNT)?;
self.compensate_dropped()?;
Ok(self.pending_events.drain(..).map(InputEvent))
}
#[cfg(feature = "tokio")]
/// Return a `futures::stream` asynchronous stream of `InputEvent` compatible with Tokio.
///
/// The stream does NOT compensate for SYN_DROPPED events and will not update internal cached
/// state.
/// The Tokio runtime is expected to keep up with typical event rates.
/// This operation consumes the Device.
pub fn into_event_stream_no_sync(self) -> io::Result<tokio_stream::EventStream> {
tokio_stream::EventStream::new(self)
}
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
/// A convenience mapping from an event `(type, code)` to an enumeration.
///
/// Note that this does not capture an event's value, just the type and code.
pub enum InputEventKind { pub enum InputEventKind {
Synchronization(Synchronization), Synchronization(Synchronization),
Key(Key), Key(Key),
@ -900,26 +905,41 @@ pub enum InputEventKind {
} }
#[repr(transparent)] #[repr(transparent)]
/// A wrapped `libc::input_event` returned by the input device via the kernel.
///
/// `input_event` is a struct containing four fields:
/// - `time: timeval`
/// - `type_: u16`
/// - `code: u16`
/// - `value: s32`
///
/// The meaning of the "code" and "value" fields will depend on the underlying type of event.
pub struct InputEvent(libc::input_event); pub struct InputEvent(libc::input_event);
impl InputEvent { impl InputEvent {
#[inline] #[inline]
/// Returns the timestamp associated with the event.
pub fn timestamp(&self) -> SystemTime { pub fn timestamp(&self) -> SystemTime {
timeval_to_systime(&self.0.time) timeval_to_systime(&self.0.time)
} }
#[inline] #[inline]
/// Returns the type of event this describes, e.g. Key, Switch, etc.
pub fn event_type(&self) -> EventType { pub fn event_type(&self) -> EventType {
EventType(self.0.type_) EventType(self.0.type_)
} }
#[inline] #[inline]
/// Returns the raw "code" field directly from input_event.
pub fn code(&self) -> u16 { pub fn code(&self) -> u16 {
self.0.code self.0.code
} }
/// A convenience function to return `self.code()` wrapped in a certain newtype determined by /// A convenience function to return `self.code()` wrapped in a certain newtype determined by
/// the type of this event. /// the type of this event.
///
/// This is useful if you want to match events by specific key codes or axes. Note that this
/// does not capture the event value, just the type and code.
#[inline] #[inline]
pub fn kind(&self) -> InputEventKind { pub fn kind(&self) -> InputEventKind {
let code = self.code(); let code = self.code();
@ -937,15 +957,23 @@ impl InputEvent {
} }
#[inline] #[inline]
/// Returns the raw "value" field directly from input_event.
///
/// For keys and switches the values 0 and 1 map to pressed and not pressed respectively.
/// For axes, the values depend on the hardware and driver implementation.
pub fn value(&self) -> i32 { pub fn value(&self) -> i32 {
self.0.value self.0.value
} }
}
pub fn from_raw(raw: libc::input_event) -> Self { impl From<libc::input_event> for InputEvent {
fn from(raw: libc::input_event) -> Self {
Self(raw) Self(raw)
} }
}
pub fn as_raw(&self) -> &libc::input_event { impl<'a> Into<&'a libc::input_event> for &'a InputEvent {
fn into(self) -> &'a libc::input_event {
&self.0 &self.0
} }
} }

View file

@ -8,6 +8,7 @@ use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use tokio::io::unix::AsyncFd; use tokio::io::unix::AsyncFd;
/// An async stream of events.
pub struct EventStream { pub struct EventStream {
device: AsyncFd<Device>, device: AsyncFd<Device>,
} }