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