evdev/
raw_stream.rs

1//! A device implementation with no userspace synchronization performed.
2
3use std::fs::{File, OpenOptions};
4use std::mem::MaybeUninit;
5use std::os::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd};
6use std::path::{Path, PathBuf};
7use std::{io, mem};
8
9use crate::compat::{input_absinfo, input_event, input_id, input_keymap_entry};
10use crate::constants::*;
11use crate::ff::*;
12use crate::{
13    sys, AbsInfo, AttributeSet, AttributeSetRef, AutoRepeat, FFEffect, FFEffectCode, FFEvent,
14    InputEvent, InputId, KeyCode,
15};
16
17fn ioctl_get_cstring(
18    f: unsafe fn(RawFd, &mut [u8]) -> nix::Result<libc::c_int>,
19    fd: RawFd,
20) -> Option<Vec<u8>> {
21    let mut buf = vec![0; 256];
22    match unsafe { f(fd, buf.as_mut_slice()) } {
23        Ok(len) if len as usize > buf.capacity() => {
24            panic!("ioctl_get_cstring call overran the provided buffer!");
25        }
26        Ok(len) if len > 1 => {
27            // Our ioctl string functions apparently return the number of bytes written, including
28            // trailing \0.
29            buf.truncate(len as usize);
30            assert_eq!(buf.pop().unwrap(), 0);
31            Some(buf)
32        }
33        _ => None,
34    }
35}
36
37fn bytes_into_string_lossy(v: Vec<u8>) -> String {
38    String::from_utf8(v).unwrap_or_else(|v| String::from_utf8_lossy(v.as_bytes()).into_owned())
39}
40
41const ABSINFO_ZERO: input_absinfo = input_absinfo {
42    value: 0,
43    minimum: 0,
44    maximum: 0,
45    fuzz: 0,
46    flat: 0,
47    resolution: 0,
48};
49
50pub(crate) const ABS_VALS_INIT: [input_absinfo; AbsoluteAxisCode::COUNT] =
51    [ABSINFO_ZERO; AbsoluteAxisCode::COUNT];
52
53const INPUT_KEYMAP_BY_INDEX: u8 = 1;
54
55/// A physical or virtual device supported by evdev.
56///
57/// Each device corresponds to a path typically found in `/dev/input`, and supports access via
58/// one or more "types". For example, an optical mouse has buttons that are represented by "keys",
59/// and reflects changes in its position via "relative axis" reports.
60///
61/// If events are dropped from the kernel's internal buffer, no synchronization will be done to
62/// fetch the device's state, meaning the state as observed through events may drift from
63/// the actual state of the device.
64#[derive(Debug)]
65pub struct RawDevice {
66    fd: OwnedFd,
67    ty: AttributeSet<EventType>,
68    name: Option<String>,
69    phys: Option<String>,
70    uniq: Option<String>,
71    id: input_id,
72    props: AttributeSet<PropType>,
73    driver_version: (u8, u8, u8),
74    supported_keys: Option<AttributeSet<KeyCode>>,
75    supported_relative: Option<AttributeSet<RelativeAxisCode>>,
76    supported_absolute: Option<AttributeSet<AbsoluteAxisCode>>,
77    supported_switch: Option<AttributeSet<SwitchCode>>,
78    supported_led: Option<AttributeSet<LedCode>>,
79    supported_misc: Option<AttributeSet<MiscCode>>,
80    supported_ff: Option<AttributeSet<FFEffectCode>>,
81    auto_repeat: Option<AutoRepeat>,
82    max_ff_effects: usize,
83    // ff: Option<AttributeSet<_>>,
84    // ff_stat: Option<FFStatus>,
85    supported_snd: Option<AttributeSet<SoundCode>>,
86    pub(crate) event_buf: Vec<input_event>,
87    grabbed: bool,
88}
89
90impl RawDevice {
91    /// Opens a device, given its system path.
92    ///
93    /// Paths are typically something like `/dev/input/event0`.
94    #[inline(always)]
95    pub fn open(path: impl AsRef<Path>) -> io::Result<RawDevice> {
96        Self::_open(path.as_ref())
97    }
98
99    fn _open(path: &Path) -> io::Result<RawDevice> {
100        let mut options = OpenOptions::new();
101
102        // Try to load read/write, then fall back to read-only.
103        let fd: OwnedFd = options
104            .read(true)
105            .write(true)
106            .open(path)
107            .or_else(|_| options.write(false).open(path))?
108            .into();
109
110        Self::from_fd(fd)
111    }
112
113    /// Opens a device, given an already opened file descriptor
114    pub fn from_fd(fd: OwnedFd) -> io::Result<RawDevice> {
115        let ty = {
116            let mut ty = AttributeSet::<EventType>::new();
117            unsafe { sys::eviocgbit_type(fd.as_raw_fd(), ty.as_mut_raw_slice())? };
118            ty
119        };
120
121        let name = ioctl_get_cstring(sys::eviocgname, fd.as_raw_fd()).map(bytes_into_string_lossy);
122        let phys = ioctl_get_cstring(sys::eviocgphys, fd.as_raw_fd()).map(bytes_into_string_lossy);
123        let uniq = ioctl_get_cstring(sys::eviocguniq, fd.as_raw_fd()).map(bytes_into_string_lossy);
124
125        let id = unsafe {
126            let mut id = MaybeUninit::uninit();
127            sys::eviocgid(fd.as_raw_fd(), id.as_mut_ptr())?;
128            id.assume_init()
129        };
130        let mut driver_version: i32 = 0;
131        unsafe {
132            sys::eviocgversion(fd.as_raw_fd(), &mut driver_version)?;
133        }
134        let driver_version = (
135            ((driver_version >> 16) & 0xff) as u8,
136            ((driver_version >> 8) & 0xff) as u8,
137            (driver_version & 0xff) as u8,
138        );
139
140        let props = {
141            let mut props = AttributeSet::<PropType>::new();
142            unsafe { sys::eviocgprop(fd.as_raw_fd(), props.as_mut_raw_slice())? };
143            props
144        }; // FIXME: handle old kernel
145
146        let supported_keys = if ty.contains(EventType::KEY) {
147            let mut keys = AttributeSet::<KeyCode>::new();
148            unsafe { sys::eviocgbit_key(fd.as_raw_fd(), keys.as_mut_raw_slice())? };
149            Some(keys)
150        } else {
151            None
152        };
153
154        let supported_relative = if ty.contains(EventType::RELATIVE) {
155            let mut rel = AttributeSet::<RelativeAxisCode>::new();
156            unsafe { sys::eviocgbit_relative(fd.as_raw_fd(), rel.as_mut_raw_slice())? };
157            Some(rel)
158        } else {
159            None
160        };
161
162        let supported_absolute = if ty.contains(EventType::ABSOLUTE) {
163            let mut abs = AttributeSet::<AbsoluteAxisCode>::new();
164            unsafe { sys::eviocgbit_absolute(fd.as_raw_fd(), abs.as_mut_raw_slice())? };
165            Some(abs)
166        } else {
167            None
168        };
169
170        let supported_switch = if ty.contains(EventType::SWITCH) {
171            let mut switch = AttributeSet::<SwitchCode>::new();
172            unsafe { sys::eviocgbit_switch(fd.as_raw_fd(), switch.as_mut_raw_slice())? };
173            Some(switch)
174        } else {
175            None
176        };
177
178        let supported_led = if ty.contains(EventType::LED) {
179            let mut led = AttributeSet::<LedCode>::new();
180            unsafe { sys::eviocgbit_led(fd.as_raw_fd(), led.as_mut_raw_slice())? };
181            Some(led)
182        } else {
183            None
184        };
185
186        let supported_misc = if ty.contains(EventType::MISC) {
187            let mut misc = AttributeSet::<MiscCode>::new();
188            unsafe { sys::eviocgbit_misc(fd.as_raw_fd(), misc.as_mut_raw_slice())? };
189            Some(misc)
190        } else {
191            None
192        };
193
194        let supported_ff = if ty.contains(EventType::FORCEFEEDBACK) {
195            let mut ff = AttributeSet::<FFEffectCode>::new();
196            unsafe { sys::eviocgbit_ff(fd.as_raw_fd(), ff.as_mut_raw_slice())? };
197            Some(ff)
198        } else {
199            None
200        };
201
202        let max_ff_effects = if ty.contains(EventType::FORCEFEEDBACK) {
203            let mut max_ff_effects = 0;
204            unsafe { sys::eviocgeffects(fd.as_raw_fd(), &mut max_ff_effects)? };
205            usize::try_from(max_ff_effects).unwrap_or(0)
206        } else {
207            0
208        };
209
210        let supported_snd = if ty.contains(EventType::SOUND) {
211            let mut snd = AttributeSet::<SoundCode>::new();
212            unsafe { sys::eviocgbit_sound(fd.as_raw_fd(), snd.as_mut_raw_slice())? };
213            Some(snd)
214        } else {
215            None
216        };
217
218        let auto_repeat = if ty.contains(EventType::REPEAT) {
219            let mut auto_repeat: AutoRepeat = AutoRepeat {
220                delay: 0,
221                period: 0,
222            };
223
224            unsafe {
225                sys::eviocgrep(
226                    fd.as_raw_fd(),
227                    &mut auto_repeat as *mut AutoRepeat as *mut [u32; 2],
228                )?;
229            }
230
231            Some(auto_repeat)
232        } else {
233            None
234        };
235
236        Ok(RawDevice {
237            fd,
238            ty,
239            name,
240            phys,
241            uniq,
242            id,
243            props,
244            driver_version,
245            supported_keys,
246            supported_relative,
247            supported_absolute,
248            supported_switch,
249            supported_led,
250            supported_misc,
251            supported_ff,
252            supported_snd,
253            auto_repeat,
254            max_ff_effects,
255            event_buf: Vec::new(),
256            grabbed: false,
257        })
258    }
259
260    /// Returns the device's name as read from the kernel.
261    pub fn name(&self) -> Option<&str> {
262        self.name.as_deref()
263    }
264
265    /// Returns the device's physical location, either as set by the caller or as read from the kernel.
266    pub fn physical_path(&self) -> Option<&str> {
267        self.phys.as_deref()
268    }
269
270    /// Returns the user-defined "unique name" of the device, if one has been set.
271    pub fn unique_name(&self) -> Option<&str> {
272        self.uniq.as_deref()
273    }
274
275    /// Returns a struct containing bustype, vendor, product, and version identifiers
276    pub fn input_id(&self) -> InputId {
277        InputId::from(self.id)
278    }
279
280    /// Returns the current auto repeat settings
281    pub fn get_auto_repeat(&self) -> Option<AutoRepeat> {
282        self.auto_repeat.clone()
283    }
284
285    /// Returns the set of supported "properties" for the device (see `INPUT_PROP_*` in kernel headers)
286    pub fn properties(&self) -> &AttributeSetRef<PropType> {
287        &self.props
288    }
289
290    /// Returns a tuple of the driver version containing major, minor, rev
291    pub fn driver_version(&self) -> (u8, u8, u8) {
292        self.driver_version
293    }
294
295    /// Returns a set of the event types supported by this device (Key, Switch, etc)
296    ///
297    /// If you're interested in the individual keys or switches supported, it's probably easier
298    /// to just call the appropriate `supported_*` function instead.
299    pub fn supported_events(&self) -> &AttributeSetRef<EventType> {
300        &self.ty
301    }
302
303    /// Returns the set of supported keys reported by the device.
304    ///
305    /// For keyboards, this is the set of all possible keycodes the keyboard may emit. Controllers,
306    /// mice, and other peripherals may also report buttons as keys.
307    ///
308    /// # Examples
309    ///
310    /// ```no_run
311    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
312    /// use evdev::{Device, KeyCode};
313    /// let device = Device::open("/dev/input/event0")?;
314    ///
315    /// // Does this device have an ENTER key?
316    /// let supported = device.supported_keys().map_or(false, |keys| keys.contains(KeyCode::KEY_ENTER));
317    /// # Ok(())
318    /// # }
319    /// ```
320    pub fn supported_keys(&self) -> Option<&AttributeSetRef<KeyCode>> {
321        self.supported_keys.as_deref()
322    }
323
324    /// Returns the set of supported "relative axes" reported by the device.
325    ///
326    /// Standard mice will generally report `REL_X` and `REL_Y` along with wheel if supported.
327    ///
328    /// # Examples
329    ///
330    /// ```no_run
331    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
332    /// use evdev::{Device, RelativeAxisCode};
333    /// let device = Device::open("/dev/input/event0")?;
334    ///
335    /// // Does the device have a scroll wheel?
336    /// let supported = device
337    ///     .supported_relative_axes()
338    ///     .map_or(false, |axes| axes.contains(RelativeAxisCode::REL_WHEEL));
339    /// # Ok(())
340    /// # }
341    /// ```
342    pub fn supported_relative_axes(&self) -> Option<&AttributeSetRef<RelativeAxisCode>> {
343        self.supported_relative.as_deref()
344    }
345
346    /// Returns the set of supported "absolute axes" reported by the device.
347    ///
348    /// These are most typically supported by joysticks and touchpads.
349    ///
350    /// # Examples
351    ///
352    /// ```no_run
353    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
354    /// use evdev::{Device, AbsoluteAxisCode};
355    /// let device = Device::open("/dev/input/event0")?;
356    ///
357    /// // Does the device have an absolute X axis?
358    /// let supported = device
359    ///     .supported_absolute_axes()
360    ///     .map_or(false, |axes| axes.contains(AbsoluteAxisCode::ABS_X));
361    /// # Ok(())
362    /// # }
363    /// ```
364    pub fn supported_absolute_axes(&self) -> Option<&AttributeSetRef<AbsoluteAxisCode>> {
365        self.supported_absolute.as_deref()
366    }
367
368    /// Returns the set of supported switches reported by the device.
369    ///
370    /// These are typically used for things like software switches on laptop lids (which the
371    /// system reacts to by suspending or locking), or virtual switches to indicate whether a
372    /// headphone jack is plugged in (used to disable external speakers).
373    ///
374    /// # Examples
375    ///
376    /// ```no_run
377    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
378    /// use evdev::{Device, SwitchCode};
379    /// let device = Device::open("/dev/input/event0")?;
380    ///
381    /// // Does the device report a laptop lid switch?
382    /// let supported = device
383    ///     .supported_switches()
384    ///     .map_or(false, |axes| axes.contains(SwitchCode::SW_LID));
385    /// # Ok(())
386    /// # }
387    /// ```
388    pub fn supported_switches(&self) -> Option<&AttributeSetRef<SwitchCode>> {
389        self.supported_switch.as_deref()
390    }
391
392    /// Returns a set of supported LEDs on the device.
393    ///
394    /// Most commonly these are state indicator lights for things like Scroll Lock, but they
395    /// can also be found in cameras and other devices.
396    pub fn supported_leds(&self) -> Option<&AttributeSetRef<LedCode>> {
397        self.supported_led.as_deref()
398    }
399
400    /// Returns a set of supported "miscellaneous" capabilities.
401    ///
402    /// Aside from vendor-specific key scancodes, most of these are uncommon.
403    pub fn misc_properties(&self) -> Option<&AttributeSetRef<MiscCode>> {
404        self.supported_misc.as_deref()
405    }
406
407    /// Returns the set of supported force feedback effects supported by a device.
408    pub fn supported_ff(&self) -> Option<&AttributeSetRef<FFEffectCode>> {
409        self.supported_ff.as_deref()
410    }
411
412    /// Returns the maximum number of force feedback effects that can be played simultaneously.
413    pub fn max_ff_effects(&self) -> usize {
414        self.max_ff_effects
415    }
416
417    /// Returns the set of supported simple sounds supported by a device.
418    ///
419    /// You can use these to make really annoying beep sounds come from an internal self-test
420    /// speaker, for instance.
421    pub fn supported_sounds(&self) -> Option<&AttributeSetRef<SoundCode>> {
422        self.supported_snd.as_deref()
423    }
424
425    /// Read a maximum of `num` events into the internal buffer. If the underlying fd is not
426    /// O_NONBLOCK, this will block.
427    ///
428    /// Returns the number of events that were read, or an error.
429    pub(crate) fn fill_events(&mut self) -> io::Result<usize> {
430        let fd = self.as_raw_fd();
431        self.event_buf.reserve(crate::EVENT_BATCH_SIZE);
432
433        let spare_capacity = self.event_buf.spare_capacity_mut();
434        let spare_capacity_size = std::mem::size_of_val(spare_capacity);
435
436        // use libc::read instead of nix::unistd::read b/c we need to pass an uninitialized buf
437        let res = unsafe { libc::read(fd, spare_capacity.as_mut_ptr() as _, spare_capacity_size) };
438        let bytes_read = nix::errno::Errno::result(res)?;
439        let num_read = bytes_read as usize / mem::size_of::<input_event>();
440        unsafe {
441            let len = self.event_buf.len();
442            self.event_buf.set_len(len + num_read);
443        }
444        Ok(num_read)
445    }
446
447    /// Fetches and returns events from the kernel ring buffer without doing synchronization on
448    /// SYN_DROPPED.
449    ///
450    /// By default this will block until events are available. Typically, users will want to call
451    /// this in a tight loop within a thread.
452    pub fn fetch_events(&mut self) -> io::Result<impl Iterator<Item = InputEvent> + '_> {
453        self.fill_events()?;
454        Ok(self.event_buf.drain(..).map(InputEvent::from))
455    }
456
457    /// Retrieve the current keypress state directly via kernel syscall.
458    #[inline]
459    pub fn get_key_state(&self) -> io::Result<AttributeSet<KeyCode>> {
460        let mut key_vals = AttributeSet::new();
461        self.update_key_state(&mut key_vals)?;
462        Ok(key_vals)
463    }
464
465    /// Retrieve the current absolute axis state directly via kernel syscall.
466    #[inline]
467    pub fn get_abs_state(&self) -> io::Result<[input_absinfo; AbsoluteAxisCode::COUNT]> {
468        let mut abs_vals: [input_absinfo; AbsoluteAxisCode::COUNT] = ABS_VALS_INIT;
469        self.update_abs_state(&mut abs_vals)?;
470        Ok(abs_vals)
471    }
472
473    /// Get the AbsInfo for each supported AbsoluteAxis
474    pub fn get_absinfo(
475        &self,
476    ) -> io::Result<impl Iterator<Item = (AbsoluteAxisCode, AbsInfo)> + '_> {
477        let raw_absinfo = self.get_abs_state()?;
478        Ok(self
479            .supported_absolute_axes()
480            .into_iter()
481            .flat_map(AttributeSetRef::iter)
482            .map(move |axes| (axes, AbsInfo(raw_absinfo[axes.0 as usize]))))
483    }
484
485    /// Retrieve the current switch state directly via kernel syscall.
486    #[inline]
487    pub fn get_switch_state(&self) -> io::Result<AttributeSet<SwitchCode>> {
488        let mut switch_vals = AttributeSet::new();
489        self.update_switch_state(&mut switch_vals)?;
490        Ok(switch_vals)
491    }
492
493    /// Retrieve the current LED state directly via kernel syscall.
494    #[inline]
495    pub fn get_led_state(&self) -> io::Result<AttributeSet<LedCode>> {
496        let mut led_vals = AttributeSet::new();
497        self.update_led_state(&mut led_vals)?;
498        Ok(led_vals)
499    }
500
501    /// Fetch the current kernel key state directly into the provided buffer.
502    /// If you don't already have a buffer, you probably want
503    /// [`get_key_state`](Self::get_key_state) instead.
504    #[inline]
505    pub fn update_key_state(&self, key_vals: &mut AttributeSet<KeyCode>) -> io::Result<()> {
506        unsafe { sys::eviocgkey(self.as_raw_fd(), key_vals.as_mut_raw_slice())? };
507        Ok(())
508    }
509
510    /// Fetch the current kernel absolute axis state directly into the provided buffer.
511    /// If you don't already have a buffer, you probably want
512    /// [`get_abs_state`](Self::get_abs_state) instead.
513    #[inline]
514    pub fn update_abs_state(
515        &self,
516        abs_vals: &mut [input_absinfo; AbsoluteAxisCode::COUNT],
517    ) -> io::Result<()> {
518        if let Some(supported_abs) = self.supported_absolute_axes() {
519            for AbsoluteAxisCode(idx) in supported_abs.iter() {
520                // ignore multitouch, we'll handle that later.
521                //
522                // handling later removed. not sure what the intention of "handling that later" was
523                // the abs data seems to be fine (tested ABS_MT_POSITION_X/Y)
524                unsafe {
525                    sys::eviocgabs(self.as_raw_fd(), idx as u32, &mut abs_vals[idx as usize])?
526                };
527            }
528        }
529        Ok(())
530    }
531
532    /// Fetch the current kernel switch state directly into the provided buffer.
533    /// If you don't already have a buffer, you probably want
534    /// [`get_switch_state`](Self::get_switch_state) instead.
535    #[inline]
536    pub fn update_switch_state(
537        &self,
538        switch_vals: &mut AttributeSet<SwitchCode>,
539    ) -> io::Result<()> {
540        unsafe { sys::eviocgsw(self.as_raw_fd(), switch_vals.as_mut_raw_slice())? };
541        Ok(())
542    }
543
544    /// Fetch the current kernel LED state directly into the provided buffer.
545    /// If you don't already have a buffer, you probably want
546    /// [`get_led_state`](Self::get_led_state) instead.
547    #[inline]
548    pub fn update_led_state(&self, led_vals: &mut AttributeSet<LedCode>) -> io::Result<()> {
549        unsafe { sys::eviocgled(self.as_raw_fd(), led_vals.as_mut_raw_slice())? };
550        Ok(())
551    }
552
553    /// Update the auto repeat delays
554    #[inline]
555    pub fn update_auto_repeat(&mut self, repeat: &AutoRepeat) -> io::Result<()> {
556        unsafe {
557            sys::eviocsrep(
558                self.as_raw_fd(),
559                repeat as *const AutoRepeat as *const [u32; 2],
560            )?;
561        }
562        self.auto_repeat = Some(repeat.clone());
563        Ok(())
564    }
565
566    /// Retrieve the scancode for a keycode, if any
567    pub fn get_scancode_by_keycode(&self, keycode: u32) -> io::Result<Vec<u8>> {
568        let mut keymap = input_keymap_entry {
569            flags: 0,
570            len: 0,
571            index: 0,
572            keycode,
573            scancode: [0u8; 32],
574        };
575        unsafe { sys::eviocgkeycode_v2(self.as_raw_fd(), &mut keymap)? };
576        Ok(keymap.scancode[..keymap.len as usize].to_vec())
577    }
578
579    /// Retrieve the keycode and scancode by index, starting at 0
580    pub fn get_scancode_by_index(&self, index: u16) -> io::Result<(u32, Vec<u8>)> {
581        let mut keymap = input_keymap_entry {
582            flags: INPUT_KEYMAP_BY_INDEX,
583            len: 0,
584            index,
585            keycode: 0,
586            scancode: [0u8; 32],
587        };
588
589        unsafe { sys::eviocgkeycode_v2(self.as_raw_fd(), &mut keymap)? };
590        Ok((
591            keymap.keycode,
592            keymap.scancode[..keymap.len as usize].to_vec(),
593        ))
594    }
595
596    /// Update a scancode by index. The return value is the previous keycode
597    pub fn update_scancode_by_index(
598        &self,
599        index: u16,
600        keycode: u32,
601        scancode: &[u8],
602    ) -> io::Result<u32> {
603        let len = scancode.len();
604
605        let mut keymap = input_keymap_entry {
606            flags: INPUT_KEYMAP_BY_INDEX,
607            len: len as u8,
608            index,
609            keycode,
610            scancode: [0u8; 32],
611        };
612
613        keymap.scancode[..len].copy_from_slice(scancode);
614
615        let keycode = unsafe { sys::eviocskeycode_v2(self.as_raw_fd(), &keymap)? };
616
617        Ok(keycode as u32)
618    }
619
620    /// Update a scancode. The return value is the previous keycode
621    pub fn update_scancode(&self, keycode: u32, scancode: &[u8]) -> io::Result<u32> {
622        let len = scancode.len();
623
624        let mut keymap = input_keymap_entry {
625            flags: 0,
626            len: len as u8,
627            index: 0,
628            keycode,
629            scancode: [0u8; 32],
630        };
631
632        keymap.scancode[..len].copy_from_slice(scancode);
633
634        let keycode = unsafe { sys::eviocskeycode_v2(self.as_raw_fd(), &keymap)? };
635
636        Ok(keycode as u32)
637    }
638
639    #[cfg(feature = "tokio")]
640    #[inline]
641    pub fn into_event_stream(self) -> io::Result<EventStream> {
642        EventStream::new(self)
643    }
644
645    pub fn grab(&mut self) -> io::Result<()> {
646        if !self.grabbed {
647            unsafe {
648                sys::eviocgrab(self.as_raw_fd(), 1)?;
649            }
650            self.grabbed = true;
651        }
652        Ok(())
653    }
654
655    pub fn ungrab(&mut self) -> io::Result<()> {
656        if self.grabbed {
657            unsafe {
658                sys::eviocgrab(self.as_raw_fd(), 0)?;
659            }
660            self.grabbed = false;
661        }
662        Ok(())
663    }
664
665    /// Whether the device is currently grabbed for exclusive use or not.
666    pub fn is_grabbed(&self) -> bool {
667        self.grabbed
668    }
669
670    /// Send an event to the device.
671    ///
672    /// Events that are typically sent to devices are
673    /// [EventType::LED] (turn device LEDs on and off),
674    /// [EventType::SOUND] (play a sound on the device)
675    /// and [EventType::FORCEFEEDBACK] (play force feedback effects on the device, i.e. rumble).
676    pub fn send_events(&mut self, events: &[InputEvent]) -> io::Result<()> {
677        crate::write_events(self.fd.as_fd(), events)?;
678        Ok(())
679    }
680
681    /// Uploads a force feedback effect to the device.
682    pub fn upload_ff_effect(&mut self, data: FFEffectData) -> io::Result<FFEffect> {
683        let mut effect: sys::ff_effect = data.into();
684        effect.id = -1;
685
686        unsafe { sys::eviocsff(self.fd.as_raw_fd(), &effect)? };
687
688        let fd = self.fd.try_clone()?;
689        let id = effect.id as u16;
690
691        Ok(FFEffect { fd, id })
692    }
693
694    /// Sets the force feedback gain, i.e. how strong the force feedback effects should be for the
695    /// device. A gain of 0 means no gain, whereas `u16::MAX` is the maximum gain.
696    pub fn set_ff_gain(&mut self, value: u16) -> io::Result<()> {
697        let events = [*FFEvent::new(FFEffectCode::FF_GAIN, value.into())];
698        crate::write_events(self.fd.as_fd(), &events)?;
699
700        Ok(())
701    }
702
703    /// Enables or disables autocenter for the force feedback device.
704    pub fn set_ff_autocenter(&mut self, value: u16) -> io::Result<()> {
705        let events = [*FFEvent::new(FFEffectCode::FF_AUTOCENTER, value.into())];
706        crate::write_events(self.fd.as_fd(), &events)?;
707
708        Ok(())
709    }
710}
711
712impl AsFd for RawDevice {
713    fn as_fd(&self) -> BorrowedFd<'_> {
714        self.fd.as_fd()
715    }
716}
717
718impl AsRawFd for RawDevice {
719    fn as_raw_fd(&self) -> RawFd {
720        self.fd.as_raw_fd()
721    }
722}
723
724impl TryFrom<File> for RawDevice {
725    type Error = io::Error;
726
727    fn try_from(file: File) -> Result<Self, Self::Error> {
728        Self::from_fd(file.into())
729    }
730}
731
732/// Crawls `/dev/input` for evdev devices.
733///
734/// Will not bubble up any errors in opening devices or traversing the directory. Instead returns
735/// an empty iterator or omits the devices that could not be opened.
736pub fn enumerate() -> EnumerateDevices {
737    EnumerateDevices {
738        readdir: std::fs::read_dir("/dev/input").ok(),
739    }
740}
741
742/// An iterator over currently connected evdev devices.
743pub struct EnumerateDevices {
744    readdir: Option<std::fs::ReadDir>,
745}
746impl Iterator for EnumerateDevices {
747    type Item = (PathBuf, RawDevice);
748    fn next(&mut self) -> Option<(PathBuf, RawDevice)> {
749        use std::os::unix::ffi::OsStrExt;
750        let readdir = self.readdir.as_mut()?;
751        loop {
752            if let Ok(entry) = readdir.next()? {
753                let path = entry.path();
754                let fname = path.file_name().unwrap();
755                if fname.as_bytes().starts_with(b"event") {
756                    if let Ok(dev) = RawDevice::open(&path) {
757                        return Some((path, dev));
758                    }
759                }
760            }
761        }
762    }
763}
764
765#[cfg(feature = "tokio")]
766mod tokio_stream {
767    use super::*;
768
769    use std::future::poll_fn;
770    use std::task::{ready, Context, Poll};
771    use tokio::io::unix::AsyncFd;
772
773    /// An asynchronous stream of input events.
774    ///
775    /// This can be used by calling [`stream.next_event().await?`](Self::next_event), or if you
776    /// need to pass it as a stream somewhere, the [`futures::Stream`](Stream) implementation.
777    /// There's also a lower-level [`Self::poll_event`] function if you need to fetch an event from
778    /// inside a `Future::poll` impl.
779    pub struct EventStream {
780        device: AsyncFd<RawDevice>,
781        index: usize,
782    }
783    impl Unpin for EventStream {}
784
785    impl EventStream {
786        pub(crate) fn new(device: RawDevice) -> io::Result<Self> {
787            use nix::fcntl;
788            fcntl::fcntl(device.as_raw_fd(), fcntl::F_SETFL(fcntl::OFlag::O_NONBLOCK))?;
789            let device = AsyncFd::new(device)?;
790            Ok(Self { device, index: 0 })
791        }
792
793        /// Returns a reference to the underlying device
794        pub fn device(&self) -> &RawDevice {
795            self.device.get_ref()
796        }
797
798        /// Returns a mutable reference to the underlying device.
799        pub fn device_mut(&mut self) -> &mut RawDevice {
800            self.device.get_mut()
801        }
802
803        /// Try to wait for the next event in this stream. Any errors are likely to be fatal, i.e.
804        /// any calls afterwards will likely error as well.
805        pub async fn next_event(&mut self) -> io::Result<InputEvent> {
806            poll_fn(|cx| self.poll_event(cx)).await
807        }
808
809        /// A lower-level function for directly polling this stream.
810        pub fn poll_event(&mut self, cx: &mut Context<'_>) -> Poll<io::Result<InputEvent>> {
811            'outer: loop {
812                if let Some(&ev) = self.device.get_ref().event_buf.get(self.index) {
813                    self.index += 1;
814                    return Poll::Ready(Ok(InputEvent::from(ev)));
815                }
816
817                self.device.get_mut().event_buf.clear();
818                self.index = 0;
819
820                loop {
821                    let mut guard = ready!(self.device.poll_read_ready_mut(cx))?;
822
823                    let res = guard.try_io(|device| device.get_mut().fill_events());
824                    match res {
825                        Ok(res) => {
826                            let _ = res?;
827                            continue 'outer;
828                        }
829                        Err(_would_block) => continue,
830                    }
831                }
832            }
833        }
834    }
835
836    #[cfg(feature = "stream-trait")]
837    impl futures_core::Stream for EventStream {
838        type Item = io::Result<InputEvent>;
839        fn poll_next(
840            self: std::pin::Pin<&mut Self>,
841            cx: &mut Context<'_>,
842        ) -> Poll<Option<Self::Item>> {
843            self.get_mut().poll_event(cx).map(Some)
844        }
845    }
846}
847#[cfg(feature = "tokio")]
848pub use tokio_stream::EventStream;