1use crate::{device::DeviceWrapper, InputEvent};
2use libc::c_int;
3use std::io;
4use std::os::unix::io::RawFd;
5
6use crate::util::*;
7
8use evdev_sys as raw;
9
10pub struct UInputDevice {
12 raw: *mut raw::libevdev_uinput,
13}
14
15unsafe impl Sync for UInputDevice {}
16unsafe impl Send for UInputDevice {}
17
18impl UInputDevice {
19 fn raw(&self) -> *mut raw::libevdev_uinput {
20 self.raw
21 }
22
23 pub fn create_from_device<T: DeviceWrapper>(device: &T) -> io::Result<UInputDevice> {
28 let mut libevdev_uinput = std::ptr::null_mut();
29 let result = unsafe {
30 raw::libevdev_uinput_create_from_device(
31 device.raw(),
32 raw::LIBEVDEV_UINPUT_OPEN_MANAGED,
33 &mut libevdev_uinput,
34 )
35 };
36
37 match result {
38 0 => Ok(UInputDevice {
39 raw: libevdev_uinput,
40 }),
41 error => Err(io::Error::from_raw_os_error(-error)),
42 }
43 }
44
45 pub fn devnode(&self) -> Option<&str> {
49 unsafe { ptr_to_str(raw::libevdev_uinput_get_devnode(self.raw())) }
50 }
51
52 pub fn syspath(&self) -> Option<&str> {
61 unsafe { ptr_to_str(raw::libevdev_uinput_get_syspath(self.raw())) }
62 }
63
64 pub fn as_fd(&self) -> Option<RawFd> {
70 match unsafe { raw::libevdev_uinput_get_fd(self.raw()) } {
71 0 => None,
72 result => Some(result),
73 }
74 }
75
76 #[deprecated(
77 since = "0.5.0",
78 note = "Prefer `as_fd`. Some function names were changed so they
79 more closely match their type signature. See issue 42 for discussion
80 https://github.com/ndesh26/evdev-rs/issues/42"
81 )]
82 pub fn fd(&self) -> Option<RawFd> {
83 self.as_fd()
84 }
85
86 pub fn write_event(&self, event: &InputEvent) -> io::Result<()> {
92 let (ev_type, ev_code) = event_code_to_int(&event.event_code);
93 let ev_value = event.value as c_int;
94
95 let result = unsafe {
96 raw::libevdev_uinput_write_event(self.raw(), ev_type, ev_code, ev_value)
97 };
98
99 match result {
100 0 => Ok(()),
101 error => Err(io::Error::from_raw_os_error(-error)),
102 }
103 }
104}
105
106impl Drop for UInputDevice {
107 fn drop(&mut self) {
108 unsafe {
109 raw::libevdev_uinput_destroy(self.raw());
110 }
111 }
112}
113
114impl std::fmt::Debug for UInputDevice {
115 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
116 f.debug_struct("UInputDevice")
117 .field("devnode", &self.devnode())
118 .finish()
119 }
120}