Skip to content

Commit

Permalink
fix(CompositeDevice): use early and late rules to fix hiding devices …
Browse files Browse the repository at this point in the history
…at boot time
  • Loading branch information
ShadowApex committed Feb 15, 2025
1 parent 89e861a commit be878ad
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 13 deletions.
6 changes: 0 additions & 6 deletions src/input/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,12 +211,6 @@ impl Manager {
/// Starts listening for [Command] messages to be sent from clients and
/// dispatch those events.
pub async fn run(&mut self) -> Result<(), Box<dyn Error + Send + Sync>> {
// Delay initial discovery by a short amount of time to allow udev
// rules to process for the first time.
// TODO: Figure out a better way to prevent udev from not running hiding
// rules too early in boot.
tokio::time::sleep(Duration::from_millis(4000)).await;

let dbus_for_listen_on_dbus = self.dbus.clone();

let cmd_tx_all_devices = self.tx.clone();
Expand Down
34 changes: 27 additions & 7 deletions src/udev/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ use udev::Enumerator;

use self::device::Device;

const RULE_HIDE_DEVICE_PRIORITY: &str = "50";
const RULE_HIDE_DEVICE_EARLY_PRIORITY: &str = "50";
const RULE_HIDE_DEVICE_LATE_PRIORITY: &str = "96";
const RULES_PREFIX: &str = "/run/udev/rules.d";

/// Hide the given input device from regular users.
Expand All @@ -36,7 +37,7 @@ pub async fn hide_device(path: &str) -> Result<(), Box<dyn Error>> {
"/usr/bin/chmod"
};

// Create a udev rule to hide the device
// Create an early udev rule to hide the device
let rule = format!(
r#"# Hides devices stemming from {name}
# Managed by InputPlumber, this file will be autoremoved during configuration changes.
Expand All @@ -48,11 +49,26 @@ KERNEL=="hidraw[0-9]*", SUBSYSTEM=="{subsystem}", MODE:="0000", GROUP:="root", R
LABEL="inputplumber_end"
"#
);

// Write the udev rule
fs::create_dir_all(RULES_PREFIX)?;
let rule_path =
format!("{RULES_PREFIX}/{RULE_HIDE_DEVICE_PRIORITY}-inputplumber-hide-{name}.rules");
format!("{RULES_PREFIX}/{RULE_HIDE_DEVICE_EARLY_PRIORITY}-inputplumber-hide-{name}.rules");
fs::write(rule_path, rule)?;

// Create a late udev rule to hide the device. This is needed for devices that
// are available at boot time because the early rule will not be applied.
let rule = format!(
r#"# Hides devices stemming from {name}
# Managed by InputPlumber, this file will be autoremoved during configuration changes.
{match_rule}, GOTO="inputplumber_valid"
GOTO="inputplumber_end"
LABEL="inputplumber_valid"
KERNEL=="js[0-9]*|event[0-9]*", SUBSYSTEM=="{subsystem}", MODE="000", GROUP="root", TAG-="uaccess", RUN+="{chmod_cmd} 000 /dev/input/%k"
KERNEL=="hidraw[0-9]*", SUBSYSTEM=="{subsystem}", MODE="000", GROUP="root", TAG-="uaccess", RUN+="{chmod_cmd} 000 /dev/%k"
LABEL="inputplumber_end"
"#
);
let rule_path =
format!("{RULES_PREFIX}/{RULE_HIDE_DEVICE_LATE_PRIORITY}-inputplumber-hide-{name}.rules");
fs::write(rule_path, rule)?;

// Reload udev
Expand All @@ -70,7 +86,10 @@ pub async fn unhide_device(path: String) -> Result<(), Box<dyn Error>> {
return Err("Unable to determine parent for device".into());
};
let rule_path =
format!("{RULES_PREFIX}/{RULE_HIDE_DEVICE_PRIORITY}-inputplumber-hide-{name}.rules");
format!("{RULES_PREFIX}/{RULE_HIDE_DEVICE_EARLY_PRIORITY}-inputplumber-hide-{name}.rules");
fs::remove_file(rule_path)?;
let rule_path =
format!("{RULES_PREFIX}/{RULE_HIDE_DEVICE_LATE_PRIORITY}-inputplumber-hide-{name}.rules");
fs::remove_file(rule_path)?;

// Reload udev
Expand All @@ -87,7 +106,8 @@ pub async fn unhide_all() -> Result<(), Box<dyn Error>> {
continue;
};
let filename = entry.file_name().to_string_lossy().to_string();
if !filename.starts_with(format!("{RULE_HIDE_DEVICE_PRIORITY}-inputplumber-hide").as_str())
if !filename
.starts_with(format!("{RULE_HIDE_DEVICE_EARLY_PRIORITY}-inputplumber-hide").as_str())
{
continue;
}
Expand Down

0 comments on commit be878ad

Please sign in to comment.