Merge branch 'inputd_pull_vt_events' into 'master'
inputd: Major refactorings to the inputd interface See merge request redox-os/drivers!210
This commit is contained in:
Generated
+1
@@ -1681,6 +1681,7 @@ dependencies = [
|
||||
"ransid",
|
||||
"redox-daemon",
|
||||
"redox-scheme",
|
||||
"redox_event",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
[package]
|
||||
name = "vesad"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
orbclient = "0.3.27"
|
||||
ransid = "0.4"
|
||||
redox_syscall = "0.5"
|
||||
redox-daemon = "0.1"
|
||||
redox_event = "0.4.1"
|
||||
|
||||
common = { path = "../../common" }
|
||||
inputd = { path = "../../inputd" }
|
||||
|
||||
+121
-63
@@ -2,15 +2,15 @@
|
||||
extern crate orbclient;
|
||||
extern crate syscall;
|
||||
|
||||
use redox_scheme::{RequestKind, SignalBehavior, Socket, V2};
|
||||
use event::{user_data, EventQueue};
|
||||
use libredox::errno::{EAGAIN, EINTR};
|
||||
use redox_scheme::{RequestKind, Response, SignalBehavior, Socket, V2};
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::os::fd::AsRawFd;
|
||||
use syscall::EVENT_READ;
|
||||
|
||||
use crate::{
|
||||
framebuffer::FrameBuffer,
|
||||
scheme::{DisplayScheme, HandleKind},
|
||||
};
|
||||
use crate::{framebuffer::FrameBuffer, scheme::DisplayScheme};
|
||||
|
||||
mod display;
|
||||
mod framebuffer;
|
||||
@@ -80,80 +80,138 @@ fn main() {
|
||||
}
|
||||
fn inner(daemon: redox_daemon::Daemon, framebuffers: Vec<FrameBuffer>, spec: &[()]) -> ! {
|
||||
let socket: Socket<V2> =
|
||||
Socket::create("display.vesa").expect("vesad: failed to create display scheme");
|
||||
Socket::nonblock("display.vesa").expect("vesad: failed to create display scheme");
|
||||
|
||||
let mut scheme = DisplayScheme::new(framebuffers, &spec);
|
||||
|
||||
let mut inputd_control_handle = inputd::ControlHandle::new().unwrap();
|
||||
|
||||
user_data! {
|
||||
enum Source {
|
||||
Input,
|
||||
Scheme,
|
||||
}
|
||||
}
|
||||
|
||||
let event_queue: EventQueue<Source> =
|
||||
EventQueue::new().expect("vesad: failed to create event queue");
|
||||
event_queue
|
||||
.subscribe(
|
||||
scheme.inputd_handle.inner().as_raw_fd() as usize,
|
||||
Source::Input,
|
||||
event::EventFlags::READ,
|
||||
)
|
||||
.unwrap();
|
||||
event_queue
|
||||
.subscribe(
|
||||
socket.inner().raw(),
|
||||
Source::Scheme,
|
||||
event::EventFlags::READ,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let _ = File::open("/scheme/debug/disable-graphical-debug");
|
||||
|
||||
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 {
|
||||
let Some(request) = socket
|
||||
.next_request(SignalBehavior::Restart)
|
||||
.expect("vesad: failed to read display scheme")
|
||||
else {
|
||||
// Scheme likely got unmounted
|
||||
std::process::exit(0);
|
||||
};
|
||||
|
||||
match request.kind() {
|
||||
RequestKind::Call(call_request) => {
|
||||
if let Some(resp) = call_request.handle_scheme_block_mut(&mut scheme) {
|
||||
socket
|
||||
.write_response(resp, SignalBehavior::Restart)
|
||||
.expect("vesad: failed to write display scheme");
|
||||
} else {
|
||||
blocked.push(call_request);
|
||||
let all = [Source::Input, Source::Scheme];
|
||||
for event in all
|
||||
.into_iter()
|
||||
.chain(event_queue.map(|e| e.expect("vesad: failed to get next event").user_data))
|
||||
{
|
||||
match event {
|
||||
Source::Input => {
|
||||
while let Some(vt_event) = scheme
|
||||
.inputd_handle
|
||||
.read_vt_event()
|
||||
.expect("vesad: failed to read display handle")
|
||||
{
|
||||
scheme.handle_vt_event(vt_event);
|
||||
}
|
||||
}
|
||||
RequestKind::Cancellation(_cancellation_request) => {}
|
||||
RequestKind::MsyncMsg | RequestKind::MunmapMsg | RequestKind::MmapMsg => unreachable!(),
|
||||
}
|
||||
Source::Scheme => {
|
||||
loop {
|
||||
let request = match socket.next_request(SignalBehavior::Restart) {
|
||||
Ok(Some(request)) => request,
|
||||
Ok(None) => {
|
||||
// Scheme likely got unmounted
|
||||
std::process::exit(0);
|
||||
}
|
||||
Err(err) if err.errno == EAGAIN => break,
|
||||
Err(err) => panic!("vesad: failed to read display scheme: {err}"),
|
||||
};
|
||||
|
||||
// If there are blocked readers, try to handle them.
|
||||
{
|
||||
let mut i = 0;
|
||||
while i < blocked.len() {
|
||||
if let Some(resp) = blocked[i].handle_scheme_block_mut(&mut scheme) {
|
||||
socket
|
||||
.write_response(resp, SignalBehavior::Restart)
|
||||
.expect("vesad: failed to write display scheme");
|
||||
blocked.remove(i);
|
||||
} else {
|
||||
i += 1;
|
||||
match request.kind() {
|
||||
RequestKind::Call(call_request) => {
|
||||
if let Some(resp) = call_request.handle_scheme_block_mut(&mut scheme) {
|
||||
socket
|
||||
.write_response(resp, SignalBehavior::Restart)
|
||||
.expect("vesad: failed to write display scheme");
|
||||
} else {
|
||||
blocked.push(call_request);
|
||||
}
|
||||
}
|
||||
RequestKind::Cancellation(cancellation_request) => {
|
||||
if let Some(i) = blocked.iter().position(|req| {
|
||||
req.request().request_id() == cancellation_request.id
|
||||
}) {
|
||||
let blocked_req = blocked.remove(i);
|
||||
let resp =
|
||||
Response::new(&blocked_req, Err(syscall::Error::new(EINTR)));
|
||||
socket
|
||||
.write_response(resp, SignalBehavior::Restart)
|
||||
.expect("vesad: failed to write display scheme");
|
||||
}
|
||||
}
|
||||
RequestKind::MsyncMsg | RequestKind::MunmapMsg | RequestKind::MmapMsg => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
// If there are blocked readers, try to handle them.
|
||||
{
|
||||
let mut i = 0;
|
||||
while i < blocked.len() {
|
||||
if let Some(resp) = blocked[i].handle_scheme_block_mut(&mut scheme) {
|
||||
socket
|
||||
.write_response(resp, SignalBehavior::Restart)
|
||||
.expect("vesad: failed to write display scheme");
|
||||
blocked.remove(i);
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (handle_id, handle) in scheme.handles.iter_mut() {
|
||||
if handle.notified_read || !handle.events.contains(EVENT_READ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let can_read = scheme
|
||||
.vts
|
||||
.get(&handle.vt)
|
||||
.and_then(|screens| screens.get(&handle.screen))
|
||||
.map_or(false, |screen| screen.can_read());
|
||||
|
||||
if can_read {
|
||||
handle.notified_read = true;
|
||||
socket
|
||||
.post_fevent(*handle_id, EVENT_READ.bits())
|
||||
.expect("vesad: failed to write display event");
|
||||
} else {
|
||||
handle.notified_read = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (handle_id, handle) in scheme.handles.iter_mut() {
|
||||
if handle.notified_read || !handle.events.contains(EVENT_READ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let can_read = if let HandleKind::Screen(vt_i, screen_i) = handle.kind {
|
||||
scheme
|
||||
.vts
|
||||
.get(&vt_i)
|
||||
.and_then(|screens| screens.get(&screen_i))
|
||||
.map_or(false, |screen| screen.can_read())
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if can_read {
|
||||
handle.notified_read = true;
|
||||
socket
|
||||
.post_fevent(*handle_id, EVENT_READ.bits())
|
||||
.expect("vesad: failed to write display event");
|
||||
} else {
|
||||
handle.notified_read = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
panic!();
|
||||
}
|
||||
|
||||
+77
-125
@@ -1,6 +1,7 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::str;
|
||||
|
||||
use inputd::{VtEvent, VtEventKind};
|
||||
use redox_scheme::SchemeBlockMut;
|
||||
use syscall::{Error, EventFlags, MapFlags, Result, EBADF, EINVAL, ENOENT, O_NONBLOCK};
|
||||
|
||||
@@ -12,15 +13,11 @@ pub struct VtIndex(usize);
|
||||
#[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd, Debug)]
|
||||
pub struct ScreenIndex(usize);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum HandleKind {
|
||||
Input,
|
||||
Screen(VtIndex, ScreenIndex),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Handle {
|
||||
pub kind: HandleKind,
|
||||
pub vt: VtIndex,
|
||||
pub screen: ScreenIndex,
|
||||
|
||||
pub flags: usize,
|
||||
pub events: EventFlags,
|
||||
pub notified_read: bool,
|
||||
@@ -32,12 +29,12 @@ pub struct DisplayScheme {
|
||||
pub vts: BTreeMap<VtIndex, BTreeMap<ScreenIndex, GraphicScreen>>,
|
||||
next_id: usize,
|
||||
pub handles: BTreeMap<usize, Handle>,
|
||||
pub inputd_handle: inputd::Handle,
|
||||
pub 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 +44,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 {
|
||||
@@ -84,6 +81,32 @@ impl DisplayScheme {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_vt_event(&mut self, vt_event: VtEvent) {
|
||||
match vt_event.kind {
|
||||
VtEventKind::Activate => {
|
||||
let vt_i = VtIndex(vt_event.vt);
|
||||
|
||||
if let Some(screens) = self.vts.get_mut(&vt_i) {
|
||||
for (screen_i, screen) in screens.iter_mut() {
|
||||
screen.redraw(&mut self.framebuffers[screen_i.0]);
|
||||
}
|
||||
}
|
||||
|
||||
self.active = vt_i;
|
||||
}
|
||||
VtEventKind::Deactivate => {
|
||||
// Nothing to do for deactivate :)
|
||||
}
|
||||
VtEventKind::Resize => {
|
||||
self.resize(
|
||||
vt_event.width as usize,
|
||||
vt_event.height as usize,
|
||||
vt_event.stride as usize,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SchemeBlockMut for DisplayScheme {
|
||||
@@ -94,21 +117,6 @@ impl SchemeBlockMut for DisplayScheme {
|
||||
_uid: u32,
|
||||
_gid: u32,
|
||||
) -> Result<Option<usize>> {
|
||||
if path_str == "handle" {
|
||||
let id = self.next_id;
|
||||
self.next_id += 1;
|
||||
self.handles.insert(
|
||||
id,
|
||||
Handle {
|
||||
kind: HandleKind::Input,
|
||||
flags,
|
||||
events: EventFlags::empty(),
|
||||
notified_read: false,
|
||||
},
|
||||
);
|
||||
return Ok(Some(id));
|
||||
}
|
||||
|
||||
let mut parts = path_str.split('/');
|
||||
let mut vt_screen = parts.next().unwrap_or("").split('.');
|
||||
let vt_i = VtIndex(vt_screen.next().unwrap_or("").parse::<usize>().unwrap_or(1));
|
||||
@@ -121,7 +129,9 @@ impl SchemeBlockMut for DisplayScheme {
|
||||
self.handles.insert(
|
||||
id,
|
||||
Handle {
|
||||
kind: HandleKind::Screen(vt_i, screen_i),
|
||||
vt: vt_i,
|
||||
screen: screen_i,
|
||||
|
||||
flags,
|
||||
events: EventFlags::empty(),
|
||||
notified_read: false,
|
||||
@@ -164,39 +174,25 @@ impl SchemeBlockMut for DisplayScheme {
|
||||
let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
handle.notified_read = false;
|
||||
|
||||
if let HandleKind::Screen(_vt_i, _screen_i) = handle.kind {
|
||||
handle.events = flags;
|
||||
Ok(Some(syscall::EventFlags::empty()))
|
||||
} else {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
handle.events = flags;
|
||||
Ok(Some(syscall::EventFlags::empty()))
|
||||
}
|
||||
|
||||
fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result<Option<usize>> {
|
||||
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
let path_str = match handle.kind {
|
||||
HandleKind::Input => {
|
||||
//TODO: allow inputs associated with other framebuffers?
|
||||
format!(
|
||||
"display:input/{}/{}",
|
||||
self.framebuffers[0].width, self.framebuffers[0].height
|
||||
)
|
||||
}
|
||||
HandleKind::Screen(vt_i, screen_i) => {
|
||||
if let Some(screens) = self.vts.get(&vt_i) {
|
||||
if let Some(screen) = screens.get(&screen_i) {
|
||||
format!(
|
||||
"display:{}.{}/{}/{}",
|
||||
vt_i.0, screen_i.0, screen.width, screen.height
|
||||
)
|
||||
} else {
|
||||
return Err(Error::new(EBADF));
|
||||
}
|
||||
let path_str = {
|
||||
if let Some(screens) = self.vts.get(&handle.vt) {
|
||||
if let Some(screen) = screens.get(&handle.screen) {
|
||||
format!(
|
||||
"display:{}.{}/{}/{}",
|
||||
handle.vt.0, handle.screen.0, screen.width, screen.height
|
||||
)
|
||||
} else {
|
||||
return Err(Error::new(EBADF));
|
||||
}
|
||||
} else {
|
||||
return Err(Error::new(EBADF));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -214,14 +210,12 @@ impl SchemeBlockMut for DisplayScheme {
|
||||
fn fsync(&mut self, id: usize) -> Result<Option<usize>> {
|
||||
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
if let HandleKind::Screen(vt_i, screen_i) = handle.kind {
|
||||
if let Some(screens) = self.vts.get_mut(&vt_i) {
|
||||
if let Some(screen) = screens.get_mut(&screen_i) {
|
||||
if vt_i == self.active {
|
||||
screen.sync(&mut self.framebuffers[screen_i.0]);
|
||||
}
|
||||
return Ok(Some(0));
|
||||
if let Some(screens) = self.vts.get_mut(&handle.vt) {
|
||||
if let Some(screen) = screens.get_mut(&handle.screen) {
|
||||
if handle.vt == self.active {
|
||||
screen.sync(&mut self.framebuffers[handle.screen.0]);
|
||||
}
|
||||
return Ok(Some(0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,18 +231,16 @@ impl SchemeBlockMut for DisplayScheme {
|
||||
) -> Result<Option<usize>> {
|
||||
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
if let HandleKind::Screen(vt_i, screen_i) = handle.kind {
|
||||
if let Some(screens) = self.vts.get_mut(&vt_i) {
|
||||
if let Some(screen) = screens.get_mut(&screen_i) {
|
||||
let nread = screen.read(buf)?;
|
||||
if nread != 0 {
|
||||
return Ok(Some(nread));
|
||||
if let Some(screens) = self.vts.get_mut(&handle.vt) {
|
||||
if let Some(screen) = screens.get_mut(&handle.screen) {
|
||||
let nread = screen.read(buf)?;
|
||||
if nread != 0 {
|
||||
return Ok(Some(nread));
|
||||
} else {
|
||||
if handle.flags & O_NONBLOCK == O_NONBLOCK {
|
||||
return Ok(Some(0));
|
||||
} else {
|
||||
if handle.flags & O_NONBLOCK == O_NONBLOCK {
|
||||
return Ok(Some(0));
|
||||
} else {
|
||||
return Ok(None);
|
||||
}
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -266,56 +258,18 @@ impl SchemeBlockMut for DisplayScheme {
|
||||
) -> Result<Option<usize>> {
|
||||
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
match handle.kind {
|
||||
HandleKind::Input => {
|
||||
use inputd::Cmd as DisplayCommand;
|
||||
|
||||
let command = inputd::parse_command(buf).unwrap();
|
||||
|
||||
match command {
|
||||
DisplayCommand::Activate { vt } => {
|
||||
let vt_i = VtIndex(vt);
|
||||
|
||||
if let Some(screens) = self.vts.get_mut(&vt_i) {
|
||||
for (screen_i, screen) in screens.iter_mut() {
|
||||
screen.redraw(&mut self.framebuffers[screen_i.0]);
|
||||
}
|
||||
}
|
||||
|
||||
self.active = vt_i;
|
||||
}
|
||||
|
||||
DisplayCommand::Resize {
|
||||
width,
|
||||
height,
|
||||
stride,
|
||||
..
|
||||
} => {
|
||||
self.resize(width as usize, height as usize, stride as usize);
|
||||
}
|
||||
|
||||
// Nothing to do for deactivate :)
|
||||
DisplayCommand::Deactivate(_) => {}
|
||||
}
|
||||
|
||||
Ok(Some(buf.len()))
|
||||
}
|
||||
|
||||
HandleKind::Screen(vt_i, screen_i) => {
|
||||
if let Some(screens) = self.vts.get_mut(&vt_i) {
|
||||
if let Some(screen) = screens.get_mut(&screen_i) {
|
||||
let count = screen.write(buf)?;
|
||||
if vt_i == self.active {
|
||||
screen.sync(&mut self.framebuffers[screen_i.0]);
|
||||
}
|
||||
Ok(Some(count))
|
||||
} else {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
} else {
|
||||
Err(Error::new(EBADF))
|
||||
if let Some(screens) = self.vts.get_mut(&handle.vt) {
|
||||
if let Some(screen) = screens.get_mut(&handle.screen) {
|
||||
let count = screen.write(buf)?;
|
||||
if handle.vt == self.active {
|
||||
screen.sync(&mut self.framebuffers[handle.screen.0]);
|
||||
}
|
||||
Ok(Some(count))
|
||||
} else {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
} else {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,14 +286,12 @@ impl SchemeBlockMut for DisplayScheme {
|
||||
) -> Result<Option<usize>> {
|
||||
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
if let HandleKind::Screen(vt_i, screen_i) = handle.kind {
|
||||
if let Some(screens) = self.vts.get(&vt_i) {
|
||||
if let Some(screen) = screens.get(&screen_i) {
|
||||
if off as usize + size <= screen.offscreen.len() * 4 {
|
||||
return Ok(Some(screen.offscreen.as_ptr() as usize + off as usize));
|
||||
} else {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
if let Some(screens) = self.vts.get(&handle.vt) {
|
||||
if let Some(screen) = screens.get(&handle.screen) {
|
||||
if off as usize + size <= screen.offscreen.len() * 4 {
|
||||
return Ok(Some(screen.offscreen.as_ptr() as usize + off as usize));
|
||||
} else {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use std::sync::atomic::{AtomicBool, AtomicU32, AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use common::{dma::Dma, sgl};
|
||||
use inputd::Damage;
|
||||
use inputd::{Damage, VtEvent, VtEventKind};
|
||||
|
||||
use redox_scheme::SchemeMut;
|
||||
use syscall::{Error as SysError, MapFlags, EAGAIN, EINVAL, PAGE_SIZE};
|
||||
@@ -246,12 +246,9 @@ impl<'a> Display<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
enum Handle<'a> {
|
||||
Vt {
|
||||
display: Arc<Display<'a>>,
|
||||
vt: usize,
|
||||
},
|
||||
Input,
|
||||
struct Handle<'a> {
|
||||
display: Arc<Display<'a>>,
|
||||
vt: usize,
|
||||
}
|
||||
|
||||
pub struct Scheme<'a> {
|
||||
@@ -331,17 +328,52 @@ impl<'a> Scheme<'a> {
|
||||
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
// FIXME wire this up
|
||||
fn handle_vt_event(&mut self, vt_event: VtEvent) {
|
||||
match vt_event.kind {
|
||||
VtEventKind::Activate => {
|
||||
log::info!("activate {}", vt_event.vt);
|
||||
|
||||
for handle in self.handles.values() {
|
||||
if handle.vt != vt_event.vt {
|
||||
continue;
|
||||
}
|
||||
|
||||
log::warn!("virtio-gpu: activating");
|
||||
|
||||
futures::executor::block_on(handle.display.init()).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
VtEventKind::Deactivate => {
|
||||
log::info!("deactivate {}", vt_event.vt);
|
||||
|
||||
for handle in self.handles.values() {
|
||||
if handle.vt != vt_event.vt {
|
||||
continue;
|
||||
}
|
||||
|
||||
log::warn!("virtio-gpu: deactivating");
|
||||
|
||||
futures::executor::block_on(handle.display.detach()).unwrap();
|
||||
break;
|
||||
}
|
||||
|
||||
// for display in self.displays.iter() {
|
||||
// futures::executor::block_on(display.detach()).unwrap();
|
||||
// }
|
||||
}
|
||||
|
||||
VtEventKind::Resize => {
|
||||
log::warn!("virtio-gpu: resize is not implemented yet")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SchemeMut for Scheme<'a> {
|
||||
fn open(&mut self, path: &str, _flags: usize, _uid: u32, _gid: u32) -> syscall::Result<usize> {
|
||||
if path == "handle" {
|
||||
let fd = self.next_id.fetch_add(1, Ordering::SeqCst);
|
||||
self.handles.insert(fd, Handle::Input);
|
||||
|
||||
return Ok(fd);
|
||||
}
|
||||
|
||||
let mut parts = path.split('/');
|
||||
let mut screen = parts.next().unwrap_or("").split('.');
|
||||
|
||||
@@ -355,7 +387,7 @@ impl<'a> SchemeMut for Scheme<'a> {
|
||||
let fd = self.next_id.fetch_add(1, Ordering::SeqCst);
|
||||
self.handles.insert(
|
||||
fd,
|
||||
Handle::Vt {
|
||||
Handle {
|
||||
display: display.clone(),
|
||||
vt,
|
||||
},
|
||||
@@ -364,25 +396,15 @@ impl<'a> SchemeMut for Scheme<'a> {
|
||||
}
|
||||
|
||||
fn fpath(&mut self, id: usize, buf: &mut [u8]) -> syscall::Result<usize> {
|
||||
match self.handles.get(&id).unwrap() {
|
||||
Handle::Vt { display, .. } => {
|
||||
let bytes_copied = futures::executor::block_on(display.get_fpath(buf)).unwrap();
|
||||
Ok(bytes_copied)
|
||||
}
|
||||
|
||||
Handle::Input => unreachable!(),
|
||||
}
|
||||
let handle = self.handles.get(&id).unwrap();
|
||||
let bytes_copied = futures::executor::block_on(handle.display.get_fpath(buf)).unwrap();
|
||||
Ok(bytes_copied)
|
||||
}
|
||||
|
||||
fn fsync(&mut self, id: usize) -> syscall::Result<usize> {
|
||||
match self.handles.get(&id).ok_or(SysError::new(EINVAL))? {
|
||||
Handle::Vt { display, .. } => {
|
||||
futures::executor::block_on(display.flush(None)).unwrap();
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
_ => unreachable!(),
|
||||
}
|
||||
let handle = self.handles.get(&id).ok_or(SysError::new(EINVAL))?;
|
||||
futures::executor::block_on(handle.display.flush(None)).unwrap();
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn read(
|
||||
@@ -404,73 +426,26 @@ impl<'a> SchemeMut for Scheme<'a> {
|
||||
_offset: u64,
|
||||
_fcntl_flags: u32,
|
||||
) -> syscall::Result<usize> {
|
||||
match self.handles.get(&id).ok_or(SysError::new(EINVAL))? {
|
||||
Handle::Vt { display, .. } => {
|
||||
// The VT is not active and the device is reseted. Ask them to try
|
||||
// again later.
|
||||
if display.is_reseted.load(Ordering::SeqCst) {
|
||||
return Err(SysError::new(EAGAIN));
|
||||
}
|
||||
let handle = self.handles.get(&id).ok_or(SysError::new(EINVAL))?;
|
||||
|
||||
let damages = unsafe {
|
||||
core::slice::from_raw_parts(
|
||||
buf.as_ptr() as *const Damage,
|
||||
buf.len() / core::mem::size_of::<Damage>(),
|
||||
)
|
||||
};
|
||||
|
||||
for damage in damages {
|
||||
futures::executor::block_on(display.flush(Some(damage))).unwrap();
|
||||
}
|
||||
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
Handle::Input => {
|
||||
use inputd::Cmd as DisplayCommand;
|
||||
|
||||
let command = inputd::parse_command(buf).unwrap();
|
||||
|
||||
match command {
|
||||
DisplayCommand::Activate { vt } => {
|
||||
let target_vt = vt;
|
||||
|
||||
for handle in self.handles.values() {
|
||||
if let Handle::Vt { display, vt } = handle {
|
||||
if *vt != target_vt {
|
||||
continue;
|
||||
}
|
||||
|
||||
futures::executor::block_on(display.init()).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DisplayCommand::Deactivate(target_vt) => {
|
||||
for handle in self.handles.values() {
|
||||
if let Handle::Vt { display, vt } = handle {
|
||||
if *vt != target_vt {
|
||||
continue;
|
||||
}
|
||||
|
||||
futures::executor::block_on(display.detach()).unwrap();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// for display in self.displays.iter() {
|
||||
// futures::executor::block_on(display.detach()).unwrap();
|
||||
// }
|
||||
}
|
||||
|
||||
DisplayCommand::Resize { .. } => {
|
||||
log::warn!("virtio-gpu: resize is not implemented yet")
|
||||
}
|
||||
}
|
||||
|
||||
Ok(buf.len())
|
||||
}
|
||||
// The VT is not active and the device is reseted. Ask them to try
|
||||
// again later.
|
||||
if handle.display.is_reseted.load(Ordering::SeqCst) {
|
||||
return Err(SysError::new(EAGAIN));
|
||||
}
|
||||
|
||||
let damages = unsafe {
|
||||
core::slice::from_raw_parts(
|
||||
buf.as_ptr() as *const Damage,
|
||||
buf.len() / core::mem::size_of::<Damage>(),
|
||||
)
|
||||
};
|
||||
|
||||
for damage in damages {
|
||||
futures::executor::block_on(handle.display.flush(Some(damage))).unwrap();
|
||||
}
|
||||
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn close(&mut self, _id: usize) -> syscall::Result<usize> {
|
||||
@@ -484,12 +459,8 @@ impl<'a> SchemeMut for Scheme<'a> {
|
||||
flags: MapFlags,
|
||||
) -> syscall::Result<usize> {
|
||||
log::info!("KSMSG MMAP {} {:?} {} {}", id, flags, offset, size);
|
||||
match self.handles.get(&id).ok_or(SysError::new(EINVAL))? {
|
||||
Handle::Vt { display, .. } => Ok(futures::executor::block_on(
|
||||
display.map_screen(offset as usize),
|
||||
)
|
||||
.unwrap() as usize),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
let handle = self.handles.get(&id).ok_or(SysError::new(EINVAL))?;
|
||||
let ptr = futures::executor::block_on(handle.display.map_screen(offset as usize)).unwrap();
|
||||
Ok(ptr as usize)
|
||||
}
|
||||
}
|
||||
|
||||
+53
-113
@@ -2,9 +2,15 @@
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{Error, Read, Write};
|
||||
use std::mem::size_of;
|
||||
use std::os::fd::{AsFd, BorrowedFd};
|
||||
|
||||
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>())
|
||||
std::slice::from_raw_parts((p as *const T) as *const u8, size_of::<T>())
|
||||
}
|
||||
|
||||
unsafe fn any_as_u8_slice_mut<T: Sized>(p: &mut T) -> &mut [u8] {
|
||||
std::slice::from_raw_parts_mut((p as *mut T) as *mut u8, size_of::<T>())
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -13,9 +19,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,131 +29,65 @@ 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 fn read_vt_event(&mut self) -> Result<Option<VtEvent>, Error> {
|
||||
let mut event = VtEvent {
|
||||
kind: VtEventKind::Resize,
|
||||
vt: usize::MAX,
|
||||
width: u32::MAX,
|
||||
height: u32::MAX,
|
||||
stride: u32::MAX,
|
||||
};
|
||||
|
||||
let nread = self.0.read(unsafe { any_as_u8_slice_mut(&mut event) })?;
|
||||
|
||||
if nread == 0 {
|
||||
Ok(None)
|
||||
} else {
|
||||
assert_eq!(nread, size_of::<VtEvent>());
|
||||
Ok(Some(event))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn inner(&self) -> BorrowedFd<'_> {
|
||||
self.0.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
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) })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
#[repr(u8)]
|
||||
enum CmdTy {
|
||||
Unknown = 0,
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(usize)]
|
||||
pub enum VtEventKind {
|
||||
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,
|
||||
},
|
||||
#[repr(C)]
|
||||
pub struct VtEvent {
|
||||
pub kind: VtEventKind,
|
||||
pub vt: usize,
|
||||
|
||||
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 } => {
|
||||
let cmd = VtActivate { vt };
|
||||
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 })
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
pub stride: u32,
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
|
||||
+190
-116
@@ -11,12 +11,12 @@
|
||||
//! Read events from `input:consumer`. Optionally, set the `EVENT_READ` flag to be notified when
|
||||
//! events are available.
|
||||
|
||||
use core::mem::size_of;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fs::File;
|
||||
use std::os::fd::AsRawFd;
|
||||
use std::mem::transmute;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use inputd::{Cmd, VtActivate};
|
||||
use inputd::{VtActivate, VtEvent, VtEventKind};
|
||||
|
||||
use redox_scheme::{RequestKind, SchemeMut, SignalBehavior, Socket, V2};
|
||||
|
||||
@@ -31,9 +31,13 @@ enum Handle {
|
||||
notified: bool,
|
||||
vt: usize,
|
||||
},
|
||||
Device {
|
||||
Display {
|
||||
events: EventFlags,
|
||||
pending: Vec<VtEvent>,
|
||||
notified: bool,
|
||||
device: String,
|
||||
},
|
||||
Control,
|
||||
}
|
||||
|
||||
impl Handle {
|
||||
@@ -44,28 +48,14 @@ impl Handle {
|
||||
|
||||
struct Vt {
|
||||
display: String,
|
||||
index: usize,
|
||||
|
||||
/// This is *required* to be lazily initialized since opening the handle to the display
|
||||
/// requires the system call to return first. Otherwise, it will block indefinitely.
|
||||
handle_file: Option<File>,
|
||||
}
|
||||
|
||||
impl Vt {
|
||||
fn new(display: impl Into<String>, index: usize) -> Self {
|
||||
fn new(display: impl Into<String>) -> Self {
|
||||
Self {
|
||||
display: display.into(),
|
||||
handle_file: None,
|
||||
index,
|
||||
}
|
||||
}
|
||||
|
||||
fn send_command(&mut self, cmd: Cmd) -> Result<(), libredox::error::Error> {
|
||||
let handle_file = self
|
||||
.handle_file
|
||||
.get_or_insert_with(|| File::open(format!("/scheme/{}/handle", self.display)).unwrap());
|
||||
inputd::send_comand(handle_file, cmd)
|
||||
}
|
||||
}
|
||||
|
||||
struct InputScheme {
|
||||
@@ -78,7 +68,6 @@ struct InputScheme {
|
||||
super_key: bool,
|
||||
active_vt: Option<usize>,
|
||||
|
||||
pending_activate: Option<VtActivate>,
|
||||
has_new_events: bool,
|
||||
}
|
||||
|
||||
@@ -93,10 +82,67 @@ impl InputScheme {
|
||||
super_key: false,
|
||||
active_vt: None,
|
||||
|
||||
pending_activate: None,
|
||||
has_new_events: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn switch_vt(&mut self, new_active: usize) -> syscall::Result<()> {
|
||||
if let Some(active_vt) = self.active_vt {
|
||||
if new_active == active_vt {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
if !self.vts.contains_key(&new_active) {
|
||||
log::warn!("inputd: switch to non-existent VT #{new_active} was requested");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
log::info!(
|
||||
"inputd: switching from VT #{} to VT #{new_active}",
|
||||
self.active_vt.unwrap_or(0)
|
||||
);
|
||||
|
||||
for handle in self.handles.values_mut() {
|
||||
match handle {
|
||||
Handle::Display {
|
||||
pending,
|
||||
notified,
|
||||
device,
|
||||
..
|
||||
} => {
|
||||
if let Some(active_vt) = self.active_vt {
|
||||
if &self.vts[&active_vt].display == &*device {
|
||||
pending.push(VtEvent {
|
||||
kind: VtEventKind::Deactivate,
|
||||
vt: self.active_vt.unwrap(),
|
||||
width: 0,
|
||||
height: 0,
|
||||
stride: 0,
|
||||
});
|
||||
*notified = false;
|
||||
}
|
||||
}
|
||||
|
||||
if &self.vts[&new_active].display == &*device {
|
||||
pending.push(VtEvent {
|
||||
kind: VtEventKind::Activate,
|
||||
vt: new_active,
|
||||
width: 0,
|
||||
height: 0,
|
||||
stride: 0,
|
||||
});
|
||||
*notified = false;
|
||||
}
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
|
||||
self.active_vt = Some(new_active);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl SchemeMut for InputScheme {
|
||||
@@ -123,8 +169,14 @@ impl SchemeMut for InputScheme {
|
||||
}
|
||||
"handle" => {
|
||||
let display = path_parts.collect::<Vec<_>>().join(".");
|
||||
Handle::Device { device: display }
|
||||
Handle::Display {
|
||||
events: EventFlags::empty(),
|
||||
pending: Vec::new(),
|
||||
notified: false,
|
||||
device: display,
|
||||
}
|
||||
}
|
||||
"control" => Handle::Control,
|
||||
|
||||
_ => {
|
||||
log::error!("inputd: invalid path {path}");
|
||||
@@ -174,18 +226,42 @@ impl SchemeMut for InputScheme {
|
||||
Ok(copy)
|
||||
}
|
||||
|
||||
Handle::Device { device } => {
|
||||
assert!(buf.is_empty());
|
||||
Handle::Display {
|
||||
pending, device, ..
|
||||
} => {
|
||||
// FIXME Create new VT through a write instead and return a NewVt event on read
|
||||
// This allows also returning events for VT (de)activation from the display handle
|
||||
// rather than pushing them to the graphics driver.
|
||||
if buf.is_empty() {
|
||||
// Trying to do an empty read creates a new VT.
|
||||
let vt = self.next_vt_id.fetch_add(1, Ordering::SeqCst);
|
||||
log::info!("inputd: created VT #{vt} for {device}");
|
||||
self.vts.insert(vt, Vt::new(device.clone()));
|
||||
Ok(vt)
|
||||
} else if buf.len() % size_of::<VtEvent>() == 0 {
|
||||
let copy = core::cmp::min(pending.len(), buf.len() / size_of::<VtEvent>());
|
||||
|
||||
let vt = self.next_vt_id.fetch_add(1, Ordering::SeqCst);
|
||||
self.vts.insert(vt, Vt::new(device.clone(), vt));
|
||||
Ok(vt)
|
||||
for (i, event) in pending.drain(..copy).enumerate() {
|
||||
buf[i * size_of::<VtEvent>()..(i + 1) * size_of::<VtEvent>()]
|
||||
.copy_from_slice(&unsafe {
|
||||
transmute::<VtEvent, [u8; size_of::<VtEvent>()]>(event)
|
||||
});
|
||||
}
|
||||
Ok(copy * size_of::<VtEvent>())
|
||||
} else {
|
||||
log::error!("inputd: display tried to read incorrectly sized event");
|
||||
return Err(SysError::new(EINVAL));
|
||||
}
|
||||
}
|
||||
|
||||
Handle::Producer => {
|
||||
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,17 +277,16 @@ impl SchemeMut for InputScheme {
|
||||
let handle = self.handles.get_mut(&id).ok_or(SysError::new(EINVAL))?;
|
||||
|
||||
match handle {
|
||||
Handle::Device { device } => {
|
||||
if buf.len() != core::mem::size_of::<VtActivate>() {
|
||||
log::error!("inputd: device tried to write incorrectly sized command");
|
||||
Handle::Control => {
|
||||
if buf.len() != size_of::<VtActivate>() {
|
||||
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());
|
||||
self.switch_vt(cmd.vt)?;
|
||||
|
||||
return Ok(buf.len());
|
||||
}
|
||||
@@ -220,6 +295,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 => {}
|
||||
}
|
||||
|
||||
@@ -230,11 +309,11 @@ impl SchemeMut for InputScheme {
|
||||
let events = unsafe {
|
||||
core::slice::from_raw_parts(
|
||||
buf.as_ptr() as *const Event,
|
||||
buf.len() / core::mem::size_of::<Event>(),
|
||||
buf.len() / size_of::<Event>(),
|
||||
)
|
||||
};
|
||||
|
||||
'out: for event in events.iter() {
|
||||
for event in events.iter() {
|
||||
let mut new_active_opt = None;
|
||||
match event.to_option() {
|
||||
EventOption::Key(key_event) => match key_event.scancode {
|
||||
@@ -262,42 +341,41 @@ impl SchemeMut for InputScheme {
|
||||
},
|
||||
|
||||
EventOption::Resize(resize_event) => {
|
||||
let active_vt = self.vts.get_mut(&self.active_vt.unwrap()).unwrap();
|
||||
active_vt.send_command(Cmd::Resize {
|
||||
vt: active_vt.index,
|
||||
width: resize_event.width,
|
||||
height: resize_event.height,
|
||||
for handle in self.handles.values_mut() {
|
||||
match handle {
|
||||
Handle::Display {
|
||||
pending,
|
||||
notified,
|
||||
device,
|
||||
..
|
||||
} => {
|
||||
if &self.vts[&self.active_vt.unwrap()].display == &*device {
|
||||
pending.push(VtEvent {
|
||||
kind: VtEventKind::Resize,
|
||||
vt: self.active_vt.unwrap(),
|
||||
width: resize_event.width,
|
||||
height: resize_event.height,
|
||||
|
||||
// TODO(andypython): Figure out how to get the stride.
|
||||
stride: resize_event.width,
|
||||
})?;
|
||||
// TODO(andypython): Figure out how to get the stride.
|
||||
stride: resize_event.width,
|
||||
});
|
||||
*notified = false;
|
||||
}
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => continue,
|
||||
}
|
||||
|
||||
if let Some(new_active) = new_active_opt {
|
||||
if new_active == self.vts[&self.active_vt.unwrap()].index {
|
||||
continue 'out;
|
||||
}
|
||||
|
||||
if self.vts.contains_key(&new_active) {
|
||||
let active_vt = self.vts.get_mut(&self.active_vt.unwrap()).unwrap();
|
||||
|
||||
active_vt.send_command(Cmd::Deactivate(active_vt.index))?;
|
||||
}
|
||||
|
||||
if let Some(new_active) = self.vts.get_mut(&new_active) {
|
||||
new_active.send_command(Cmd::Activate {
|
||||
vt: new_active.index,
|
||||
})?;
|
||||
self.active_vt = Some(new_active.index);
|
||||
} else {
|
||||
log::warn!("inputd: switch to non-existent VT #{new_active} was requested");
|
||||
}
|
||||
self.switch_vt(new_active)?;
|
||||
}
|
||||
}
|
||||
|
||||
let handle = self.handles.get_mut(&id).ok_or(SysError::new(EINVAL))?;
|
||||
assert!(handle.is_producer());
|
||||
|
||||
let active_vt = self.active_vt.unwrap();
|
||||
@@ -340,8 +418,17 @@ 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::Display {
|
||||
ref mut events,
|
||||
ref mut notified,
|
||||
..
|
||||
} => {
|
||||
*events = flags;
|
||||
*notified = false;
|
||||
Ok(EventFlags::empty())
|
||||
}
|
||||
Handle::Producer | Handle::Control => {
|
||||
log::error!("inputd: producer or control tried to use an event queue");
|
||||
Err(SysError::new(EINVAL))
|
||||
}
|
||||
}
|
||||
@@ -377,44 +464,51 @@ fn deamon(deamon: redox_daemon::Daemon) -> anyhow::Result<()> {
|
||||
RequestKind::MsyncMsg | RequestKind::MunmapMsg | RequestKind::MmapMsg => unreachable!(),
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
scheme.active_vt = Some(vt.index);
|
||||
}
|
||||
|
||||
if !scheme.has_new_events {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (id, handle) in scheme.handles.iter_mut() {
|
||||
if let Handle::Consumer {
|
||||
events,
|
||||
pending,
|
||||
ref mut notified,
|
||||
vt,
|
||||
} = handle
|
||||
{
|
||||
if pending.is_empty() || *notified || !events.contains(EventFlags::EVENT_READ) {
|
||||
continue;
|
||||
match handle {
|
||||
Handle::Consumer {
|
||||
events,
|
||||
pending,
|
||||
ref mut notified,
|
||||
vt,
|
||||
} => {
|
||||
if pending.is_empty() || *notified || !events.contains(EventFlags::EVENT_READ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let active_vt = scheme.active_vt.unwrap();
|
||||
|
||||
// The activate VT is not the same as the VT that the consumer is listening to
|
||||
// for events.
|
||||
if active_vt != *vt {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Notify the consumer that we have some events to read. Yum yum.
|
||||
socket_file.post_fevent(*id, EventFlags::EVENT_READ.bits())?;
|
||||
|
||||
*notified = true;
|
||||
}
|
||||
Handle::Display {
|
||||
events,
|
||||
pending,
|
||||
ref mut notified,
|
||||
..
|
||||
} => {
|
||||
if pending.is_empty() || *notified || !events.contains(EventFlags::EVENT_READ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let active_vt = scheme.active_vt.unwrap();
|
||||
// Notify the consumer that we have some events to read. Yum yum.
|
||||
socket_file.post_fevent(*id, EventFlags::EVENT_READ.bits())?;
|
||||
|
||||
// The activate VT is not the same as the VT that the consumer is listening to
|
||||
// for events.
|
||||
if active_vt != *vt {
|
||||
continue;
|
||||
*notified = true;
|
||||
}
|
||||
|
||||
// Notify the consumer that we have some events to read. Yum yum.
|
||||
socket_file.post_fevent(*id, EventFlags::EVENT_READ.bits())?;
|
||||
|
||||
*notified = true;
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -442,31 +536,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