From 779947195abbcf2cf95f2eaed8e5be35fa11ef1c Mon Sep 17 00:00:00 2001 From: siikamiika Date: Tue, 13 Nov 2018 19:54:41 +0200 Subject: [PATCH] select devices from args --- src/input_thread.rs | 68 +++++++++++++++++++++++++++ src/main.rs | 112 +++++++++++++++++--------------------------- 2 files changed, 112 insertions(+), 68 deletions(-) create mode 100644 src/input_thread.rs diff --git a/src/input_thread.rs b/src/input_thread.rs new file mode 100644 index 0000000..ccc6430 --- /dev/null +++ b/src/input_thread.rs @@ -0,0 +1,68 @@ +use std::thread; +use std::time::Duration; + +use evdev_rs::util::event_code_to_int; + +use crossbeam::crossbeam_channel::{unbounded, Select, Receiver, Sender}; + +use super::event::ThreadInputEvent; +use super::hw_device; + +pub fn create_evdev_thread(device_path: &str) -> (String, Receiver, Sender) { + // send out input events, receive stop command + let (send_event_channel, recv_event_channel) = unbounded(); + let (send_stop_channel, recv_stop_channel) = unbounded(); + + // thread safety and stuff + let device_path = String::from(device_path); + let return_device_path = device_path.clone(); + + thread::spawn(move || { + // open device + let mut dev = hw_device::HwDevice::new(&device_path); + // wait for device init + thread::sleep(Duration::from_secs(1)); + // don't deliver events elsewhere + dev.device.grab(evdev_rs::GrabMode::Grab).unwrap(); + // sleep for testing purposes + thread::sleep(Duration::from_secs(1)); + + loop { + // check for stop requests + let mut sel = Select::new(); + // create stop channel receive operation + let oper1 = sel.recv(&recv_stop_channel); + // try to select from stop channel + let oper = sel.try_select(); + match oper { + // no stop requests + Err(_) => (), + // stop request received, break out of the loop + Ok(oper) => match oper.index() { + i if i == oper1 => { + assert_eq!(oper.recv(&recv_stop_channel), Ok(true)); + break; + }, + // shouldn't happen + _ => (), + }, + } + + // read next input event + let event = dev.device.next_event(evdev_rs::NORMAL | evdev_rs::BLOCKING); + match event { + // send input event to event channel + Ok(e) => send_event_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(_) => (), + } + } + }); + + (return_device_path, recv_event_channel, send_stop_channel) +} diff --git a/src/main.rs b/src/main.rs index 111b139..151cb4d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,31 +1,39 @@ extern crate uinput; extern crate evdev_rs; -#[macro_use] extern crate crossbeam; -use std::thread; +use std::env::args; use std::time::Duration; +use std::collections::HashMap; -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; +use crossbeam::crossbeam_channel:: Select; mod virtual_mouse; mod virtual_kbd; mod hw_device; mod event; +mod input_thread; -use self::event::ThreadInputEvent; +use self::input_thread::create_evdev_thread; 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 args: Vec<_> = args().collect(); - let kbd_receiver = create_evdev_thread(kbd_path); - let mouse_receiver = create_evdev_thread(mouse_path); + // (path, receiver, stopper) + let mut devices = Vec::new(); + // let mut disabled_devices = Vec::new(); + + for device_path in &args[1..] { + devices.push(create_evdev_thread(&device_path)); + } + + // testing device removal + // thread::sleep(Duration::from_secs(1)); + // devices[1].2.send(true).unwrap(); + // disabled_devices.push(devices.remove(1)); // init virtual devices let mut virt_kbd = virtual_kbd::VirtualKeyboard::new("test-kbd"); @@ -33,66 +41,34 @@ fn main() { // 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(); - } - } - _ => (), + // init select + let mut sel = Select::new(); + + // create device input event receive operations and map them to devices + let mut device_idx_by_oper = HashMap::new(); + for (i, (_, receiver, _)) in devices.iter().enumerate() { + let o = sel.recv(&receiver); + device_idx_by_oper.insert(o, i); + } + + // select from available device(s) + let oper = sel.select(); + + // read from selected device + let index = oper.index(); + match oper.recv(&devices[device_idx_by_oper[&index]].1) { + Ok(e) => { + // mouse event + 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(); + // keyboard event + } 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(); } }, + _ => (), } } } - -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 -}