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