Implement listing devices

pull/39/head
Takashi Kokubun 3 years ago
parent 1a8b2b15d1
commit 6fbd45a19a
No known key found for this signature in database
GPG Key ID: 6FFC433B12EE23DD

@ -1,19 +1,84 @@
extern crate evdev;
extern crate nix;
use evdev::Device;
use crate::output::build_device;
use crate::transform::on_event;
use crate::Config;
use evdev::{Device, EventType};
use nix::sys::select::select;
use nix::sys::select::FdSet;
use std::collections::HashMap;
use std::error::Error;
use std::fs::read_dir;
use std::os::unix::ffi::OsStrExt;
use std::os::unix::io::AsRawFd;
pub fn select_device() -> Result<Device, Box<dyn Error>> {
// TODO: stop hard-coding the device
pub fn select_device(_devices: &Vec<String>) -> Result<Vec<Device>, Box<dyn Error>> {
let path_devices = list_devices()?;
let mut paths: Vec<&String> = path_devices.keys().collect();
paths.sort_by(|a, b| device_index(a).partial_cmp(&device_index(b)).unwrap());
println!("Selecting from the following devices:");
println!("------------------------------------------------------------------------------");
for path in paths {
if let Some(device) = path_devices.get(path) {
println!("{:18}: {}", path, device.name().unwrap_or("<Unnamed device>"));
}
}
println!("------------------------------------------------------------------------------");
let device = Device::open("/dev/input/event19")?;
return Ok(device);
return Ok(vec![device]);
}
pub fn event_loop(mut input_devices: Vec<Device>, _config: &Config) -> Result<(), Box<dyn Error>> {
let mut input_device = input_devices.remove(0);
let mut output_device = build_device(&input_device)
.map_err(|e| format!("Failed to build an output device: {}", e))?;
input_device
.grab()
.map_err(|e| format!("Failed to grab an input device: {}", e))?;
loop {
if !is_readable(&mut input_device)? {
continue;
}
for event in input_device.fetch_events()? {
if event.event_type() == EventType::KEY {
on_event(event, &mut output_device)?;
} else {
output_device.emit(&[event])?;
}
}
}
}
// We can't know the device path from evdev::enumerate(). So we re-implement it.
fn list_devices() -> Result<HashMap<String, Device>, Box<dyn Error>> {
let mut path_devices: HashMap<String, Device> = HashMap::new();
if let Some(dev_input) = read_dir("/dev/input").as_mut().ok() {
while let Some(entry) = dev_input.next() {
let path = entry?.path();
if let Some(fname) = path.file_name() {
if fname.as_bytes().starts_with(b"event") {
let device = Device::open(&path)?;
if let Ok(path) = path.into_os_string().into_string() {
path_devices.insert(path, device);
}
}
}
}
}
return Ok(path_devices);
}
fn device_index(path: &str) -> i32 {
path.trim_start_matches("/dev/input/event")
.parse::<i32>()
.unwrap()
}
pub fn is_readable(device: &mut Device) -> Result<bool, Box<dyn Error>> {
fn is_readable(device: &mut Device) -> Result<bool, Box<dyn Error>> {
let mut read_fds = FdSet::new();
read_fds.insert(device.as_raw_fd());
select(None, &mut read_fds, None, None, None)?;

@ -1,9 +1,8 @@
use evdev::EventType;
use std::env;
use crate::config::Config;
use crate::input::{event_loop, select_device};
use getopts::Options;
use std::error::Error;
use std::env;
use std::process::exit;
use crate::config::Config;
extern crate getopts;
@ -12,30 +11,6 @@ mod input;
mod output;
mod transform;
fn event_loop(_config: &Config) -> Result<(), Box<dyn Error>> {
let mut input_device =
input::select_device().map_err(|e| format!("Failed to open an input device: {}", e))?;
let mut output_device = output::build_device(&input_device)
.map_err(|e| format!("Failed to build an output device: {}", e))?;
input_device
.grab()
.map_err(|e| format!("Failed to grab an input device: {}", e))?;
loop {
if !input::is_readable(&mut input_device)? {
continue;
}
for event in input_device.fetch_events()? {
if event.event_type() == EventType::KEY {
transform::on_event(event, &mut output_device)?;
} else {
output_device.emit(&[event])?;
}
}
}
}
fn usage(program: &str, opts: Options) -> String {
let brief = format!("Usage: {} CONFIG [options]", program);
opts.usage(&brief)
@ -58,6 +33,10 @@ fn main() {
Ok(args) => args,
Err(e) => abort(&e.to_string()),
};
if args.opt_present("h") {
println!("{}", &usage(&program, opts));
return;
}
let filename = match &args.free.iter().map(String::as_str).collect::<Vec<&str>>()[..] {
&[filename] => filename,
@ -68,7 +47,13 @@ fn main() {
Err(e) => abort(&format!("Failed to load config '{}': {}", filename, e)),
};
if let Err(e) = event_loop(&config) {
let devices = args.opt_strs("device");
let input_devices = match select_device(&devices) {
Ok(input_devices) => input_devices,
Err(e) => abort(&format!("Failed to select devices: {}", e)),
};
if let Err(e) = event_loop(input_devices, &config) {
abort(&format!("Error: {}", e));
}
}

Loading…
Cancel
Save