diff --git a/crates/libkos/src/display.rs b/crates/libkos/src/display.rs new file mode 100644 index 0000000..1230f98 --- /dev/null +++ b/crates/libkos/src/display.rs @@ -0,0 +1,31 @@ +use types::bounded::CapSlot; +use types::display::{Color, Dimension, ScreenCoord}; +use crate::syscall; + +fn ipc(ep: CapSlot, w0: usize, w1: usize, w2: usize, w3: usize) -> (usize, usize, usize, usize) { + syscall::send(ep, w0, w1, w2, w3); + syscall::receive(ep) +} + +pub fn draw_rect(ep: CapSlot, x: ScreenCoord, y: ScreenCoord, w: Dimension, h: Dimension, color: Color) { + let xy = (x.raw() as usize) | ((y.raw() as usize) << 16); + let wh = (w.raw() as usize) | ((h.raw() as usize) << 16); + ipc(ep, 0, xy, wh, color.raw() as usize); +} + +pub fn clear(ep: CapSlot, color: Color) { + ipc(ep, 1, color.raw() as usize, 0, 0); +} + +pub fn flush(ep: CapSlot) { + ipc(ep, 2, 0, 0, 0); +} + +pub fn get_dimensions(ep: CapSlot) -> (Dimension, Dimension) { + let (tag, w, h, _) = ipc(ep, 3, 0, 0, 0); + if tag == 1 { + (Dimension::new(w as u16), Dimension::new(h as u16)) + } else { + (Dimension::new(0), Dimension::new(0)) + } +} diff --git a/crates/libkos/src/fs.rs b/crates/libkos/src/fs.rs new file mode 100644 index 0000000..f8d08f7 --- /dev/null +++ b/crates/libkos/src/fs.rs @@ -0,0 +1,73 @@ +use types::bounded::CapSlot; +use crate::syscall; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct FileHandle(u16); + +impl FileHandle { + pub const fn raw(&self) -> u16 { self.0 } +} + +fn pack_path(path: &[u8]) -> (usize, usize) { + let mut w0 = [0u8; 8]; + let mut w1 = [0u8; 8]; + for (i, &b) in path.iter().enumerate() { + if i < 8 { w0[i] = b; } + else if i < 16 { w1[i - 8] = b; } + } + (usize::from_le_bytes(w0), usize::from_le_bytes(w1)) +} + +fn ipc(ep: CapSlot, w0: usize, w1: usize, w2: usize, w3: usize) -> (usize, usize, usize, usize) { + syscall::send(ep, w0, w1, w2, w3); + syscall::receive(ep) +} + +pub fn open(ep: CapSlot, path: &[u8]) -> Option { + let (p0, p1) = pack_path(path); + let (tag, handle, _, _) = ipc(ep, 0, p0, p1, 0); + if tag == 0 { Some(FileHandle(handle as u16)) } else { None } +} + +pub fn read(ep: CapSlot, handle: FileHandle, max_bytes: usize) -> Option { + let (tag, bytes_read, _, _) = ipc(ep, 1, handle.0 as usize, max_bytes, 0); + if tag == 1 { Some(bytes_read) } else { None } +} + +pub fn write(ep: CapSlot, handle: FileHandle, data_word: usize) -> Option { + let (tag, bytes_written, _, _) = ipc(ep, 2, handle.0 as usize, data_word, 0); + if tag == 2 { Some(bytes_written) } else { None } +} + +pub fn close(ep: CapSlot, handle: FileHandle) { + ipc(ep, 3, handle.0 as usize, 0, 0); +} + +pub fn list_dir(ep: CapSlot, path: &[u8]) -> Option { + let (p0, p1) = pack_path(path); + let (tag, count, _, _) = ipc(ep, 4, p0, p1, 0); + if tag == 4 { Some(count) } else { None } +} + +pub fn create(ep: CapSlot, path: &[u8]) -> Option { + let (p0, p1) = pack_path(path); + let (tag, handle, _, _) = ipc(ep, 5, p0, p1, 0); + if tag == 0 { Some(FileHandle(handle as u16)) } else { None } +} + +pub fn delete(ep: CapSlot, path: &[u8]) -> bool { + let (p0, p1) = pack_path(path); + let (tag, _, _, _) = ipc(ep, 6, p0, p1, 0); + tag == 3 +} + +pub fn file_size(ep: CapSlot, handle: FileHandle) -> Option { + let (tag, size, _, _) = ipc(ep, 7, handle.0 as usize, 0, 0); + if tag == 5 { Some(size) } else { None } +} + +pub fn mkdir(ep: CapSlot, path: &[u8]) -> bool { + let (p0, p1) = pack_path(path); + let (tag, _, _, _) = ipc(ep, 8, p0, p1, 0); + tag == 3 +} diff --git a/crates/libkos/src/input.rs b/crates/libkos/src/input.rs new file mode 100644 index 0000000..d6ff72c --- /dev/null +++ b/crates/libkos/src/input.rs @@ -0,0 +1,63 @@ +use types::bounded::CapSlot; +use crate::syscall; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Key { + Up, + Down, + Left, + Right, + Enter, + Escape, + Space, + Backspace, + Tab, + Char(u8), +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum InputEvent { + KeyDown(Key), + KeyUp(Key), +} + +fn decode_key(kind: usize, extra: usize) -> Option { + match kind { + 0 => Some(Key::Up), + 1 => Some(Key::Down), + 2 => Some(Key::Left), + 3 => Some(Key::Right), + 4 => Some(Key::Enter), + 5 => Some(Key::Escape), + 6 => Some(Key::Space), + 7 => Some(Key::Backspace), + 8 => Some(Key::Tab), + 9 => Some(Key::Char(extra as u8)), + _ => None, + } +} + +pub fn poll_event(ep: CapSlot) -> Option { + syscall::send(ep, 0, 0, 0, 0); + let (tag, kind, extra, _) = syscall::receive(ep); + match tag { + 0 => None, + 1 => decode_key(kind, extra).map(InputEvent::KeyDown), + 2 => decode_key(kind, extra).map(InputEvent::KeyUp), + _ => None, + } +} + +pub fn drain_events(ep: CapSlot) -> Option { + let mut last = None; + loop { + match poll_event(ep) { + None => return last, + Some(ev) => { + if matches!(ev, InputEvent::KeyDown(_)) { + last = Some(ev); + } + } + } + } +} diff --git a/crates/libkos/src/lib.rs b/crates/libkos/src/lib.rs index 3d47de7..29c8614 100644 --- a/crates/libkos/src/lib.rs +++ b/crates/libkos/src/lib.rs @@ -6,6 +6,9 @@ mod arch; pub mod syscall; pub mod alloc_impl; pub mod io; +pub mod fs; +pub mod display; +pub mod input; mod rt; #[cfg(target_os = "none")]