Files
RedBear-OS/inputd/src/lib.rs
T
bjorn3 fd8dabd1bc Use the new scheme format in most places
The graphics subsystem still uses the old format as orbital manually
parses the fpath result.
2024-07-11 21:14:45 +02:00

172 lines
4.2 KiB
Rust

#![feature(iter_next_chunk)]
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 {
Graphic = 1,
Default = 2,
}
#[derive(Debug, Clone)]
#[repr(C)]
pub struct VtActivate {
pub vt: usize,
pub mode: VtMode,
}
pub struct Handle(File);
impl Handle {
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)?))
}
// 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> {
self.0.read(&mut [])
}
pub fn activate(&mut self, vt: usize, mode: VtMode) -> Result<usize, Error> {
let cmd = VtActivate { vt, mode };
self.0.write(unsafe { any_as_u8_slice(&cmd) })
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[repr(u8)]
enum CmdTy {
Unknown = 0,
Activate,
Deactivate,
Resize,
}
impl From<u8> for CmdTy {
fn from(value: u8) -> Self {
match value {
1 => CmdTy::Activate,
2 => CmdTy::Deactivate,
3 => CmdTy::Resize,
_ => CmdTy::Unknown,
}
}
}
#[derive(Debug)]
pub enum Cmd {
// TODO(andypython): #VT should really need to be a `u8`.
Activate {
vt: usize,
mode: VtMode,
},
Deactivate(usize /* #VT */),
Resize {
// TODO(andypython): do we really need to pass the VT here?
vt: usize,
width: u32,
height: u32,
stride: u32,
},
}
impl Cmd {
fn ty(&self) -> CmdTy {
match self {
Cmd::Activate { .. } => CmdTy::Activate,
Cmd::Deactivate(_) => CmdTy::Deactivate,
Cmd::Resize { .. } => CmdTy::Resize,
}
}
}
pub fn send_comand(file: &mut File, command: Cmd) -> Result<(), libredox::error::Error> {
use std::os::fd::AsRawFd;
let mut result = vec![];
result.push(command.ty() as u8);
match command {
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,
height,
stride,
} => {
result.extend_from_slice(&vt.to_le_bytes());
result.extend(width.to_le_bytes());
result.extend(height.to_le_bytes());
result.extend(stride.to_le_bytes());
}
};
let written = libredox::call::write(file.as_raw_fd() as usize, &result)?;
// XXX: Ensure all of the data is written.
assert_eq!(written, result.len());
Ok(())
}
pub fn parse_command(buffer: &[u8]) -> Option<Cmd> {
const U32_SIZE: usize = core::mem::size_of::<u32>();
const USIZE_SIZE: usize = core::mem::size_of::<usize>();
let mut parser = buffer.iter().cloned();
let command = CmdTy::from(parser.next()?);
let vt = usize::from_le_bytes(parser.next_chunk::<USIZE_SIZE>().ok()?);
match command {
CmdTy::Activate => {
let cmd = unsafe { &*buffer.as_ptr().offset(1).cast::<VtActivate>() };
Some(Cmd::Activate {
vt: cmd.vt,
mode: cmd.mode,
})
}
CmdTy::Deactivate => Some(Cmd::Deactivate(vt)),
CmdTy::Resize => {
let width = parser.next_chunk::<U32_SIZE>().ok()?;
let height = parser.next_chunk::<U32_SIZE>().ok()?;
let stride = parser.next_chunk::<U32_SIZE>().ok()?;
Some(Cmd::Resize {
vt,
width: u32::from_le_bytes(width),
height: u32::from_le_bytes(height),
stride: u32::from_le_bytes(stride),
})
}
CmdTy::Unknown => None,
}
}
#[repr(packed)]
pub struct Damage {
pub x: i32,
pub y: i32,
pub width: i32,
pub height: i32,
}