Ergonomics (#38)
* Hide sync_* implementations, expose get_* for state * Add get_abs_state and rustdoc * Refactor * Update rustdoc Co-authored-by: Jeff Hiner <jeff-hiner@users.noreply.github.com>
This commit is contained in:
parent
3581aa25e0
commit
79b6c2b403
5 changed files with 193 additions and 96 deletions
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "evdev"
|
name = "evdev"
|
||||||
version = "0.11.0-alpha.5"
|
version = "0.11.0-alpha.6"
|
||||||
authors = ["Corey Richardson <corey@octayn.net>"]
|
authors = ["Corey Richardson <corey@octayn.net>"]
|
||||||
description = "evdev interface for Linux"
|
description = "evdev interface for Linux"
|
||||||
license = "Apache-2.0 OR MIT"
|
license = "Apache-2.0 OR MIT"
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use crate::constants::*;
|
use crate::{constants::*, raw_stream::RawDevice};
|
||||||
use crate::{AttributeSet, AttributeSetRef, InputEvent, InputEventKind, Key};
|
use crate::{AttributeSet, AttributeSetRef, InputEvent, InputEventKind, Key};
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
/// A cached representation of device state at a certain time.
|
/// A **cached** representation of device state at a certain time.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DeviceState {
|
pub struct DeviceState {
|
||||||
/// The state corresponds to kernel state at this timestamp.
|
/// The state corresponds to kernel state at this timestamp.
|
||||||
pub(crate) timestamp: libc::timeval,
|
pub(crate) timestamp: SystemTime,
|
||||||
/// Set = key pressed
|
/// Set = key pressed
|
||||||
pub(crate) key_vals: Option<AttributeSet<Key>>,
|
pub(crate) key_vals: Option<AttributeSet<Key>>,
|
||||||
pub(crate) abs_vals: Option<Box<[libc::input_absinfo; AbsoluteAxisType::COUNT]>>,
|
pub(crate) abs_vals: Option<Box<[libc::input_absinfo; AbsoluteAxisType::COUNT]>>,
|
||||||
|
@ -37,9 +37,43 @@ impl Clone for DeviceState {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeviceState {
|
impl DeviceState {
|
||||||
|
/// Create an empty `DeviceState`. The `{abs,key,etc}_vals` for the returned state will return
|
||||||
|
/// `Some` if `supported_events()` contains that `EventType`.
|
||||||
|
pub(crate) fn new(device: &RawDevice) -> Self {
|
||||||
|
let supports = device.supported_events();
|
||||||
|
|
||||||
|
let key_vals = if supports.contains(EventType::KEY) {
|
||||||
|
Some(AttributeSet::new())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let abs_vals = if supports.contains(EventType::ABSOLUTE) {
|
||||||
|
Some(Box::new(crate::raw_stream::ABS_VALS_INIT))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let switch_vals = if supports.contains(EventType::SWITCH) {
|
||||||
|
Some(AttributeSet::new())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let led_vals = if supports.contains(EventType::LED) {
|
||||||
|
Some(AttributeSet::new())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
DeviceState {
|
||||||
|
timestamp: std::time::UNIX_EPOCH,
|
||||||
|
key_vals,
|
||||||
|
abs_vals,
|
||||||
|
switch_vals,
|
||||||
|
led_vals,
|
||||||
|
}
|
||||||
|
}
|
||||||
/// Returns the time when this snapshot was taken.
|
/// Returns the time when this snapshot was taken.
|
||||||
pub fn timestamp(&self) -> SystemTime {
|
pub fn timestamp(&self) -> SystemTime {
|
||||||
crate::timeval_to_systime(&self.timestamp)
|
self.timestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the set of keys pressed when the snapshot was taken.
|
/// Returns the set of keys pressed when the snapshot was taken.
|
||||||
|
|
39
src/lib.rs
39
src/lib.rs
|
@ -28,20 +28,37 @@
|
||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! This state can be queried. For example, the [`DeviceState::led_vals`] method will tell you which
|
//! The evdev crate exposes functions to query the current state of a device from the kernel, as
|
||||||
//! LEDs are currently lit on the device. As the application reads events, this state will be
|
//! well as a function that can be called continuously to provide an iterator over update events
|
||||||
//! updated, and it will be fully synchronized with the kernel if the stream drops any events.
|
//! as they arrive.
|
||||||
//!
|
//!
|
||||||
//! As the state changes, the kernel will write events into a ring buffer. The application can read
|
//! # Synchronizing versus Raw modes
|
||||||
//! from this ring buffer, thus retrieving events. However, if the ring buffer becomes full, the
|
//!
|
||||||
//! kernel will *drop* every event in the ring buffer and leave an event telling userspace that it
|
//! This library can be used in either Raw or Synchronizing modes, which correspond roughly to
|
||||||
|
//! evdev's `LIBEVDEV_READ_FLAG_NORMAL` and `LIBEVDEV_READ_FLAG_SYNC` modes, respectively.
|
||||||
|
//! In both modes, calling `fetch_events` and driving the resulting iterator to completion
|
||||||
|
//! will provide a stream of real-time events from the underlying kernel device state.
|
||||||
|
//! As the state changes, the kernel will write events into a ring buffer. If the buffer becomes full, the
|
||||||
|
//! kernel will *drop* events from 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
|
//! 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
|
//! 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
|
//! events.
|
||||||
//! 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
|
//! In synchronous mode, this library tries to ease that pain by removing the corrupted events
|
||||||
//! state with the kernel, only one (or zero, if the switch is in the same state as it was before
|
//! and injecting fake events as if the device had updated normally. Note that this is best-effort;
|
||||||
//! the sync) switch events will be emulated.
|
//! events can never be recovered once lost. This synchronization comes at a performance cost: each
|
||||||
|
//! set of input events read from the kernel in turn updates an internal state buffer, and events
|
||||||
|
//! must be internally held back until the end of each frame. If this latency is unacceptable or
|
||||||
|
//! for any reason you want to see every event directly, a raw stream reader is also provided.
|
||||||
|
//!
|
||||||
|
//! As an example of how synchronization behaves, 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 visible in the stream.
|
||||||
|
//!
|
||||||
|
//! This cache can also be queried. For example, the [`DeviceState::led_vals`] method will tell you which
|
||||||
|
//! LEDs are currently lit on the device. As calling code consumes each iterator, this state will be
|
||||||
|
//! updated, and it will be fully re-synchronized with the kernel if the stream drops any events.
|
||||||
//!
|
//!
|
||||||
//! It is recommended that you dedicate a thread to processing input events, or use epoll or an
|
//! It is recommended that you dedicate a thread to processing input events, or use epoll or an
|
||||||
//! async runtime with the fd returned by `<Device as AsRawFd>::as_raw_fd` to process events when
|
//! async runtime with the fd returned by `<Device as AsRawFd>::as_raw_fd` to process events when
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::path::Path;
|
||||||
use std::{io, mem};
|
use std::{io, mem};
|
||||||
|
|
||||||
use crate::constants::*;
|
use crate::constants::*;
|
||||||
use crate::{nix_err, sys, AttributeSet, AttributeSetRef, DeviceState, InputEvent, InputId, Key};
|
use crate::{nix_err, sys, AttributeSet, AttributeSetRef, InputEvent, InputId, Key};
|
||||||
|
|
||||||
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>,
|
||||||
|
@ -31,6 +31,13 @@ fn bytes_into_string_lossy(v: Vec<u8>) -> String {
|
||||||
String::from_utf8(v).unwrap_or_else(|v| String::from_utf8_lossy(v.as_bytes()).into_owned())
|
String::from_utf8(v).unwrap_or_else(|v| String::from_utf8_lossy(v.as_bytes()).into_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const ABSINFO_ZERO: libc::input_absinfo = libc::input_absinfo {
|
||||||
|
value: 0, minimum: 0, maximum: 0, fuzz: 0, flat: 0, resolution: 0,
|
||||||
|
};
|
||||||
|
pub(crate) const ABS_VALS_INIT: [libc::input_absinfo; AbsoluteAxisType::COUNT] =
|
||||||
|
[ABSINFO_ZERO; AbsoluteAxisType::COUNT];
|
||||||
|
|
||||||
/// A physical or virtual device supported by evdev.
|
/// A physical or virtual device supported by evdev.
|
||||||
///
|
///
|
||||||
/// Each device corresponds to a path typically found in `/dev/input`, and supports access via
|
/// Each device corresponds to a path typically found in `/dev/input`, and supports access via
|
||||||
|
@ -398,71 +405,57 @@ impl RawDevice {
|
||||||
Ok(self.event_buf.drain(..).map(InputEvent))
|
Ok(self.event_buf.drain(..).map(InputEvent))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an empty `DeviceState`. The `{abs,key,etc}_vals` for the returned state will return
|
/// Retrieve the current keypress state directly via kernel syscall.
|
||||||
/// `Some` if `self.supported_events()` contains that `EventType`.
|
#[inline]
|
||||||
pub fn empty_state(&self) -> DeviceState {
|
pub fn get_key_state(&self) -> io::Result<AttributeSet<Key>> {
|
||||||
let supports = self.supported_events();
|
let mut key_vals = AttributeSet::new();
|
||||||
|
self.update_key_state(&mut key_vals)?;
|
||||||
let key_vals = if supports.contains(EventType::KEY) {
|
Ok(key_vals)
|
||||||
Some(AttributeSet::new())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
let abs_vals = if supports.contains(EventType::ABSOLUTE) {
|
|
||||||
#[rustfmt::skip]
|
|
||||||
const ABSINFO_ZERO: libc::input_absinfo = libc::input_absinfo {
|
|
||||||
value: 0, minimum: 0, maximum: 0, fuzz: 0, flat: 0, resolution: 0,
|
|
||||||
};
|
|
||||||
const ABS_VALS_INIT: [libc::input_absinfo; AbsoluteAxisType::COUNT] =
|
|
||||||
[ABSINFO_ZERO; AbsoluteAxisType::COUNT];
|
|
||||||
Some(Box::new(ABS_VALS_INIT))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
let switch_vals = if supports.contains(EventType::SWITCH) {
|
|
||||||
Some(AttributeSet::new())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
let led_vals = if supports.contains(EventType::LED) {
|
|
||||||
Some(AttributeSet::new())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
DeviceState {
|
|
||||||
timestamp: libc::timeval {
|
|
||||||
tv_sec: 0,
|
|
||||||
tv_usec: 0,
|
|
||||||
},
|
|
||||||
key_vals,
|
|
||||||
abs_vals,
|
|
||||||
switch_vals,
|
|
||||||
led_vals,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sync_state(&self, state: &mut DeviceState) -> io::Result<()> {
|
/// Retrieve the current absolute axis state directly via kernel syscall.
|
||||||
self.sync_key_state(state)?;
|
#[inline]
|
||||||
self.sync_abs_state(state)?;
|
pub fn get_abs_state(&self) -> io::Result<[libc::input_absinfo; AbsoluteAxisType::COUNT]> {
|
||||||
self.sync_switch_state(state)?;
|
let mut abs_vals: [libc::input_absinfo; AbsoluteAxisType::COUNT] = ABS_VALS_INIT;
|
||||||
self.sync_led_state(state)?;
|
self.update_abs_state(&mut abs_vals)?;
|
||||||
Ok(())
|
Ok(abs_vals)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sync_key_state(&self, state: &mut DeviceState) -> io::Result<()> {
|
/// Retrieve the current switch state directly via kernel syscall.
|
||||||
if let Some(key_vals) = &mut state.key_vals {
|
#[inline]
|
||||||
unsafe {
|
pub fn get_switch_state(&self) -> io::Result<AttributeSet<SwitchType>> {
|
||||||
sys::eviocgkey(self.as_raw_fd(), key_vals.as_mut_raw_slice()).map_err(nix_err)?
|
let mut switch_vals = AttributeSet::new();
|
||||||
};
|
self.update_switch_state(&mut switch_vals)?;
|
||||||
}
|
Ok(switch_vals)
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sync_abs_state(&self, state: &mut DeviceState) -> io::Result<()> {
|
/// Retrieve the current LED state directly via kernel syscall.
|
||||||
if let (Some(supported_abs), Some(abs_vals)) =
|
#[inline]
|
||||||
(self.supported_absolute_axes(), &mut state.abs_vals)
|
pub fn get_led_state(&self) -> io::Result<AttributeSet<LedType>> {
|
||||||
{
|
let mut led_vals = AttributeSet::new();
|
||||||
|
self.update_led_state(&mut led_vals)?;
|
||||||
|
Ok(led_vals)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch the current kernel key state directly into the provided buffer.
|
||||||
|
/// If you don't already have a buffer, you probably want
|
||||||
|
/// [`get_key_state`](Self::get_key_state) instead.
|
||||||
|
#[inline]
|
||||||
|
pub fn update_key_state(&self, key_vals: &mut AttributeSet<Key>) -> io::Result<()> {
|
||||||
|
unsafe { sys::eviocgkey(self.as_raw_fd(), key_vals.as_mut_raw_slice()) }
|
||||||
|
.map(|_| ())
|
||||||
|
.map_err(nix_err)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch the current kernel absolute axis state directly into the provided buffer.
|
||||||
|
/// If you don't already have a buffer, you probably want
|
||||||
|
/// [`get_abs_state`](Self::get_abs_state) instead.
|
||||||
|
#[inline]
|
||||||
|
pub fn update_abs_state(
|
||||||
|
&self,
|
||||||
|
abs_vals: &mut [libc::input_absinfo; AbsoluteAxisType::COUNT],
|
||||||
|
) -> io::Result<()> {
|
||||||
|
if let Some(supported_abs) = self.supported_absolute_axes() {
|
||||||
for AbsoluteAxisType(idx) in supported_abs.iter() {
|
for AbsoluteAxisType(idx) in supported_abs.iter() {
|
||||||
// ignore multitouch, we'll handle that later.
|
// ignore multitouch, we'll handle that later.
|
||||||
//
|
//
|
||||||
|
@ -477,22 +470,27 @@ impl RawDevice {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sync_switch_state(&self, state: &mut DeviceState) -> io::Result<()> {
|
/// Fetch the current kernel switch state directly into the provided buffer.
|
||||||
if let Some(switch_vals) = &mut state.switch_vals {
|
/// If you don't already have a buffer, you probably want
|
||||||
unsafe {
|
/// [`get_switch_state`](Self::get_switch_state) instead.
|
||||||
sys::eviocgsw(self.as_raw_fd(), switch_vals.as_mut_raw_slice()).map_err(nix_err)?
|
#[inline]
|
||||||
};
|
pub fn update_switch_state(
|
||||||
}
|
&self,
|
||||||
Ok(())
|
switch_vals: &mut AttributeSet<SwitchType>,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
unsafe { sys::eviocgsw(self.as_raw_fd(), switch_vals.as_mut_raw_slice()) }
|
||||||
|
.map(|_| ())
|
||||||
|
.map_err(nix_err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sync_led_state(&self, state: &mut DeviceState) -> io::Result<()> {
|
/// Fetch the current kernel LED state directly into the provided buffer.
|
||||||
if let Some(led_vals) = &mut state.led_vals {
|
/// If you don't already have a buffer, you probably want
|
||||||
unsafe {
|
/// [`get_led_state`](Self::get_led_state) instead.
|
||||||
sys::eviocgled(self.as_raw_fd(), led_vals.as_mut_raw_slice()).map_err(nix_err)?
|
#[inline]
|
||||||
};
|
pub fn update_led_state(&self, led_vals: &mut AttributeSet<LedType>) -> io::Result<()> {
|
||||||
}
|
unsafe { sys::eviocgled(self.as_raw_fd(), led_vals.as_mut_raw_slice()) }
|
||||||
Ok(())
|
.map(|_| ())
|
||||||
|
.map_err(nix_err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
use crate::constants::*;
|
use crate::constants::*;
|
||||||
|
use crate::device_state::DeviceState;
|
||||||
use crate::raw_stream::RawDevice;
|
use crate::raw_stream::RawDevice;
|
||||||
use crate::{AttributeSetRef, DeviceState, InputEvent, InputEventKind, InputId, Key};
|
use crate::{AttributeSet, AttributeSetRef, InputEvent, InputEventKind, InputId, Key};
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::time::SystemTime;
|
||||||
use std::{fmt, io};
|
use std::{fmt, io};
|
||||||
|
|
||||||
/// A physical or virtual device supported by evdev.
|
/// A physical or virtual device supported by evdev.
|
||||||
|
@ -16,7 +18,7 @@ use std::{fmt, io};
|
||||||
///
|
///
|
||||||
/// If `fetch_events()` isn't called often enough and the kernel drops events from its internal
|
/// If `fetch_events()` isn't called often enough and the kernel drops events from its internal
|
||||||
/// buffer, synthetic events will be injected into the iterator returned by `fetch_events()` and
|
/// buffer, synthetic events will be injected into the iterator returned by `fetch_events()` and
|
||||||
/// [`Device::state()`] will be kept up to date when `fetch_events()` is called.
|
/// [`Device::cached_state()`] will be kept up to date when `fetch_events()` is called.
|
||||||
pub struct Device {
|
pub struct Device {
|
||||||
raw: RawDevice,
|
raw: RawDevice,
|
||||||
prev_state: DeviceState,
|
prev_state: DeviceState,
|
||||||
|
@ -36,7 +38,7 @@ impl Device {
|
||||||
fn _open(path: &Path) -> io::Result<Device> {
|
fn _open(path: &Path) -> io::Result<Device> {
|
||||||
let raw = RawDevice::open(path)?;
|
let raw = RawDevice::open(path)?;
|
||||||
|
|
||||||
let state = raw.empty_state();
|
let state = DeviceState::new(&raw);
|
||||||
let prev_state = state.clone();
|
let prev_state = state.clone();
|
||||||
|
|
||||||
Ok(Device {
|
Ok(Device {
|
||||||
|
@ -47,7 +49,15 @@ impl Device {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn state(&self) -> &DeviceState {
|
/// Returns the synchronization engine's current understanding (cache) of the device state.
|
||||||
|
///
|
||||||
|
/// Note that this represents the internal cache of the synchronization engine as of the last
|
||||||
|
/// entry that was pulled out. The advantage to calling this instead of invoking
|
||||||
|
/// [`get_key_state`](RawDevice::get_key_state)
|
||||||
|
/// and the like directly is speed: because reading this cache doesn't require any syscalls it's
|
||||||
|
/// easy to do inside a tight loop. The downside is that if the stream is not being driven quickly,
|
||||||
|
/// this can very quickly get desynchronized from the kernel and provide inaccurate data.
|
||||||
|
pub fn cached_state(&self) -> &DeviceState {
|
||||||
&self.state
|
&self.state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,6 +215,43 @@ impl Device {
|
||||||
self.raw.supported_sounds()
|
self.raw.supported_sounds()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieve the current keypress state directly via kernel syscall.
|
||||||
|
pub fn get_key_state(&self) -> io::Result<AttributeSet<Key>> {
|
||||||
|
self.raw.get_key_state()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve the current absolute axis state directly via kernel syscall.
|
||||||
|
pub fn get_abs_state(&self) -> io::Result<[libc::input_absinfo; AbsoluteAxisType::COUNT]> {
|
||||||
|
self.raw.get_abs_state()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve the current switch state directly via kernel syscall.
|
||||||
|
pub fn get_switch_state(&self) -> io::Result<AttributeSet<SwitchType>> {
|
||||||
|
self.raw.get_switch_state()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve the current LED state directly via kernel syscall.
|
||||||
|
pub fn get_led_state(&self) -> io::Result<AttributeSet<LedType>> {
|
||||||
|
self.raw.get_led_state()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sync_state(&mut self, now: SystemTime) -> io::Result<()> {
|
||||||
|
if let Some(ref mut key_vals) = self.state.key_vals {
|
||||||
|
self.raw.update_key_state(key_vals)?;
|
||||||
|
}
|
||||||
|
if let Some(ref mut abs_vals) = self.state.abs_vals {
|
||||||
|
self.raw.update_abs_state(abs_vals)?;
|
||||||
|
}
|
||||||
|
if let Some(ref mut switch_vals) = self.state.switch_vals {
|
||||||
|
self.raw.update_switch_state(switch_vals)?;
|
||||||
|
}
|
||||||
|
if let Some(ref mut led_vals) = self.state.led_vals {
|
||||||
|
self.raw.update_led_state(led_vals)?;
|
||||||
|
}
|
||||||
|
self.state.timestamp = now;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Fetches and returns events from the kernel ring buffer, doing synchronization on SYN_DROPPED.
|
/// 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
|
/// By default this will block until events are available. Typically, users will want to call
|
||||||
|
@ -214,9 +261,10 @@ impl Device {
|
||||||
let block_dropped = std::mem::take(&mut self.block_dropped);
|
let block_dropped = std::mem::take(&mut self.block_dropped);
|
||||||
let sync = if block_dropped {
|
let sync = if block_dropped {
|
||||||
self.prev_state.clone_from(&self.state);
|
self.prev_state.clone_from(&self.state);
|
||||||
self.raw.sync_state(&mut self.state)?;
|
let now = SystemTime::now();
|
||||||
|
self.sync_state(now)?;
|
||||||
Some(SyncState::Keys {
|
Some(SyncState::Keys {
|
||||||
time: crate::systime_to_timeval(&std::time::SystemTime::now()),
|
time: crate::systime_to_timeval(&now),
|
||||||
start: Key::new(0),
|
start: Key::new(0),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue