extern crate uinput; extern crate evdev_rs; #[macro_use] extern crate crossbeam; use std::thread; use std::time::Duration; use evdev_rs::util::event_code_to_int; use evdev_rs::enums::EventType::{EV_KEY, EV_REL}; use crossbeam::crossbeam_channel::unbounded; use crossbeam::crossbeam_channel::Receiver; mod virtual_mouse; mod virtual_kbd; mod hw_device; mod event; use self::event::ThreadInputEvent; fn main() { let kbd_path = "/dev/input/by-id/usb-04d9_USB_Keyboard-event-kbd"; let mouse_path = "/dev/input/by-id/usb-Kingsis_Peripherals_ZOWIE_Gaming_mouse-event-mouse"; let kbd_receiver = create_evdev_thread(kbd_path); let mouse_receiver = create_evdev_thread(mouse_path); // init virtual devices let mut virt_kbd = virtual_kbd::VirtualKeyboard::new("test-kbd"); let mut virt_mouse = virtual_mouse::VirtualMouse::new("test-mouse"); // read events and feed them to the virtual devices loop { // TODO: use Select struct // https://docs.rs/crossbeam/0.5.0/crossbeam/channel/struct.Select.html select! { recv(kbd_receiver) -> msg => { match msg { Ok(e) => { if e.typ == EV_KEY as u32 && e.code == 1 { // quit on esc break; } else if e.typ == EV_KEY as u32 { virt_kbd.device.write(e.typ as i32, e.code as i32, e.value).unwrap(); virt_kbd.device.synchronize().unwrap(); } } _ => (), } }, recv(mouse_receiver) -> msg => { match msg { Ok(e) => { if e.typ == EV_REL as u32 || (e.code >= 272 && e.code <= 276) { virt_mouse.device.write(e.typ as i32, e.code as i32, e.value).unwrap(); virt_mouse.device.synchronize().unwrap(); } } _ => (), } }, } } } fn create_evdev_thread(device_path: &str) -> Receiver { let (send_channel, recv_channel) = unbounded(); // whatever let device_path = String::from(device_path); thread::spawn(move || { // open device let mut dev = hw_device::HwDevice::new(&device_path); // wait for device init thread::sleep(Duration::from_millis(200)); // don't deliver events elsewhere dev.device.grab(evdev_rs::GrabMode::Grab).unwrap(); // read events and put them to queue loop { let event = dev.device.next_event(evdev_rs::NORMAL | evdev_rs::BLOCKING); match event { Ok(e) => send_channel.send( ThreadInputEvent { typ: e.1.event_type as u32, code: event_code_to_int(&e.1.event_code).1, value: e.1.value, } ).unwrap(), Err(_) => (), } } }); recv_channel }