diff --git a/src/api/console.rs b/src/api/console.rs index 6be934e7..7947dd77 100644 --- a/src/api/console.rs +++ b/src/api/console.rs @@ -1,6 +1,8 @@ use crate::sys; use core::fmt; +pub use crate::sys::console::{ETX_KEY, EOT_KEY}; + #[derive(Clone, Copy)] pub struct Style { foreground: Option, diff --git a/src/api/fs.rs b/src/api/fs.rs index ca37b390..ec061af4 100644 --- a/src/api/fs.rs +++ b/src/api/fs.rs @@ -88,8 +88,7 @@ pub fn open_device(path: &str) -> Option { pub fn create_device(path: &str, kind: DeviceType) -> Option { let flags = OpenFlag::Create as usize | OpenFlag::Device as usize; if let Some(handle) = syscall::open(path, flags) { - let buf = [kind as u8; 1]; - syscall::write(handle, &buf); + syscall::write(handle, &kind.buf()); return Some(handle); } None diff --git a/src/api/prompt.rs b/src/api/prompt.rs index c4e63727..b9e88856 100644 --- a/src/api/prompt.rs +++ b/src/api/prompt.rs @@ -32,11 +32,11 @@ impl Prompt { let mut parser = Parser::new(); while let Some(c) = io::stdin().read_char() { match c { - '\x03' => { // End of Text (^C) + console::ETX_KEY => { // End of Text (^C) println!(); return Some(String::new()); }, - '\x04' => { // End of Transmission (^D) + console::EOT_KEY => { // End of Transmission (^D) println!(); return None; }, diff --git a/src/sys/console.rs b/src/sys/console.rs index d880fa6c..fff5b8f0 100644 --- a/src/sys/console.rs +++ b/src/sys/console.rs @@ -91,10 +91,10 @@ pub fn is_raw_enabled() -> bool { *RAW.lock() } -const ETX_KEY: char = '\x03'; // End of Text -const EOT_KEY: char = '\x04'; // End of Transmission -const BS_KEY: char = '\x08'; // Backspace -const ESC_KEY: char = '\x1B'; // Escape +pub const ETX_KEY: char = '\x03'; // End of Text +pub const EOT_KEY: char = '\x04'; // End of Transmission +pub const BS_KEY: char = '\x08'; // Backspace +pub const ESC_KEY: char = '\x1B'; // Escape pub fn key_handle(key: char) { let mut stdin = STDIN.lock(); diff --git a/src/sys/fs/device.rs b/src/sys/fs/device.rs index c9080511..efff10a6 100644 --- a/src/sys/fs/device.rs +++ b/src/sys/fs/device.rs @@ -3,9 +3,12 @@ use super::dir::Dir; use super::file::File; use super::block::LinkedBlock; +use alloc::vec; +use alloc::vec::Vec; use crate::sys::console::Console; use crate::sys::random::Random; +#[derive(PartialEq, Clone, Copy)] #[repr(u8)] pub enum DeviceType { File = 0, @@ -14,6 +17,16 @@ pub enum DeviceType { Null = 3, } +impl DeviceType { + pub fn buf(self) -> Vec { + if self == DeviceType::Console { + vec![self as u8, 0, 0, 0] // 4 bytes + } else { + vec![self as u8] // 1 byte + } + } +} + #[derive(Debug, Clone)] pub enum Device { File(File), @@ -22,8 +35,8 @@ pub enum Device { Null, } -impl Device { - fn new(i: u8) -> Self { +impl From for Device { + fn from(i: u8) -> Self { match i { i if i == DeviceType::Console as u8 => Device::Console(Console::new()), i if i == DeviceType::Random as u8 => Device::Random(Random::new()), @@ -31,7 +44,9 @@ impl Device { _ => unimplemented!(), } } +} +impl Device { pub fn create(pathname: &str) -> Option { let pathname = realpath(pathname); let dirname = dirname(&pathname); @@ -53,7 +68,7 @@ impl Device { if dir_entry.is_device() { let block = LinkedBlock::read(dir_entry.addr()); let data = block.data(); - return Some(Self::new(data[0])); + return Some(data[0].into()); } } } @@ -67,7 +82,7 @@ impl FileIO for Device { Device::File(io) => io.read(buf), Device::Console(io) => io.read(buf), Device::Random(io) => io.read(buf), - Device::Null => Ok(0), + Device::Null => Err(()), } } fn write(&mut self, buf: &[u8]) -> Result { diff --git a/src/sys/fs/dir.rs b/src/sys/fs/dir.rs index 28127d0e..a69d74f4 100644 --- a/src/sys/fs/dir.rs +++ b/src/sys/fs/dir.rs @@ -242,11 +242,7 @@ impl FileIO for Dir { break; } } - if i > 0 { - Ok(i) - } else { - Err(()) - } + Ok(i) } fn write(&mut self, _buf: &[u8]) -> Result { Err(()) diff --git a/src/usr/install.rs b/src/usr/install.rs index 1b6cd01b..0c325305 100644 --- a/src/usr/install.rs +++ b/src/usr/install.rs @@ -21,6 +21,9 @@ pub fn copy_files(verbose: bool) { copy_file("/bin/sleep", include_bytes!("../../dsk/bin/sleep"), verbose); create_dir("/dev/clk", verbose); // Clocks + create_dev("/dev/clk/uptime", DeviceType::File, verbose); // TODO + create_dev("/dev/clk/realtime", DeviceType::File, verbose); // TODO + create_dev("/dev/rtc", DeviceType::File, verbose); // TODO create_dev("/dev/null", DeviceType::Null, verbose); create_dev("/dev/random", DeviceType::Random, verbose); create_dev("/dev/console", DeviceType::Console, verbose); diff --git a/src/usr/pow.rs b/src/usr/pow.rs index 0ba96f24..1af6fc3d 100644 --- a/src/usr/pow.rs +++ b/src/usr/pow.rs @@ -1,6 +1,6 @@ use crate::usr; use crate::api::console::Style; -use crate::api::{io, random}; +use crate::api::{io, random, console}; use core::fmt; use alloc::format; use alloc::string::ToString; @@ -34,7 +34,7 @@ impl Game { let mut parser = Parser::new(); while let Some(c) = io::stdin().read_char() { match c { - 'q' | '\x03' | '\x04' => { // ^C and ^D + 'q' | console::ETX_KEY | console::EOT_KEY => { return; }, c => { diff --git a/src/usr/read.rs b/src/usr/read.rs index 0cc8f886..b5a7de37 100644 --- a/src/usr/read.rs +++ b/src/usr/read.rs @@ -1,7 +1,9 @@ use crate::{api, sys, usr}; +use crate::api::console; use crate::api::fs; use crate::api::syscall; use crate::sys::cmos::CMOS; + use alloc::borrow::ToOwned; use alloc::vec::Vec; @@ -18,6 +20,7 @@ pub fn main(args: &[&str]) -> usr::shell::ExitCode { path = path.trim_end_matches('/'); } + // TODO: Create device drivers for `/dev` and `/net` hardcoded commands match path { "/dev/rtc" => { let rtc = CMOS::new().rtc(); @@ -81,14 +84,33 @@ pub fn main(args: &[&str]) -> usr::shell::ExitCode { } else if info.is_dir() { usr::list::main(args) } else if info.is_device() { + let is_console = info.size() == 4; // TODO: Improve device detection loop { - if let Ok(bytes) = fs::read_to_bytes(path) { - print!("{}", bytes[0] as char); - } if sys::console::end_of_text() { println!(); return usr::shell::ExitCode::CommandSuccessful; } + if let Ok(bytes) = fs::read_to_bytes(path) { + if is_console && bytes.len() == 1 { + match bytes[0] as char { + console::ETX_KEY => { + println!("^C"); + return usr::shell::ExitCode::CommandSuccessful; + } + console::EOT_KEY => { + println!("^D"); + return usr::shell::ExitCode::CommandSuccessful; + } + _ => {} + } + } + for b in bytes { + print!("{}", b as char); + } + } else { + eprintln!("Could not read '{}'", path); + return usr::shell::ExitCode::CommandError; + } } } else { eprintln!("Could not read type of '{}'", path);