virtio-gpu: remove the +1 workaround
Signed-off-by: Anhad Singh <andypython@protonmail.com>
This commit is contained in:
+46
-7
@@ -3,6 +3,25 @@
|
||||
use std::fs::File;
|
||||
use std::io::{Error, Read, Write};
|
||||
|
||||
unsafe fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] {
|
||||
::core::slice::from_raw_parts((p as *const T) as *const u8, ::core::mem::size_of::<T>())
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
#[repr(usize)]
|
||||
pub enum VtMode {
|
||||
Text = 0,
|
||||
Graphic = 1,
|
||||
Default = 2,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct VtActivate {
|
||||
pub vt: usize,
|
||||
pub mode: VtMode,
|
||||
}
|
||||
|
||||
pub struct Handle(File);
|
||||
|
||||
impl Handle {
|
||||
@@ -14,11 +33,12 @@ 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> {
|
||||
Ok(dbg!(self.0.read(&mut [])?))
|
||||
Ok(self.0.read(&mut [])?)
|
||||
}
|
||||
|
||||
pub fn activate(&mut self, vt: usize) -> Result<usize, Error> {
|
||||
Ok(dbg!(self.0.write(&vt.to_le_bytes())?))
|
||||
pub fn activate(&mut self, vt: usize, mode: VtMode) -> Result<usize, Error> {
|
||||
let cmd = VtActivate { vt, mode };
|
||||
Ok(self.0.write(unsafe { any_as_u8_slice(&cmd) })?)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,9 +63,14 @@ impl From<u8> for CmdTy {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Cmd {
|
||||
// TODO(andypython): #VT should really need to be a `u8`.
|
||||
Activate(usize /* #VT */),
|
||||
Activate {
|
||||
vt: usize,
|
||||
mode: VtMode,
|
||||
},
|
||||
|
||||
Deactivate(usize /* #VT */),
|
||||
Resize {
|
||||
// TODO(andypython): do we really need to pass the VT here?
|
||||
@@ -60,7 +85,7 @@ pub enum Cmd {
|
||||
impl Cmd {
|
||||
fn ty(&self) -> CmdTy {
|
||||
match self {
|
||||
Cmd::Activate(_) => CmdTy::Activate,
|
||||
Cmd::Activate { .. } => CmdTy::Activate,
|
||||
Cmd::Deactivate(_) => CmdTy::Deactivate,
|
||||
Cmd::Resize { .. } => CmdTy::Resize,
|
||||
}
|
||||
@@ -74,7 +99,14 @@ pub fn send_comand(file: &mut File, command: Cmd) -> Result<(), syscall::Error>
|
||||
result.push(command.ty() as u8);
|
||||
|
||||
match command {
|
||||
Cmd::Activate(vt) | Cmd::Deactivate(vt) => result.extend_from_slice(&vt.to_le_bytes()),
|
||||
Cmd::Activate { vt, mode } => {
|
||||
let cmd = VtActivate { vt, mode };
|
||||
let bytes = unsafe { any_as_u8_slice(&cmd) };
|
||||
|
||||
result.extend_from_slice(bytes);
|
||||
}
|
||||
|
||||
Cmd::Deactivate(vt) => result.extend_from_slice(&vt.to_le_bytes()),
|
||||
Cmd::Resize {
|
||||
vt,
|
||||
width,
|
||||
@@ -105,7 +137,14 @@ pub fn parse_command(buffer: &[u8]) -> Option<Cmd> {
|
||||
let vt = usize::from_le_bytes(parser.next_chunk::<USIZE_SIZE>().ok()?);
|
||||
|
||||
match command {
|
||||
CmdTy::Activate => Some(Cmd::Activate(vt)),
|
||||
CmdTy::Activate => {
|
||||
let cmd = unsafe { &*buffer.as_ptr().offset(1).cast::<VtActivate>() };
|
||||
Some(Cmd::Activate {
|
||||
vt: cmd.vt,
|
||||
mode: VtMode::from(cmd.mode),
|
||||
})
|
||||
}
|
||||
|
||||
CmdTy::Deactivate => Some(Cmd::Deactivate(vt)),
|
||||
CmdTy::Resize => {
|
||||
let width = parser.next_chunk::<U32_SIZE>().ok()?;
|
||||
|
||||
+81
-22
@@ -17,7 +17,7 @@ use std::io::{Read, Write};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use inputd::Cmd;
|
||||
use inputd::{Cmd, VtActivate, VtMode};
|
||||
|
||||
use spin::Mutex;
|
||||
|
||||
@@ -49,6 +49,7 @@ impl Handle {
|
||||
/// requires the system call to return first. Otherwise, it will block indefinitely.
|
||||
struct VtInner {
|
||||
handle_file: File,
|
||||
mode: VtMode,
|
||||
}
|
||||
|
||||
struct Vt {
|
||||
@@ -72,8 +73,10 @@ impl Vt {
|
||||
pub fn inner(&self) -> &Mutex<VtInner> {
|
||||
self.inner.call_once(|| {
|
||||
let handle_file = File::open(format!("{}:handle", self.display)).unwrap();
|
||||
|
||||
Mutex::new(VtInner { handle_file })
|
||||
Mutex::new(VtInner {
|
||||
handle_file,
|
||||
mode: VtMode::Default,
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -88,7 +91,7 @@ struct InputScheme {
|
||||
super_key: bool,
|
||||
active_vt: Option<Arc<Vt>>,
|
||||
|
||||
todo: Vec<usize>,
|
||||
todo: Vec<VtActivate>,
|
||||
}
|
||||
|
||||
impl InputScheme {
|
||||
@@ -186,19 +189,19 @@ impl SchemeMut for InputScheme {
|
||||
let handle = self.handles.get_mut(&id).ok_or(SysError::new(EINVAL))?;
|
||||
|
||||
match handle {
|
||||
Handle::Device { .. } | Handle::Consumer { .. } => {
|
||||
if buf.len() == core::mem::size_of::<usize>() {
|
||||
// The device is requesting to activate a VT.
|
||||
let vt =
|
||||
usize::from_le_bytes(buf.try_into().map_err(|_| SysError::new(EINVAL))?);
|
||||
Handle::Device { device } => {
|
||||
assert!(buf.len() == core::mem::size_of::<VtActivate>());
|
||||
|
||||
self.todo.push(vt);
|
||||
return Ok(buf.len());
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
// 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.todo.push(cmd.clone());
|
||||
|
||||
return Ok(buf.len());
|
||||
}
|
||||
|
||||
Handle::Consumer { .. } => unreachable!(),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@@ -276,7 +279,10 @@ impl SchemeMut for InputScheme {
|
||||
|
||||
inputd::send_comand(
|
||||
&mut vt_inner.handle_file,
|
||||
Cmd::Activate(new_active.index),
|
||||
Cmd::Activate {
|
||||
vt: new_active.index,
|
||||
mode: VtMode::Default,
|
||||
},
|
||||
)?;
|
||||
self.active_vt = Some(new_active.clone());
|
||||
} else {
|
||||
@@ -287,7 +293,7 @@ impl SchemeMut for InputScheme {
|
||||
|
||||
assert!(handle.is_producer());
|
||||
|
||||
let active_vt = self.active_vt.as_ref().unwrap();
|
||||
let active_vt = self.active_vt.as_ref().unwrap();
|
||||
for handle in self.handles.values_mut() {
|
||||
match handle {
|
||||
Handle::Consumer {
|
||||
@@ -357,17 +363,22 @@ fn deamon(deamon: redox_daemon::Daemon) -> anyhow::Result<()> {
|
||||
scheme.handle(&mut packet);
|
||||
socket_file.write(&packet)?;
|
||||
|
||||
while let Some(vt) = scheme.todo.pop() {
|
||||
let vt = scheme.vts.get_mut(&vt).unwrap();
|
||||
while let Some(cmd) = scheme.todo.pop() {
|
||||
let vt = scheme.vts.get_mut(&cmd.vt).unwrap();
|
||||
let mut vt_inner = vt.inner().lock();
|
||||
|
||||
// Failing to activate a VT is not a fatal error.
|
||||
if let Err(err) =
|
||||
inputd::send_comand(&mut vt_inner.handle_file, Cmd::Activate(vt.index))
|
||||
{
|
||||
if let Err(err) = inputd::send_comand(
|
||||
&mut vt_inner.handle_file,
|
||||
Cmd::Activate {
|
||||
vt: vt.index,
|
||||
mode: VtMode::from(cmd.mode),
|
||||
},
|
||||
) {
|
||||
log::error!("inputd: failed to activate VT #{}: {err}", vt.index)
|
||||
}
|
||||
|
||||
vt_inner.mode = cmd.mode;
|
||||
scheme.active_vt = Some(vt.clone());
|
||||
}
|
||||
|
||||
@@ -454,5 +465,53 @@ pub fn setup_logging(level: log::LevelFilter, name: &str) {
|
||||
pub fn main() {
|
||||
#[cfg(target_os = "redox")]
|
||||
setup_logging(log::LevelFilter::Trace, "inputd");
|
||||
redox_daemon::Daemon::new(daemon_runner).expect("virtio-core: failed to daemonize");
|
||||
|
||||
let mut args = std::env::args().skip(1);
|
||||
|
||||
if let Some(val) = args.next() {
|
||||
if val != "-G" {
|
||||
panic!("inputd: invalid argument: {}", val);
|
||||
}
|
||||
|
||||
let vt = args.next().unwrap().parse::<usize>().unwrap();
|
||||
|
||||
// On startup, the VESA display driver is started which basically makes use of the framebuffer
|
||||
// provided by the firmware. The GPU device are latter started by `pcid` (such as `virtio-gpu`).
|
||||
let mut devices = vec![];
|
||||
let schemes = std::fs::read_dir(":").unwrap();
|
||||
|
||||
for entry in schemes {
|
||||
let path = entry.unwrap().path();
|
||||
let path_str = path
|
||||
.into_os_string()
|
||||
.into_string()
|
||||
.expect("inputd: failed to convert path to string");
|
||||
|
||||
if path_str.contains("display") {
|
||||
println!("inputd: found display scheme {}", path_str);
|
||||
devices.push(path_str);
|
||||
}
|
||||
}
|
||||
|
||||
let device = devices
|
||||
.iter()
|
||||
.filter(|d| !d.contains("vesa"))
|
||||
.collect::<Vec<_>>();
|
||||
let device = if device.is_empty() {
|
||||
"vesa"
|
||||
} else {
|
||||
// TODO: What should we do when there are multiple display devices?
|
||||
device[0].split("/").nth(2).unwrap()
|
||||
};
|
||||
|
||||
dbg!(&device);
|
||||
let mut handle =
|
||||
inputd::Handle::new(device).expect("inputd: failed to open display handle");
|
||||
|
||||
handle
|
||||
.activate(vt, VtMode::Graphic)
|
||||
.expect("inputd: failed to activate VT in graphic mode");
|
||||
} else {
|
||||
redox_daemon::Daemon::new(daemon_runner).expect("virtio-core: failed to daemonize");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user