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.
This commit is contained in:
@@ -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();
|
||||
|
||||
|
||||
@@ -36,13 +36,10 @@ pub struct FbconScheme {
|
||||
pub vts: BTreeMap<VtIndex, TextScreen>,
|
||||
next_id: usize,
|
||||
pub handles: BTreeMap<usize, Handle>,
|
||||
pub inputd_handle: inputd::Handle,
|
||||
}
|
||||
|
||||
impl FbconScheme {
|
||||
pub fn new(vt_ids: &[usize], event_queue: &mut EventQueue<VtIndex>) -> 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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,11 +86,13 @@ fn inner(daemon: redox_daemon::Daemon, framebuffers: Vec<FrameBuffer>, 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 {
|
||||
|
||||
@@ -32,12 +32,12 @@ pub struct DisplayScheme {
|
||||
pub vts: BTreeMap<VtIndex, BTreeMap<ScreenIndex, GraphicScreen>>,
|
||||
next_id: usize,
|
||||
pub handles: BTreeMap<usize, Handle>,
|
||||
pub inputd_handle: inputd::Handle,
|
||||
_inputd_handle: inputd::DisplayHandle,
|
||||
}
|
||||
|
||||
impl DisplayScheme {
|
||||
pub fn new(framebuffers: Vec<FrameBuffer>, spec: &[()]) -> DisplayScheme {
|
||||
let mut inputd_handle = inputd::Handle::new("vesa").unwrap();
|
||||
let mut inputd_handle = inputd::DisplayHandle::new("vesa").unwrap();
|
||||
|
||||
let mut vts = BTreeMap::<VtIndex, BTreeMap<ScreenIndex, GraphicScreen>>::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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-4
@@ -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<S: Into<String>>(device_name: S) -> Result<Self, Error> {
|
||||
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<usize, Error> {
|
||||
pub fn register_vt(&mut self) -> Result<usize, Error> {
|
||||
self.0.read(&mut [])
|
||||
}
|
||||
|
||||
pub fn activate(&mut self, vt: usize) -> Result<usize, Error> {
|
||||
}
|
||||
|
||||
pub struct ControlHandle(File);
|
||||
|
||||
impl ControlHandle {
|
||||
pub fn new() -> Result<Self, Error> {
|
||||
let path = format!("/scheme/input/control");
|
||||
Ok(Self(File::open(path)?))
|
||||
}
|
||||
|
||||
pub fn activate_vt(&mut self, vt: usize) -> Result<usize, Error> {
|
||||
let cmd = VtActivate { vt };
|
||||
self.0.write(unsafe { any_as_u8_slice(&cmd) })
|
||||
}
|
||||
|
||||
+31
-40
@@ -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::<Vec<_>>().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::<VtActivate>() {
|
||||
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::<VtActivate>() };
|
||||
|
||||
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::<usize>().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),
|
||||
|
||||
Reference in New Issue
Block a user