2015-07-19 21:45:05 +00:00
|
|
|
//! Linux event device handling.
|
|
|
|
//!
|
|
|
|
//! The Linux kernel's "evdev" subsystem exposes input devices to userspace in a generic,
|
|
|
|
//! consistent way. I'll try to explain the device model as completely as possible. The upstream
|
|
|
|
//! kernel documentation is split across two files:
|
|
|
|
//!
|
|
|
|
//! - https://www.kernel.org/doc/Documentation/input/event-codes.txt
|
|
|
|
//! - https://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt
|
|
|
|
//!
|
|
|
|
//! Devices can expose a few different kinds of events, specified by the `Types` bitflag. Each
|
|
|
|
//! event type (except for RELATIVE and SYNCHRONIZATION) also has some associated state. See the documentation for
|
|
|
|
//! `Types` on what each type corresponds to.
|
|
|
|
//!
|
2015-07-21 09:15:21 +00:00
|
|
|
//! This state can be queried. For example, the `DeviceState::led_vals` field will tell you which
|
|
|
|
//! LEDs are currently lit on the device. This state is not automatically synchronized with the
|
|
|
|
//! kernel. However, as the application reads events, this state will be updated if the event is
|
|
|
|
//! newer than the state timestamp (maintained internally). Additionally, you can call
|
|
|
|
//! `Device::sync_state` to explicitly synchronize with the kernel state.
|
2015-07-19 21:45:05 +00:00
|
|
|
//!
|
2015-07-21 09:15:21 +00:00
|
|
|
//! As the state changes, the kernel will write events into a ring buffer. The application can read
|
2017-04-27 23:42:45 +00:00
|
|
|
//! from this ring buffer, thus retrieving events. However, if the ring buffer becomes full, the
|
2015-07-21 09:15:21 +00:00
|
|
|
//! kernel will *drop* every event in the ring buffer and leave an event telling userspace that it
|
|
|
|
//! did so. At this point, if the application were using the events it received to update its
|
|
|
|
//! internal idea of what state the hardware device is in, it will be wrong: it is missing some
|
|
|
|
//! events. This library tries to ease that pain, but it is best-effort. Events can never be
|
|
|
|
//! recovered once lost. For example, if a switch is toggled twice, there will be two switch events
|
|
|
|
//! in the buffer. However if the kernel needs to drop events, when the device goes to synchronize
|
|
|
|
//! state with the kernel, only one (or zero, if the switch is in the same state as it was before
|
|
|
|
//! the sync) switch events will be emulated.
|
2015-07-19 21:45:05 +00:00
|
|
|
//!
|
2015-07-21 09:15:21 +00:00
|
|
|
//! It is recommended that you dedicate a thread to processing input events, or use epoll with the
|
|
|
|
//! fd returned by `Device::fd` to process events when they are ready.
|
|
|
|
|
2017-12-01 19:44:06 +00:00
|
|
|
#![cfg(any(unix, target_os = "android"))]
|
2017-04-27 23:42:45 +00:00
|
|
|
#![allow(non_camel_case_types)]
|
2015-07-19 21:45:05 +00:00
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
mod constants;
|
2017-05-28 20:05:28 +00:00
|
|
|
pub mod raw;
|
2021-02-21 02:26:34 +00:00
|
|
|
mod scancodes;
|
2017-05-28 20:05:28 +00:00
|
|
|
|
2015-05-31 11:41:42 +00:00
|
|
|
use fixedbitset::FixedBitSet;
|
2021-02-22 17:57:25 +00:00
|
|
|
use std::fs::File;
|
|
|
|
use std::fs::OpenOptions;
|
2021-02-23 20:31:36 +00:00
|
|
|
use std::mem;
|
2021-02-22 17:57:25 +00:00
|
|
|
use std::os::unix::{
|
|
|
|
fs::OpenOptionsExt,
|
|
|
|
io::{AsRawFd, RawFd},
|
|
|
|
};
|
2021-02-21 02:26:34 +00:00
|
|
|
use std::path::Path;
|
2021-02-22 17:57:25 +00:00
|
|
|
use std::time::SystemTime;
|
2021-02-23 18:28:20 +00:00
|
|
|
use std::{ffi::CString, mem::MaybeUninit};
|
2017-05-28 20:05:28 +00:00
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
pub use crate::constants::FFEffect::*;
|
2021-02-21 02:26:34 +00:00
|
|
|
pub use crate::scancodes::*;
|
|
|
|
pub use crate::Synchronization::*;
|
2015-07-19 21:56:44 +00:00
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
pub use crate::constants::*;
|
2021-02-21 02:26:34 +00:00
|
|
|
use crate::raw::*;
|
2017-05-28 20:05:28 +00:00
|
|
|
|
2021-02-22 17:57:25 +00:00
|
|
|
fn ioctl_get_cstring(
|
|
|
|
f: unsafe fn(RawFd, &mut [u8]) -> nix::Result<libc::c_int>,
|
|
|
|
fd: RawFd,
|
|
|
|
) -> Option<CString> {
|
|
|
|
const CAPACITY: usize = 256;
|
|
|
|
let mut buf = vec![0; CAPACITY];
|
|
|
|
match unsafe { f(fd, buf.as_mut_slice()) } {
|
|
|
|
Ok(len) if len as usize > CAPACITY => {
|
|
|
|
panic!("ioctl_get_cstring call overran the provided buffer!");
|
2017-12-01 19:44:06 +00:00
|
|
|
}
|
2021-02-22 17:57:25 +00:00
|
|
|
Ok(len) if len > 0 => {
|
|
|
|
// Our ioctl string functions apparently return the number of bytes written, including
|
|
|
|
// trailing \0.
|
|
|
|
buf.truncate(len as usize);
|
|
|
|
assert_eq!(buf.pop().unwrap(), 0);
|
|
|
|
CString::new(buf).ok()
|
|
|
|
}
|
|
|
|
Ok(_) => {
|
|
|
|
// if len < 0 => Explicit errno
|
|
|
|
None
|
|
|
|
}
|
|
|
|
Err(_) => None,
|
|
|
|
}
|
2017-12-01 19:44:06 +00:00
|
|
|
}
|
|
|
|
|
2015-07-21 16:04:26 +00:00
|
|
|
macro_rules! impl_number {
|
|
|
|
($($t:ident),*) => {
|
|
|
|
$(impl $t {
|
|
|
|
/// Given a bitflag with only a single flag set, returns the event code corresponding to that
|
|
|
|
/// event. If multiple flags are set, the one with the most significant bit wins. In debug
|
|
|
|
/// mode,
|
|
|
|
#[inline(always)]
|
2021-02-21 02:09:39 +00:00
|
|
|
pub fn number<T: num_traits::FromPrimitive>(&self) -> T {
|
2017-04-27 23:42:45 +00:00
|
|
|
let val = self.bits().trailing_zeros();
|
|
|
|
debug_assert!(self.bits() == 1 << val, "{:?} ought to have only one flag set to be used with .number()", self);
|
|
|
|
T::from_u32(val).unwrap()
|
2015-07-21 16:04:26 +00:00
|
|
|
}
|
|
|
|
})*
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-21 02:26:34 +00:00
|
|
|
impl_number!(
|
|
|
|
Types,
|
|
|
|
Props,
|
|
|
|
RelativeAxis,
|
|
|
|
AbsoluteAxis,
|
|
|
|
Switch,
|
|
|
|
Led,
|
|
|
|
Misc,
|
|
|
|
FFStatus,
|
|
|
|
Repeat,
|
|
|
|
Sound
|
|
|
|
);
|
2015-07-21 16:04:26 +00:00
|
|
|
|
2021-02-22 17:57:25 +00:00
|
|
|
#[repr(u16)]
|
2015-07-19 21:45:05 +00:00
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
|
|
pub enum Synchronization {
|
|
|
|
/// Terminates a packet of events from the device.
|
|
|
|
SYN_REPORT = 0,
|
|
|
|
/// Appears to be unused.
|
|
|
|
SYN_CONFIG = 1,
|
|
|
|
/// "Used to synchronize and separate touch events"
|
|
|
|
SYN_MT_REPORT = 2,
|
|
|
|
/// Ring buffer filled, events were dropped.
|
|
|
|
SYN_DROPPED = 3,
|
|
|
|
}
|
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
#[derive(Debug, Clone)]
|
2015-07-19 21:57:56 +00:00
|
|
|
pub struct DeviceState {
|
2015-07-21 09:16:30 +00:00
|
|
|
/// The state corresponds to kernel state at this timestamp.
|
|
|
|
pub timestamp: libc::timeval,
|
|
|
|
/// Set = key pressed
|
2021-02-23 18:28:20 +00:00
|
|
|
pub key_vals: Option<FixedBitSet>,
|
|
|
|
pub abs_vals: Option<Vec<input_absinfo>>,
|
2015-07-21 09:16:30 +00:00
|
|
|
/// Set = switch enabled (closed)
|
2021-02-23 18:28:20 +00:00
|
|
|
pub switch_vals: Option<FixedBitSet>,
|
2015-07-21 09:16:30 +00:00
|
|
|
/// Set = LED lit
|
2021-02-23 18:28:20 +00:00
|
|
|
pub led_vals: Option<FixedBitSet>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for DeviceState {
|
|
|
|
fn default() -> Self {
|
|
|
|
DeviceState {
|
|
|
|
timestamp: libc::timeval {
|
|
|
|
tv_sec: 0,
|
|
|
|
tv_usec: 0,
|
|
|
|
},
|
|
|
|
key_vals: None,
|
|
|
|
abs_vals: None,
|
|
|
|
switch_vals: None,
|
|
|
|
led_vals: None,
|
|
|
|
}
|
|
|
|
}
|
2015-07-19 21:57:56 +00:00
|
|
|
}
|
|
|
|
|
2021-02-22 17:57:25 +00:00
|
|
|
/// Publicly visible errors which can be returned from evdev
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
|
|
pub enum Error {
|
|
|
|
#[error("libc/system error: {0}")]
|
|
|
|
NixError(#[from] nix::Error),
|
|
|
|
#[error("standard i/o error: {0}")]
|
|
|
|
StdIoError(#[from] std::io::Error),
|
|
|
|
}
|
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
#[derive(Debug)]
|
2015-05-31 11:41:42 +00:00
|
|
|
pub struct Device {
|
2021-02-22 17:57:25 +00:00
|
|
|
file: File,
|
2015-05-31 11:41:42 +00:00
|
|
|
ty: Types,
|
2021-02-24 00:27:05 +00:00
|
|
|
name: Option<String>,
|
|
|
|
phys: Option<String>,
|
|
|
|
uniq: Option<String>,
|
2017-05-28 20:05:28 +00:00
|
|
|
id: input_id,
|
2015-05-31 11:41:42 +00:00
|
|
|
props: Props,
|
2015-07-07 22:31:28 +00:00
|
|
|
driver_version: (u8, u8, u8),
|
2021-02-23 18:28:20 +00:00
|
|
|
supported_keys: Option<FixedBitSet>,
|
|
|
|
supported_relative: Option<RelativeAxis>,
|
|
|
|
supported_absolute: Option<AbsoluteAxis>,
|
|
|
|
supported_switch: Option<Switch>,
|
|
|
|
supported_led: Option<Led>,
|
|
|
|
supported_misc: Option<Misc>,
|
|
|
|
// ff: Option<FixedBitSet>,
|
|
|
|
// ff_stat: Option<FFStatus>,
|
|
|
|
// rep: Option<Repeat>,
|
|
|
|
supported_snd: Option<Sound>,
|
2017-05-28 20:05:28 +00:00
|
|
|
pending_events: Vec<input_event>,
|
2015-07-21 09:16:30 +00:00
|
|
|
// pending_events[last_seen..] is the events that have occurred since the last sync.
|
2015-07-19 21:57:56 +00:00
|
|
|
last_seen: usize,
|
|
|
|
state: DeviceState,
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
|
2021-02-23 20:31:36 +00:00
|
|
|
impl AsRawFd for Device {
|
|
|
|
fn as_raw_fd(&self) -> RawFd {
|
|
|
|
self.file.as_raw_fd()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
const fn bus_name(x: u16) -> &'static str {
|
2015-07-07 22:31:28 +00:00
|
|
|
match x {
|
|
|
|
0x1 => "PCI",
|
|
|
|
0x2 => "ISA Plug 'n Play",
|
|
|
|
0x3 => "USB",
|
|
|
|
0x4 => "HIL",
|
|
|
|
0x5 => "Bluetooth",
|
|
|
|
0x6 => "Virtual",
|
|
|
|
0x10 => "ISA",
|
|
|
|
0x11 => "i8042",
|
|
|
|
0x12 => "XTKBD",
|
|
|
|
0x13 => "RS232",
|
|
|
|
0x14 => "Gameport",
|
|
|
|
0x15 => "Parallel Port",
|
|
|
|
0x16 => "Amiga",
|
|
|
|
0x17 => "ADB",
|
|
|
|
0x18 => "I2C",
|
|
|
|
0x19 => "Host",
|
|
|
|
0x1A => "GSC",
|
|
|
|
0x1B => "Atari",
|
|
|
|
0x1C => "SPI",
|
|
|
|
_ => "Unknown",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl std::fmt::Display for Device {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
2021-02-21 02:26:34 +00:00
|
|
|
writeln!(f, "{:?}", self.name)?;
|
|
|
|
writeln!(
|
|
|
|
f,
|
|
|
|
" Driver version: {}.{}.{}",
|
|
|
|
self.driver_version.0, self.driver_version.1, self.driver_version.2
|
|
|
|
)?;
|
2015-07-07 22:31:28 +00:00
|
|
|
if let Some(ref phys) = self.phys {
|
2021-02-21 02:26:34 +00:00
|
|
|
writeln!(f, " Physical address: {:?}", phys)?;
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
if let Some(ref uniq) = self.uniq {
|
2021-02-21 02:26:34 +00:00
|
|
|
writeln!(f, " Unique name: {:?}", uniq)?;
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
|
2021-02-21 02:26:34 +00:00
|
|
|
writeln!(f, " Bus: {}", bus_name(self.id.bustype))?;
|
|
|
|
writeln!(f, " Vendor: 0x{:x}", self.id.vendor)?;
|
|
|
|
writeln!(f, " Product: 0x{:x}", self.id.product)?;
|
|
|
|
writeln!(f, " Version: 0x{:x}", self.id.version)?;
|
|
|
|
writeln!(f, " Properties: {:?}", self.props)?;
|
2015-07-07 22:31:28 +00:00
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
if let (Some(supported_keys), Some(key_vals)) = (&self.supported_keys, &self.state.key_vals)
|
|
|
|
{
|
2021-02-21 02:26:34 +00:00
|
|
|
writeln!(f, " Keys supported:")?;
|
2021-02-23 18:28:20 +00:00
|
|
|
for key_idx in 0..supported_keys.len() {
|
|
|
|
if supported_keys.contains(key_idx) {
|
2021-02-21 02:26:34 +00:00
|
|
|
writeln!(
|
|
|
|
f,
|
|
|
|
" {:?} ({}index {})",
|
2021-02-23 18:28:20 +00:00
|
|
|
Key::new(key_idx as u32),
|
|
|
|
if key_vals.contains(key_idx) {
|
2021-02-21 02:26:34 +00:00
|
|
|
"pressed, "
|
|
|
|
} else {
|
|
|
|
""
|
|
|
|
},
|
|
|
|
key_idx
|
|
|
|
)?;
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-02-23 18:28:20 +00:00
|
|
|
|
|
|
|
if let Some(supported_relative) = self.supported_relative {
|
|
|
|
writeln!(f, " Relative Axes: {:?}", supported_relative)?;
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
2021-02-23 18:28:20 +00:00
|
|
|
|
|
|
|
if let (Some(supported_abs), Some(abs_vals)) =
|
|
|
|
(self.supported_absolute, &self.state.abs_vals)
|
|
|
|
{
|
2021-02-21 02:26:34 +00:00
|
|
|
writeln!(f, " Absolute Axes:")?;
|
2021-02-23 18:28:20 +00:00
|
|
|
for idx in 0..AbsoluteAxis::MAX {
|
|
|
|
let abs = AbsoluteAxis::from_bits_truncate(1 << idx);
|
|
|
|
if supported_abs.contains(abs) {
|
|
|
|
writeln!(f, " {:?} ({:?}, index {})", abs, abs_vals[idx], idx)?;
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-02-23 18:28:20 +00:00
|
|
|
|
|
|
|
if let Some(supported_misc) = self.supported_misc {
|
|
|
|
writeln!(f, " Miscellaneous capabilities: {:?}", supported_misc)?;
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
2021-02-23 18:28:20 +00:00
|
|
|
|
|
|
|
if let (Some(supported_switch), Some(switch_vals)) =
|
|
|
|
(self.supported_switch, &self.state.switch_vals)
|
|
|
|
{
|
2021-02-21 02:26:34 +00:00
|
|
|
writeln!(f, " Switches:")?;
|
2021-02-23 18:28:20 +00:00
|
|
|
for idx in 0..Switch::MAX {
|
|
|
|
let sw = Switch::from_bits(1 << idx).unwrap();
|
|
|
|
if supported_switch.contains(sw) {
|
|
|
|
writeln!(f, " {:?} ({:?}, index {})", sw, switch_vals[idx], idx)?;
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-02-23 18:28:20 +00:00
|
|
|
|
|
|
|
if let (Some(supported_led), Some(led_vals)) = (self.supported_led, &self.state.led_vals) {
|
2021-02-21 02:26:34 +00:00
|
|
|
writeln!(f, " LEDs:")?;
|
2021-02-23 18:28:20 +00:00
|
|
|
for idx in 0..Led::MAX {
|
|
|
|
let led = Led::from_bits_truncate(1 << idx);
|
|
|
|
if supported_led.contains(led) {
|
|
|
|
writeln!(f, " {:?} ({:?}, index {})", led, led_vals[idx], idx)?;
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-02-23 18:28:20 +00:00
|
|
|
|
|
|
|
if let Some(supported_snd) = self.supported_snd {
|
|
|
|
writeln!(f, " Sound: {:?}", supported_snd)?;
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
2021-02-23 18:28:20 +00:00
|
|
|
|
|
|
|
// if let Some(rep) = self.rep {
|
|
|
|
// writeln!(f, " Repeats: {:?}", rep)?;
|
|
|
|
// }
|
|
|
|
|
2021-02-21 02:09:39 +00:00
|
|
|
if self.ty.contains(Types::FORCEFEEDBACK) {
|
2021-02-21 02:26:34 +00:00
|
|
|
writeln!(f, " Force Feedback supported")?;
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
2021-02-23 18:28:20 +00:00
|
|
|
|
2021-02-21 02:09:39 +00:00
|
|
|
if self.ty.contains(Types::POWER) {
|
2021-02-21 02:26:34 +00:00
|
|
|
writeln!(f, " Power supported")?;
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
2021-02-23 18:28:20 +00:00
|
|
|
|
2021-02-21 02:09:39 +00:00
|
|
|
if self.ty.contains(Types::FORCEFEEDBACKSTATUS) {
|
2021-02-21 02:26:34 +00:00
|
|
|
writeln!(f, " Force Feedback status supported")?;
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
2021-02-23 18:28:20 +00:00
|
|
|
|
2015-07-07 22:31:28 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-31 11:41:42 +00:00
|
|
|
impl Device {
|
2015-07-07 22:31:28 +00:00
|
|
|
pub fn events_supported(&self) -> Types {
|
|
|
|
self.ty
|
|
|
|
}
|
|
|
|
|
2021-02-24 00:27:05 +00:00
|
|
|
pub fn name(&self) -> Option<&str> {
|
|
|
|
self.name.as_deref()
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
|
2021-02-24 00:27:05 +00:00
|
|
|
pub fn physical_path(&self) -> Option<&str> {
|
|
|
|
self.phys.as_deref()
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
|
2021-02-24 00:27:05 +00:00
|
|
|
pub fn unique_name(&self) -> Option<&str> {
|
|
|
|
self.uniq.as_deref()
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
|
2017-05-28 20:05:28 +00:00
|
|
|
pub fn input_id(&self) -> input_id {
|
2015-07-07 22:31:28 +00:00
|
|
|
self.id
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn properties(&self) -> Props {
|
|
|
|
self.props
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn driver_version(&self) -> (u8, u8, u8) {
|
|
|
|
self.driver_version
|
|
|
|
}
|
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
pub fn keys_supported(&self) -> &Option<FixedBitSet> {
|
2021-02-22 20:43:58 +00:00
|
|
|
&self.supported_keys
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
pub fn relative_axes_supported(&self) -> Option<RelativeAxis> {
|
|
|
|
self.supported_relative
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
pub fn absolute_axes_supported(&self) -> Option<AbsoluteAxis> {
|
|
|
|
self.supported_absolute
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
pub fn switches_supported(&self) -> Option<Switch> {
|
|
|
|
self.supported_switch
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
pub fn leds_supported(&self) -> Option<Led> {
|
|
|
|
self.supported_led
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
pub fn misc_properties(&self) -> Option<Misc> {
|
|
|
|
self.supported_misc
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
// pub fn repeats_supported(&self) -> Option<Repeat> {
|
|
|
|
// self.rep
|
|
|
|
// }
|
2015-07-07 22:31:28 +00:00
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
pub fn sounds_supported(&self) -> Option<Sound> {
|
|
|
|
self.supported_snd
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
|
2015-07-19 21:57:56 +00:00
|
|
|
pub fn state(&self) -> &DeviceState {
|
|
|
|
&self.state
|
|
|
|
}
|
|
|
|
|
2021-02-23 20:31:36 +00:00
|
|
|
#[inline(always)]
|
|
|
|
pub fn open(path: impl AsRef<Path>) -> Result<Device, Error> {
|
|
|
|
Self::_open(path.as_ref())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn _open(path: &Path) -> Result<Device, Error> {
|
2021-02-22 17:57:25 +00:00
|
|
|
let mut options = OpenOptions::new();
|
|
|
|
|
|
|
|
// Try to load read/write, then fall back to read-only.
|
|
|
|
let file = options
|
|
|
|
.read(true)
|
|
|
|
.write(true)
|
|
|
|
.custom_flags(libc::O_NONBLOCK)
|
|
|
|
.open(path)
|
|
|
|
.or_else(|_| options.write(false).open(path))?;
|
2015-07-07 22:31:28 +00:00
|
|
|
|
2021-02-23 20:31:36 +00:00
|
|
|
let mut ty = 0;
|
|
|
|
unsafe { eviocgbit_type(file.as_raw_fd(), &mut ty)? };
|
|
|
|
let ty = Types::from_bits(ty).expect("evdev: unexpected type bits! report a bug");
|
2015-07-07 22:31:28 +00:00
|
|
|
|
2021-02-24 00:27:05 +00:00
|
|
|
let name = ioctl_get_cstring(eviocgname, file.as_raw_fd())
|
|
|
|
.map(|s| s.to_string_lossy().into_owned());
|
|
|
|
let phys = ioctl_get_cstring(eviocgphys, file.as_raw_fd())
|
|
|
|
.map(|s| s.to_string_lossy().into_owned());
|
|
|
|
let uniq = ioctl_get_cstring(eviocguniq, file.as_raw_fd())
|
|
|
|
.map(|s| s.to_string_lossy().into_owned());
|
2015-07-07 22:31:28 +00:00
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
let id = unsafe {
|
|
|
|
let mut id = MaybeUninit::uninit();
|
|
|
|
eviocgid(file.as_raw_fd(), id.as_mut_ptr())?;
|
|
|
|
id.assume_init()
|
|
|
|
};
|
2015-07-07 22:31:28 +00:00
|
|
|
let mut driver_version: i32 = 0;
|
2021-02-22 20:43:41 +00:00
|
|
|
unsafe {
|
2021-02-23 18:28:20 +00:00
|
|
|
eviocgversion(file.as_raw_fd(), &mut driver_version)?;
|
2021-02-22 20:43:41 +00:00
|
|
|
}
|
2021-02-23 18:28:20 +00:00
|
|
|
let driver_version = (
|
2021-02-21 02:26:34 +00:00
|
|
|
((driver_version >> 16) & 0xff) as u8,
|
|
|
|
((driver_version >> 8) & 0xff) as u8,
|
|
|
|
(driver_version & 0xff) as u8,
|
|
|
|
);
|
|
|
|
|
2021-02-23 20:31:36 +00:00
|
|
|
let mut props = 0;
|
2021-02-22 17:57:25 +00:00
|
|
|
unsafe {
|
2021-02-23 20:31:36 +00:00
|
|
|
eviocgprop(file.as_raw_fd(), &mut props)?;
|
2021-02-22 20:43:41 +00:00
|
|
|
} // FIXME: handle old kernel
|
2021-02-23 20:31:36 +00:00
|
|
|
let props = Props::from_bits(props).expect("evdev: unexpected prop bits! report a bug");
|
2021-02-23 18:28:20 +00:00
|
|
|
|
|
|
|
let mut state = DeviceState::default();
|
2015-07-07 22:31:28 +00:00
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
let supported_keys = if ty.contains(Types::KEY) {
|
|
|
|
let mut supported_keys = FixedBitSet::with_capacity(Key::MAX);
|
|
|
|
debug_assert!(supported_keys.len() % 8 == 0);
|
|
|
|
let key_slice = supported_keys.as_mut_slice();
|
2021-02-22 17:57:25 +00:00
|
|
|
unsafe {
|
2021-02-22 20:43:58 +00:00
|
|
|
let (_, supported_keys_as_u8_slice, _) = key_slice.align_to_mut();
|
|
|
|
debug_assert!(supported_keys_as_u8_slice.len() == Key::MAX / 8);
|
2021-02-23 20:31:36 +00:00
|
|
|
eviocgbit_key(file.as_raw_fd(), supported_keys_as_u8_slice)?;
|
2021-02-22 20:43:41 +00:00
|
|
|
}
|
2021-02-23 18:28:20 +00:00
|
|
|
let key_vals = FixedBitSet::with_capacity(Key::MAX);
|
|
|
|
debug_assert!(key_vals.len() % 8 == 0);
|
|
|
|
state.key_vals = Some(key_vals);
|
|
|
|
|
|
|
|
Some(supported_keys)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
2015-07-07 22:31:28 +00:00
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
let supported_relative = if ty.contains(Types::RELATIVE) {
|
2021-02-23 20:31:36 +00:00
|
|
|
let mut rel = 0;
|
|
|
|
unsafe { eviocgbit_relative(file.as_raw_fd(), &mut rel)? };
|
|
|
|
Some(RelativeAxis::from_bits(rel).expect("evdev: unexpected rel bits! report a bug"))
|
2021-02-23 18:28:20 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
2015-07-07 22:31:28 +00:00
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
let supported_absolute = if ty.contains(Types::ABSOLUTE) {
|
2021-02-23 20:31:36 +00:00
|
|
|
let mut abs = 0;
|
|
|
|
unsafe { eviocgbit_absolute(file.as_raw_fd(), &mut abs)? };
|
2021-02-23 18:28:20 +00:00
|
|
|
state.abs_vals = Some(vec![input_absinfo_default(); 0x3f]);
|
2021-02-23 20:31:36 +00:00
|
|
|
Some(AbsoluteAxis::from_bits(abs).expect("evdev: unexpected abs bits! report a bug"))
|
2021-02-23 18:28:20 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
2015-07-07 22:31:28 +00:00
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
let supported_switch = if ty.contains(Types::SWITCH) {
|
2021-02-23 20:31:36 +00:00
|
|
|
let mut switch = 0;
|
|
|
|
unsafe { eviocgbit_switch(file.as_raw_fd(), &mut switch)? };
|
2021-02-23 18:28:20 +00:00
|
|
|
state.switch_vals = Some(FixedBitSet::with_capacity(0x10));
|
|
|
|
|
2021-02-23 20:31:36 +00:00
|
|
|
Some(Switch::from_bits(switch).expect("evdev: unexpected switch bits! report a bug"))
|
2021-02-23 18:28:20 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
2015-07-07 22:31:28 +00:00
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
let supported_led = if ty.contains(Types::LED) {
|
2021-02-23 20:31:36 +00:00
|
|
|
let mut led = 0;
|
|
|
|
unsafe { eviocgbit_led(file.as_raw_fd(), &mut led)? };
|
2021-02-23 18:28:20 +00:00
|
|
|
let led_vals = FixedBitSet::with_capacity(0x10);
|
|
|
|
debug_assert!(led_vals.len() % 8 == 0);
|
|
|
|
state.led_vals = Some(led_vals);
|
2015-07-07 22:31:28 +00:00
|
|
|
|
2021-02-23 20:31:36 +00:00
|
|
|
Some(Led::from_bits(led).expect("evdev: unexpected led bits! report a bug"))
|
2021-02-23 18:28:20 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
|
|
|
let supported_misc = if ty.contains(Types::MISC) {
|
2021-02-23 20:31:36 +00:00
|
|
|
let mut misc = 0;
|
|
|
|
unsafe { eviocgbit_misc(file.as_raw_fd(), &mut misc)? };
|
|
|
|
Some(Misc::from_bits(misc).expect("evdev: unexpected misc bits! report a bug"))
|
2021-02-23 18:28:20 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
2015-07-07 22:31:28 +00:00
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
//unsafe { eviocgbit(file.as_raw_fd(), ffs(FORCEFEEDBACK.bits()), 0x7f, bits_as_u8_slice)?; }
|
2015-07-07 22:31:28 +00:00
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
let supported_snd = if ty.contains(Types::SOUND) {
|
2021-02-23 20:31:36 +00:00
|
|
|
let mut snd = 0;
|
|
|
|
unsafe { eviocgbit_sound(file.as_raw_fd(), &mut snd)? };
|
|
|
|
Some(Sound::from_bits(snd).expect("evdev: unexpected sound bits! report a bug"))
|
2021-02-23 18:28:20 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut dev = Device {
|
|
|
|
file,
|
|
|
|
ty,
|
|
|
|
name,
|
|
|
|
phys,
|
|
|
|
uniq,
|
|
|
|
id,
|
|
|
|
props,
|
|
|
|
driver_version,
|
|
|
|
supported_keys,
|
|
|
|
supported_relative,
|
|
|
|
supported_absolute,
|
|
|
|
supported_switch,
|
|
|
|
supported_led,
|
|
|
|
supported_misc,
|
|
|
|
supported_snd,
|
|
|
|
pending_events: Vec::with_capacity(64),
|
|
|
|
last_seen: 0,
|
|
|
|
state,
|
|
|
|
};
|
2015-07-07 22:31:28 +00:00
|
|
|
|
2021-02-21 02:26:34 +00:00
|
|
|
dev.sync_state()?;
|
2015-07-07 22:31:28 +00:00
|
|
|
|
2015-05-31 11:41:42 +00:00
|
|
|
Ok(dev)
|
|
|
|
}
|
2015-07-07 22:31:28 +00:00
|
|
|
|
|
|
|
/// Synchronize the `Device` state with the kernel device state.
|
|
|
|
///
|
|
|
|
/// If there is an error at any point, the state will not be synchronized completely.
|
2015-07-19 21:57:56 +00:00
|
|
|
pub fn sync_state(&mut self) -> Result<(), Error> {
|
2021-02-23 20:31:36 +00:00
|
|
|
let fd = self.as_raw_fd();
|
2021-02-23 18:28:20 +00:00
|
|
|
if let Some(key_vals) = &mut self.state.key_vals {
|
2021-02-22 17:57:25 +00:00
|
|
|
unsafe {
|
2021-02-23 18:28:20 +00:00
|
|
|
let key_slice = key_vals.as_mut_slice();
|
2021-02-22 17:57:25 +00:00
|
|
|
let (_, key_vals_as_u8_slice, _) = key_slice.align_to_mut();
|
2021-02-23 20:31:36 +00:00
|
|
|
eviocgkey(fd, key_vals_as_u8_slice)?;
|
2021-02-22 20:43:41 +00:00
|
|
|
}
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
2021-02-23 18:28:20 +00:00
|
|
|
|
|
|
|
if let (Some(supported_abs), Some(abs_vals)) =
|
|
|
|
(self.supported_absolute, &mut self.state.abs_vals)
|
|
|
|
{
|
|
|
|
for idx in 0..AbsoluteAxis::MAX {
|
|
|
|
let abs = AbsoluteAxis::from_bits_truncate(1 << idx);
|
2015-07-07 22:31:28 +00:00
|
|
|
// ignore multitouch, we'll handle that later.
|
2020-11-04 21:15:50 +00:00
|
|
|
//
|
|
|
|
// handling later removed. not sure what the intention of "handling that later" was
|
|
|
|
// the abs data seems to be fine (tested ABS_MT_POSITION_X/Y)
|
2021-02-23 18:28:20 +00:00
|
|
|
if supported_abs.contains(abs) {
|
2021-02-22 17:57:25 +00:00
|
|
|
unsafe {
|
2021-02-23 20:31:36 +00:00
|
|
|
eviocgabs(fd, idx as u32, &mut abs_vals[idx])?;
|
2021-02-22 20:43:41 +00:00
|
|
|
}
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-02-23 18:28:20 +00:00
|
|
|
|
|
|
|
if let Some(switch_vals) = &mut self.state.switch_vals {
|
2021-02-22 17:57:25 +00:00
|
|
|
unsafe {
|
2021-02-23 18:28:20 +00:00
|
|
|
let switch_slice = switch_vals.as_mut_slice();
|
2021-02-22 17:57:25 +00:00
|
|
|
let (_, switch_vals_as_u8_slice, _) = switch_slice.align_to_mut();
|
2021-02-23 20:31:36 +00:00
|
|
|
eviocgsw(fd, switch_vals_as_u8_slice)?;
|
2021-02-22 20:43:41 +00:00
|
|
|
}
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
2021-02-23 18:28:20 +00:00
|
|
|
|
|
|
|
if let Some(led_vals) = &mut self.state.led_vals {
|
2021-02-22 17:57:25 +00:00
|
|
|
unsafe {
|
2021-02-23 18:28:20 +00:00
|
|
|
let led_slice = led_vals.as_mut_slice();
|
2021-02-22 17:57:25 +00:00
|
|
|
let (_, led_vals_as_u8_slice, _) = led_slice.align_to_mut();
|
2021-02-23 20:31:36 +00:00
|
|
|
eviocgled(fd, led_vals_as_u8_slice)?;
|
2021-02-22 20:43:41 +00:00
|
|
|
}
|
2015-07-19 21:57:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2015-07-21 09:16:30 +00:00
|
|
|
|
|
|
|
/// Do SYN_DROPPED synchronization, and compensate for missing events by inserting events into
|
|
|
|
/// the stream which, when applied to any state being kept outside of this `Device`, will
|
|
|
|
/// synchronize it with the kernel state.
|
2015-07-21 09:26:47 +00:00
|
|
|
fn compensate_dropped(&mut self) -> Result<(), Error> {
|
2015-07-21 09:16:30 +00:00
|
|
|
let mut drop_from = None;
|
|
|
|
for (idx, event) in self.pending_events[self.last_seen..].iter().enumerate() {
|
2021-02-22 17:57:25 +00:00
|
|
|
if event.type_ == SYN_DROPPED as u16 {
|
2015-07-21 09:16:30 +00:00
|
|
|
drop_from = Some(idx);
|
2021-02-21 02:26:34 +00:00
|
|
|
break;
|
2015-07-21 09:16:30 +00:00
|
|
|
}
|
|
|
|
}
|
2015-07-21 12:22:12 +00:00
|
|
|
// FIXME: see if we can *not* drop EV_REL events. EV_REL doesn't have any state, so
|
|
|
|
// dropping its events isn't really helping much.
|
2015-07-21 09:16:30 +00:00
|
|
|
if let Some(idx) = drop_from {
|
|
|
|
// look for the nearest SYN_REPORT before the SYN_DROPPED, remove everything after it.
|
|
|
|
let mut prev_report = 0; // (if there's no previous SYN_REPORT, then the entire vector is bogus)
|
|
|
|
for (idx, event) in self.pending_events[..idx].iter().enumerate().rev() {
|
2021-02-22 17:57:25 +00:00
|
|
|
if event.type_ == SYN_REPORT as u16 {
|
2015-07-21 09:16:30 +00:00
|
|
|
prev_report = idx;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.pending_events.truncate(prev_report);
|
2017-05-28 21:52:38 +00:00
|
|
|
} else {
|
2021-02-21 02:26:34 +00:00
|
|
|
return Ok(());
|
2015-07-21 09:16:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Alright, pending_events is in a sane state. Now, let's sync the local state. We will
|
|
|
|
// create a phony packet that contains deltas from the previous device state to the current
|
|
|
|
// device state.
|
|
|
|
let old_state = self.state.clone();
|
2021-02-21 02:26:34 +00:00
|
|
|
self.sync_state()?;
|
2021-02-22 17:57:25 +00:00
|
|
|
|
|
|
|
let time = into_timeval(&SystemTime::now()).unwrap();
|
2015-07-21 09:16:30 +00:00
|
|
|
|
2021-02-23 18:28:20 +00:00
|
|
|
if let (Some(supported_keys), Some(key_vals)) = (&self.supported_keys, &self.state.key_vals)
|
|
|
|
{
|
|
|
|
for key_idx in 0..supported_keys.len() {
|
|
|
|
if supported_keys.contains(key_idx)
|
|
|
|
&& old_state.key_vals.as_ref().map(|v| v[key_idx]) != Some(key_vals[key_idx])
|
2021-02-22 17:57:25 +00:00
|
|
|
{
|
|
|
|
self.pending_events.push(raw::input_event {
|
|
|
|
time,
|
|
|
|
type_: Types::KEY.number(),
|
|
|
|
code: key_idx as u16,
|
2021-02-23 18:28:20 +00:00
|
|
|
value: if key_vals[key_idx] { 1 } else { 0 },
|
2021-02-22 17:57:25 +00:00
|
|
|
});
|
2015-07-21 09:16:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-02-23 18:28:20 +00:00
|
|
|
|
|
|
|
if let (Some(supported_abs), Some(abs_vals)) =
|
|
|
|
(self.supported_absolute, &self.state.abs_vals)
|
|
|
|
{
|
|
|
|
for idx in 0..AbsoluteAxis::MAX {
|
|
|
|
let abs = AbsoluteAxis::from_bits_truncate(1 << idx);
|
|
|
|
if supported_abs.contains(abs)
|
|
|
|
&& old_state.abs_vals.as_ref().map(|v| v[idx]) != Some(abs_vals[idx])
|
2021-02-22 17:57:25 +00:00
|
|
|
{
|
|
|
|
self.pending_events.push(raw::input_event {
|
|
|
|
time,
|
|
|
|
type_: Types::ABSOLUTE.number(),
|
|
|
|
code: idx as u16,
|
2021-02-23 18:28:20 +00:00
|
|
|
value: abs_vals[idx].value,
|
2021-02-22 17:57:25 +00:00
|
|
|
});
|
2015-07-21 09:16:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-02-23 18:28:20 +00:00
|
|
|
|
|
|
|
if let (Some(supported_switch), Some(switch_vals)) =
|
|
|
|
(self.supported_switch, &self.state.switch_vals)
|
|
|
|
{
|
|
|
|
for idx in 0..Switch::MAX {
|
|
|
|
let sw = Switch::from_bits(1 << idx).unwrap();
|
|
|
|
if supported_switch.contains(sw)
|
|
|
|
&& old_state.switch_vals.as_ref().map(|v| v[idx]) != Some(switch_vals[idx])
|
2021-02-22 17:57:25 +00:00
|
|
|
{
|
|
|
|
self.pending_events.push(raw::input_event {
|
|
|
|
time,
|
|
|
|
type_: Types::SWITCH.number(),
|
|
|
|
code: idx as u16,
|
2021-02-23 18:28:20 +00:00
|
|
|
value: if switch_vals[idx] { 1 } else { 0 },
|
2021-02-22 17:57:25 +00:00
|
|
|
});
|
2015-07-21 09:16:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-02-23 18:28:20 +00:00
|
|
|
|
|
|
|
if let (Some(supported_led), Some(led_vals)) = (self.supported_led, &self.state.led_vals) {
|
|
|
|
for idx in 0..Led::MAX {
|
|
|
|
let led = Led::from_bits_truncate(1 << idx);
|
|
|
|
if supported_led.contains(led)
|
|
|
|
&& old_state.led_vals.as_ref().map(|v| v[idx]) != Some(led_vals[idx])
|
2021-02-22 17:57:25 +00:00
|
|
|
{
|
|
|
|
self.pending_events.push(raw::input_event {
|
|
|
|
time,
|
|
|
|
type_: Types::LED.number(),
|
|
|
|
code: idx as u16,
|
2021-02-23 18:28:20 +00:00
|
|
|
value: if led_vals[idx] { 1 } else { 0 },
|
2021-02-22 17:57:25 +00:00
|
|
|
});
|
2015-07-21 09:16:30 +00:00
|
|
|
}
|
|
|
|
}
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
|
2017-05-28 20:05:28 +00:00
|
|
|
self.pending_events.push(raw::input_event {
|
2021-02-22 17:57:25 +00:00
|
|
|
time,
|
|
|
|
type_: Types::SYNCHRONIZATION.number(),
|
2015-07-21 09:16:30 +00:00
|
|
|
code: SYN_REPORT as u16,
|
|
|
|
value: 0,
|
|
|
|
});
|
2015-07-07 22:31:28 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2015-07-12 21:22:05 +00:00
|
|
|
fn fill_events(&mut self) -> Result<(), Error> {
|
2021-02-23 20:31:36 +00:00
|
|
|
let fd = self.as_raw_fd();
|
2017-12-01 20:06:03 +00:00
|
|
|
let buf = &mut self.pending_events;
|
2015-07-07 22:31:28 +00:00
|
|
|
loop {
|
|
|
|
buf.reserve(20);
|
2021-02-23 20:31:36 +00:00
|
|
|
// TODO: use Vec::spare_capacity_mut or Vec::split_at_spare_mut when they stabilize
|
|
|
|
let spare_capacity = vec_spare_capacity_mut(buf);
|
|
|
|
let (_, uninit_buf, _) =
|
|
|
|
unsafe { spare_capacity.align_to_mut::<mem::MaybeUninit<u8>>() };
|
|
|
|
|
|
|
|
// use libc::read instead of nix::unistd::read b/c we need to pass an uninitialized buf
|
|
|
|
let res = unsafe { libc::read(fd, uninit_buf.as_mut_ptr() as _, uninit_buf.len()) };
|
|
|
|
match nix::errno::Errno::result(res) {
|
2021-02-22 17:57:25 +00:00
|
|
|
Ok(bytes_read) => unsafe {
|
2021-02-23 20:31:36 +00:00
|
|
|
let pre_len = buf.len();
|
|
|
|
buf.set_len(
|
|
|
|
pre_len + (bytes_read as usize / mem::size_of::<raw::input_event>()),
|
|
|
|
);
|
2021-02-22 17:57:25 +00:00
|
|
|
},
|
|
|
|
Err(e) => {
|
|
|
|
if e == nix::Error::Sys(::nix::errno::Errno::EAGAIN) {
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
return Err(e.into());
|
2021-02-22 20:43:41 +00:00
|
|
|
}
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-07-12 21:22:05 +00:00
|
|
|
Ok(())
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Exposes the raw evdev events without doing synchronization on SYN_DROPPED.
|
2015-07-19 21:45:05 +00:00
|
|
|
pub fn events_no_sync(&mut self) -> Result<RawEvents, Error> {
|
2021-02-21 02:26:34 +00:00
|
|
|
self.fill_events()?;
|
2015-07-12 21:22:05 +00:00
|
|
|
Ok(RawEvents::new(self))
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
|
2015-07-19 21:45:05 +00:00
|
|
|
/// Exposes the raw evdev events, doing synchronization on SYN_DROPPED.
|
|
|
|
///
|
|
|
|
/// Will insert "fake" events
|
|
|
|
pub fn events(&mut self) -> Result<RawEvents, Error> {
|
2021-02-21 02:26:34 +00:00
|
|
|
self.fill_events()?;
|
|
|
|
self.compensate_dropped()?;
|
2015-07-19 21:45:05 +00:00
|
|
|
|
2021-02-23 20:31:36 +00:00
|
|
|
Ok(RawEvents::new(self))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn wait_ready(&self) -> nix::Result<()> {
|
|
|
|
use nix::poll;
|
|
|
|
let mut pfd = poll::PollFd::new(self.as_raw_fd(), poll::PollFlags::POLLIN);
|
|
|
|
poll::poll(std::slice::from_mut(&mut pfd), -1)?;
|
|
|
|
Ok(())
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Events<'a>(&'a mut Device);
|
|
|
|
|
|
|
|
pub struct RawEvents<'a>(&'a mut Device);
|
|
|
|
|
|
|
|
impl<'a> RawEvents<'a> {
|
|
|
|
fn new(dev: &'a mut Device) -> RawEvents<'a> {
|
|
|
|
dev.pending_events.reverse();
|
|
|
|
RawEvents(dev)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Drop for RawEvents<'a> {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
self.0.pending_events.reverse();
|
2015-07-19 21:45:05 +00:00
|
|
|
self.0.last_seen = self.0.pending_events.len();
|
2015-07-07 22:31:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Iterator for RawEvents<'a> {
|
2017-05-28 20:05:28 +00:00
|
|
|
type Item = raw::input_event;
|
2015-07-07 22:31:28 +00:00
|
|
|
|
|
|
|
#[inline(always)]
|
2017-05-28 20:05:28 +00:00
|
|
|
fn next(&mut self) -> Option<raw::input_event> {
|
2015-07-07 22:31:28 +00:00
|
|
|
self.0.pending_events.pop()
|
|
|
|
}
|
2015-05-31 11:41:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Crawls `/dev/input` for evdev devices.
|
|
|
|
///
|
|
|
|
/// Will not bubble up any errors in opening devices or traversing the directory. Instead returns
|
2021-02-23 20:31:36 +00:00
|
|
|
/// 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 = Device;
|
|
|
|
fn next(&mut self) -> Option<Device> {
|
|
|
|
let readdir = self.readdir.as_mut()?;
|
|
|
|
loop {
|
|
|
|
if let Ok(entry) = readdir.next()? {
|
|
|
|
if let Ok(dev) = Device::open(entry.path()) {
|
|
|
|
return Some(dev);
|
2015-05-31 11:41:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-05-29 18:57:46 +00:00
|
|
|
}
|
2021-02-22 17:57:25 +00:00
|
|
|
|
|
|
|
/// A safe Rust version of clock_gettime against CLOCK_REALTIME
|
|
|
|
fn into_timeval(time: &SystemTime) -> Result<libc::timeval, std::time::SystemTimeError> {
|
|
|
|
let now_duration = time.duration_since(SystemTime::UNIX_EPOCH)?;
|
|
|
|
|
|
|
|
Ok(libc::timeval {
|
|
|
|
tv_sec: now_duration.as_secs() as libc::time_t,
|
|
|
|
tv_usec: now_duration.subsec_micros() as libc::suseconds_t,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-02-23 20:31:36 +00:00
|
|
|
/// A copy of the unstable Vec::spare_capacity_mut
|
|
|
|
#[inline]
|
|
|
|
fn vec_spare_capacity_mut<T>(v: &mut Vec<T>) -> &mut [mem::MaybeUninit<T>] {
|
|
|
|
let (len, cap) = (v.len(), v.capacity());
|
|
|
|
unsafe {
|
|
|
|
std::slice::from_raw_parts_mut(
|
|
|
|
v.as_mut_ptr().add(len) as *mut mem::MaybeUninit<T>,
|
|
|
|
cap - len,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-22 17:57:25 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use std::mem::MaybeUninit;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn align_to_mut_is_sane() {
|
|
|
|
// We assume align_to_mut -> u8 puts everything in inner. Let's double check.
|
|
|
|
let mut bits: u32 = 0;
|
|
|
|
let (prefix, inner, suffix) =
|
|
|
|
unsafe { std::slice::from_mut(&mut bits).align_to_mut::<u8>() };
|
|
|
|
assert_eq!(prefix.len(), 0);
|
|
|
|
assert_eq!(inner.len(), std::mem::size_of::<u32>());
|
|
|
|
assert_eq!(suffix.len(), 0);
|
|
|
|
|
|
|
|
let mut ev: MaybeUninit<libc::input_event> = MaybeUninit::uninit();
|
|
|
|
let (prefix, inner, suffix) = unsafe { std::slice::from_mut(&mut ev).align_to_mut::<u8>() };
|
|
|
|
assert_eq!(prefix.len(), 0);
|
|
|
|
assert_eq!(inner.len(), std::mem::size_of::<libc::input_event>());
|
|
|
|
assert_eq!(suffix.len(), 0);
|
|
|
|
}
|
|
|
|
}
|