Skip to content

Commit 2d2b476

Browse files
committed
Add --wait-for-device flag
This is a simple approach for the case where the device isn't plugged in on startup. It works by polling the devices in a loop every few seconds. It is probably better and more robust to use udev rules for this purpose, but this approach will do for a quick and dirty ad-hoc user. closes: #35 closes: #46 closes: #60
1 parent 9b18364 commit 2d2b476

File tree

1 file changed

+45
-2
lines changed

1 file changed

+45
-2
lines changed

src/main.rs

+45-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::deviceinfo::DeviceInfo;
12
use crate::mapping::*;
23
use crate::remapper::*;
34
use anyhow::{Context, Result};
@@ -40,6 +41,14 @@ enum Opt {
4041
/// Override the phys device specified by the config file
4142
#[arg(long)]
4243
phys: Option<String>,
44+
45+
/// If the device isn't found on startup, wait forever
46+
/// until the device is plugged in. This works by polling
47+
/// the set of devices every few seconds. It is not as
48+
/// efficient as setting up a udev rule to spawn evremap,
49+
/// but is simpler to setup ad-hoc.
50+
#[arg(long)]
51+
wait_for_device: bool,
4352
},
4453
}
4554

@@ -68,6 +77,36 @@ fn setup_logger() {
6877
builder.init();
6978
}
7079

80+
fn get_device(
81+
device_name: &str,
82+
phys: Option<&str>,
83+
wait_for_device: bool,
84+
) -> anyhow::Result<DeviceInfo> {
85+
match deviceinfo::DeviceInfo::with_name(device_name, phys) {
86+
Ok(dev) => return Ok(dev),
87+
Err(err) if !wait_for_device => return Err(err),
88+
Err(err) => {
89+
log::warn!("{err:#}. Will wait until it is attached.");
90+
}
91+
}
92+
93+
const MAX_SLEEP: Duration = Duration::from_secs(10);
94+
const ONE_SECOND: Duration = Duration::from_secs(1);
95+
let mut sleep = ONE_SECOND;
96+
97+
loop {
98+
std::thread::sleep(sleep);
99+
sleep = (sleep + ONE_SECOND).min(MAX_SLEEP);
100+
101+
match deviceinfo::DeviceInfo::with_name(device_name, phys) {
102+
Ok(dev) => return Ok(dev),
103+
Err(err) => {
104+
log::debug!("{err:#}");
105+
}
106+
}
107+
}
108+
}
109+
71110
fn main() -> Result<()> {
72111
setup_logger();
73112
let opt = Opt::parse();
@@ -80,6 +119,7 @@ fn main() -> Result<()> {
80119
delay,
81120
device_name,
82121
phys,
122+
wait_for_device,
83123
} => {
84124
let mut mapping_config = MappingConfig::from_file(&config_file).context(format!(
85125
"loading MappingConfig from {}",
@@ -104,8 +144,11 @@ fn main() -> Result<()> {
104144
log::warn!("Short delay: release any keys now!");
105145
std::thread::sleep(Duration::from_secs_f64(delay));
106146

107-
let device_info =
108-
deviceinfo::DeviceInfo::with_name(device_name, mapping_config.phys.as_deref())?;
147+
let device_info = get_device(
148+
device_name,
149+
mapping_config.phys.as_deref(),
150+
wait_for_device,
151+
)?;
109152

110153
let mut mapper = InputMapper::create_mapper(device_info.path, mapping_config.mappings)?;
111154
mapper.run_mapper()

0 commit comments

Comments
 (0)