summaryrefslogtreecommitdiff
path: root/src/deviceinfo.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/deviceinfo.rs')
-rw-r--r--src/deviceinfo.rs69
1 files changed, 61 insertions, 8 deletions
diff --git a/src/deviceinfo.rs b/src/deviceinfo.rs
index cc05e47..9097433 100644
--- a/src/deviceinfo.rs
+++ b/src/deviceinfo.rs
@@ -1,11 +1,13 @@
use anyhow::*;
use evdev_rs::Device;
+use std::cmp::Ordering;
use std::path::PathBuf;
#[derive(Debug, Clone)]
pub struct DeviceInfo {
pub name: String,
pub path: PathBuf,
+ pub phys: String,
}
impl DeviceInfo {
@@ -18,18 +20,51 @@ impl DeviceInfo {
Ok(Self {
name: input.name().unwrap_or("").to_string(),
+ phys: input.phys().unwrap_or("").to_string(),
path,
})
}
- pub fn with_name(name: &str) -> Result<Self> {
- let devices = Self::obtain_device_list()?;
- for item in devices {
- if item.name == name {
- return Ok(item);
+ pub fn with_name(name: &str, phys: Option<&str>) -> Result<Self> {
+ let mut devices = Self::obtain_device_list()?;
+
+ if let Some(phys) = phys {
+ match devices.iter().position(|item| item.phys == phys) {
+ Some(idx) => return Ok(devices.remove(idx)),
+ None => {
+ bail!(
+ "Requested device `{}` with phys=`{}` was not found",
+ name,
+ phys
+ );
+ }
+ }
+ }
+
+ let mut devices_with_name: Vec<_> = devices
+ .into_iter()
+ .filter(|item| item.name == name)
+ .collect();
+
+ if devices_with_name.is_empty() {
+ bail!("No device found with name `{}`", name);
+ }
+
+ if devices_with_name.len() > 1 {
+ log::warn!("The following devices match name `{}`:", name);
+ for dev in &devices_with_name {
+ log::warn!("{:?}", dev);
}
+ log::warn!(
+ "evremap will use the first entry. If you want to \
+ use one of the others, add the corresponding phys \
+ value to your configuration, for example, \
+ `phys = \"{}\"` for the second entry in the list.",
+ devices_with_name[1].phys
+ );
}
- bail!("No device found with name `{}`", name);
+
+ Ok(devices_with_name.remove(0))
}
fn obtain_device_list() -> Result<Vec<DeviceInfo>> {
@@ -52,20 +87,38 @@ impl DeviceInfo {
match DeviceInfo::with_path(path) {
Ok(item) => devices.push(item),
- Err(err) => log::error!("{}", err),
+ Err(err) => log::error!("{:#}", err),
}
}
- devices.sort_by(|a, b| a.name.cmp(&b.name));
+ // Order by name, but when multiple devices have the same name,
+ // order by the event device unit number
+ devices.sort_by(|a, b| match a.name.cmp(&b.name) {
+ Ordering::Equal => {
+ event_number_from_path(&a.path).cmp(&event_number_from_path(&b.path))
+ }
+ different => different,
+ });
Ok(devices)
}
}
+fn event_number_from_path(path: &PathBuf) -> u32 {
+ match path.to_str() {
+ Some(s) => match s.rfind("event") {
+ Some(idx) => s[idx + 5..].parse().unwrap_or(0),
+ None => 0,
+ },
+ None => 0,
+ }
+}
+
pub fn list_devices() -> Result<()> {
let devices = DeviceInfo::obtain_device_list()?;
for item in &devices {
println!("Name: {}", item.name);
println!("Path: {}", item.path.display());
+ println!("Phys: {}", item.phys);
println!();
}
Ok(())