refactoring

This commit is contained in:
siikamiika 2018-11-14 03:41:32 +02:00
parent a5de77f321
commit f564f0064c
3 changed files with 127 additions and 130 deletions

View File

@ -1,20 +1,127 @@
use std::thread;
use std::fs::File; use std::fs::File;
use std::time::Duration;
use evdev_rs::util::event_code_to_int;
use evdev_rs::enums::EventType::EV_REL;
use crossbeam::crossbeam_channel::{unbounded, Select, Receiver, Sender};
use super::event::ThreadInputEvent;
pub struct HwDevice { pub struct HwDevice {
pub device: evdev_rs::Device, pub path: String,
_file: File, // pub device: evdev_rs::Device,
pub event_channel: Receiver<ThreadInputEvent>,
stop_channel: Sender<bool>,
} }
impl HwDevice { impl HwDevice {
pub fn new(path: &str) -> Self { pub fn new(device_path: &str) -> Self {
let f = File::open(path).unwrap(); // send out input events, receive stop command
let mut d = evdev_rs::Device::new().unwrap(); let (send_event_channel, recv_event_channel) = unbounded();
d.set_fd(&f).unwrap(); let (send_stop_channel, recv_stop_channel) = unbounded();
// thread safety and stuff
let path = String::from(device_path);
let return_device_path = path.clone();
thread::spawn(move || {
// open device
let fd = File::open(path).unwrap();
let mut dev = evdev_rs::Device::new().unwrap();
dev.set_fd(&fd).unwrap();
// wait for device init
thread::sleep(Duration::from_secs(1));
// don't deliver events elsewhere
dev.grab(evdev_rs::GrabMode::Grab).unwrap();
// sleep for testing purposes
thread::sleep(Duration::from_secs(1));
// cache mouse movement before consuming all events
let mut mouse_move = vec![0, 0];
loop {
if stop_requested(&recv_stop_channel) {
break;
}
loop {
let mut event = dev.next_event(evdev_rs::NORMAL | evdev_rs::BLOCKING);
let mut first = true;
// pending events not required for first round
while first || dev.has_event_pending() {
first = false;
match event {
// send input event to event channel
Ok(e) => {
let e = ThreadInputEvent {
typ: e.1.event_type as u32,
code: event_code_to_int(&e.1.event_code).1,
value: e.1.value,
};
// EV_REL, REL_X/REL_Y
if e.typ == 2 && e.code <= 1 {
mouse_move[e.code as usize] += e.value;
} else {
send_event_channel.send(e).unwrap();
}
},
Err(_) => (),
}
// read next input event
event = dev.next_event(evdev_rs::NORMAL | evdev_rs::BLOCKING);
}
// combined mouse event
send_combined_mouse_move(&mut mouse_move, &send_event_channel);
// save cpu by sleeping after consuming all events
thread::sleep(Duration::from_millis(5));
}
}
});
HwDevice { HwDevice {
device: d, path: return_device_path,
// keep fd open event_channel: recv_event_channel,
_file: f, stop_channel: send_stop_channel,
}
}
pub fn stop(&mut self) {
self.stop_channel.send(true).unwrap();
}
}
fn stop_requested(chan: &Receiver<bool>) -> bool {
// check for stop requests
let mut sel = Select::new();
// create stop channel receive operation
let oper1 = sel.recv(&chan);
// try to select from stop channel
let oper = sel.try_select();
match oper {
// no stop requests
Err(_) => false,
// stop request received, break out of the loop
Ok(oper) => match oper.index() {
i if i == oper1 => {
oper.recv(&chan).unwrap()
},
// shouldn't happen
_ => false,
},
}
}
fn send_combined_mouse_move(mouse_move: &mut Vec<i32>, chan: &Sender<ThreadInputEvent>) {
// REL_X..=REL_Y
for code in 0..=1 {
if mouse_move[code] != 0 {
chan.send(ThreadInputEvent {
typ: EV_REL as u32,
code: code as u32,
value: mouse_move[code],
}).unwrap();
mouse_move[code] = 0;
} }
} }
} }

View File

@ -1,108 +0,0 @@
use std::thread;
use std::time::Duration;
use evdev_rs::util::event_code_to_int;
use evdev_rs::enums::EventType::EV_REL;
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<ThreadInputEvent>, Sender<bool>) {
// 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));
// cache mouse movement before consuming all events
let mut mouse_move = vec![0, 0];
loop {
if stop_requested(&recv_stop_channel) {
continue;
}
loop {
// block before starting while loop again
let mut first = true;
let mut event = dev.device.next_event(evdev_rs::NORMAL | evdev_rs::BLOCKING);
// pending events not required for first round
while first || dev.device.has_event_pending() {
first = false;
match event {
// send input event to event channel
Ok(e) => {
let e = ThreadInputEvent {
typ: e.1.event_type as u32,
code: event_code_to_int(&e.1.event_code).1,
value: e.1.value,
};
if e.typ == 2 && e.code <= 1 {
mouse_move[e.code as usize] += e.value;
} else {
send_event_channel.send(e).unwrap();
}
},
Err(_) => (),
}
// read next input event
event = dev.device.next_event(evdev_rs::NORMAL | evdev_rs::BLOCKING);
}
// combined mouse event
send_combined_mouse_move(&mut mouse_move, &send_event_channel);
// save cpu by sleeping after consuming all events
thread::sleep(Duration::from_millis(5));
}
}
});
(return_device_path, recv_event_channel, send_stop_channel)
}
fn stop_requested(chan: &Receiver<bool>) -> bool {
// check for stop requests
let mut sel = Select::new();
// create stop channel receive operation
let oper1 = sel.recv(&chan);
// try to select from stop channel
let oper = sel.try_select();
match oper {
// no stop requests
Err(_) => false,
// stop request received, break out of the loop
Ok(oper) => match oper.index() {
i if i == oper1 => {
oper.recv(&chan).unwrap()
},
// shouldn't happen
_ => false,
},
}
}
fn send_combined_mouse_move(mouse_move: &mut Vec<i32>, chan: &Sender<ThreadInputEvent>) {
// REL_X..=REL_Y
for code in 0..=1 {
if mouse_move[code] != 0 {
chan.send(ThreadInputEvent {
typ: EV_REL as u32,
code: code as u32,
value: mouse_move[code],
}).unwrap();
mouse_move[code] = 0;
}
}
}

View File

@ -5,7 +5,6 @@ extern crate crossbeam;
use std::thread; use std::thread;
use std::env::args; use std::env::args;
use std::time::Duration; use std::time::Duration;
use std::collections::HashMap;
use evdev_rs::enums::EventType::{EV_KEY, EV_REL}; use evdev_rs::enums::EventType::{EV_KEY, EV_REL};
@ -15,9 +14,6 @@ mod virtual_mouse;
mod virtual_kbd; mod virtual_kbd;
mod hw_device; mod hw_device;
mod event; mod event;
mod input_thread;
use self::input_thread::create_evdev_thread;
fn main() { fn main() {
@ -28,13 +24,17 @@ fn main() {
// let mut disabled_devices = Vec::new(); // let mut disabled_devices = Vec::new();
for device_path in &args[1..] { for device_path in &args[1..] {
devices.push(create_evdev_thread(&device_path)); devices.push(hw_device::HwDevice::new(&device_path));
} }
// testing device removal // // testing device removal
// thread::sleep(Duration::from_secs(1)); // thread::sleep(Duration::from_secs(1));
// devices[1].2.send(true).unwrap(); // devices[1].stop();
// disabled_devices.push(devices.remove(1)); // disabled_devices.push(devices.remove(1));
// thread::sleep(Duration::from_secs(1));
// // add it again
// devices.push(hw_device::HwDevice::new(&args[1]));
// init virtual devices // init virtual devices
let mut virt_kbd = virtual_kbd::VirtualKeyboard::new("test-kbd"); let mut virt_kbd = virtual_kbd::VirtualKeyboard::new("test-kbd");
@ -45,11 +45,9 @@ fn main() {
// init select // init select
let mut sel = Select::new(); let mut sel = Select::new();
// create device input event receive operations and map them to devices // add select operations
let mut device_idx_by_oper = HashMap::new(); for d in &devices {
for (i, (_, receiver, _)) in devices.iter().enumerate() { sel.recv(&d.event_channel);
let o = sel.recv(&receiver);
device_idx_by_oper.insert(o, i);
} }
// select from available device(s) // select from available device(s)
@ -57,7 +55,7 @@ fn main() {
// read from selected device // read from selected device
let index = oper.index(); let index = oper.index();
match oper.recv(&devices[device_idx_by_oper[&index]].1) { match oper.recv(&devices[index].event_channel) {
Ok(e) => { Ok(e) => {
// mouse event // mouse event
if e.typ == EV_REL as u32 || (e.code >= 272 && e.code <= 276) { if e.typ == EV_REL as u32 || (e.code >= 272 && e.code <= 276) {