sweetacid_evdev/
sync_stream.rs

1use crate::constants::*;
2use crate::device_state::DeviceState;
3use crate::raw_stream::RawDevice;
4use crate::{AttributeSet, AttributeSetRef, AutoRepeat, InputEvent, InputEventKind, InputId, Key};
5use std::os::unix::io::{AsRawFd, RawFd};
6use std::path::Path;
7use std::time::SystemTime;
8use std::{fmt, io};
9
10/// A physical or virtual device supported by evdev.
11///
12/// Each device corresponds to a path typically found in `/dev/input`, and supports access via
13/// one or more "types". For example, an optical mouse has buttons that are represented by "keys",
14/// and reflects changes in its position via "relative axis" reports.
15///
16/// This type specifically is a wrapper over [`RawDevice`],that synchronizes with the kernel's
17/// state when events are dropped.
18///
19/// If `fetch_events()` isn't called often enough and the kernel drops events from its internal
20/// buffer, synthetic events will be injected into the iterator returned by `fetch_events()` and
21/// [`Device::cached_state()`] will be kept up to date when `fetch_events()` is called.
22pub struct Device {
23    raw: RawDevice,
24    prev_state: DeviceState,
25    state: DeviceState,
26    block_dropped: bool,
27}
28
29impl Device {
30    /// Opens a device, given its system path.
31    ///
32    /// Paths are typically something like `/dev/input/event0`.
33    #[inline(always)]
34    pub fn open(path: impl AsRef<Path>) -> io::Result<Device> {
35        Self::_open(path.as_ref())
36    }
37
38    #[inline]
39    fn _open(path: &Path) -> io::Result<Device> {
40        RawDevice::open(path).map(Self::from_raw_device)
41    }
42
43    // TODO: should this be public?
44    pub(crate) fn from_raw_device(raw: RawDevice) -> Device {
45        let state = DeviceState::new(&raw);
46        let prev_state = state.clone();
47
48        Device {
49            raw,
50            prev_state,
51            state,
52            block_dropped: false,
53        }
54    }
55
56    /// Returns the synchronization engine's current understanding (cache) of the device state.
57    ///
58    /// Note that this represents the internal cache of the synchronization engine as of the last
59    /// entry that was pulled out. The advantage to calling this instead of invoking
60    /// [`get_key_state`](RawDevice::get_key_state)
61    /// and the like directly is speed: because reading this cache doesn't require any syscalls it's
62    /// easy to do inside a tight loop. The downside is that if the stream is not being driven quickly,
63    /// this can very quickly get desynchronized from the kernel and provide inaccurate data.
64    pub fn cached_state(&self) -> &DeviceState {
65        &self.state
66    }
67
68    /// Returns the device's name as read from the kernel.
69    pub fn name(&self) -> Option<&str> {
70        self.raw.name()
71    }
72
73    /// Returns the device's physical location, either as set by the caller or as read from the kernel.
74    pub fn physical_path(&self) -> Option<&str> {
75        self.raw.physical_path()
76    }
77
78    /// Returns the user-defined "unique name" of the device, if one has been set.
79    pub fn unique_name(&self) -> Option<&str> {
80        self.raw.unique_name()
81    }
82
83    /// Returns a struct containing bustype, vendor, product, and version identifiers
84    pub fn input_id(&self) -> InputId {
85        self.raw.input_id()
86    }
87
88    /// Returns a struct containing the delay and period for auto repeat
89    pub fn get_auto_repeat(&self) -> Option<AutoRepeat> {
90        self.raw.get_auto_repeat()
91    }
92
93    /// Update the delay and period for autorepeat
94    pub fn update_auto_repeat(&mut self, repeat: &AutoRepeat) -> io::Result<()> {
95        self.raw.update_auto_repeat(repeat)
96    }
97
98    /// Retrieve the scancode for a keycode, if any
99    pub fn get_scancode_by_keycode(&self, keycode: Key) -> io::Result<Vec<u8>> {
100        self.raw.get_scancode_by_keycode(keycode.code() as u32)
101    }
102
103    /// Retrieve the keycode and scancode by index, starting at 0
104    pub fn get_scancode_by_index(&self, index: u16) -> io::Result<(u32, Vec<u8>)> {
105        self.raw.get_scancode_by_index(index)
106    }
107
108    /// Update a scancode. The return value is the previous keycode
109    pub fn update_scancode(&self, keycode: Key, scancode: &[u8]) -> io::Result<Key> {
110        self.raw
111            .update_scancode(keycode.code() as u32, scancode)
112            .map(|keycode| Key::new(keycode as u16))
113    }
114
115    /// Update a scancode by index. The return value is the previous keycode
116    pub fn update_scancode_by_index(
117        &self,
118        index: u16,
119        keycode: Key,
120        scancode: &[u8],
121    ) -> io::Result<u32> {
122        self.raw
123            .update_scancode_by_index(index, keycode.code() as u32, scancode)
124    }
125
126    /// Returns the set of supported "properties" for the device (see `INPUT_PROP_*` in kernel headers)
127    pub fn properties(&self) -> &AttributeSetRef<PropType> {
128        self.raw.properties()
129    }
130
131    /// Returns a tuple of the driver version containing major, minor, rev
132    pub fn driver_version(&self) -> (u8, u8, u8) {
133        self.raw.driver_version()
134    }
135
136    /// Returns a set of the event types supported by this device (Key, Switch, etc)
137    ///
138    /// If you're interested in the individual keys or switches supported, it's probably easier
139    /// to just call the appropriate `supported_*` function instead.
140    pub fn supported_events(&self) -> &AttributeSetRef<EventType> {
141        self.raw.supported_events()
142    }
143
144    /// Returns the set of supported keys reported by the device.
145    ///
146    /// For keyboards, this is the set of all possible keycodes the keyboard may emit. Controllers,
147    /// mice, and other peripherals may also report buttons as keys.
148    ///
149    /// # Examples
150    ///
151    /// ```no_run
152    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
153    /// use evdev::{Device, Key};
154    /// let device = Device::open("/dev/input/event0")?;
155    ///
156    /// // Does this device have an ENTER key?
157    /// let supported = device.supported_keys().map_or(false, |keys| keys.contains(Key::KEY_ENTER));
158    /// # Ok(())
159    /// # }
160    /// ```
161    pub fn supported_keys(&self) -> Option<&AttributeSetRef<Key>> {
162        self.raw.supported_keys()
163    }
164
165    /// Returns the set of supported "relative axes" reported by the device.
166    ///
167    /// Standard mice will generally report `REL_X` and `REL_Y` along with wheel if supported.
168    ///
169    /// # Examples
170    ///
171    /// ```no_run
172    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
173    /// use evdev::{Device, RelativeAxisType};
174    /// let device = Device::open("/dev/input/event0")?;
175    ///
176    /// // Does the device have a scroll wheel?
177    /// let supported = device
178    ///     .supported_relative_axes()
179    ///     .map_or(false, |axes| axes.contains(RelativeAxisType::REL_WHEEL));
180    /// # Ok(())
181    /// # }
182    /// ```
183    pub fn supported_relative_axes(&self) -> Option<&AttributeSetRef<RelativeAxisType>> {
184        self.raw.supported_relative_axes()
185    }
186
187    /// Returns the set of supported "absolute axes" reported by the device.
188    ///
189    /// These are most typically supported by joysticks and touchpads.
190    ///
191    /// # Examples
192    ///
193    /// ```no_run
194    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
195    /// use evdev::{Device, AbsoluteAxisType};
196    /// let device = Device::open("/dev/input/event0")?;
197    ///
198    /// // Does the device have an absolute X axis?
199    /// let supported = device
200    ///     .supported_absolute_axes()
201    ///     .map_or(false, |axes| axes.contains(AbsoluteAxisType::ABS_X));
202    /// # Ok(())
203    /// # }
204    /// ```
205    pub fn supported_absolute_axes(&self) -> Option<&AttributeSetRef<AbsoluteAxisType>> {
206        self.raw.supported_absolute_axes()
207    }
208
209    /// Returns the set of supported switches reported by the device.
210    ///
211    /// These are typically used for things like software switches on laptop lids (which the
212    /// system reacts to by suspending or locking), or virtual switches to indicate whether a
213    /// headphone jack is plugged in (used to disable external speakers).
214    ///
215    /// # Examples
216    ///
217    /// ```no_run
218    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
219    /// use evdev::{Device, SwitchType};
220    /// let device = Device::open("/dev/input/event0")?;
221    ///
222    /// // Does the device report a laptop lid switch?
223    /// let supported = device
224    ///     .supported_switches()
225    ///     .map_or(false, |axes| axes.contains(SwitchType::SW_LID));
226    /// # Ok(())
227    /// # }
228    /// ```
229    pub fn supported_switches(&self) -> Option<&AttributeSetRef<SwitchType>> {
230        self.raw.supported_switches()
231    }
232
233    /// Returns a set of supported LEDs on the device.
234    ///
235    /// Most commonly these are state indicator lights for things like Scroll Lock, but they
236    /// can also be found in cameras and other devices.
237    pub fn supported_leds(&self) -> Option<&AttributeSetRef<LedType>> {
238        self.raw.supported_leds()
239    }
240
241    /// Returns a set of supported "miscellaneous" capabilities.
242    ///
243    /// Aside from vendor-specific key scancodes, most of these are uncommon.
244    pub fn misc_properties(&self) -> Option<&AttributeSetRef<MiscType>> {
245        self.raw.misc_properties()
246    }
247
248    /// Returns the set of supported simple sounds supported by a device.
249    ///
250    /// You can use these to make really annoying beep sounds come from an internal self-test
251    /// speaker, for instance.
252    pub fn supported_sounds(&self) -> Option<&AttributeSetRef<SoundType>> {
253        self.raw.supported_sounds()
254    }
255
256    /// Retrieve the current keypress state directly via kernel syscall.
257    pub fn get_key_state(&self) -> io::Result<AttributeSet<Key>> {
258        self.raw.get_key_state()
259    }
260
261    /// Retrieve the current absolute axis state directly via kernel syscall.
262    pub fn get_abs_state(&self) -> io::Result<[libc::input_absinfo; AbsoluteAxisType::COUNT]> {
263        self.raw.get_abs_state()
264    }
265
266    /// Retrieve the current switch state directly via kernel syscall.
267    pub fn get_switch_state(&self) -> io::Result<AttributeSet<SwitchType>> {
268        self.raw.get_switch_state()
269    }
270
271    /// Retrieve the current LED state directly via kernel syscall.
272    pub fn get_led_state(&self) -> io::Result<AttributeSet<LedType>> {
273        self.raw.get_led_state()
274    }
275
276    fn sync_state(&mut self, now: SystemTime) -> io::Result<()> {
277        if let Some(ref mut key_vals) = self.state.key_vals {
278            self.raw.update_key_state(key_vals)?;
279        }
280        if let Some(ref mut abs_vals) = self.state.abs_vals {
281            self.raw.update_abs_state(abs_vals)?;
282        }
283        if let Some(ref mut switch_vals) = self.state.switch_vals {
284            self.raw.update_switch_state(switch_vals)?;
285        }
286        if let Some(ref mut led_vals) = self.state.led_vals {
287            self.raw.update_led_state(led_vals)?;
288        }
289        self.state.timestamp = now;
290        Ok(())
291    }
292
293    fn fetch_events_inner(&mut self) -> io::Result<Option<SyncState>> {
294        let block_dropped = std::mem::take(&mut self.block_dropped);
295        let sync = if block_dropped {
296            self.prev_state.clone_from(&self.state);
297            let now = SystemTime::now();
298            self.sync_state(now)?;
299            Some(SyncState::Keys {
300                time: crate::systime_to_timeval(&now),
301                start: Key::new(0),
302            })
303        } else {
304            None
305        };
306
307        self.raw.fill_events()?;
308
309        Ok(sync)
310    }
311
312    /// Fetches and returns events from the kernel ring buffer, doing synchronization on SYN_DROPPED.
313    ///
314    /// By default this will block until events are available. Typically, users will want to call
315    /// this in a tight loop within a thread.
316    /// Will insert "fake" events.
317    pub fn fetch_events(&mut self) -> io::Result<FetchEventsSynced<'_>> {
318        let sync = self.fetch_events_inner()?;
319
320        Ok(FetchEventsSynced {
321            dev: self,
322            range: 0..0,
323            consumed_to: 0,
324            sync,
325        })
326    }
327
328    #[cfg(feature = "tokio")]
329    pub fn into_event_stream(self) -> io::Result<EventStream> {
330        EventStream::new(self)
331    }
332
333    /// Grab the device through a kernel syscall.
334    ///
335    /// This prevents other clients (including kernel-internal ones such as rfkill) from receiving
336    /// events from this device.
337    pub fn grab(&mut self) -> io::Result<()> {
338        self.raw.grab()
339    }
340
341    /// Ungrab the device through a kernel syscall.
342    pub fn ungrab(&mut self) -> io::Result<()> {
343        self.raw.ungrab()
344    }
345}
346
347impl AsRawFd for Device {
348    fn as_raw_fd(&self) -> RawFd {
349        self.raw.as_raw_fd()
350    }
351}
352
353/// An iterator over events of a [`Device`], produced by [`Device::fetch_events`].
354pub struct FetchEventsSynced<'a> {
355    dev: &'a mut Device,
356    /// The current block of the events we're returning to the consumer. If empty
357    /// (i.e. for any x, range == x..x) then we'll find another block on the next `next()` call.
358    range: std::ops::Range<usize>,
359    /// The index into dev.raw.event_buf up to which we'll delete events when dropped.
360    consumed_to: usize,
361    /// Our current synchronization state, i.e. whether we're currently diffing key_vals,
362    /// abs_vals, switch_vals, led_vals, or none of them.
363    sync: Option<SyncState>,
364}
365
366enum SyncState {
367    Keys {
368        time: libc::timeval,
369        start: Key,
370    },
371    Absolutes {
372        time: libc::timeval,
373        start: AbsoluteAxisType,
374    },
375    Switches {
376        time: libc::timeval,
377        start: SwitchType,
378    },
379    Leds {
380        time: libc::timeval,
381        start: LedType,
382    },
383}
384
385#[inline]
386fn compensate_events(state: &mut Option<SyncState>, dev: &mut Device) -> Option<InputEvent> {
387    let sync = state.as_mut()?;
388    // this macro checks if there are any differences between the old state and the new for the
389    // specific substate(?) that we're checking and if so returns an input_event with the value set
390    // to the value from the up-to-date state
391    macro_rules! try_compensate {
392        ($time:expr, $start:ident : $typ:ident, $evtype:ident, $sync:ident, $supporteds:ident, $state:ty, $get_state:expr, $get_value:expr) => {
393            if let Some(supported_types) = dev.$supporteds() {
394                let types_to_check = supported_types.slice(*$start);
395                let get_state: fn(&DeviceState) -> $state = $get_state;
396                let vals = get_state(&dev.state);
397                let old_vals = get_state(&dev.prev_state);
398                let get_value: fn($state, $typ) -> _ = $get_value;
399                for typ in types_to_check.iter() {
400                    let prev = get_value(old_vals, typ);
401                    let value = get_value(vals, typ);
402                    if prev != value {
403                        $start.0 = typ.0 + 1;
404                        let ev = InputEvent(libc::input_event {
405                            time: *$time,
406                            type_: EventType::$evtype.0,
407                            code: typ.0,
408                            value: value as _,
409                        });
410                        return Some(ev);
411                    }
412                }
413            }
414        };
415    }
416    loop {
417        // check keys, then abs axes, then switches, then leds
418        match sync {
419            SyncState::Keys { time, start } => {
420                try_compensate!(
421                    time,
422                    start: Key,
423                    KEY,
424                    Keys,
425                    supported_keys,
426                    &AttributeSetRef<Key>,
427                    |st| st.key_vals().unwrap(),
428                    |vals, key| vals.contains(key)
429                );
430                *sync = SyncState::Absolutes {
431                    time: *time,
432                    start: AbsoluteAxisType(0),
433                };
434                continue;
435            }
436            SyncState::Absolutes { time, start } => {
437                try_compensate!(
438                    time,
439                    start: AbsoluteAxisType,
440                    ABSOLUTE,
441                    Absolutes,
442                    supported_absolute_axes,
443                    &[libc::input_absinfo],
444                    |st| st.abs_vals().unwrap(),
445                    |vals, abs| vals[abs.0 as usize].value
446                );
447                *sync = SyncState::Switches {
448                    time: *time,
449                    start: SwitchType(0),
450                };
451                continue;
452            }
453            SyncState::Switches { time, start } => {
454                try_compensate!(
455                    time,
456                    start: SwitchType,
457                    SWITCH,
458                    Switches,
459                    supported_switches,
460                    &AttributeSetRef<SwitchType>,
461                    |st| st.switch_vals().unwrap(),
462                    |vals, sw| vals.contains(sw)
463                );
464                *sync = SyncState::Leds {
465                    time: *time,
466                    start: LedType(0),
467                };
468                continue;
469            }
470            SyncState::Leds { time, start } => {
471                try_compensate!(
472                    time,
473                    start: LedType,
474                    LED,
475                    Leds,
476                    supported_leds,
477                    &AttributeSetRef<LedType>,
478                    |st| st.led_vals().unwrap(),
479                    |vals, led| vals.contains(led)
480                );
481                let ev = InputEvent(libc::input_event {
482                    time: *time,
483                    type_: EventType::SYNCHRONIZATION.0,
484                    code: Synchronization::SYN_REPORT.0,
485                    value: 0,
486                });
487                *state = None;
488                return Some(ev);
489            }
490        }
491    }
492}
493
494impl<'a> Iterator for FetchEventsSynced<'a> {
495    type Item = InputEvent;
496    fn next(&mut self) -> Option<InputEvent> {
497        // first: check if we need to emit compensatory events due to a SYN_DROPPED we found in the
498        // last batch of blocks
499        if let Some(ev) = compensate_events(&mut self.sync, &mut self.dev) {
500            return Some(ev);
501        }
502        let state = &mut self.dev.state;
503        let (res, consumed_to) = sync_events(&mut self.range, &self.dev.raw.event_buf, |ev| {
504            state.process_event(ev)
505        });
506        if let Some(end) = consumed_to {
507            self.consumed_to = end
508        }
509        match res {
510            Ok(ev) => Some(InputEvent(ev)),
511            Err(requires_sync) => {
512                if requires_sync {
513                    self.dev.block_dropped = true;
514                }
515                None
516            }
517        }
518    }
519}
520
521impl<'a> Drop for FetchEventsSynced<'a> {
522    fn drop(&mut self) {
523        self.dev.raw.event_buf.drain(..self.consumed_to);
524    }
525}
526
527/// Err(true) means the device should sync the state with ioctl
528#[inline]
529fn sync_events(
530    range: &mut std::ops::Range<usize>,
531    event_buf: &[libc::input_event],
532    mut handle_event: impl FnMut(InputEvent),
533) -> (Result<libc::input_event, bool>, Option<usize>) {
534    let mut consumed_to = None;
535    let res = 'outer: loop {
536        if let Some(idx) = range.next() {
537            // we're going through and emitting the events of a block that we checked
538            break Ok(event_buf[idx]);
539        }
540        // find the range of this new block: look for a SYN_REPORT
541        let block_start = range.end;
542        let mut block_dropped = false;
543        for (i, ev) in event_buf.iter().enumerate().skip(block_start) {
544            let ev = InputEvent(*ev);
545            match ev.kind() {
546                InputEventKind::Synchronization(Synchronization::SYN_DROPPED) => {
547                    block_dropped = true;
548                }
549                InputEventKind::Synchronization(Synchronization::SYN_REPORT) => {
550                    consumed_to = Some(i + 1);
551                    if block_dropped {
552                        *range = event_buf.len()..event_buf.len();
553                        break 'outer Err(true);
554                    } else {
555                        *range = block_start..i + 1;
556                        continue 'outer;
557                    }
558                }
559                _ => handle_event(ev),
560            }
561        }
562        break Err(false);
563    };
564    (res, consumed_to)
565}
566
567impl fmt::Display for Device {
568    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
569        writeln!(f, "{}:", self.name().unwrap_or("Unnamed device"))?;
570        let (maj, min, pat) = self.driver_version();
571        writeln!(f, "  Driver version: {}.{}.{}", maj, min, pat)?;
572        if let Some(ref phys) = self.physical_path() {
573            writeln!(f, "  Physical address: {:?}", phys)?;
574        }
575        if let Some(ref uniq) = self.unique_name() {
576            writeln!(f, "  Unique name: {:?}", uniq)?;
577        }
578
579        let id = self.input_id();
580
581        writeln!(f, "  Bus: {}", id.bus_type())?;
582        writeln!(f, "  Vendor: {:#x}", id.vendor())?;
583        writeln!(f, "  Product: {:#x}", id.product())?;
584        writeln!(f, "  Version: {:#x}", id.version())?;
585        writeln!(f, "  Properties: {:?}", self.properties())?;
586
587        if let (Some(supported_keys), Some(key_vals)) =
588            (self.supported_keys(), self.state.key_vals())
589        {
590            writeln!(f, "  Keys supported:")?;
591            for key in supported_keys.iter() {
592                let key_idx = key.code() as usize;
593                writeln!(
594                    f,
595                    "    {:?} ({}index {})",
596                    key,
597                    if key_vals.contains(key) {
598                        "pressed, "
599                    } else {
600                        ""
601                    },
602                    key_idx
603                )?;
604            }
605        }
606
607        if let Some(supported_relative) = self.supported_relative_axes() {
608            writeln!(f, "  Relative Axes: {:?}", supported_relative)?;
609        }
610
611        if let (Some(supported_abs), Some(abs_vals)) =
612            (self.supported_absolute_axes(), &self.state.abs_vals)
613        {
614            writeln!(f, "  Absolute Axes:")?;
615            for abs in supported_abs.iter() {
616                writeln!(
617                    f,
618                    "    {:?} ({:?}, index {})",
619                    abs, abs_vals[abs.0 as usize], abs.0
620                )?;
621            }
622        }
623
624        if let Some(supported_misc) = self.misc_properties() {
625            writeln!(f, "  Miscellaneous capabilities: {:?}", supported_misc)?;
626        }
627
628        if let (Some(supported_switch), Some(switch_vals)) =
629            (self.supported_switches(), self.state.switch_vals())
630        {
631            writeln!(f, "  Switches:")?;
632            for sw in supported_switch.iter() {
633                writeln!(
634                    f,
635                    "    {:?} ({:?}, index {})",
636                    sw,
637                    switch_vals.contains(sw),
638                    sw.0
639                )?;
640            }
641        }
642
643        if let (Some(supported_led), Some(led_vals)) =
644            (self.supported_leds(), self.state.led_vals())
645        {
646            writeln!(f, "  LEDs:")?;
647            for led in supported_led.iter() {
648                writeln!(
649                    f,
650                    "    {:?} ({:?}, index {})",
651                    led,
652                    led_vals.contains(led),
653                    led.0
654                )?;
655            }
656        }
657
658        if let Some(supported_snd) = self.supported_sounds() {
659            write!(f, "  Sounds:")?;
660            for snd in supported_snd.iter() {
661                writeln!(f, "    {:?} (index {})", snd, snd.0)?;
662            }
663        }
664
665        // if let Some(rep) = self.rep {
666        //     writeln!(f, "  Repeats: {:?}", rep)?;
667        // }
668
669        let evs = self.supported_events();
670
671        if evs.contains(EventType::FORCEFEEDBACK) {
672            writeln!(f, "  Force Feedback supported")?;
673        }
674
675        if evs.contains(EventType::POWER) {
676            writeln!(f, "  Power supported")?;
677        }
678
679        if evs.contains(EventType::FORCEFEEDBACKSTATUS) {
680            writeln!(f, "  Force Feedback status supported")?;
681        }
682
683        Ok(())
684    }
685}
686
687#[cfg(feature = "tokio")]
688mod tokio_stream {
689    use super::*;
690
691    use tokio_1 as tokio;
692
693    use crate::raw_stream::poll_fn;
694    use futures_core::{ready, Stream};
695    use std::pin::Pin;
696    use std::task::{Context, Poll};
697    use tokio::io::unix::AsyncFd;
698
699    /// An asynchronous stream of input events.
700    ///
701    /// This can be used by calling [`stream.next_event().await?`](Self::next_event), or if you
702    /// need to pass it as a stream somewhere, the [`futures::Stream`](Stream) implementation.
703    /// There's also a lower-level [`poll_event`] function if you need to fetch an event from
704    /// inside a `Future::poll` impl.
705    pub struct EventStream {
706        device: AsyncFd<Device>,
707        event_range: std::ops::Range<usize>,
708        consumed_to: usize,
709        sync: Option<SyncState>,
710    }
711    impl Unpin for EventStream {}
712
713    impl EventStream {
714        pub(crate) fn new(device: Device) -> io::Result<Self> {
715            use nix::fcntl;
716            fcntl::fcntl(device.as_raw_fd(), fcntl::F_SETFL(fcntl::OFlag::O_NONBLOCK))?;
717            let device = AsyncFd::new(device)?;
718            Ok(Self {
719                device,
720                event_range: 0..0,
721                consumed_to: 0,
722                sync: None,
723            })
724        }
725
726        /// Returns a reference to the underlying device
727        pub fn device(&self) -> &Device {
728            self.device.get_ref()
729        }
730
731        /// Try to wait for the next event in this stream. Any errors are likely to be fatal, i.e.
732        /// any calls afterwards will likely error as well.
733        pub async fn next_event(&mut self) -> io::Result<InputEvent> {
734            poll_fn(|cx| self.poll_event(cx)).await
735        }
736
737        /// A lower-level function for directly polling this stream.
738        pub fn poll_event(&mut self, cx: &mut Context<'_>) -> Poll<io::Result<InputEvent>> {
739            'outer: loop {
740                let dev = self.device.get_mut();
741                if let Some(ev) = compensate_events(&mut self.sync, dev) {
742                    return Poll::Ready(Ok(ev));
743                }
744                let state = &mut dev.state;
745                let (res, consumed_to) =
746                    sync_events(&mut self.event_range, &dev.raw.event_buf, |ev| {
747                        state.process_event(ev)
748                    });
749                if let Some(end) = consumed_to {
750                    self.consumed_to = end
751                }
752                match res {
753                    Ok(ev) => return Poll::Ready(Ok(InputEvent(ev))),
754                    Err(requires_sync) => {
755                        if requires_sync {
756                            dev.block_dropped = true;
757                        }
758                    }
759                }
760                dev.raw.event_buf.drain(..self.consumed_to);
761                self.consumed_to = 0;
762
763                loop {
764                    let mut guard = ready!(self.device.poll_read_ready_mut(cx))?;
765
766                    let res = guard.try_io(|device| device.get_mut().fetch_events_inner());
767                    match res {
768                        Ok(res) => {
769                            self.sync = res?;
770                            self.event_range = 0..0;
771                            continue 'outer;
772                        }
773                        Err(_would_block) => continue,
774                    }
775                }
776            }
777        }
778    }
779
780    impl Stream for EventStream {
781        type Item = io::Result<InputEvent>;
782        fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
783            self.get_mut().poll_event(cx).map(Some)
784        }
785    }
786}
787#[cfg(feature = "tokio")]
788pub use tokio_stream::EventStream;
789
790#[cfg(test)]
791mod tests {
792    use super::*;
793
794    fn result_events_iter(
795        events: &[libc::input_event],
796    ) -> impl Iterator<Item = Result<libc::input_event, ()>> + '_ {
797        let mut range = 0..0;
798        std::iter::from_fn(move || {
799            let (res, _) = sync_events(&mut range, events, |_| {});
800            match res {
801                Ok(x) => Some(Ok(x)),
802                Err(true) => Some(Err(())),
803                Err(false) => None,
804            }
805        })
806    }
807
808    fn events_iter(events: &[libc::input_event]) -> impl Iterator<Item = libc::input_event> + '_ {
809        result_events_iter(events).flatten()
810    }
811
812    #[allow(non_upper_case_globals)]
813    const time: libc::timeval = libc::timeval {
814        tv_sec: 0,
815        tv_usec: 0,
816    };
817    const KEY4: libc::input_event = libc::input_event {
818        time,
819        type_: EventType::KEY.0,
820        code: Key::KEY_4.0,
821        value: 1,
822    };
823    const REPORT: libc::input_event = libc::input_event {
824        time,
825        type_: EventType::SYNCHRONIZATION.0,
826        code: Synchronization::SYN_REPORT.0,
827        value: 0,
828    };
829    const DROPPED: libc::input_event = libc::input_event {
830        code: Synchronization::SYN_DROPPED.0,
831        ..REPORT
832    };
833
834    #[test]
835    fn test_sync_impl() {
836        itertools::assert_equal(events_iter(&[]), vec![]);
837        itertools::assert_equal(events_iter(&[KEY4]), vec![]);
838        itertools::assert_equal(events_iter(&[KEY4, REPORT]), vec![KEY4, REPORT]);
839        itertools::assert_equal(events_iter(&[KEY4, REPORT, KEY4]), vec![KEY4, REPORT]);
840        itertools::assert_equal(
841            result_events_iter(&[KEY4, REPORT, KEY4, DROPPED, REPORT]),
842            vec![Ok(KEY4), Ok(REPORT), Err(())],
843        );
844    }
845
846    #[test]
847    fn test_iter_consistency() {
848        // once it sees a SYN_DROPPED, it shouldn't mark the block after it as consumed even if we
849        // keep calling the iterator like an idiot
850        let evs = &[KEY4, REPORT, DROPPED, REPORT, KEY4, REPORT, KEY4];
851        let mut range = 0..0;
852        let mut next = || sync_events(&mut range, evs, |_| {});
853        assert_eq!(next(), (Ok(KEY4), Some(2)));
854        assert_eq!(next(), (Ok(REPORT), None));
855        assert_eq!(next(), (Err(true), Some(4)));
856        assert_eq!(next(), (Err(false), None));
857        assert_eq!(next(), (Err(false), None));
858        assert_eq!(next(), (Err(false), None));
859    }
860}