Convert vesad to be handle based, allow O_NONBLOCK
This commit is contained in:
+5
-5
@@ -7,7 +7,7 @@ extern crate alloc;
|
||||
extern crate orbclient;
|
||||
extern crate syscall;
|
||||
|
||||
use std::{env, mem};
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use syscall::{physmap, physunmap, Packet, SchemeMut, EVENT_READ, MAP_WRITE, MAP_WRITE_COMBINE};
|
||||
@@ -68,7 +68,7 @@ fn main() {
|
||||
socket.read(&mut packet).expect("vesad: failed to read display scheme");
|
||||
|
||||
// If it is a read packet, and there is no data, block it. Otherwise, handle packet
|
||||
if packet.a == syscall::number::SYS_READ && packet.d > 0 && scheme.will_block(packet.b) {
|
||||
if packet.a == syscall::number::SYS_READ && packet.d > 0 && scheme.can_read(packet.b).is_none() {
|
||||
blocked.push(packet);
|
||||
} else {
|
||||
scheme.handle(&mut packet);
|
||||
@@ -79,7 +79,7 @@ fn main() {
|
||||
{
|
||||
let mut i = 0;
|
||||
while i < blocked.len() {
|
||||
if ! scheme.will_block(blocked[i].b) {
|
||||
if scheme.can_read(blocked[i].b).is_some() {
|
||||
let mut packet = blocked.remove(i);
|
||||
scheme.handle(&mut packet);
|
||||
socket.write(&packet).expect("vesad: failed to write display scheme");
|
||||
@@ -90,7 +90,7 @@ fn main() {
|
||||
}
|
||||
|
||||
for (screen_id, screen) in scheme.screens.iter() {
|
||||
if ! screen.will_block() {
|
||||
if let Some(count) = screen.can_read() {
|
||||
let event_packet = Packet {
|
||||
id: 0,
|
||||
pid: 0,
|
||||
@@ -99,7 +99,7 @@ fn main() {
|
||||
a: syscall::number::SYS_FEVENT,
|
||||
b: *screen_id,
|
||||
c: EVENT_READ,
|
||||
d: mem::size_of::<orbclient::Event>()
|
||||
d: count
|
||||
};
|
||||
|
||||
socket.write(&event_packet).expect("vesad: failed to write display event");
|
||||
|
||||
+131
-51
@@ -2,16 +2,30 @@ use std::collections::BTreeMap;
|
||||
use std::{mem, slice, str};
|
||||
|
||||
use orbclient::{Event, EventOption};
|
||||
use syscall::{Result, Error, EACCES, EBADF, ENOENT, SchemeMut};
|
||||
use syscall::{Result, Error, EACCES, EBADF, ENOENT, O_NONBLOCK, SchemeMut};
|
||||
|
||||
use display::Display;
|
||||
use screen::{Screen, GraphicScreen, TextScreen};
|
||||
|
||||
#[derive(Clone)]
|
||||
enum HandleKind {
|
||||
Input,
|
||||
Screen(usize),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Handle {
|
||||
kind: HandleKind,
|
||||
flags: usize,
|
||||
}
|
||||
|
||||
pub struct DisplayScheme {
|
||||
width: usize,
|
||||
height: usize,
|
||||
active: usize,
|
||||
pub screens: BTreeMap<usize, Box<Screen>>
|
||||
pub screens: BTreeMap<usize, Box<Screen>>,
|
||||
next_id: usize,
|
||||
handles: BTreeMap<usize, Handle>,
|
||||
}
|
||||
|
||||
impl DisplayScheme {
|
||||
@@ -32,37 +46,67 @@ impl DisplayScheme {
|
||||
width: width,
|
||||
height: height,
|
||||
active: 1,
|
||||
screens: screens
|
||||
screens: screens,
|
||||
next_id: 0,
|
||||
handles: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn will_block(&self, id: usize) -> bool {
|
||||
if let Some(screen) = self.screens.get(&id) {
|
||||
screen.will_block()
|
||||
} else {
|
||||
false
|
||||
pub fn can_read(&self, id: usize) -> Option<usize> {
|
||||
if let Some(handle) = self.handles.get(&id) {
|
||||
if let HandleKind::Screen(screen_i) = handle.kind {
|
||||
if let Some(screen) = self.screens.get(&screen_i) {
|
||||
match screen.can_read() {
|
||||
Some(count) => return Some(count),
|
||||
None => if handle.flags & O_NONBLOCK == O_NONBLOCK {
|
||||
return Some(0);
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(0)
|
||||
}
|
||||
}
|
||||
|
||||
impl SchemeMut for DisplayScheme {
|
||||
fn open(&mut self, path: &[u8], _flags: usize, uid: u32, _gid: u32) -> Result<usize> {
|
||||
fn open(&mut self, path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result<usize> {
|
||||
if path == b"input" {
|
||||
if uid == 0 {
|
||||
Ok(0)
|
||||
let id = self.next_id;
|
||||
self.next_id += 1;
|
||||
|
||||
self.handles.insert(id, Handle {
|
||||
kind: HandleKind::Input,
|
||||
flags: flags
|
||||
});
|
||||
|
||||
Ok(id)
|
||||
} else {
|
||||
Err(Error::new(EACCES))
|
||||
}
|
||||
} else {
|
||||
let path_str = str::from_utf8(path).unwrap_or("").trim_matches('/');
|
||||
let mut parts = path_str.split('/');
|
||||
let id = parts.next().unwrap_or("").parse::<usize>().unwrap_or(0);
|
||||
if self.screens.contains_key(&id) {
|
||||
let screen_i = parts.next().unwrap_or("").parse::<usize>().unwrap_or(0);
|
||||
if self.screens.contains_key(&screen_i) {
|
||||
for cmd in parts {
|
||||
if cmd == "activate" {
|
||||
self.active = id;
|
||||
self.active = screen_i;
|
||||
}
|
||||
}
|
||||
|
||||
let id = self.next_id;
|
||||
self.next_id += 1;
|
||||
|
||||
self.handles.insert(id, Handle {
|
||||
kind: HandleKind::Screen(screen_i),
|
||||
flags: flags
|
||||
});
|
||||
|
||||
Ok(id)
|
||||
} else {
|
||||
Err(Error::new(ENOENT))
|
||||
@@ -71,32 +115,52 @@ impl SchemeMut for DisplayScheme {
|
||||
}
|
||||
|
||||
fn dup(&mut self, id: usize, _buf: &[u8]) -> Result<usize> {
|
||||
Ok(id)
|
||||
let handle = self.handles.get(&id).map(|handle| handle.clone()).ok_or(Error::new(EBADF))?;
|
||||
|
||||
let new_id = self.next_id;
|
||||
self.next_id += 1;
|
||||
|
||||
self.handles.insert(new_id, handle.clone());
|
||||
|
||||
Ok(new_id)
|
||||
}
|
||||
|
||||
fn fevent(&mut self, id: usize, flags: usize) -> Result<usize> {
|
||||
if let Some(mut screen) = self.screens.get_mut(&id) {
|
||||
screen.event(flags).and(Ok(id))
|
||||
} else {
|
||||
Err(Error::new(EBADF))
|
||||
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
if let HandleKind::Screen(screen_i) = handle.kind {
|
||||
if let Some(mut screen) = self.screens.get_mut(&screen_i) {
|
||||
return screen.event(flags).and(Ok(screen_i));
|
||||
}
|
||||
}
|
||||
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
|
||||
fn fmap(&mut self, id: usize, offset: usize, size: usize) -> Result<usize> {
|
||||
if let Some(screen) = self.screens.get(&id) {
|
||||
screen.map(offset, size)
|
||||
} else {
|
||||
Err(Error::new(EBADF))
|
||||
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
if let HandleKind::Screen(screen_i) = handle.kind {
|
||||
if let Some(screen) = self.screens.get(&screen_i) {
|
||||
return screen.map(offset, size);
|
||||
}
|
||||
}
|
||||
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
|
||||
fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
let path_str = if id == 0 {
|
||||
format!("display:input/{}/{}", self.width, self.height)
|
||||
} else if let Some(screen) = self.screens.get(&id) {
|
||||
format!("display:{}/{}/{}", id, screen.width(), screen.height())
|
||||
} else {
|
||||
return Err(Error::new(EBADF));
|
||||
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
let path_str = match handle.kind {
|
||||
HandleKind::Input => {
|
||||
format!("display:input/{}/{}", self.width, self.height)
|
||||
},
|
||||
HandleKind::Screen(screen_i) => if let Some(screen) = self.screens.get(&screen_i) {
|
||||
format!("display:{}/{}/{}", screen_i, screen.width(), screen.height())
|
||||
} else {
|
||||
return Err(Error::new(EBADF));
|
||||
}
|
||||
};
|
||||
|
||||
let path = path_str.as_bytes();
|
||||
@@ -111,27 +175,37 @@ impl SchemeMut for DisplayScheme {
|
||||
}
|
||||
|
||||
fn fsync(&mut self, id: usize) -> Result<usize> {
|
||||
if let Some(mut screen) = self.screens.get_mut(&id) {
|
||||
if id == self.active {
|
||||
screen.sync();
|
||||
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
if let HandleKind::Screen(screen_i) = handle.kind {
|
||||
if let Some(mut screen) = self.screens.get_mut(&screen_i) {
|
||||
if screen_i == self.active {
|
||||
screen.sync();
|
||||
}
|
||||
return Ok(0);
|
||||
}
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
|
||||
fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
if let Some(mut screen) = self.screens.get_mut(&id) {
|
||||
screen.read(buf)
|
||||
} else {
|
||||
Err(Error::new(EBADF))
|
||||
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
if let HandleKind::Screen(screen_i) = handle.kind {
|
||||
if let Some(mut screen) = self.screens.get_mut(&screen_i) {
|
||||
return screen.read(buf);
|
||||
}
|
||||
}
|
||||
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
|
||||
fn write(&mut self, id: usize, buf: &[u8]) -> Result<usize> {
|
||||
if id == 0 {
|
||||
if buf.len() == 1 && buf[0] >= 0xF4 {
|
||||
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
match handle.kind {
|
||||
HandleKind::Input => if buf.len() == 1 && buf[0] >= 0xF4 {
|
||||
let new_active = (buf[0] - 0xF4) as usize + 1;
|
||||
if let Some(mut screen) = self.screens.get_mut(&new_active) {
|
||||
self.active = new_active;
|
||||
@@ -158,9 +232,9 @@ impl SchemeMut for DisplayScheme {
|
||||
},
|
||||
EventOption::Resize(resize_event) => {
|
||||
println!("Resizing to {}, {}", resize_event.width, resize_event.height);
|
||||
for (screen_id, screen) in self.screens.iter_mut() {
|
||||
for (screen_i, screen) in self.screens.iter_mut() {
|
||||
screen.resize(resize_event.width as usize, resize_event.height as usize);
|
||||
if *screen_id == self.active {
|
||||
if *screen_i == self.active {
|
||||
screen.redraw();
|
||||
}
|
||||
}
|
||||
@@ -181,23 +255,29 @@ impl SchemeMut for DisplayScheme {
|
||||
}
|
||||
|
||||
Ok(events.len() * mem::size_of::<Event>())
|
||||
},
|
||||
HandleKind::Screen(screen_i) => if let Some(mut screen) = self.screens.get_mut(&screen_i) {
|
||||
screen.write(buf, screen_i == self.active)
|
||||
} else {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
} else if let Some(mut screen) = self.screens.get_mut(&id) {
|
||||
screen.write(buf, id == self.active)
|
||||
} else {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
}
|
||||
|
||||
fn seek(&mut self, id: usize, pos: usize, whence: usize) -> Result<usize> {
|
||||
if let Some(mut screen) = self.screens.get_mut(&id) {
|
||||
screen.seek(pos, whence)
|
||||
} else {
|
||||
Err(Error::new(EBADF))
|
||||
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
if let HandleKind::Screen(screen_i) = handle.kind {
|
||||
if let Some(mut screen) = self.screens.get_mut(&screen_i) {
|
||||
return screen.seek(pos, whence);
|
||||
}
|
||||
}
|
||||
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
|
||||
fn close(&mut self, _id: usize) -> Result<usize> {
|
||||
fn close(&mut self, id: usize) -> Result<usize> {
|
||||
self.handles.remove(&id).ok_or(Error::new(EBADF))?;
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,8 +75,12 @@ impl Screen for GraphicScreen {
|
||||
Ok(i * mem::size_of::<Event>())
|
||||
}
|
||||
|
||||
fn will_block(&self) -> bool {
|
||||
self.input.is_empty()
|
||||
fn can_read(&self) -> Option<usize> {
|
||||
if self.input.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(self.input.len() * mem::size_of::<Event>())
|
||||
}
|
||||
}
|
||||
|
||||
fn write(&mut self, buf: &[u8], sync: bool) -> Result<usize> {
|
||||
|
||||
@@ -22,7 +22,7 @@ pub trait Screen {
|
||||
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
|
||||
|
||||
fn will_block(&self) -> bool;
|
||||
fn can_read(&self) -> Option<usize>;
|
||||
|
||||
fn write(&mut self, buf: &[u8], sync: bool) -> Result<usize>;
|
||||
|
||||
|
||||
@@ -167,8 +167,14 @@ impl Screen for TextScreen {
|
||||
Ok(i)
|
||||
}
|
||||
|
||||
fn will_block(&self) -> bool {
|
||||
self.input.is_empty() && ! self.end_of_input
|
||||
fn can_read(&self) -> Option<usize> {
|
||||
if self.end_of_input {
|
||||
Some(0)
|
||||
} else if self.input.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(self.input.len())
|
||||
}
|
||||
}
|
||||
|
||||
fn write(&mut self, buf: &[u8], sync: bool) -> Result<usize> {
|
||||
|
||||
Reference in New Issue
Block a user