1use 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 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#[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 supported_snd: Option<AttributeSet<SoundCode>>,
86 pub(crate) event_buf: Vec<input_event>,
87 grabbed: bool,
88}
89
90impl RawDevice {
91 #[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 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 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 }; 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 pub fn name(&self) -> Option<&str> {
262 self.name.as_deref()
263 }
264
265 pub fn physical_path(&self) -> Option<&str> {
267 self.phys.as_deref()
268 }
269
270 pub fn unique_name(&self) -> Option<&str> {
272 self.uniq.as_deref()
273 }
274
275 pub fn input_id(&self) -> InputId {
277 InputId::from(self.id)
278 }
279
280 pub fn get_auto_repeat(&self) -> Option<AutoRepeat> {
282 self.auto_repeat.clone()
283 }
284
285 pub fn properties(&self) -> &AttributeSetRef<PropType> {
287 &self.props
288 }
289
290 pub fn driver_version(&self) -> (u8, u8, u8) {
292 self.driver_version
293 }
294
295 pub fn supported_events(&self) -> &AttributeSetRef<EventType> {
300 &self.ty
301 }
302
303 pub fn supported_keys(&self) -> Option<&AttributeSetRef<KeyCode>> {
321 self.supported_keys.as_deref()
322 }
323
324 pub fn supported_relative_axes(&self) -> Option<&AttributeSetRef<RelativeAxisCode>> {
343 self.supported_relative.as_deref()
344 }
345
346 pub fn supported_absolute_axes(&self) -> Option<&AttributeSetRef<AbsoluteAxisCode>> {
365 self.supported_absolute.as_deref()
366 }
367
368 pub fn supported_switches(&self) -> Option<&AttributeSetRef<SwitchCode>> {
389 self.supported_switch.as_deref()
390 }
391
392 pub fn supported_leds(&self) -> Option<&AttributeSetRef<LedCode>> {
397 self.supported_led.as_deref()
398 }
399
400 pub fn misc_properties(&self) -> Option<&AttributeSetRef<MiscCode>> {
404 self.supported_misc.as_deref()
405 }
406
407 pub fn supported_ff(&self) -> Option<&AttributeSetRef<FFEffectCode>> {
409 self.supported_ff.as_deref()
410 }
411
412 pub fn max_ff_effects(&self) -> usize {
414 self.max_ff_effects
415 }
416
417 pub fn supported_sounds(&self) -> Option<&AttributeSetRef<SoundCode>> {
422 self.supported_snd.as_deref()
423 }
424
425 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 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 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 #[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 #[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 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 #[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 #[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 #[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 #[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 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 #[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 #[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 #[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 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 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 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 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 pub fn is_grabbed(&self) -> bool {
667 self.grabbed
668 }
669
670 pub fn send_events(&mut self, events: &[InputEvent]) -> io::Result<()> {
677 crate::write_events(self.fd.as_fd(), events)?;
678 Ok(())
679 }
680
681 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 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 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
732pub fn enumerate() -> EnumerateDevices {
737 EnumerateDevices {
738 readdir: std::fs::read_dir("/dev/input").ok(),
739 }
740}
741
742pub 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 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 pub fn device(&self) -> &RawDevice {
795 self.device.get_ref()
796 }
797
798 pub fn device_mut(&mut self) -> &mut RawDevice {
800 self.device.get_mut()
801 }
802
803 pub async fn next_event(&mut self) -> io::Result<InputEvent> {
806 poll_fn(|cx| self.poll_event(cx)).await
807 }
808
809 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;