1 //! This library provides access to Linux uinput.
2 
3 use libc;
4 use nix;
5 use std::ffi::CString;
6 use std::mem;
7 use std::slice;
8 
9 // Supported AVRCP Keys
10 const AVC_PLAY: u8 = 0x44;
11 const AVC_STOP: u8 = 0x45;
12 const AVC_PAUSE: u8 = 0x46;
13 const AVC_REWIND: u8 = 0x48;
14 const AVC_FAST_FORWAED: u8 = 0x49;
15 const AVC_FORWARD: u8 = 0x4B;
16 const AVC_BACKWARD: u8 = 0x4C;
17 
18 // Supported uinput keys
19 const KEY_NEXTSONG: libc::c_uint = 163;
20 const KEY_PREVIOUSSONG: libc::c_uint = 165;
21 const KEY_STOPCD: libc::c_uint = 166;
22 const KEY_REWIND: libc::c_uint = 168;
23 const KEY_PLAYCD: libc::c_uint = 200;
24 const KEY_PAUSECD: libc::c_uint = 201;
25 const KEY_FASTFORWAED: libc::c_uint = 208;
26 
27 // uinput setup constants
28 const UINPUT_MAX_NAME_SIZE: usize = 80;
29 const UINPUT_SUFFIX: &str = " (AVRCP)";
30 const UINPUT_SUFFIX_SIZE: usize = UINPUT_SUFFIX.len();
31 const ABS_MAX: usize = 0x3F;
32 const BUS_BLUETOOTH: u16 = 0x05;
33 const UINPUT_IOCTL_BASE: libc::c_char = 'U' as libc::c_char;
34 
35 const EV_SYN: libc::c_int = 0x00;
36 const EV_KEY: libc::c_int = 0x01;
37 const EV_REL: libc::c_int = 0x02;
38 const EV_REP: libc::c_int = 0x14;
39 
40 const SYN_REPORT: libc::c_int = 0;
41 
42 const UI_DEV_CREATE: libc::c_ulong = nix::request_code_none!(UINPUT_IOCTL_BASE, 1);
43 const UI_DEV_DESTROY: libc::c_ulong = nix::request_code_none!(UINPUT_IOCTL_BASE, 2);
44 const UI_SET_EVBIT: libc::c_ulong =
45     nix::request_code_write!(UINPUT_IOCTL_BASE, 100, mem::size_of::<libc::c_int>());
46 const UI_SET_PHYS: libc::c_ulong =
47     nix::request_code_write!(UINPUT_IOCTL_BASE, 108, mem::size_of::<libc::c_char>());
48 const UI_SET_KEYBIT: libc::c_ulong =
49     nix::request_code_write!(UINPUT_IOCTL_BASE, 101, mem::size_of::<libc::c_int>());
50 
51 // Conversion key map from AVRCP keys to uinput keys.
52 #[allow(dead_code)]
53 struct KeyMap {
54     avc: u8,
55     uinput: libc::c_uint,
56 }
57 
58 const KEY_MAP: [KeyMap; 7] = [
59     KeyMap { avc: AVC_PLAY, uinput: KEY_PLAYCD },
60     KeyMap { avc: AVC_STOP, uinput: KEY_STOPCD },
61     KeyMap { avc: AVC_PAUSE, uinput: KEY_PAUSECD },
62     KeyMap { avc: AVC_REWIND, uinput: KEY_REWIND },
63     KeyMap { avc: AVC_FAST_FORWAED, uinput: KEY_FASTFORWAED },
64     KeyMap { avc: AVC_FORWARD, uinput: KEY_NEXTSONG },
65     KeyMap { avc: AVC_BACKWARD, uinput: KEY_PREVIOUSSONG },
66 ];
67 
68 #[repr(C, packed)]
69 struct UInputId {
70     bustype: libc::c_ushort,
71     vendor: libc::c_ushort,
72     product: libc::c_ushort,
73     version: libc::c_ushort,
74 }
75 
76 impl Default for UInputId {
default() -> Self77     fn default() -> Self {
78         UInputId { bustype: BUS_BLUETOOTH, vendor: 0, product: 0, version: 0 }
79     }
80 }
81 
82 #[repr(C, packed)]
83 struct UInputDevInfo {
84     name: [libc::c_char; UINPUT_MAX_NAME_SIZE],
85     id: UInputId,
86     ff_effects_max: libc::c_int,
87     absmax: [libc::c_int; ABS_MAX + 1],
88     absmin: [libc::c_int; ABS_MAX + 1],
89     absfuzz: [libc::c_int; ABS_MAX + 1],
90     absflat: [libc::c_int; ABS_MAX + 1],
91 }
92 
93 impl Default for UInputDevInfo {
default() -> Self94     fn default() -> Self {
95         UInputDevInfo {
96             name: [0; UINPUT_MAX_NAME_SIZE],
97             id: UInputId::default(),
98             ff_effects_max: 0,
99             absmax: [0; ABS_MAX + 1],
100             absmin: [0; ABS_MAX + 1],
101             absfuzz: [0; ABS_MAX + 1],
102             absflat: [0; ABS_MAX + 1],
103         }
104     }
105 }
106 
107 impl UInputDevInfo {
serialize(&mut self) -> &[u8]108     pub fn serialize(&mut self) -> &[u8] {
109         unsafe {
110             slice::from_raw_parts(
111                 (self as *const UInputDevInfo) as *const u8,
112                 mem::size_of::<UInputDevInfo>(),
113             )
114         }
115     }
116 }
117 
118 #[repr(C, packed)]
119 struct UInputEvent {
120     time: libc::timeval,
121     event_type: libc::c_ushort,
122     code: libc::c_ushort,
123     value: libc::c_int,
124 }
125 
126 impl UInputEvent {
serialize(&mut self) -> &[u8]127     pub fn serialize(&mut self) -> &[u8] {
128         unsafe {
129             slice::from_raw_parts(
130                 (self as *const UInputEvent) as *const u8,
131                 mem::size_of::<UInputEvent>(),
132             )
133         }
134     }
135 }
136 
137 struct UInputDev {
138     fd: i32,
139     addr: String,
140     device: UInputDevInfo,
141 }
142 
143 impl Default for UInputDev {
default() -> Self144     fn default() -> Self {
145         UInputDev {
146             fd: -1,
147             addr: String::from("00:00:00:00:00:00"),
148             device: UInputDevInfo::default(),
149         }
150     }
151 }
152 
153 impl Drop for UInputDev {
drop(&mut self)154     fn drop(&mut self) {
155         self.close();
156     }
157 }
158 
159 impl UInputDev {
160     #[allow(temporary_cstring_as_ptr)]
init(&mut self, mut name: String, addr: String) -> Result<(), String>161     fn init(&mut self, mut name: String, addr: String) -> Result<(), String> {
162         // Truncate the device name if over the max size allowed.
163         name.truncate(UINPUT_MAX_NAME_SIZE - UINPUT_SUFFIX_SIZE);
164         name.push_str(UINPUT_SUFFIX);
165         for (i, ch) in name.chars().enumerate() {
166             self.device.name[i] = ch as libc::c_char;
167         }
168 
169         let mut fd = -1;
170 
171         unsafe {
172             for path in ["/dev/uinput", "/dev/input/uinput", "/dev/misc/uinput"] {
173                 fd = libc::open(CString::new(path).unwrap().as_ptr().cast(), libc::O_RDWR);
174                 if fd >= 0 {
175                     break;
176                 }
177             }
178 
179             if fd < -1 {
180                 return Err(format!(
181                     "Failed to open uinput for {}: {}",
182                     addr,
183                     std::io::Error::last_os_error()
184                 ));
185             }
186 
187             if libc::write(
188                 fd,
189                 self.device.serialize().as_ptr() as *const libc::c_void,
190                 mem::size_of::<UInputDevInfo>(),
191             ) < 0
192             {
193                 libc::close(fd);
194                 return Err(format!(
195                     "Can't write device information for {}: {}",
196                     addr,
197                     std::io::Error::last_os_error()
198                 ));
199             }
200 
201             libc::ioctl(fd, UI_SET_EVBIT, EV_KEY);
202             libc::ioctl(fd, UI_SET_EVBIT, EV_REL);
203             libc::ioctl(fd, UI_SET_EVBIT, EV_REP);
204             libc::ioctl(fd, UI_SET_EVBIT, EV_SYN);
205             libc::ioctl(fd, UI_SET_PHYS, addr.clone());
206 
207             for key_map in KEY_MAP {
208                 libc::ioctl(fd, UI_SET_KEYBIT, key_map.uinput);
209             }
210 
211             if libc::ioctl(fd, UI_DEV_CREATE, 0) < 0 {
212                 libc::close(fd);
213                 return Err(format!(
214                     "Can't create uinput device for {}: {}",
215                     addr,
216                     std::io::Error::last_os_error()
217                 ));
218             }
219         }
220 
221         self.fd = fd;
222         self.addr = addr;
223         Ok(())
224     }
225 
close(&mut self)226     fn close(&mut self) {
227         unsafe {
228             libc::ioctl(self.fd, UI_DEV_DESTROY, 0);
229             libc::close(self.fd);
230         }
231     }
232 
send_event( &mut self, event_type: libc::c_ushort, code: libc::c_ushort, value: libc::c_int, ) -> i32233     fn send_event(
234         &mut self,
235         event_type: libc::c_ushort,
236         code: libc::c_ushort,
237         value: libc::c_int,
238     ) -> i32 {
239         let mut event = UInputEvent {
240             time: libc::timeval { tv_sec: 0, tv_usec: 0 },
241             event_type: event_type,
242             code: code,
243             value: value,
244         };
245 
246         unsafe {
247             libc::write(
248                 self.fd,
249                 event.serialize().as_ptr() as *const libc::c_void,
250                 mem::size_of::<UInputDevInfo>(),
251             )
252             .try_into()
253             .unwrap()
254         }
255     }
256 
send_key(&mut self, key: u8, value: u8) -> Result<(), String>257     fn send_key(&mut self, key: u8, value: u8) -> Result<(), String> {
258         let mut uinput_key: libc::c_ushort = 0;
259 
260         for key_map in KEY_MAP {
261             if key_map.avc == key {
262                 uinput_key = key_map.uinput.try_into().unwrap();
263             }
264         }
265 
266         if uinput_key == 0 {
267             return Err(format!("AVRCP key: {} is not supported for device: {}", key, self.addr));
268         }
269 
270         if self.send_event(EV_KEY.try_into().unwrap(), uinput_key, value.into()) < 0
271             || self.send_event(EV_SYN.try_into().unwrap(), SYN_REPORT.try_into().unwrap(), 0) < 0
272         {
273             return Err(format!(
274                 "Failed to send uinput event: {} for device: {}",
275                 std::io::Error::last_os_error(),
276                 self.addr
277             ));
278         }
279         Ok(())
280     }
281 }
282 
283 pub struct UInput {
284     /// A vector that holds uinput objects.
285     devices: Vec<UInputDev>,
286     /// The address of current active device.
287     active_device: String,
288 }
289 
290 impl Drop for UInput {
drop(&mut self)291     fn drop(&mut self) {
292         for device in self.devices.iter_mut() {
293             device.close();
294         }
295     }
296 }
297 
298 impl UInput {
get_device(&mut self, addr: String) -> Option<&mut UInputDev>299     fn get_device(&mut self, addr: String) -> Option<&mut UInputDev> {
300         for device in self.devices.iter_mut() {
301             if device.addr == addr {
302                 return Some(device);
303             }
304         }
305         None
306     }
307 
308     /// Create a new UInput struct that holds a vector of uinput objects.
new() -> Self309     pub fn new() -> Self {
310         UInput {
311             devices: Vec::<UInputDev>::new(),
312             active_device: String::from("00:00:00:00:00:00"),
313         }
314     }
315 
316     /// Initialize a uinput device with kernel.
create(&mut self, name: String, addr: String) -> Result<(), String>317     pub fn create(&mut self, name: String, addr: String) -> Result<(), String> {
318         if self.get_device(addr.clone()).is_some() {
319             return Ok(());
320         }
321 
322         let mut device = UInputDev::default();
323         match device.init(name, addr) {
324             Ok(()) => {
325                 self.devices.push(device);
326                 Ok(())
327             }
328             Err(e) => Err(e),
329         }
330     }
331 
332     /// Close the specified uinput device with kernel if created.
close(&mut self, addr: String)333     pub fn close(&mut self, addr: String) {
334         if addr == self.active_device {
335             self.active_device = String::from("00:00:00:00:00:00");
336         }
337 
338         // Remove the device from the list. uinput will get closed with the kernel through device
339         // Drop trait.
340         if let Some(pos) = self.devices.iter().position(|device| device.addr == addr) {
341             self.devices.remove(pos);
342         }
343     }
344 
345     /// Set a device to be AVRCP active.
set_active_device(&mut self, addr: String)346     pub fn set_active_device(&mut self, addr: String) {
347         self.active_device = addr;
348     }
349 
350     /// Send key event to the active uinput.
send_key(&mut self, key: u8, value: u8) -> Result<(), String>351     pub fn send_key(&mut self, key: u8, value: u8) -> Result<(), String> {
352         match self.active_device.as_str() {
353             "00:00:00:00:00:00" => Err(format!("Active device is not specified")),
354             _ => match self.get_device(self.active_device.clone()) {
355                 Some(device) => device.send_key(key, value),
356                 None => Err(format!("uinput: {} is not initialized", self.active_device)),
357             },
358         }
359     }
360 }
361