From 273cbda8725e0e9594c0f3d66ba89a2fc1ba28bb Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 21 Dec 2024 17:08:15 +0100 Subject: [PATCH] inputd: Split ControlHandle and DisplayHandle ControlHandle is used to switch the active vt, while DisplayHandle is used by display drivers to register new vt's. There are entirely unrelated tasks and the fact that they had been merged together has been confusing me for a while. Also changed activating a VT to no longer create a new vt when none existed previously. The target graphics driver may not be able to handle the new VT. inputd -A already didn't allow activating non-existent VT's as it first tried to open a consumer handle for the target VT. --- graphics/fbcond/src/main.rs | 4 +- graphics/fbcond/src/scheme.rs | 4 -- graphics/vesad/src/main.rs | 4 +- graphics/vesad/src/scheme.rs | 8 ++-- inputd/src/lib.rs | 18 +++++++-- inputd/src/main.rs | 71 +++++++++++++++-------------------- 6 files changed, 55 insertions(+), 54 deletions(-) diff --git a/graphics/fbcond/src/main.rs b/graphics/fbcond/src/main.rs index 4393c9185c..7449d5a4d7 100644 --- a/graphics/fbcond/src/main.rs +++ b/graphics/fbcond/src/main.rs @@ -53,11 +53,13 @@ fn inner(daemon: redox_daemon::Daemon, vt_ids: &[usize]) -> ! { let mut scheme = FbconScheme::new(vt_ids, &mut event_queue); + let mut inputd_control_handle = inputd::ControlHandle::new().unwrap(); + libredox::call::setrens(0, 0).expect("fbcond: failed to enter null namespace"); daemon.ready().expect("failed to notify parent"); - scheme.inputd_handle.activate(1).unwrap(); + inputd_control_handle.activate_vt(1).unwrap(); let mut blocked = Vec::new(); diff --git a/graphics/fbcond/src/scheme.rs b/graphics/fbcond/src/scheme.rs index bd128f2e5a..9ff10d4dbe 100644 --- a/graphics/fbcond/src/scheme.rs +++ b/graphics/fbcond/src/scheme.rs @@ -36,13 +36,10 @@ pub struct FbconScheme { pub vts: BTreeMap, next_id: usize, pub handles: BTreeMap, - pub inputd_handle: inputd::Handle, } impl FbconScheme { pub fn new(vt_ids: &[usize], event_queue: &mut EventQueue) -> FbconScheme { - let inputd_handle = inputd::Handle::new("vesa").unwrap(); - let mut vts = BTreeMap::new(); for &vt_i in vt_ids { @@ -61,7 +58,6 @@ impl FbconScheme { vts, next_id: 0, handles: BTreeMap::new(), - inputd_handle, } } diff --git a/graphics/vesad/src/main.rs b/graphics/vesad/src/main.rs index 9b01e97624..6bbab330e1 100644 --- a/graphics/vesad/src/main.rs +++ b/graphics/vesad/src/main.rs @@ -86,11 +86,13 @@ fn inner(daemon: redox_daemon::Daemon, framebuffers: Vec, spec: &[( let _ = File::open("/scheme/debug/disable-graphical-debug"); + let mut inputd_control_handle = inputd::ControlHandle::new().unwrap(); + libredox::call::setrens(0, 0).expect("vesad: failed to enter null namespace"); daemon.ready().expect("failed to notify parent"); - scheme.inputd_handle.activate(1).unwrap(); + inputd_control_handle.activate_vt(1).unwrap(); let mut blocked = Vec::new(); loop { diff --git a/graphics/vesad/src/scheme.rs b/graphics/vesad/src/scheme.rs index 65baf8dace..b3218b2834 100644 --- a/graphics/vesad/src/scheme.rs +++ b/graphics/vesad/src/scheme.rs @@ -32,12 +32,12 @@ pub struct DisplayScheme { pub vts: BTreeMap>, next_id: usize, pub handles: BTreeMap, - pub inputd_handle: inputd::Handle, + _inputd_handle: inputd::DisplayHandle, } impl DisplayScheme { pub fn new(framebuffers: Vec, spec: &[()]) -> DisplayScheme { - let mut inputd_handle = inputd::Handle::new("vesa").unwrap(); + let mut inputd_handle = inputd::DisplayHandle::new("vesa").unwrap(); let mut vts = BTreeMap::>::new(); @@ -47,7 +47,7 @@ impl DisplayScheme { let fb = &framebuffers[fb_i]; screens.insert(ScreenIndex(fb_i), GraphicScreen::new(fb.width, fb.height)); } - vts.insert(VtIndex(inputd_handle.register().unwrap()), screens); + vts.insert(VtIndex(inputd_handle.register_vt().unwrap()), screens); } DisplayScheme { @@ -56,7 +56,7 @@ impl DisplayScheme { vts, next_id: 0, handles: BTreeMap::new(), - inputd_handle, + _inputd_handle: inputd_handle, } } diff --git a/inputd/src/lib.rs b/inputd/src/lib.rs index 6c55e96949..1b1dc3a2ff 100644 --- a/inputd/src/lib.rs +++ b/inputd/src/lib.rs @@ -13,9 +13,9 @@ pub struct VtActivate { pub vt: usize, } -pub struct Handle(File); +pub struct DisplayHandle(File); -impl Handle { +impl DisplayHandle { pub fn new>(device_name: S) -> Result { let path = format!("/scheme/input/handle/display/{}", device_name.into()); Ok(Self(File::open(path)?)) @@ -23,11 +23,21 @@ impl Handle { // The return value is the display identifier. It will be used to uniquely // identify the display on activation events. - pub fn register(&mut self) -> Result { + pub fn register_vt(&mut self) -> Result { self.0.read(&mut []) } - pub fn activate(&mut self, vt: usize) -> Result { +} + +pub struct ControlHandle(File); + +impl ControlHandle { + pub fn new() -> Result { + let path = format!("/scheme/input/control"); + Ok(Self(File::open(path)?)) + } + + pub fn activate_vt(&mut self, vt: usize) -> Result { let cmd = VtActivate { vt }; self.0.write(unsafe { any_as_u8_slice(&cmd) }) } diff --git a/inputd/src/main.rs b/inputd/src/main.rs index 8aa562a888..66f204adae 100644 --- a/inputd/src/main.rs +++ b/inputd/src/main.rs @@ -13,7 +13,6 @@ use std::collections::BTreeMap; use std::fs::File; -use std::os::fd::AsRawFd; use std::sync::atomic::{AtomicUsize, Ordering}; use inputd::{Cmd, VtActivate}; @@ -31,9 +30,10 @@ enum Handle { notified: bool, vt: usize, }, - Device { + Display { device: String, }, + Control, } impl Handle { @@ -123,8 +123,9 @@ impl SchemeMut for InputScheme { } "handle" => { let display = path_parts.collect::>().join("."); - Handle::Device { device: display } + Handle::Display { device: display } } + "control" => Handle::Control, _ => { log::error!("inputd: invalid path {path}"); @@ -174,7 +175,7 @@ impl SchemeMut for InputScheme { Ok(copy) } - Handle::Device { device } => { + Handle::Display { device } => { assert!(buf.is_empty()); let vt = self.next_vt_id.fetch_add(1, Ordering::SeqCst); @@ -186,6 +187,10 @@ impl SchemeMut for InputScheme { log::error!("inputd: producer tried to read"); return Err(SysError::new(EINVAL)); } + Handle::Control => { + log::error!("inputd: control tried to read"); + return Err(SysError::new(EINVAL)); + } } } @@ -201,16 +206,15 @@ impl SchemeMut for InputScheme { let handle = self.handles.get_mut(&id).ok_or(SysError::new(EINVAL))?; match handle { - Handle::Device { device } => { + Handle::Control => { if buf.len() != core::mem::size_of::() { - log::error!("inputd: device tried to write incorrectly sized command"); + log::error!("inputd: control tried to write incorrectly sized command"); return Err(SysError::new(EINVAL)); } // SAFETY: We have verified the size of the buffer above. let cmd = unsafe { &*buf.as_ptr().cast::() }; - self.vts.insert(cmd.vt, Vt::new(device.clone(), cmd.vt)); self.pending_activate = Some(cmd.clone()); return Ok(buf.len()); @@ -220,6 +224,10 @@ impl SchemeMut for InputScheme { log::error!("inputd: consumer tried to write"); return Err(SysError::new(EINVAL)); } + Handle::Display { .. } => { + log::error!("inputd: display tried to write"); + return Err(SysError::new(EINVAL)); + } Handle::Producer => {} } @@ -340,8 +348,8 @@ impl SchemeMut for InputScheme { *notified = false; Ok(EventFlags::empty()) } - Handle::Producer | Handle::Device { .. } => { - log::error!("inputd: producer or device tried to use an event queue"); + Handle::Producer | Handle::Control | Handle::Display { .. } => { + log::error!("inputd: producer, control or display tried to use an event queue"); Err(SysError::new(EINVAL)) } } @@ -378,13 +386,16 @@ fn deamon(deamon: redox_daemon::Daemon) -> anyhow::Result<()> { } if let Some(cmd) = scheme.pending_activate.take() { - let vt = scheme.vts.get_mut(&cmd.vt).unwrap(); - // Failing to activate a VT is not a fatal error. - if let Err(err) = vt.send_command(Cmd::Activate { vt: vt.index }) { - log::error!("inputd: failed to activate VT #{}: {err}", vt.index) - } + if let Some(vt) = scheme.vts.get_mut(&cmd.vt) { + // Failing to activate a VT is not a fatal error. + if let Err(err) = vt.send_command(Cmd::Activate { vt: vt.index }) { + log::error!("inputd: failed to activate VT #{}: {err}", vt.index) + } - scheme.active_vt = Some(vt.index); + scheme.active_vt = Some(vt.index); + } else { + log::error!("inputd: failed to activate non-existent VT #{}", cmd.vt) + } } if !scheme.has_new_events { @@ -442,31 +453,11 @@ fn main() { "-A" => { let vt = args.next().unwrap().parse::().unwrap(); - let handle = File::open(format!("/scheme/input/consumer/{vt}")) - .expect("inputd: failed to open consumer handle"); - let mut display_path = [0; 4096]; - - let written = libredox::call::fpath(handle.as_raw_fd() as usize, &mut display_path) - .expect("inputd: fpath() failed"); - - assert!(written <= display_path.len()); - drop(handle); - - let display_path = std::str::from_utf8(&display_path[..written]) - .expect("inputd: display path UTF-8 validation failed"); - let display_name = display_path - .split('.') - .skip(1) - .next() - .expect("inputd: invalid display path"); - let display_scheme = display_name - .split(':') - .next() - .expect("inputd: invalid display path"); - - let mut handle = inputd::Handle::new(display_scheme) - .expect("inputd: failed to open display handle"); - handle.activate(vt).expect("inputd: failed to activate VT"); + let mut handle = + inputd::ControlHandle::new().expect("inputd: failed to open display handle"); + handle + .activate_vt(vt) + .expect("inputd: failed to activate VT"); } _ => panic!("inputd: invalid argument: {}", val),