refactoring
This commit is contained in:
parent
a5de77f321
commit
f564f0064c
125
src/hw_device.rs
125
src/hw_device.rs
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
24
src/main.rs
24
src/main.rs
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user