use uinput_sys;
use uinput_sys::uinput_user_dev;
use crate::keys::KeyCode;
use crate::keys::KeyValue;
use evdev_rs::enums::EventCode;
use evdev_rs::enums::EV_SYN;
use evdev_rs::InputEvent;
use evdev_rs::TimeVal;
use libc::input_event as raw_event;
use io::Write;
use std::fs::File;
use std::fs::OpenOptions;
use std::io;
use std::os::unix::io::AsRawFd;
use std::mem;
use std::slice;
use crate::keys::KeyEvent;
pub struct KbdOut {
device: File,
}
impl KbdOut {
pub fn new() -> Result<Self, io::Error> {
let mut uinput_out_file = OpenOptions::new()
.read(true)
.write(true)
.open("/dev/uinput")?;
unsafe {
uinput_sys::ui_set_evbit(uinput_out_file.as_raw_fd(), uinput_sys::EV_SYN);
uinput_sys::ui_set_evbit(uinput_out_file.as_raw_fd(), uinput_sys::EV_KEY);
for key in 0..uinput_sys::KEY_MAX {
uinput_sys::ui_set_keybit(uinput_out_file.as_raw_fd(), key);
}
let mut uidev: uinput_user_dev = mem::zeroed();
uidev.name[0] = 'k' as i8;
uidev.name[1] = 't' as i8;
uidev.name[2] = 'r' as i8;
uidev.name[3] = 'l' as i8;
uidev.id.bustype = 0x3; uidev.id.vendor = 0x1;
uidev.id.product = 0x1;
uidev.id.version = 1;
let uidev_bytes =
slice::from_raw_parts(mem::transmute(&uidev), mem::size_of::<uinput_user_dev>());
uinput_out_file.write(uidev_bytes)?;
uinput_sys::ui_dev_create(uinput_out_file.as_raw_fd());
}
Ok(KbdOut {
device: uinput_out_file,
})
}
pub fn write(&mut self, event: InputEvent) -> Result<(), io::Error> {
let ev = event.as_raw();
unsafe {
let ev_bytes = slice::from_raw_parts(
mem::transmute(&ev as *const raw_event),
mem::size_of::<raw_event>(),
);
self.device.write(ev_bytes)?;
};
Ok(())
}
pub fn write_key(&mut self, key: KeyCode, value: KeyValue) -> Result<(), io::Error> {
let key_ev = KeyEvent::new(key, value);
self.write(key_ev.into())?;
let sync = InputEvent::new(
&TimeVal {
tv_sec: 0,
tv_usec: 0,
},
&EventCode::EV_SYN(EV_SYN::SYN_REPORT),
0,
);
self.write(sync.into())?;
Ok(())
}
pub fn press_key(&mut self, key: KeyCode) -> Result<(), io::Error> {
self.write_key(key, KeyValue::Press)
}
pub fn release_key(&mut self, key: KeyCode) -> Result<(), io::Error> {
self.write_key(key, KeyValue::Release)
}
}