mirror of
https://github.com/joleuger/vuinputd.git
synced 2026-07-18 00:45:07 +00:00
Add command line options for vuinputd (devname, major, and minor) to control the name and properties of the virtual uinput character device
This commit is contained in:
parent
0e6abf1d85
commit
16afd2a482
4 changed files with 70 additions and 8 deletions
1
debian/control
vendored
1
debian/control
vendored
|
|
@ -21,6 +21,7 @@ Build-Depends: debhelper (>= 12),
|
|||
librust-futures-dev,
|
||||
librust-async-io-dev,
|
||||
librust-anyhow-dev,
|
||||
librust-clap-dev,
|
||||
pkg-config,
|
||||
build-essential
|
||||
Standards-Version: 4.6.0
|
||||
|
|
|
|||
|
|
@ -26,3 +26,4 @@ async-channel = "2.5.0"
|
|||
futures = "0.3.31"
|
||||
async-io = "2.6.0"
|
||||
anyhow = "1.0.100"
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
|
|
|
|||
|
|
@ -39,12 +39,64 @@ use crate::process_tools::*;
|
|||
|
||||
pub mod jobs;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
const DEV_PREFIX: &str = "/dev/";
|
||||
const DEVNAME_MAX_LEN: usize = 128 - DEV_PREFIX.len();
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[command(author, version, about)]
|
||||
struct Args {
|
||||
/// Major device number
|
||||
#[arg(long)]
|
||||
major: Option<u32>,
|
||||
|
||||
/// Minor device number
|
||||
#[arg(long)]
|
||||
minor: Option<u32>,
|
||||
|
||||
/// Device name (without /dev/)
|
||||
#[arg(long)]
|
||||
devname: Option<String>,
|
||||
}
|
||||
|
||||
fn validate_args(args: &Args) -> Result<(), String> {
|
||||
// major/minor must appear together
|
||||
match (&args.major, &args.minor) {
|
||||
(Some(_), Some(_)) | (None, None) => {}
|
||||
_ => {
|
||||
return Err(
|
||||
"--major and --minor must be specified together or not at all".into(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// devname length constraint
|
||||
if let Some(devname) = &args.devname {
|
||||
if devname.len() >= DEVNAME_MAX_LEN {
|
||||
return Err(format!(
|
||||
"--devname must be shorter than {} bytes",
|
||||
DEVNAME_MAX_LEN
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() -> std::io::Result<()> {
|
||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("debug")).init();
|
||||
|
||||
check_permissions().expect("failed to read the capabilities of the vuinputd process");
|
||||
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
let args = Args::parse();
|
||||
let argv0 = std::env::args_os().next().expect("Couldn't retrieve program name");
|
||||
|
||||
if let Err(e) = validate_args(&args) {
|
||||
eprintln!("Error: {e}");
|
||||
std::process::exit(2);
|
||||
}
|
||||
|
||||
|
||||
initialize_vuinput_state();
|
||||
VUINPUT_COUNTER.set(AtomicU64::new(3)).expect(
|
||||
|
|
@ -68,7 +120,11 @@ fn main() -> std::io::Result<()> {
|
|||
|
||||
let cuse_ops = vuinput_make_cuse_ops();
|
||||
|
||||
let vuinput_devicename = CString::new(format!("DEVNAME=vuinput")).unwrap();
|
||||
let vuinput_devicename = match &args.devname {
|
||||
None => "vuinput",
|
||||
Some(devname) => devname
|
||||
};
|
||||
let vuinput_devicename = CString::new(format!("DEVNAME={}",vuinput_devicename)).unwrap();
|
||||
|
||||
let mut dev_info_argv: Vec<*const c_char> = vec![
|
||||
vuinput_devicename.as_ptr(), // pointer to the C string
|
||||
|
|
@ -77,17 +133,19 @@ fn main() -> std::io::Result<()> {
|
|||
|
||||
// setting dev_major and dev_minor to 0 leads to a dynamic assignment of the major and minor, very likely beginning with 234:0
|
||||
// see in https://www.kernel.org/doc/Documentation/admin-guide/devices.txt
|
||||
// major 120 is reserved for local/experimental use. I picked minor 414795 with the use
|
||||
// of a random number generator to omit conflicts.
|
||||
let (major,minor) = match ((&args).major, (&args).minor) {
|
||||
(Some(major), Some(minor)) => (major,minor),
|
||||
_ => (0,0)
|
||||
};
|
||||
let ci = cuse_lowlevel::cuse_info {
|
||||
dev_major: 120,
|
||||
dev_minor: 414795,
|
||||
dev_major: major,
|
||||
dev_minor: minor,
|
||||
dev_info_argc: 1,
|
||||
dev_info_argv: dev_info_argv.as_mut_ptr(),
|
||||
flags: cuse_lowlevel::CUSE_UNRESTRICTED_IOCTL,
|
||||
};
|
||||
|
||||
let arg_program_name = CString::new(args[0].clone()).unwrap();
|
||||
let arg_program_name = CString::new(argv0.as_encoded_bytes()).unwrap();
|
||||
let parg_program_name = arg_program_name.into_raw();
|
||||
let arg_foreground = CString::new("-f").unwrap();
|
||||
let parg_foreground = arg_foreground.into_raw();
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ After=systemd-udevd.service
|
|||
Requires=systemd-udevd.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/vuinputd
|
||||
# major 120 is reserved for local/experimental use. I picked minor 414795 with the use
|
||||
# of a random number generator to omit conflicts.
|
||||
ExecStart=/usr/local/bin/vuinputd --major 120 --minor 414795
|
||||
Restart=on-failure
|
||||
|
||||
# Needs CAP_SYS_ADMIN for CUSE + /dev/uinput (I am still missing a capability for the correct working mode)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue