feat(libkos): add fs, display, input service client modules with newtypes
This commit is contained in:
31
crates/libkos/src/display.rs
Normal file
31
crates/libkos/src/display.rs
Normal file
@@ -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))
|
||||||
|
}
|
||||||
|
}
|
||||||
73
crates/libkos/src/fs.rs
Normal file
73
crates/libkos/src/fs.rs
Normal file
@@ -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<FileHandle> {
|
||||||
|
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<usize> {
|
||||||
|
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<usize> {
|
||||||
|
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<usize> {
|
||||||
|
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<FileHandle> {
|
||||||
|
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<usize> {
|
||||||
|
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
|
||||||
|
}
|
||||||
63
crates/libkos/src/input.rs
Normal file
63
crates/libkos/src/input.rs
Normal file
@@ -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<Key> {
|
||||||
|
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<InputEvent> {
|
||||||
|
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<InputEvent> {
|
||||||
|
let mut last = None;
|
||||||
|
loop {
|
||||||
|
match poll_event(ep) {
|
||||||
|
None => return last,
|
||||||
|
Some(ev) => {
|
||||||
|
if matches!(ev, InputEvent::KeyDown(_)) {
|
||||||
|
last = Some(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,9 @@ mod arch;
|
|||||||
pub mod syscall;
|
pub mod syscall;
|
||||||
pub mod alloc_impl;
|
pub mod alloc_impl;
|
||||||
pub mod io;
|
pub mod io;
|
||||||
|
pub mod fs;
|
||||||
|
pub mod display;
|
||||||
|
pub mod input;
|
||||||
mod rt;
|
mod rt;
|
||||||
|
|
||||||
#[cfg(target_os = "none")]
|
#[cfg(target_os = "none")]
|
||||||
|
|||||||
Reference in New Issue
Block a user