Typing in terminal is now supported in rust teton.
This commit is contained in:
parent
18e512cf1f
commit
f04e720811
|
@ -123,6 +123,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"mammoth",
|
"mammoth",
|
||||||
"victoriafalls",
|
"victoriafalls",
|
||||||
|
"voyageurs",
|
||||||
"yellowstone",
|
"yellowstone",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -149,6 +150,17 @@ dependencies = [
|
||||||
"yunqc",
|
"yunqc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "voyageurs"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"mammoth",
|
||||||
|
"yellowstone",
|
||||||
|
"yunq",
|
||||||
|
"yunq-derive",
|
||||||
|
"yunqc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yellowstone"
|
name = "yellowstone"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
"lib/mammoth", "lib/victoriafalls", "lib/yellowstone", "lib/yunq", "lib/yunq-derive", "sys/teton", "usr/testbed",
|
"lib/mammoth", "lib/victoriafalls", "lib/voyageurs", "lib/yellowstone", "lib/yunq", "lib/yunq-derive", "sys/teton", "usr/testbed",
|
||||||
]
|
]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ pub mod macros;
|
||||||
|
|
||||||
pub mod init;
|
pub mod init;
|
||||||
pub mod mem;
|
pub mod mem;
|
||||||
|
pub mod port;
|
||||||
pub mod syscall;
|
pub mod syscall;
|
||||||
pub mod thread;
|
pub mod thread;
|
||||||
pub mod zion;
|
pub mod zion;
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
use crate::syscall::{cap_duplicate, cap_release, port_create, port_recv};
|
||||||
|
use crate::zion::{kZionPerm_Read, z_cap_t, ZError};
|
||||||
|
|
||||||
|
pub struct PortServer {
|
||||||
|
port_cap: z_cap_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PortServer {
|
||||||
|
pub fn new() -> Result<Self, ZError> {
|
||||||
|
Ok(Self {
|
||||||
|
port_cap: port_create()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_client_cap(&self) -> Result<z_cap_t, ZError> {
|
||||||
|
cap_duplicate(self.port_cap, !kZionPerm_Read)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn recv_byte(&self) -> Result<u8, ZError> {
|
||||||
|
let mut caps: [z_cap_t; 0] = [];
|
||||||
|
let mut bytes: [u8; 1] = [0];
|
||||||
|
|
||||||
|
port_recv(self.port_cap, &mut bytes, &mut caps)?;
|
||||||
|
|
||||||
|
Ok(bytes[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn recv_u16(&self) -> Result<u16, ZError> {
|
||||||
|
let mut caps: [z_cap_t; 0] = [];
|
||||||
|
let mut bytes: [u8; 2] = [0; 2];
|
||||||
|
|
||||||
|
port_recv(self.port_cap, &mut bytes, &mut caps)?;
|
||||||
|
|
||||||
|
Ok(u16::from_le_bytes(bytes))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for PortServer {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
cap_release(self.port_cap).expect("Failed to release port cap");
|
||||||
|
}
|
||||||
|
}
|
|
@ -140,6 +140,37 @@ pub fn address_space_unmap(lower_addr: u64, upper_addr: u64) -> Result<(), ZErro
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn port_create() -> Result<z_cap_t, ZError> {
|
||||||
|
let mut port_cap = 0;
|
||||||
|
syscall(
|
||||||
|
zion::kZionPortCreate,
|
||||||
|
&zion::ZPortCreateReq {
|
||||||
|
port_cap: &mut port_cap,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
Ok(port_cap)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn port_recv(
|
||||||
|
port_cap: z_cap_t,
|
||||||
|
bytes: &mut [u8],
|
||||||
|
caps: &mut [u64],
|
||||||
|
) -> Result<(u64, u64), ZError> {
|
||||||
|
let mut num_bytes = bytes.len() as u64;
|
||||||
|
let mut num_caps = caps.len() as u64;
|
||||||
|
syscall(
|
||||||
|
zion::kZionPortRecv,
|
||||||
|
&zion::ZPortRecvReq {
|
||||||
|
port_cap,
|
||||||
|
data: bytes.as_mut_ptr() as *mut c_void,
|
||||||
|
num_bytes: &mut num_bytes as *mut u64,
|
||||||
|
caps: caps.as_mut_ptr(),
|
||||||
|
num_caps: &mut num_caps as *mut u64,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
Ok((num_bytes, num_caps))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn port_poll(
|
pub fn port_poll(
|
||||||
port_cap: z_cap_t,
|
port_cap: z_cap_t,
|
||||||
bytes: &mut [u8],
|
bytes: &mut [u8],
|
||||||
|
@ -248,6 +279,19 @@ pub fn reply_port_recv(
|
||||||
Ok((num_bytes, num_caps))
|
Ok((num_bytes, num_caps))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cap_duplicate(cap: z_cap_t, perm_mask: u64) -> Result<z_cap_t, ZError> {
|
||||||
|
let mut new_cap = 0;
|
||||||
|
syscall(
|
||||||
|
zion::kZionCapDuplicate,
|
||||||
|
&zion::ZCapDuplicateReq {
|
||||||
|
cap_in: cap,
|
||||||
|
perm_mask,
|
||||||
|
cap_out: &mut new_cap,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
Ok(new_cap)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn cap_release(cap: z_cap_t) -> Result<(), ZError> {
|
pub fn cap_release(cap: z_cap_t) -> Result<(), ZError> {
|
||||||
syscall(zion::kZionCapRelease, &zion::ZCapReleaseReq { cap })
|
syscall(zion::kZionCapRelease, &zion::ZCapReleaseReq { cap })
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
name = "voyageurs"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
mammoth = { path = "../mammoth" }
|
||||||
|
yellowstone = { path = "../yellowstone" }
|
||||||
|
yunq = {path = "../yunq"}
|
||||||
|
yunq-derive = {path = "../yunq-derive"}
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
yunqc = {path = "../../../yunq/rust"}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let input_file = "../../../sys/voyageurs/lib/voyageurs/voyageurs.yunq";
|
||||||
|
|
||||||
|
println!("cargo::rerun-if-changed={input_file}");
|
||||||
|
|
||||||
|
let input = fs::read_to_string(input_file).expect("Failed to read input file");
|
||||||
|
|
||||||
|
let code = yunqc::codegen(&input).expect("Failed to generate yunq code.");
|
||||||
|
|
||||||
|
let out = std::env::var("OUT_DIR").unwrap() + "/yunq.rs";
|
||||||
|
fs::write(out, code).expect("Failed to write generated code.");
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
#![no_std]
|
||||||
|
#![feature(box_into_inner)]
|
||||||
|
|
||||||
|
use core::include;
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/yunq.rs"));
|
||||||
|
|
||||||
|
pub mod listener;
|
|
@ -0,0 +1,262 @@
|
||||||
|
use core::cell::RefCell;
|
||||||
|
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
use alloc::rc::Rc;
|
||||||
|
use alloc::string::ToString;
|
||||||
|
use mammoth::port::PortServer;
|
||||||
|
use mammoth::thread::Thread;
|
||||||
|
use mammoth::zion::ZError;
|
||||||
|
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
|
||||||
|
enum Keycode {
|
||||||
|
UnknownKeycode = 0x0,
|
||||||
|
|
||||||
|
A = 0x1,
|
||||||
|
B = 0x2,
|
||||||
|
C = 0x3,
|
||||||
|
D = 0x4,
|
||||||
|
E = 0x5,
|
||||||
|
F = 0x6,
|
||||||
|
G = 0x7,
|
||||||
|
H = 0x8,
|
||||||
|
I = 0x9,
|
||||||
|
J = 0xA,
|
||||||
|
K = 0xB,
|
||||||
|
L = 0xC,
|
||||||
|
M = 0xD,
|
||||||
|
N = 0xE,
|
||||||
|
O = 0xF,
|
||||||
|
P = 0x10,
|
||||||
|
Q = 0x11,
|
||||||
|
R = 0x12,
|
||||||
|
S = 0x13,
|
||||||
|
T = 0x14,
|
||||||
|
U = 0x15,
|
||||||
|
V = 0x16,
|
||||||
|
W = 0x17,
|
||||||
|
X = 0x18,
|
||||||
|
Y = 0x19,
|
||||||
|
Z = 0x1A,
|
||||||
|
|
||||||
|
NUM1 = 0x20,
|
||||||
|
NUM2 = 0x21,
|
||||||
|
NUM3 = 0x22,
|
||||||
|
NUM4 = 0x23,
|
||||||
|
NUM5 = 0x24,
|
||||||
|
NUM6 = 0x25,
|
||||||
|
NUM7 = 0x26,
|
||||||
|
NUM8 = 0x27,
|
||||||
|
NUM9 = 0x28,
|
||||||
|
NUM0 = 0x29,
|
||||||
|
|
||||||
|
Space = 0x30,
|
||||||
|
Enter = 0x31,
|
||||||
|
Tab = 0x32,
|
||||||
|
Backspace = 0x33,
|
||||||
|
Delete = 0x34,
|
||||||
|
|
||||||
|
Minus = 0x40,
|
||||||
|
Equals = 0x41,
|
||||||
|
LBrace = 0x42,
|
||||||
|
RBrace = 0x43,
|
||||||
|
BSlash = 0x44,
|
||||||
|
FSlash = 0x45,
|
||||||
|
Semicolon = 0x46,
|
||||||
|
Quote = 0x47,
|
||||||
|
Comma = 0x48,
|
||||||
|
Period = 0x49,
|
||||||
|
Backtick = 0x4A,
|
||||||
|
|
||||||
|
LShift = 0x50,
|
||||||
|
RShift = 0x51,
|
||||||
|
LCtrl = 0x52,
|
||||||
|
RCtrl = 0x53,
|
||||||
|
LAlt = 0x54,
|
||||||
|
RAlt = 0x55,
|
||||||
|
Super = 0x56,
|
||||||
|
Esc = 0x57,
|
||||||
|
Up = 0x58,
|
||||||
|
Down = 0x59,
|
||||||
|
Left = 0x5A,
|
||||||
|
Right = 0x5B,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Keycode {
|
||||||
|
fn from_scancode(scancode: u16) -> Self {
|
||||||
|
match scancode as u8 {
|
||||||
|
0x04 => Keycode::A,
|
||||||
|
0x05 => Keycode::B,
|
||||||
|
0x06 => Keycode::C,
|
||||||
|
0x07 => Keycode::D,
|
||||||
|
0x08 => Keycode::E,
|
||||||
|
0x09 => Keycode::F,
|
||||||
|
0x0A => Keycode::G,
|
||||||
|
0x0B => Keycode::H,
|
||||||
|
0x0C => Keycode::I,
|
||||||
|
0x0D => Keycode::J,
|
||||||
|
0x0E => Keycode::K,
|
||||||
|
0x0F => Keycode::L,
|
||||||
|
0x10 => Keycode::M,
|
||||||
|
0x11 => Keycode::N,
|
||||||
|
0x12 => Keycode::O,
|
||||||
|
0x13 => Keycode::P,
|
||||||
|
0x14 => Keycode::Q,
|
||||||
|
0x15 => Keycode::R,
|
||||||
|
0x16 => Keycode::S,
|
||||||
|
0x17 => Keycode::T,
|
||||||
|
0x18 => Keycode::U,
|
||||||
|
0x19 => Keycode::V,
|
||||||
|
0x1A => Keycode::W,
|
||||||
|
0x1B => Keycode::X,
|
||||||
|
0x1C => Keycode::Y,
|
||||||
|
0x1D => Keycode::Z,
|
||||||
|
0x1E => Keycode::NUM1,
|
||||||
|
0x1F => Keycode::NUM2,
|
||||||
|
0x20 => Keycode::NUM3,
|
||||||
|
0x21 => Keycode::NUM4,
|
||||||
|
0x22 => Keycode::NUM5,
|
||||||
|
0x23 => Keycode::NUM6,
|
||||||
|
0x24 => Keycode::NUM7,
|
||||||
|
0x25 => Keycode::NUM8,
|
||||||
|
0x26 => Keycode::NUM9,
|
||||||
|
0x27 => Keycode::NUM0,
|
||||||
|
0x28 => Keycode::Enter,
|
||||||
|
0x29 => Keycode::Esc,
|
||||||
|
0x2A => Keycode::Backspace,
|
||||||
|
0x2B => Keycode::Tab,
|
||||||
|
0x2C => Keycode::Space,
|
||||||
|
0x2D => Keycode::Minus,
|
||||||
|
0x2E => Keycode::Equals,
|
||||||
|
0x2F => Keycode::LBrace,
|
||||||
|
0x30 => Keycode::RBrace,
|
||||||
|
0x31 => Keycode::BSlash,
|
||||||
|
0x33 => Keycode::Semicolon,
|
||||||
|
0x34 => Keycode::Quote,
|
||||||
|
0x35 => Keycode::Backtick,
|
||||||
|
0x36 => Keycode::Comma,
|
||||||
|
0x37 => Keycode::Period,
|
||||||
|
0x38 => Keycode::FSlash,
|
||||||
|
0x39 => Keycode::Esc,
|
||||||
|
_ => Keycode::UnknownKeycode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Modifiers(u8);
|
||||||
|
|
||||||
|
impl Modifiers {
|
||||||
|
fn from_scancode(scancode: u16) -> Self {
|
||||||
|
Self((scancode >> 8) as u8)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_shift(&self) -> bool {
|
||||||
|
((self.0 & 0x20) == 0x20) || ((self.0 & 0x2) == 0x2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_char(keycode: Keycode, modifiers: Modifiers) -> char {
|
||||||
|
match keycode {
|
||||||
|
k if (Keycode::A..=Keycode::Z).contains(&k) => {
|
||||||
|
if modifiers.is_shift() {
|
||||||
|
let chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
chars.as_bytes()[k as usize - Keycode::A as usize] as char
|
||||||
|
} else {
|
||||||
|
let chars = "abcdefghijklmnopqrstuvwxyz";
|
||||||
|
chars.as_bytes()[k as usize - Keycode::A as usize] as char
|
||||||
|
}
|
||||||
|
}
|
||||||
|
k if (Keycode::NUM1..=Keycode::NUM0).contains(&k) => {
|
||||||
|
if modifiers.is_shift() {
|
||||||
|
let chars = "!@#$%^&*()";
|
||||||
|
chars.as_bytes()[k as usize - Keycode::NUM1 as usize] as char
|
||||||
|
} else {
|
||||||
|
let chars = "12345687890";
|
||||||
|
chars.as_bytes()[k as usize - Keycode::NUM1 as usize] as char
|
||||||
|
}
|
||||||
|
}
|
||||||
|
k if (Keycode::Minus..=Keycode::Backtick).contains(&k) => {
|
||||||
|
if modifiers.is_shift() {
|
||||||
|
let chars = "_+{}|?:\"<>~";
|
||||||
|
chars.as_bytes()[k as usize - Keycode::Minus as usize] as char
|
||||||
|
} else {
|
||||||
|
let chars = "-=[]\\/;',.`";
|
||||||
|
chars.as_bytes()[k as usize - Keycode::Minus as usize] as char
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Keycode::Enter => '\n',
|
||||||
|
Keycode::Space => ' ',
|
||||||
|
Keycode::Tab => '\t',
|
||||||
|
Keycode::Backspace => '\x08',
|
||||||
|
_ => '\0',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait KeyboardHandler {
|
||||||
|
fn handle_char(&mut self, c: char);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct KeyboardListener {
|
||||||
|
listen_port: PortServer,
|
||||||
|
listen_thread: Option<Box<Thread>>,
|
||||||
|
handler: Rc<RefCell<dyn KeyboardHandler>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KeyboardListener {
|
||||||
|
pub fn new(handler: Rc<RefCell<dyn KeyboardHandler>>) -> Result<Box<Self>, ZError> {
|
||||||
|
let mut listnr = Box::new(Self {
|
||||||
|
listen_port: PortServer::new()?,
|
||||||
|
listen_thread: None,
|
||||||
|
handler,
|
||||||
|
});
|
||||||
|
|
||||||
|
let voyageur_endpoint = yellowstone::from_init_endpoint()
|
||||||
|
.get_endpoint(&yellowstone::GetEndpointRequest {
|
||||||
|
endpoint_name: "voyageurs".to_string(),
|
||||||
|
})?
|
||||||
|
.endpoint;
|
||||||
|
|
||||||
|
let mut voyageur_client = crate::VoyageursClient::new(voyageur_endpoint);
|
||||||
|
|
||||||
|
voyageur_client.register_keyboard_listener(&crate::KeyboardListener {
|
||||||
|
port_capability: listnr.listen_port.create_client_cap()?,
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let thread_entry = |self_raw| {
|
||||||
|
let listener = unsafe {
|
||||||
|
(self_raw as *mut KeyboardListener)
|
||||||
|
.as_mut()
|
||||||
|
.expect("Failed to convert to keyboard listener")
|
||||||
|
};
|
||||||
|
listener.listen_loop();
|
||||||
|
};
|
||||||
|
|
||||||
|
listnr.listen_thread = Some(Thread::spawn(
|
||||||
|
thread_entry,
|
||||||
|
&*listnr as *const Self as *const core::ffi::c_void,
|
||||||
|
)?);
|
||||||
|
|
||||||
|
Ok(listnr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn listen_loop(&mut self) {
|
||||||
|
loop {
|
||||||
|
let scancode = self
|
||||||
|
.listen_port
|
||||||
|
.recv_u16()
|
||||||
|
.expect("Failed to recieve scancode");
|
||||||
|
|
||||||
|
let keycode = Keycode::from_scancode(scancode);
|
||||||
|
let modifiers = Modifiers::from_scancode(scancode);
|
||||||
|
|
||||||
|
self.handler
|
||||||
|
.as_ref()
|
||||||
|
.borrow_mut()
|
||||||
|
.handle_char(into_char(keycode, modifiers))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn join(&self) -> Result<(), ZError> {
|
||||||
|
self.listen_thread.as_ref().unwrap().join()
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,4 +6,5 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
mammoth = { path = "../../lib/mammoth" }
|
mammoth = { path = "../../lib/mammoth" }
|
||||||
victoriafalls = { path = "../../lib/victoriafalls" }
|
victoriafalls = { path = "../../lib/victoriafalls" }
|
||||||
|
voyageurs = { path = "../../lib/voyageurs" }
|
||||||
yellowstone = { path = "../../lib/yellowstone" }
|
yellowstone = { path = "../../lib/yellowstone" }
|
||||||
|
|
|
@ -4,15 +4,56 @@ use crate::psf::Psf;
|
||||||
pub struct Console {
|
pub struct Console {
|
||||||
framebuffer: Framebuffer,
|
framebuffer: Framebuffer,
|
||||||
psf: Psf,
|
psf: Psf,
|
||||||
|
row: u32,
|
||||||
|
col: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Console {
|
impl Console {
|
||||||
pub fn new(framebuffer: Framebuffer, psf: Psf) -> Self {
|
pub fn new(framebuffer: Framebuffer, psf: Psf) -> Self {
|
||||||
Self { framebuffer, psf }
|
Self {
|
||||||
|
framebuffer,
|
||||||
|
psf,
|
||||||
|
row: 0,
|
||||||
|
col: 0,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_char(&self, c: char) {
|
fn incr_cursor(&mut self) {
|
||||||
let glyph = self.psf.glyph(c as u32);
|
self.col += 1;
|
||||||
self.framebuffer.draw_glyph(glyph, 0, 0)
|
if self.col >= self.cols() {
|
||||||
|
self.col = 0;
|
||||||
|
self.row += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.row >= self.rows() {
|
||||||
|
panic!("Scroll unimplemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_char(&mut self, chr: char) {
|
||||||
|
if chr == '\x08' {
|
||||||
|
// Backspace.
|
||||||
|
if self.col > 1 {
|
||||||
|
self.col -= 1;
|
||||||
|
self.write_char(' ');
|
||||||
|
self.col -= 1;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let glyph = self.psf.glyph(chr as u32);
|
||||||
|
self.framebuffer.draw_glyph(
|
||||||
|
glyph,
|
||||||
|
self.row * (self.psf.height() + 1),
|
||||||
|
self.col * (self.psf.width() + 1),
|
||||||
|
);
|
||||||
|
self.incr_cursor()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cols(&self) -> u32 {
|
||||||
|
self.framebuffer.width() / (self.psf.width() + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rows(&self) -> u32 {
|
||||||
|
self.framebuffer.height() / (self.psf.height() + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,4 +35,12 @@ impl Framebuffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn width(&self) -> u32 {
|
||||||
|
self.fb_info.width as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn height(&self) -> u32 {
|
||||||
|
self.fb_info.height as u32
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,13 @@ extern crate alloc;
|
||||||
mod console;
|
mod console;
|
||||||
mod framebuffer;
|
mod framebuffer;
|
||||||
mod psf;
|
mod psf;
|
||||||
|
mod terminal;
|
||||||
|
|
||||||
|
use core::cell::RefCell;
|
||||||
|
|
||||||
|
use alloc::rc::Rc;
|
||||||
use mammoth::{debug, define_entry, zion::z_err_t};
|
use mammoth::{debug, define_entry, zion::z_err_t};
|
||||||
|
use voyageurs::listener::KeyboardListener;
|
||||||
|
|
||||||
define_entry!();
|
define_entry!();
|
||||||
|
|
||||||
|
@ -33,18 +38,16 @@ extern "C" fn main() -> z_err_t {
|
||||||
.expect("Failed to create framebuffer");
|
.expect("Failed to create framebuffer");
|
||||||
|
|
||||||
let psf = psf::Psf::new("/default8x16.psfu").expect("Failed to open font file.");
|
let psf = psf::Psf::new("/default8x16.psfu").expect("Failed to open font file.");
|
||||||
let console = console::Console::new(framebuffer, psf);
|
let mut console = console::Console::new(framebuffer, psf);
|
||||||
console.write_char('>');
|
console.write_char('>');
|
||||||
|
|
||||||
/*
|
let terminal = Rc::new(RefCell::new(terminal::Terminal::new(console)));
|
||||||
|
|
||||||
Terminal terminal(console);
|
let kb_listener = KeyboardListener::new(terminal).expect("Failed to create keyboard listener");
|
||||||
terminal.Register();
|
|
||||||
|
|
||||||
Thread lthread = terminal.Listen();
|
kb_listener
|
||||||
|
.join()
|
||||||
check(lthread.Join());
|
.expect("Failed to wait on keyboard listener");
|
||||||
*/
|
|
||||||
|
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,4 +68,12 @@ impl Psf {
|
||||||
let len: usize = self.header.bytes_per_glyph as usize;
|
let len: usize = self.header.bytes_per_glyph as usize;
|
||||||
&self.file.slice(offset, len)
|
&self.file.slice(offset, len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn width(&self) -> u32 {
|
||||||
|
self.header.width
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn height(&self) -> u32 {
|
||||||
|
self.header.height
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
use crate::console::Console;
|
||||||
|
use voyageurs::listener::KeyboardHandler;
|
||||||
|
|
||||||
|
pub struct Terminal {
|
||||||
|
console: Console,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KeyboardHandler for Terminal {
|
||||||
|
fn handle_char(&mut self, c: char) {
|
||||||
|
self.console.write_char(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Terminal {
|
||||||
|
pub fn new(console: Console) -> Self {
|
||||||
|
Self { console }
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue