diff --git a/vesad/src/main.rs b/vesad/src/main.rs index 211058cea504db83427648fe49f5952ec7ad8605..5f072078cb301a6f297c109f643f49a85cc5aa47 100644 --- a/vesad/src/main.rs +++ b/vesad/src/main.rs @@ -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::() + d: count }; socket.write(&event_packet).expect("vesad: failed to write display event"); diff --git a/vesad/src/scheme.rs b/vesad/src/scheme.rs index d34f74b67f9b0a4181d5a9a8987ec632d0ef8fa7..bc933d7255d5776822f8ff263322dcc04ffa5471 100644 --- a/vesad/src/scheme.rs +++ b/vesad/src/scheme.rs @@ -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> + pub screens: BTreeMap>, + next_id: usize, + handles: BTreeMap, } 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 { + 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 { + fn open(&mut self, path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { 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::().unwrap_or(0); - if self.screens.contains_key(&id) { + let screen_i = parts.next().unwrap_or("").parse::().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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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::()) + }, + 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 { - 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 { + fn close(&mut self, id: usize) -> Result { + self.handles.remove(&id).ok_or(Error::new(EBADF))?; Ok(0) } } diff --git a/vesad/src/screen/graphic.rs b/vesad/src/screen/graphic.rs index 089787a81a0cb2728d1fc7fea161f2074d2a2693..45d4f9fcd2d5ed343b0ef4f24e96c5e92b1c13de 100644 --- a/vesad/src/screen/graphic.rs +++ b/vesad/src/screen/graphic.rs @@ -75,8 +75,12 @@ impl Screen for GraphicScreen { Ok(i * mem::size_of::()) } - fn will_block(&self) -> bool { - self.input.is_empty() + fn can_read(&self) -> Option { + if self.input.is_empty() { + None + } else { + Some(self.input.len() * mem::size_of::()) + } } fn write(&mut self, buf: &[u8], sync: bool) -> Result { diff --git a/vesad/src/screen/mod.rs b/vesad/src/screen/mod.rs index 4558546412fd984cc89bc9c6bd03fcce23007987..5927cf4f505bf7ad8fd922eb7c287b292d140c8a 100644 --- a/vesad/src/screen/mod.rs +++ b/vesad/src/screen/mod.rs @@ -22,7 +22,7 @@ pub trait Screen { fn read(&mut self, buf: &mut [u8]) -> Result; - fn will_block(&self) -> bool; + fn can_read(&self) -> Option; fn write(&mut self, buf: &[u8], sync: bool) -> Result; diff --git a/vesad/src/screen/text.rs b/vesad/src/screen/text.rs index 7436be5cbb850551ae73418f5a35290d7071cf52..49ba28e9c42a4dddac3e26ed307f7b6bf31ed43a 100644 --- a/vesad/src/screen/text.rs +++ b/vesad/src/screen/text.rs @@ -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 { + 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 {