1use std::fs::{File, OpenOptions};
2use std::mem::MaybeUninit;
3use std::os::unix::io::{AsRawFd, RawFd};
4use std::path::Path;
5use std::{io, mem};
6
7use crate::constants::*;
8use crate::{sys, AttributeSet, AttributeSetRef, InputEvent, InputId, Key};
9
10fn ioctl_get_cstring(
11 f: unsafe fn(RawFd, &mut [u8]) -> nix::Result<libc::c_int>,
12 fd: RawFd,
13) -> Option<Vec<u8>> {
14 let mut buf = vec![0; 256];
15 match unsafe { f(fd, buf.as_mut_slice()) } {
16 Ok(len) if len as usize > buf.capacity() => {
17 panic!("ioctl_get_cstring call overran the provided buffer!");
18 }
19 Ok(len) if len > 1 => {
20 buf.truncate(len as usize);
23 assert_eq!(buf.pop().unwrap(), 0);
24 Some(buf)
25 }
26 _ => None,
27 }
28}
29
30fn bytes_into_string_lossy(v: Vec<u8>) -> String {
31 String::from_utf8(v).unwrap_or_else(|v| String::from_utf8_lossy(v.as_bytes()).into_owned())
32}
33
34#[rustfmt::skip]
35const ABSINFO_ZERO: libc::input_absinfo = libc::input_absinfo {
36 value: 0, minimum: 0, maximum: 0, fuzz: 0, flat: 0, resolution: 0,
37};
38pub(crate) const ABS_VALS_INIT: [libc::input_absinfo; AbsoluteAxisType::COUNT] =
39 [ABSINFO_ZERO; AbsoluteAxisType::COUNT];
40
41const INPUT_KEYMAP_BY_INDEX: u8 = 1;
42
43#[derive(Debug)]
49pub struct RawDevice {
50 file: File,
51 ty: AttributeSet<EventType>,
52 name: Option<String>,
53 phys: Option<String>,
54 uniq: Option<String>,
55 id: libc::input_id,
56 props: AttributeSet<PropType>,
57 driver_version: (u8, u8, u8),
58 supported_keys: Option<AttributeSet<Key>>,
59 supported_relative: Option<AttributeSet<RelativeAxisType>>,
60 supported_absolute: Option<AttributeSet<AbsoluteAxisType>>,
61 supported_switch: Option<AttributeSet<SwitchType>>,
62 supported_led: Option<AttributeSet<LedType>>,
63 supported_misc: Option<AttributeSet<MiscType>>,
64 auto_repeat: Option<AutoRepeat>,
65 supported_snd: Option<AttributeSet<SoundType>>,
68 pub(crate) event_buf: Vec<libc::input_event>,
69 grabbed: bool,
70}
71
72#[derive(Debug, Clone)]
73#[repr(C)]
74pub struct AutoRepeat {
75 pub delay: u32,
76 pub period: u32,
77}
78
79impl RawDevice {
80 #[inline(always)]
84 pub fn open(path: impl AsRef<Path>) -> io::Result<RawDevice> {
85 Self::_open(path.as_ref())
86 }
87
88 fn _open(path: &Path) -> io::Result<RawDevice> {
89 let mut options = OpenOptions::new();
90
91 let file = options
93 .read(true)
94 .write(true)
95 .open(path)
96 .or_else(|_| options.write(false).open(path))?;
97
98 let ty = {
99 let mut ty = AttributeSet::<EventType>::new();
100 unsafe { sys::eviocgbit_type(file.as_raw_fd(), ty.as_mut_raw_slice())? };
101 ty
102 };
103
104 let name =
105 ioctl_get_cstring(sys::eviocgname, file.as_raw_fd()).map(bytes_into_string_lossy);
106 let phys =
107 ioctl_get_cstring(sys::eviocgphys, file.as_raw_fd()).map(bytes_into_string_lossy);
108 let uniq =
109 ioctl_get_cstring(sys::eviocguniq, file.as_raw_fd()).map(bytes_into_string_lossy);
110
111 let id = unsafe {
112 let mut id = MaybeUninit::uninit();
113 sys::eviocgid(file.as_raw_fd(), id.as_mut_ptr())?;
114 id.assume_init()
115 };
116 let mut driver_version: i32 = 0;
117 unsafe {
118 sys::eviocgversion(file.as_raw_fd(), &mut driver_version)?;
119 }
120 let driver_version = (
121 ((driver_version >> 16) & 0xff) as u8,
122 ((driver_version >> 8) & 0xff) as u8,
123 (driver_version & 0xff) as u8,
124 );
125
126 let props = {
127 let mut props = AttributeSet::<PropType>::new();
128 unsafe { sys::eviocgprop(file.as_raw_fd(), props.as_mut_raw_slice())? };
129 props
130 }; let supported_keys = if ty.contains(EventType::KEY) {
133 let mut keys = AttributeSet::<Key>::new();
134 unsafe { sys::eviocgbit_key(file.as_raw_fd(), keys.as_mut_raw_slice())? };
135 Some(keys)
136 } else {
137 None
138 };
139
140 let supported_relative = if ty.contains(EventType::RELATIVE) {
141 let mut rel = AttributeSet::<RelativeAxisType>::new();
142 unsafe { sys::eviocgbit_relative(file.as_raw_fd(), rel.as_mut_raw_slice())? };
143 Some(rel)
144 } else {
145 None
146 };
147
148 let supported_absolute = if ty.contains(EventType::ABSOLUTE) {
149 let mut abs = AttributeSet::<AbsoluteAxisType>::new();
150 unsafe { sys::eviocgbit_absolute(file.as_raw_fd(), abs.as_mut_raw_slice())? };
151 Some(abs)
152 } else {
153 None
154 };
155
156 let supported_switch = if ty.contains(EventType::SWITCH) {
157 let mut switch = AttributeSet::<SwitchType>::new();
158 unsafe { sys::eviocgbit_switch(file.as_raw_fd(), switch.as_mut_raw_slice())? };
159 Some(switch)
160 } else {
161 None
162 };
163
164 let supported_led = if ty.contains(EventType::LED) {
165 let mut led = AttributeSet::<LedType>::new();
166 unsafe { sys::eviocgbit_led(file.as_raw_fd(), led.as_mut_raw_slice())? };
167 Some(led)
168 } else {
169 None
170 };
171
172 let supported_misc = if ty.contains(EventType::MISC) {
173 let mut misc = AttributeSet::<MiscType>::new();
174 unsafe { sys::eviocgbit_misc(file.as_raw_fd(), misc.as_mut_raw_slice())? };
175 Some(misc)
176 } else {
177 None
178 };
179
180 let supported_snd = if ty.contains(EventType::SOUND) {
183 let mut snd = AttributeSet::<SoundType>::new();
184 unsafe { sys::eviocgbit_sound(file.as_raw_fd(), snd.as_mut_raw_slice())? };
185 Some(snd)
186 } else {
187 None
188 };
189
190 let auto_repeat = if ty.contains(EventType::REPEAT) {
191 let mut auto_repeat: AutoRepeat = AutoRepeat {
192 delay: 0,
193 period: 0,
194 };
195
196 unsafe {
197 sys::eviocgrep(
198 file.as_raw_fd(),
199 &mut auto_repeat as *mut AutoRepeat as *mut [u32; 2],
200 )?;
201 }
202
203 Some(auto_repeat)
204 } else {
205 None
206 };
207
208 Ok(RawDevice {
209 file,
210 ty,
211 name,
212 phys,
213 uniq,
214 id,
215 props,
216 driver_version,
217 supported_keys,
218 supported_relative,
219 supported_absolute,
220 supported_switch,
221 supported_led,
222 supported_misc,
223 supported_snd,
224 auto_repeat,
225 event_buf: Vec::new(),
226 grabbed: false,
227 })
228 }
229
230 pub fn name(&self) -> Option<&str> {
232 self.name.as_deref()
233 }
234
235 pub fn physical_path(&self) -> Option<&str> {
237 self.phys.as_deref()
238 }
239
240 pub fn unique_name(&self) -> Option<&str> {
242 self.uniq.as_deref()
243 }
244
245 pub fn input_id(&self) -> InputId {
247 InputId::from(self.id)
248 }
249
250 pub fn get_auto_repeat(&self) -> Option<AutoRepeat> {
252 self.auto_repeat.clone()
253 }
254
255 pub fn properties(&self) -> &AttributeSetRef<PropType> {
257 &self.props
258 }
259
260 pub fn driver_version(&self) -> (u8, u8, u8) {
262 self.driver_version
263 }
264
265 pub fn supported_events(&self) -> &AttributeSetRef<EventType> {
270 &self.ty
271 }
272
273 pub fn supported_keys(&self) -> Option<&AttributeSetRef<Key>> {
291 self.supported_keys.as_deref()
292 }
293
294 pub fn supported_relative_axes(&self) -> Option<&AttributeSetRef<RelativeAxisType>> {
313 self.supported_relative.as_deref()
314 }
315
316 pub fn supported_absolute_axes(&self) -> Option<&AttributeSetRef<AbsoluteAxisType>> {
335 self.supported_absolute.as_deref()
336 }
337
338 pub fn supported_switches(&self) -> Option<&AttributeSetRef<SwitchType>> {
359 self.supported_switch.as_deref()
360 }
361
362 pub fn supported_leds(&self) -> Option<&AttributeSetRef<LedType>> {
367 self.supported_led.as_deref()
368 }
369
370 pub fn misc_properties(&self) -> Option<&AttributeSetRef<MiscType>> {
374 self.supported_misc.as_deref()
375 }
376
377 pub fn supported_sounds(&self) -> Option<&AttributeSetRef<SoundType>> {
382 self.supported_snd.as_deref()
383 }
384
385 pub(crate) fn fill_events(&mut self) -> io::Result<usize> {
390 let fd = self.as_raw_fd();
391 self.event_buf.reserve(crate::EVENT_BATCH_SIZE);
392
393 let spare_capacity = vec_spare_capacity_mut(&mut self.event_buf);
395 let spare_capacity_size = std::mem::size_of_val(spare_capacity);
396
397 let res = unsafe { libc::read(fd, spare_capacity.as_mut_ptr() as _, spare_capacity_size) };
399 let bytes_read = nix::errno::Errno::result(res)?;
400 let num_read = bytes_read as usize / mem::size_of::<libc::input_event>();
401 unsafe {
402 let len = self.event_buf.len();
403 self.event_buf.set_len(len + num_read);
404 }
405 Ok(num_read)
406 }
407
408 pub fn fetch_events(&mut self) -> io::Result<impl Iterator<Item = InputEvent> + '_> {
414 self.fill_events()?;
415 Ok(self.event_buf.drain(..).map(InputEvent))
416 }
417
418 #[inline]
420 pub fn get_key_state(&self) -> io::Result<AttributeSet<Key>> {
421 let mut key_vals = AttributeSet::new();
422 self.update_key_state(&mut key_vals)?;
423 Ok(key_vals)
424 }
425
426 #[inline]
428 pub fn get_abs_state(&self) -> io::Result<[libc::input_absinfo; AbsoluteAxisType::COUNT]> {
429 let mut abs_vals: [libc::input_absinfo; AbsoluteAxisType::COUNT] = ABS_VALS_INIT;
430 self.update_abs_state(&mut abs_vals)?;
431 Ok(abs_vals)
432 }
433
434 #[inline]
436 pub fn get_switch_state(&self) -> io::Result<AttributeSet<SwitchType>> {
437 let mut switch_vals = AttributeSet::new();
438 self.update_switch_state(&mut switch_vals)?;
439 Ok(switch_vals)
440 }
441
442 #[inline]
444 pub fn get_led_state(&self) -> io::Result<AttributeSet<LedType>> {
445 let mut led_vals = AttributeSet::new();
446 self.update_led_state(&mut led_vals)?;
447 Ok(led_vals)
448 }
449
450 #[inline]
454 pub fn update_key_state(&self, key_vals: &mut AttributeSet<Key>) -> io::Result<()> {
455 unsafe { sys::eviocgkey(self.as_raw_fd(), key_vals.as_mut_raw_slice())? };
456 Ok(())
457 }
458
459 #[inline]
463 pub fn update_abs_state(
464 &self,
465 abs_vals: &mut [libc::input_absinfo; AbsoluteAxisType::COUNT],
466 ) -> io::Result<()> {
467 if let Some(supported_abs) = self.supported_absolute_axes() {
468 for AbsoluteAxisType(idx) in supported_abs.iter() {
469 unsafe {
474 sys::eviocgabs(self.as_raw_fd(), idx as u32, &mut abs_vals[idx as usize])?
475 };
476 }
477 }
478 Ok(())
479 }
480
481 #[inline]
485 pub fn update_switch_state(
486 &self,
487 switch_vals: &mut AttributeSet<SwitchType>,
488 ) -> io::Result<()> {
489 unsafe { sys::eviocgsw(self.as_raw_fd(), switch_vals.as_mut_raw_slice())? };
490 Ok(())
491 }
492
493 #[inline]
497 pub fn update_led_state(&self, led_vals: &mut AttributeSet<LedType>) -> io::Result<()> {
498 unsafe { sys::eviocgled(self.as_raw_fd(), led_vals.as_mut_raw_slice())? };
499 Ok(())
500 }
501
502 #[inline]
504 pub fn update_auto_repeat(&mut self, repeat: &AutoRepeat) -> io::Result<()> {
505 unsafe {
506 sys::eviocsrep(
507 self.as_raw_fd(),
508 repeat as *const AutoRepeat as *const [u32; 2],
509 )?;
510 }
511 self.auto_repeat = Some(repeat.clone());
512 Ok(())
513 }
514
515 pub fn get_scancode_by_keycode(&self, keycode: u32) -> io::Result<Vec<u8>> {
517 let mut keymap = libc::input_keymap_entry {
518 flags: 0,
519 len: 0,
520 index: 0,
521 keycode,
522 scancode: [0u8; 32],
523 };
524 unsafe { sys::eviocgkeycode_v2(self.as_raw_fd(), &mut keymap)? };
525 Ok(keymap.scancode[..keymap.len as usize].to_vec())
526 }
527
528 pub fn get_scancode_by_index(&self, index: u16) -> io::Result<(u32, Vec<u8>)> {
530 let mut keymap = libc::input_keymap_entry {
531 flags: INPUT_KEYMAP_BY_INDEX,
532 len: 0,
533 index,
534 keycode: 0,
535 scancode: [0u8; 32],
536 };
537
538 unsafe { sys::eviocgkeycode_v2(self.as_raw_fd(), &mut keymap)? };
539 Ok((
540 keymap.keycode,
541 keymap.scancode[..keymap.len as usize].to_vec(),
542 ))
543 }
544
545 pub fn update_scancode_by_index(
547 &self,
548 index: u16,
549 keycode: u32,
550 scancode: &[u8],
551 ) -> io::Result<u32> {
552 let len = scancode.len();
553
554 let mut keymap = libc::input_keymap_entry {
555 flags: INPUT_KEYMAP_BY_INDEX,
556 len: len as u8,
557 index,
558 keycode,
559 scancode: [0u8; 32],
560 };
561
562 keymap.scancode[..len].copy_from_slice(scancode);
563
564 let keycode = unsafe { sys::eviocskeycode_v2(self.as_raw_fd(), &keymap)? };
565
566 Ok(keycode as u32)
567 }
568
569 pub fn update_scancode(&self, keycode: u32, scancode: &[u8]) -> io::Result<u32> {
571 let len = scancode.len();
572
573 let mut keymap = libc::input_keymap_entry {
574 flags: 0,
575 len: len as u8,
576 index: 0,
577 keycode,
578 scancode: [0u8; 32],
579 };
580
581 keymap.scancode[..len].copy_from_slice(scancode);
582
583 let keycode = unsafe { sys::eviocskeycode_v2(self.as_raw_fd(), &keymap)? };
584
585 Ok(keycode as u32)
586 }
587
588 #[cfg(feature = "tokio")]
589 #[inline]
590 pub fn into_event_stream(self) -> io::Result<EventStream> {
591 EventStream::new(self)
592 }
593
594 pub fn grab(&mut self) -> io::Result<()> {
595 if !self.grabbed {
596 unsafe {
597 sys::eviocgrab(self.as_raw_fd(), 1)?;
598 }
599 self.grabbed = true;
600 }
601 Ok(())
602 }
603
604 pub fn ungrab(&mut self) -> io::Result<()> {
605 if self.grabbed {
606 unsafe {
607 sys::eviocgrab(self.as_raw_fd(), 0)?;
608 }
609 self.grabbed = false;
610 }
611 Ok(())
612 }
613}
614
615impl AsRawFd for RawDevice {
616 fn as_raw_fd(&self) -> RawFd {
617 self.file.as_raw_fd()
618 }
619}
620
621#[inline]
623fn vec_spare_capacity_mut<T>(v: &mut Vec<T>) -> &mut [mem::MaybeUninit<T>] {
624 let (len, cap) = (v.len(), v.capacity());
625 unsafe {
626 std::slice::from_raw_parts_mut(
627 v.as_mut_ptr().add(len) as *mut mem::MaybeUninit<T>,
628 cap - len,
629 )
630 }
631}
632
633pub fn enumerate() -> EnumerateDevices {
638 EnumerateDevices {
639 readdir: std::fs::read_dir("/dev/input").ok(),
640 }
641}
642
643pub struct EnumerateDevices {
644 readdir: Option<std::fs::ReadDir>,
645}
646impl Iterator for EnumerateDevices {
647 type Item = RawDevice;
648 fn next(&mut self) -> Option<RawDevice> {
649 use std::os::unix::ffi::OsStrExt;
650 let readdir = self.readdir.as_mut()?;
651 loop {
652 if let Ok(entry) = readdir.next()? {
653 let path = entry.path();
654 let fname = path.file_name().unwrap();
655 if fname.as_bytes().starts_with(b"event") {
656 if let Ok(dev) = RawDevice::open(&path) {
657 return Some(dev);
658 }
659 }
660 }
661 }
662 }
663}
664
665#[cfg(feature = "tokio")]
666mod tokio_stream {
667 use super::*;
668
669 use tokio_1 as tokio;
670
671 use futures_core::{ready, Stream};
672 use std::pin::Pin;
673 use std::task::{Context, Poll};
674 use tokio::io::unix::AsyncFd;
675
676 pub struct EventStream {
683 device: AsyncFd<RawDevice>,
684 index: usize,
685 }
686 impl Unpin for EventStream {}
687
688 impl EventStream {
689 pub(crate) fn new(device: RawDevice) -> io::Result<Self> {
690 use nix::fcntl;
691 fcntl::fcntl(device.as_raw_fd(), fcntl::F_SETFL(fcntl::OFlag::O_NONBLOCK))?;
692 let device = AsyncFd::new(device)?;
693 Ok(Self { device, index: 0 })
694 }
695
696 pub fn device(&self) -> &RawDevice {
698 self.device.get_ref()
699 }
700
701 pub async fn next_event(&mut self) -> io::Result<InputEvent> {
704 poll_fn(|cx| self.poll_event(cx)).await
705 }
706
707 pub fn poll_event(&mut self, cx: &mut Context<'_>) -> Poll<io::Result<InputEvent>> {
709 'outer: loop {
710 if let Some(&ev) = self.device.get_ref().event_buf.get(self.index) {
711 self.index += 1;
712 return Poll::Ready(Ok(InputEvent(ev)));
713 }
714
715 self.device.get_mut().event_buf.clear();
716 self.index = 0;
717
718 loop {
719 let mut guard = ready!(self.device.poll_read_ready_mut(cx))?;
720
721 let res = guard.try_io(|device| device.get_mut().fill_events());
722 match res {
723 Ok(res) => {
724 let _ = res?;
725 continue 'outer;
726 }
727 Err(_would_block) => continue,
728 }
729 }
730 }
731 }
732 }
733
734 impl Stream for EventStream {
735 type Item = io::Result<InputEvent>;
736 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
737 self.get_mut().poll_event(cx).map(Some)
738 }
739 }
740
741 pub(crate) fn poll_fn<T, F: FnMut(&mut Context<'_>) -> Poll<T> + Unpin>(f: F) -> PollFn<F> {
743 PollFn(f)
744 }
745 pub(crate) struct PollFn<F>(F);
746 impl<T, F: FnMut(&mut Context<'_>) -> Poll<T> + Unpin> std::future::Future for PollFn<F> {
747 type Output = T;
748 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
749 (self.get_mut().0)(cx)
750 }
751 }
752}
753#[cfg(feature = "tokio")]
754pub(crate) use tokio_stream::poll_fn;
755#[cfg(feature = "tokio")]
756pub use tokio_stream::EventStream;