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(&self) -> &[u8]108     pub fn serialize(&self) -> &[u8] {
109         unsafe { slice::from_raw_parts((self as *const Self) as *const u8, mem::size_of::<Self>()) }
110     }
111 }
112 
113 #[repr(C, packed)]
114 struct UInputEvent {
115     time: libc::timeval,
116     event_type: libc::c_ushort,
117     code: libc::c_ushort,
118     value: libc::c_int,
119 }
120 
121 impl UInputEvent {
serialize(&self) -> &[u8]122     pub fn serialize(&self) -> &[u8] {
123         unsafe { slice::from_raw_parts((self as *const Self) as *const u8, mem::size_of::<Self>()) }
124     }
125 }
126 
127 struct UInputDev {
128     fd: i32,
129     addr: String,
130     device: UInputDevInfo,
131 }
132 
133 impl Default for UInputDev {
default() -> Self134     fn default() -> Self {
135         UInputDev {
136             fd: -1,
137             addr: String::from("00:00:00:00:00:00"),
138             device: UInputDevInfo::default(),
139         }
140     }
141 }
142 
143 impl Drop for UInputDev {
drop(&mut self)144     fn drop(&mut self) {
145         self.close();
146     }
147 }
148 
149 impl UInputDev {
floor_char_boundary(str: &String, upper_bound: usize) -> usize150     fn floor_char_boundary(str: &String, upper_bound: usize) -> usize {
151         // Some string operation can only be done at UTF8 boundary, e.g. truncate.
152         // It is guaranteed that there would be at least one such boundary in every 4 bytes,
153         // therefore we can just brute force it.
154         // This can be replaced with str::floor_char_boundary() once that function is available.
155         if str.len() < upper_bound {
156             return str.len();
157         }
158 
159         for i in (0..upper_bound + 1).rev() {
160             if str.is_char_boundary(i) {
161                 return i;
162             }
163         }
164         return 0;
165     }
166 
167     #[allow(temporary_cstring_as_ptr)]
init(&mut self, mut name: String, addr: String) -> Result<(), String>168     fn init(&mut self, mut name: String, addr: String) -> Result<(), String> {
169         // Truncate the device name if over the max size allowed.
170         let new_len = Self::floor_char_boundary(&name, UINPUT_MAX_NAME_SIZE - UINPUT_SUFFIX_SIZE);
171         name.truncate(new_len);
172         name.push_str(UINPUT_SUFFIX);
173         for (i, ch) in name.chars().enumerate() {
174             self.device.name[i] = ch as libc::c_char;
175         }
176 
177         let mut fd = -1;
178 
179         unsafe {
180             for path in ["/dev/uinput", "/dev/input/uinput", "/dev/misc/uinput"] {
181                 fd = libc::open(CString::new(path).unwrap().as_ptr().cast(), libc::O_RDWR);
182                 if fd >= 0 {
183                     break;
184                 }
185             }
186 
187             if fd < -1 {
188                 return Err(format!(
189                     "Failed to open uinput for {}: {}",
190                     addr,
191                     std::io::Error::last_os_error()
192                 ));
193             }
194 
195             let device_serialized = self.device.serialize();
196             if libc::write(
197                 fd,
198                 device_serialized.as_ptr() as *const libc::c_void,
199                 device_serialized.len(),
200             ) < 0
201             {
202                 libc::close(fd);
203                 return Err(format!(
204                     "Can't write device information for {}: {}",
205                     addr,
206                     std::io::Error::last_os_error()
207                 ));
208             }
209 
210             libc::ioctl(fd, UI_SET_EVBIT, EV_KEY);
211             libc::ioctl(fd, UI_SET_EVBIT, EV_REL);
212             libc::ioctl(fd, UI_SET_EVBIT, EV_REP);
213             libc::ioctl(fd, UI_SET_EVBIT, EV_SYN);
214             libc::ioctl(fd, UI_SET_PHYS, addr.clone());
215 
216             for key_map in KEY_MAP {
217                 libc::ioctl(fd, UI_SET_KEYBIT, key_map.uinput);
218             }
219 
220             if libc::ioctl(fd, UI_DEV_CREATE, 0) < 0 {
221                 libc::close(fd);
222                 return Err(format!(
223                     "Can't create uinput device for {}: {}",
224                     addr,
225                     std::io::Error::last_os_error()
226                 ));
227             }
228         }
229 
230         self.fd = fd;
231         self.addr = addr;
232         Ok(())
233     }
234 
close(&mut self)235     fn close(&mut self) {
236         unsafe {
237             libc::ioctl(self.fd, UI_DEV_DESTROY, 0);
238             libc::close(self.fd);
239         }
240     }
241 
send_event( &mut self, event_type: libc::c_ushort, code: libc::c_ushort, value: libc::c_int, ) -> i32242     fn send_event(
243         &mut self,
244         event_type: libc::c_ushort,
245         code: libc::c_ushort,
246         value: libc::c_int,
247     ) -> i32 {
248         let event =
249             UInputEvent { time: libc::timeval { tv_sec: 0, tv_usec: 0 }, event_type, code, value };
250 
251         unsafe {
252             let event_serialized = event.serialize();
253             libc::write(
254                 self.fd,
255                 event_serialized.as_ptr() as *const libc::c_void,
256                 event_serialized.len(),
257             )
258             .try_into()
259             .unwrap()
260         }
261     }
262 
send_key(&mut self, key: u8, value: u8) -> Result<(), String>263     fn send_key(&mut self, key: u8, value: u8) -> Result<(), String> {
264         let mut uinput_key: libc::c_ushort = 0;
265 
266         for key_map in KEY_MAP {
267             if key_map.avc == key {
268                 uinput_key = key_map.uinput.try_into().unwrap();
269             }
270         }
271 
272         if uinput_key == 0 {
273             return Err(format!("AVRCP key: {} is not supported for device: {}", key, self.addr));
274         }
275 
276         if self.send_event(EV_KEY.try_into().unwrap(), uinput_key, value.into()) < 0
277             || self.send_event(EV_SYN.try_into().unwrap(), SYN_REPORT.try_into().unwrap(), 0) < 0
278         {
279             return Err(format!(
280                 "Failed to send uinput event: {} for device: {}",
281                 std::io::Error::last_os_error(),
282                 self.addr
283             ));
284         }
285         Ok(())
286     }
287 }
288 
289 pub struct UInput {
290     /// A vector that holds uinput objects.
291     devices: Vec<UInputDev>,
292     /// The address of current active device.
293     active_device: String,
294 }
295 
296 impl Drop for UInput {
drop(&mut self)297     fn drop(&mut self) {
298         for device in self.devices.iter_mut() {
299             device.close();
300         }
301     }
302 }
303 
304 impl Default for UInput {
default() -> Self305     fn default() -> Self {
306         Self { devices: Vec::<UInputDev>::new(), active_device: String::from("00:00:00:00:00:00") }
307     }
308 }
309 
310 impl UInput {
get_device(&mut self, addr: String) -> Option<&mut UInputDev>311     fn get_device(&mut self, addr: String) -> Option<&mut UInputDev> {
312         for device in self.devices.iter_mut() {
313             if device.addr == addr {
314                 return Some(device);
315             }
316         }
317         None
318     }
319 
320     /// Create a new UInput struct that holds a vector of uinput objects.
new() -> Self321     pub fn new() -> Self {
322         Default::default()
323     }
324 
325     /// Initialize a uinput device with kernel.
create(&mut self, name: String, addr: String) -> Result<(), String>326     pub fn create(&mut self, name: String, addr: String) -> Result<(), String> {
327         if self.get_device(addr.clone()).is_some() {
328             return Ok(());
329         }
330 
331         let mut device = UInputDev::default();
332         match device.init(name, addr) {
333             Ok(()) => {
334                 self.devices.push(device);
335                 Ok(())
336             }
337             Err(e) => Err(e),
338         }
339     }
340 
341     /// Close the specified uinput device with kernel if created.
close(&mut self, addr: String)342     pub fn close(&mut self, addr: String) {
343         if addr == self.active_device {
344             self.active_device = String::from("00:00:00:00:00:00");
345         }
346 
347         // Remove the device from the list. uinput will get closed with the kernel through device
348         // Drop trait.
349         if let Some(pos) = self.devices.iter().position(|device| device.addr == addr) {
350             self.devices.remove(pos);
351         }
352     }
353 
354     /// Set a device to be AVRCP active.
set_active_device(&mut self, addr: String)355     pub fn set_active_device(&mut self, addr: String) {
356         self.active_device = addr;
357     }
358 
359     /// Send key event to the active uinput.
send_key(&mut self, key: u8, value: u8) -> Result<(), String>360     pub fn send_key(&mut self, key: u8, value: u8) -> Result<(), String> {
361         match self.active_device.as_str() {
362             "00:00:00:00:00:00" => Err("Active device is not specified".to_string()),
363             _ => match self.get_device(self.active_device.clone()) {
364                 Some(device) => device.send_key(key, value),
365                 None => Err(format!("uinput: {} is not initialized", self.active_device)),
366             },
367         }
368     }
369 }
370