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