From 014119fec57177135d3ac727b4a307bf6a032d19 Mon Sep 17 00:00:00 2001 From: Johannes Leupolz Date: Sun, 9 Nov 2025 22:48:25 +0000 Subject: [PATCH] Fixes for compat mode (used by steam) --- vuinputd/src/compat.rs | 34 +++++++++++++++++++++++++ vuinputd/src/main.rs | 41 ++++++++++++++++-------------- vuinputd/src/requesting_process.rs | 4 +-- 3 files changed, 58 insertions(+), 21 deletions(-) create mode 100644 vuinputd/src/compat.rs diff --git a/vuinputd/src/compat.rs b/vuinputd/src/compat.rs new file mode 100644 index 0000000..b7f609c --- /dev/null +++ b/vuinputd/src/compat.rs @@ -0,0 +1,34 @@ +use libc::{__s32, __u16, c_ulong, input_event}; + + +#[repr(C)] +pub struct input_event_compat { + pub input_event_sec: u32, + pub input_event_usec: u32, + pub type_: __u16, + pub code: __u16, + pub value: __s32, +} + +// this is static for the architecture +pub fn compat_uses_64bit_time() -> bool { + let uname = nix::sys::utsname::uname().unwrap(); + let arch = uname.machine().to_str().unwrap(); + + match arch { + "x86_64" => false, + "ppc64" => false, // some setups still 32-bit time_t + _ => true, // arm64, riscv64, s390x all use 64-bit + } +} + +pub fn map_to_64_bit(compat: &input_event_compat) -> input_event{ + let mut mapped: input_event = unsafe { std::mem::zeroed() }; + mapped.time.tv_sec=compat.input_event_sec.into(); + mapped.time.tv_usec=compat.input_event_usec.into(); + mapped.type_=compat.type_; + mapped.code=compat.code; + mapped.value=compat.value; + + mapped +} \ No newline at end of file diff --git a/vuinputd/src/main.rs b/vuinputd/src/main.rs index 580eb05..204f0c2 100644 --- a/vuinputd/src/main.rs +++ b/vuinputd/src/main.rs @@ -39,6 +39,8 @@ use uinput_ioctls::*; pub mod requesting_process; pub mod monitor_udev; +pub mod compat; +use crate::compat::input_event_compat; use crate::container::inject_in_container_job::InjectInContainerJob; use crate::container::remove_from_container_job::RemoveFromContainerJob; use crate::monitor_udev::MonitorBackgroundLoop; @@ -282,19 +284,32 @@ unsafe extern "C" fn vuinput_write( return; } - let chunksize = std::mem::size_of::(); - let mut bytes = 0; let mut result = Result::Ok(()); - while bytes + chunksize <= _size && result.is_ok() { - result = vuinput_state.file.write_all(&slice[bytes..bytes + chunksize]); - bytes += chunksize; - } + let compat_size= std::mem::size_of::(); + let normal_size= std::mem::size_of::(); + let is_compat = vuinput_state.requesting_process.is_compat; + + if !is_compat { + while bytes + normal_size <= _size && result.is_ok() { + result = vuinput_state.file.write_all(&slice[bytes..bytes + normal_size]); + bytes += normal_size; + } + } else { + while bytes + compat_size <= _size && result.is_ok() { + let compat = _buf.byte_add(bytes) as *const input_event_compat; + let normal = compat::map_to_64_bit(&*compat); + let normal_ptr=(&normal as *const libc::input_event) as *const u8; + let slice = std::slice::from_raw_parts(normal_ptr,normal_size); + result = vuinput_state.file.write_all(&slice); + bytes += compat_size; + } + }; match result { Ok(_) => { - debug!("wrote {} bytes", bytes); + trace!("wrote {} of {} bytes (compat {})", bytes,_size,is_compat); fuse_lowlevel::fuse_reply_write(_req, bytes); } Err(e) => { @@ -711,18 +726,6 @@ fn check_permissions() -> Result<(), std::io::Error> { }) } -// this is static for the architecture -pub fn compat_uses_64bit_time() -> bool { - let uname = nix::sys::utsname::uname().unwrap(); - let arch = uname.machine().to_str().unwrap(); - - match arch { - "x86_64" => false, - "ppc64" => false, // some setups still 32-bit time_t - _ => true, // arm64, riscv64, s390x all use 64-bit - } -} - fn main() -> std::io::Result<()> { env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("debug")).init(); diff --git a/vuinputd/src/requesting_process.rs b/vuinputd/src/requesting_process.rs index 4397e82..546199a 100644 --- a/vuinputd/src/requesting_process.rs +++ b/vuinputd/src/requesting_process.rs @@ -189,11 +189,11 @@ pub fn get_requesting_process(pid: Pid) -> RequestingProcess { Pid::Pid(_) => { let is_compat = match is_compat_process(pid) { - Some(true) => { + Some(false) => { debug!("identified process {} as 64 bit process",pid.path()); false }, - Some(false) => { + Some(true) => { debug!("identified process {} as 32 bit process",pid.path()); true },