Start stdin
This commit is contained in:
BIN
assets/cursor.png
Normal file
BIN
assets/cursor.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 249 B |
@@ -10,3 +10,4 @@ proc-macro = true
|
||||
proc-macro2 = "1"
|
||||
quote = "1"
|
||||
syn = { version = "2", features = ["full"] }
|
||||
zyn = "0.5"
|
||||
|
||||
@@ -1,27 +1,44 @@
|
||||
use core::iter::Iterator;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{Meta, parse_macro_input, spanned::Spanned};
|
||||
use syn::{Meta, spanned::Spanned};
|
||||
use zyn::zyn;
|
||||
|
||||
#[proc_macro_derive(VolatilePackedStruct, attributes(read_only))]
|
||||
pub fn derive_volatile_packed_struct(item: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(item as syn::DeriveInput);
|
||||
#[zyn::element(debug)]
|
||||
fn struct_getter(field: syn::Field) -> zyn::TokenStream {
|
||||
let field_name = field.ident.as_ref().unwrap();
|
||||
|
||||
zyn! {
|
||||
pub fn {{ field_name | ident:"get_{}" }}(self: *const Self) -> {{ field.ty }} {
|
||||
unsafe {
|
||||
(&raw const (*self).{{ field_name }}).read_volatile()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#[zyn::element]
|
||||
fn struct_setter(field: syn::Field) -> zyn::TokenStream {
|
||||
let field_name = field.ident.as_ref().unwrap();
|
||||
|
||||
zyn! {
|
||||
pub fn {{ field_name | ident:"set_{}" }}(self: *mut Self, value: {{ field.ty }}) {
|
||||
unsafe {
|
||||
(&raw mut (*self).{{ field_name }}).write_volatile(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[zyn::derive("VolatilePackedStruct", attributes(read_only), debug)]
|
||||
pub fn derive_volatile_packed_struct(#[zyn(input)] input: syn::DeriveInput) -> TokenStream {
|
||||
if !input.attrs.iter().any(|attr| match &attr.meta {
|
||||
Meta::List(list) => list.path.segments.last().is_some_and(|s| s.ident == "repr"),
|
||||
_ => false,
|
||||
}) {
|
||||
return syn::Error::new(
|
||||
input.span(),
|
||||
"Item should use a #[repr(packed)] representation",
|
||||
)
|
||||
.into_compile_error()
|
||||
.into();
|
||||
bail!("Item should use a #[repr(packed)] representation");
|
||||
}
|
||||
|
||||
let fields = match input.data {
|
||||
syn::Data::Struct(data_struct) => match data_struct.fields {
|
||||
let fields = match &input.data {
|
||||
syn::Data::Struct(data_struct) => match &data_struct.fields {
|
||||
syn::Fields::Named(fields_named) => fields_named,
|
||||
syn::Fields::Unnamed(_) | syn::Fields::Unit => unimplemented!(),
|
||||
},
|
||||
@@ -29,42 +46,16 @@ pub fn derive_volatile_packed_struct(item: TokenStream) -> TokenStream {
|
||||
syn::Data::Union(_) => unimplemented!(),
|
||||
};
|
||||
|
||||
let mut getters = Vec::new();
|
||||
let mut setters = Vec::new();
|
||||
|
||||
for field in fields.named {
|
||||
let field_name = field.ident.unwrap();
|
||||
if field_name.to_string().starts_with("_") {
|
||||
continue;
|
||||
}
|
||||
let ty = field.ty;
|
||||
let getter_name = format_ident!("get_{}", field_name);
|
||||
let setter_name = format_ident!("set_{}", field_name);
|
||||
|
||||
getters.push(quote! {
|
||||
pub fn #getter_name(self: *const Self) -> #ty {
|
||||
unsafe {
|
||||
(&raw const (*self).#field_name).read_volatile()
|
||||
}
|
||||
}
|
||||
});
|
||||
setters.push(quote! {
|
||||
pub fn #setter_name(self: *mut Self, value: #ty) {
|
||||
unsafe {
|
||||
(&raw mut (*self).#field_name).write_volatile(value);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let struct_path = input.ident;
|
||||
let (impl_generics, type_generics, where_clause) = input.generics.split_for_impl();
|
||||
|
||||
quote! {
|
||||
impl #impl_generics #struct_path #type_generics #where_clause {
|
||||
#(#getters)*
|
||||
#(#setters)*
|
||||
zyn! {
|
||||
impl {{ impl_generics }} {{ input.ident }} {{ type_generics }} {{ where_clause }} {
|
||||
@for (field in &fields.named) {
|
||||
@if (!field.ident.as_ref().unwrap().to_string().starts_with("_")) {
|
||||
@struct_getter(field = field.clone())
|
||||
@struct_setter(field = field.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
@@ -12,3 +12,4 @@ regex = "1"
|
||||
proc-macro2 = "1"
|
||||
quote = "1"
|
||||
syn = { version = "2", features = ["full"] }
|
||||
zyn = "0.5"
|
||||
|
||||
@@ -96,7 +96,7 @@ pub fn parse_image(
|
||||
Ok((width, height, name_ident, byte_count, byte_tokens))
|
||||
}
|
||||
|
||||
pub fn include_font_plate_impl(input: TokenStream) -> TokenStream {
|
||||
pub fn include_bitmap_image_impl(input: TokenStream) -> TokenStream {
|
||||
let (_, _, _, _, byte_tokens) = parse_image(input).unwrap();
|
||||
|
||||
let output = quote! {
|
||||
|
||||
@@ -3,6 +3,6 @@ mod image;
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
#[proc_macro]
|
||||
pub fn include_font_plate(input: TokenStream) -> TokenStream {
|
||||
image::include_font_plate_impl(input)
|
||||
pub fn include_bitmap_image(input: TokenStream) -> TokenStream {
|
||||
image::include_bitmap_image_impl(input)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::fs::File;
|
||||
|
||||
#[repr(u64)]
|
||||
pub enum SysCall {
|
||||
Read = 0,
|
||||
Write = 1,
|
||||
Open = 2,
|
||||
Seek = 8,
|
||||
@@ -22,6 +23,7 @@ pub enum SysCall {
|
||||
impl From<u64> for SysCall {
|
||||
fn from(value: u64) -> Self {
|
||||
match value {
|
||||
0 => SysCall::Read,
|
||||
1 => SysCall::Write,
|
||||
2 => SysCall::Open,
|
||||
8 => SysCall::Seek,
|
||||
@@ -151,6 +153,13 @@ pub fn write(file: &mut File, buf: &[u8]) {
|
||||
syscall!(SysCall::Write, file.as_fd(), ptr as u64, size as u64);
|
||||
}
|
||||
}
|
||||
pub fn read(file: &mut File, buf: &mut [u8]) {
|
||||
unsafe {
|
||||
let ptr = buf.as_ptr();
|
||||
let size = buf.len();
|
||||
syscall!(SysCall::Read, file.as_fd(), ptr as u64, size as u64);
|
||||
}
|
||||
}
|
||||
pub fn seek(file: &mut File, seek: SeekFrom) {
|
||||
unsafe {
|
||||
let (discriminant, value) = match seek {
|
||||
|
||||
38
src/cursor.rs
Normal file
38
src/cursor.rs
Normal file
@@ -0,0 +1,38 @@
|
||||
use kernel_macros::include_bitmap_image;
|
||||
|
||||
use crate::draw::{Color, Draw};
|
||||
|
||||
pub const CURSOR_WIDTH: usize = 8;
|
||||
pub const CURSOR_HEIGHT: usize = 10;
|
||||
pub const CURSOR_SIZE: usize = (CURSOR_HEIGHT * CURSOR_WIDTH) / 8;
|
||||
pub static CURSOR: [u8; CURSOR_SIZE] = include_bitmap_image! {"assets/cursor.png"};
|
||||
|
||||
pub fn draw_cursor<T: Draw>(drawer: &mut T, x: u16, y: u16) {
|
||||
for i in 0..CURSOR_HEIGHT {
|
||||
for j in 0..CURSOR_WIDTH {
|
||||
let pos = i * CURSOR_WIDTH + j;
|
||||
if CURSOR[pos / 8] & (1 << (pos % 8)) != 0 {
|
||||
unsafe {
|
||||
drawer.write_pixel_unsafe(
|
||||
x.saturating_add(j as u16),
|
||||
y.saturating_add(i as u16),
|
||||
Color::WHITE,
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn clear_cursor<T: Draw>(drawer: &mut T, x: u16, y: u16) {
|
||||
for i in 0..CURSOR_HEIGHT {
|
||||
for j in 0..CURSOR_WIDTH {
|
||||
unsafe {
|
||||
drawer.write_pixel_unsafe(
|
||||
x.saturating_add(j as u16),
|
||||
y.saturating_add(i as u16),
|
||||
Color::BLACK,
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
1
src/data_structures.rs
Normal file
1
src/data_structures.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod circular_buffer;
|
||||
55
src/data_structures/circular_buffer.rs
Normal file
55
src/data_structures/circular_buffer.rs
Normal file
@@ -0,0 +1,55 @@
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CircularBuffer<T, const SIZE: usize> {
|
||||
buffer: [MaybeUninit<T>; SIZE],
|
||||
head: usize,
|
||||
tail: usize,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl<T, const SIZE: usize> CircularBuffer<T, SIZE> {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
buffer: [const { MaybeUninit::uninit() }; SIZE],
|
||||
head: 0,
|
||||
tail: 0,
|
||||
len: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.len
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
pub fn is_full(&self) -> bool {
|
||||
self.len() == SIZE - 1
|
||||
}
|
||||
|
||||
pub fn pop(&mut self) -> Option<T> {
|
||||
if self.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let out = core::mem::replace(&mut self.buffer[self.head], MaybeUninit::uninit());
|
||||
self.head = (self.head + 1) % SIZE;
|
||||
self.len -= 1;
|
||||
// # Safety
|
||||
// the queue is not empty and head points to a valid value
|
||||
Some(unsafe { out.assume_init() })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push(&mut self, value: T) {
|
||||
self.buffer[self.tail] = MaybeUninit::new(value);
|
||||
if self.is_full() {
|
||||
self.head = (self.head + 1) % SIZE;
|
||||
} else {
|
||||
self.len += 1;
|
||||
}
|
||||
self.tail = (self.tail + 1) % SIZE;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
use kernel_macros::include_font_plate;
|
||||
use kernel_macros::include_bitmap_image;
|
||||
|
||||
/// 24-bit RGB color used by the framebuffer.
|
||||
#[repr(transparent)]
|
||||
@@ -121,4 +121,4 @@ pub const FONT_HEIGHT: usize = 13;
|
||||
pub const FONTPLATE_WIDTH: usize = 32 * FONT_WIDTH;
|
||||
pub const FONTPLATE_HEIGHT: usize = 3 * FONT_HEIGHT;
|
||||
pub const FONTPLATE_SIZE: usize = FONTPLATE_WIDTH * FONTPLATE_HEIGHT / 8;
|
||||
pub static FONTPLATE: [u8; FONTPLATE_SIZE] = include_font_plate! {"assets/fontplate.png"};
|
||||
pub static FONTPLATE: [u8; FONTPLATE_SIZE] = include_bitmap_image! {"assets/fontplate.png"};
|
||||
|
||||
@@ -149,6 +149,16 @@ unsafe extern "C" fn supervisor_trap_handler(
|
||||
let vnode = current_process.fd_table.get_mut(&fd).unwrap();
|
||||
vnode.write(buf).unwrap();
|
||||
}
|
||||
SysCall::Read => {
|
||||
let fd = a1;
|
||||
let buf =
|
||||
unsafe { core::slice::from_raw_parts_mut(a2 as *mut u8, a3 as usize) };
|
||||
|
||||
let mut scheduler = SCHEDULER.lock();
|
||||
let current_process = scheduler.get_current_process();
|
||||
let vnode = current_process.fd_table.get_mut(&fd).unwrap();
|
||||
vnode.read(buf).unwrap();
|
||||
}
|
||||
SysCall::Seek => {
|
||||
let fd = a1;
|
||||
let seek = match a2 {
|
||||
|
||||
22
src/main.rs
22
src/main.rs
@@ -19,7 +19,7 @@ use embedded_alloc::LlffHeap as Heap;
|
||||
use log::info;
|
||||
|
||||
use crate::{
|
||||
draw::{Color, Draw},
|
||||
cursor::{clear_cursor, draw_cursor},
|
||||
io::init_log,
|
||||
pci::{PciDeviceIterator, scan_virtio_devices},
|
||||
riscv::enable_supervisor_interrupt,
|
||||
@@ -28,14 +28,16 @@ use crate::{
|
||||
vga::Vga,
|
||||
virtio::{
|
||||
Virtqueue,
|
||||
input::{VirtioPciDriver, init_plic_pci},
|
||||
input::{EventCodeValue, VirtioPciDriver, init_plic_pci},
|
||||
},
|
||||
virtual_fs::init_file_system,
|
||||
virtual_fs::{FILE_SYSTEM, VirtualFileSystem, init_file_system},
|
||||
};
|
||||
|
||||
extern crate alloc;
|
||||
mod boot;
|
||||
mod critical_section;
|
||||
mod cursor;
|
||||
mod data_structures;
|
||||
mod draw;
|
||||
mod fs;
|
||||
mod interrupt;
|
||||
@@ -72,11 +74,15 @@ static mut KBD_QUEUE: Virtqueue = unsafe { core::mem::zeroed() };
|
||||
pub static mut KBD_DRIVER: VirtioPciDriver = unsafe {
|
||||
VirtioPciDriver::new(
|
||||
|event| {
|
||||
let mut kbd_buffer = FILE_SYSTEM.open("/dev/input/keyboard".as_ref()).unwrap();
|
||||
if event.is_key() {
|
||||
let event = event.as_key_event();
|
||||
println!("key, {:#?}", event);
|
||||
if event.value == EventCodeValue::Pressed {
|
||||
println!("event: {:#?}", event);
|
||||
kbd_buffer.write(&[event.code as u8]).unwrap();
|
||||
}
|
||||
} else {
|
||||
println!("key pressed, {:#?}", event);
|
||||
// println!("key pressed, {:#?}", event);
|
||||
}
|
||||
},
|
||||
&mut KBD_QUEUE,
|
||||
@@ -92,7 +98,7 @@ pub static mut MOUSE_DRIVER: VirtioPciDriver = unsafe {
|
||||
if event.is_relative() {
|
||||
let event = event.as_relative_event();
|
||||
|
||||
vga::Vga.write_pixel_unsafe(MOUSE_POSITION.0, MOUSE_POSITION.1, Color::BLACK);
|
||||
clear_cursor(&mut Vga, MOUSE_POSITION.0, MOUSE_POSITION.1);
|
||||
|
||||
match event.code {
|
||||
virtio::input::EventCodeRelative::X => {
|
||||
@@ -104,7 +110,7 @@ pub static mut MOUSE_DRIVER: VirtioPciDriver = unsafe {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
vga::Vga.write_pixel_unsafe(MOUSE_POSITION.0, MOUSE_POSITION.1, Color::RED);
|
||||
draw_cursor(&mut Vga, MOUSE_POSITION.0, MOUSE_POSITION.1);
|
||||
|
||||
// println!("mouse moved relatively, {:#?}", event);
|
||||
} else {
|
||||
@@ -122,8 +128,8 @@ pub extern "C" fn supervisor_mode_entry() {
|
||||
HEAP_INITIALIZED.store(true, core::sync::atomic::Ordering::Relaxed);
|
||||
init_log().unwrap();
|
||||
Vga::init();
|
||||
SCHEDULER.lock().init();
|
||||
init_file_system();
|
||||
SCHEDULER.lock().init();
|
||||
}
|
||||
|
||||
info!("Hello World !");
|
||||
|
||||
@@ -13,7 +13,6 @@ use alloc::{boxed::Box, format, string::String, vec::Vec};
|
||||
use bffs::path::Path;
|
||||
use goblin::elf::reloc::R_RISCV_RELATIVE;
|
||||
use hashbrown::HashMap;
|
||||
use log::info;
|
||||
use shared::syscall::exit;
|
||||
|
||||
use crate::{
|
||||
@@ -164,9 +163,7 @@ impl Scheduler {
|
||||
let name = path.as_str();
|
||||
|
||||
// Open and read the binary file
|
||||
info!("ue");
|
||||
let mut bin = unsafe { FILE_SYSTEM.open(path).unwrap() };
|
||||
info!("ue");
|
||||
println!("Creating process");
|
||||
let mut content: Vec<u8> = Vec::new();
|
||||
bin.read_to_end(&mut content).unwrap();
|
||||
@@ -300,6 +297,11 @@ impl Scheduler {
|
||||
process.state = ProcessState::Activable;
|
||||
process.entry = Some(code);
|
||||
|
||||
process.fd_table = HashMap::new();
|
||||
process
|
||||
.fd_table
|
||||
.insert(0, FILE_SYSTEM.open("/dev/input/keyboard".into()).unwrap());
|
||||
|
||||
// Configure execution context
|
||||
// a0 contains the pointer to the function to execute
|
||||
process.ctx.a[0] = &raw const *process.entry.as_ref().unwrap_unchecked() as u64;
|
||||
|
||||
@@ -8,7 +8,10 @@ use bffs::{
|
||||
use hashbrown::HashMap;
|
||||
use io::{IoBase, Read, Seek, Write};
|
||||
|
||||
use crate::{fs::Disk, tty::Tty, vga::Vga};
|
||||
pub mod keyboard;
|
||||
pub mod stdin;
|
||||
|
||||
use crate::{fs::Disk, tty::Tty, vga::Vga, virtual_fs::keyboard::KeyboardBuffer};
|
||||
|
||||
pub trait VirtualNode: IoBase<Error = ()> + Read + Write + Seek + Debug {}
|
||||
|
||||
@@ -53,6 +56,11 @@ pub unsafe fn init_file_system() {
|
||||
unsafe {
|
||||
FILE_SYSTEM.mount("/dev/fb0".into(), Box::new(VGAFileSystem));
|
||||
FILE_SYSTEM.mount("/dev/tty0".into(), Box::new(Tty::new()));
|
||||
FILE_SYSTEM.mount(
|
||||
"/dev/input/keyboard".into(),
|
||||
Box::new(KeyboardBuffer::new()),
|
||||
);
|
||||
// FILE_SYSTEM.mount("/dev/stdin".into(), Box::new(Stdin::new()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
85
src/virtual_fs/keyboard.rs
Normal file
85
src/virtual_fs/keyboard.rs
Normal file
@@ -0,0 +1,85 @@
|
||||
use core::cell::RefCell;
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use io::{IoBase, Read, Seek, Write};
|
||||
|
||||
use crate::{
|
||||
data_structures::circular_buffer::CircularBuffer,
|
||||
println,
|
||||
virtual_fs::{VirtualFileSystem, VirtualNode},
|
||||
};
|
||||
|
||||
pub const KEYBOARD_BUFFER_SIZE: usize = 4096; // 4Ko
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct KeyboardBuffer {
|
||||
buffer: RefCell<CircularBuffer<u8, KEYBOARD_BUFFER_SIZE>>,
|
||||
}
|
||||
|
||||
impl KeyboardBuffer {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
buffer: RefCell::new(CircularBuffer::new()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct KeyboardBufferNode<'a> {
|
||||
buffer: &'a KeyboardBuffer,
|
||||
}
|
||||
|
||||
impl<'a> KeyboardBufferNode<'a> {
|
||||
pub fn new(stdin: &'a KeyboardBuffer) -> Self {
|
||||
Self { buffer: stdin }
|
||||
}
|
||||
}
|
||||
|
||||
impl VirtualFileSystem for KeyboardBuffer {
|
||||
fn open(
|
||||
&mut self,
|
||||
path: &bffs::path::Path,
|
||||
) -> Result<alloc::boxed::Box<dyn crate::virtual_fs::VirtualNode + '_>, ()> {
|
||||
if !path.is_empty() {
|
||||
Err(())
|
||||
} else {
|
||||
Ok(Box::new(KeyboardBufferNode::new(self)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IoBase for KeyboardBufferNode<'_> {
|
||||
type Error = ();
|
||||
}
|
||||
|
||||
impl Read for KeyboardBufferNode<'_> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
|
||||
let mut buffer = self.buffer.buffer.borrow_mut();
|
||||
for i in 0..buf.len() {
|
||||
buf[i] = buffer.pop().unwrap();
|
||||
}
|
||||
Ok(buf.len())
|
||||
}
|
||||
}
|
||||
|
||||
impl Seek for KeyboardBufferNode<'_> {
|
||||
fn seek(&mut self, pos: io::SeekFrom) -> Result<u64, Self::Error> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for KeyboardBufferNode<'_> {
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
|
||||
let mut buffer = self.buffer.buffer.borrow_mut();
|
||||
for input in buf {
|
||||
buffer.push(*input);
|
||||
}
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> Result<(), Self::Error> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl VirtualNode for KeyboardBufferNode<'_> {}
|
||||
67
src/virtual_fs/stdin.rs
Normal file
67
src/virtual_fs/stdin.rs
Normal file
@@ -0,0 +1,67 @@
|
||||
// use core::cell::RefCell;
|
||||
|
||||
// use alloc::boxed::Box;
|
||||
// use io::{IoBase, Read, Seek, Write};
|
||||
|
||||
// use crate::virtual_fs::{VirtualFileSystem, VirtualNode};
|
||||
|
||||
// pub const STDIN_BUFFER_SIZE: usize = 4096; // 4Ko
|
||||
|
||||
// #[derive(Debug)]
|
||||
// pub struct Stdin {
|
||||
// buffer: RefCell<[u8; STDIN_BUFFER_SIZE]>,
|
||||
// }
|
||||
|
||||
// impl Stdin {
|
||||
// pub fn new() -> Self {
|
||||
// Self {
|
||||
// buffer: RefCell::new([0; _]),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[derive(Debug)]
|
||||
// pub struct StdinNode<'a> {
|
||||
// stdin: &'a Stdin,
|
||||
// }
|
||||
|
||||
// impl VirtualFileSystem for Stdin {
|
||||
// fn open(
|
||||
// &mut self,
|
||||
// path: &bffs::path::Path,
|
||||
// ) -> Result<alloc::boxed::Box<dyn crate::virtual_fs::VirtualNode + '_>, ()> {
|
||||
// if !path.is_empty() {
|
||||
// Err(())
|
||||
// } else {
|
||||
// Ok(Box::new(StdinNode { stdin: self }))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl IoBase for StdinNode<'_> {
|
||||
// type Error = ();
|
||||
// }
|
||||
|
||||
// impl Read for StdinNode<'_> {
|
||||
// fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
|
||||
// todo!()
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl Seek for StdinNode<'_> {
|
||||
// fn seek(&mut self, pos: io::SeekFrom) -> Result<u64, Self::Error> {
|
||||
// todo!()
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl Write for StdinNode<'_> {
|
||||
// fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
|
||||
// todo!()
|
||||
// }
|
||||
|
||||
// fn flush(&mut self) -> Result<(), Self::Error> {
|
||||
// todo!()
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl VirtualNode for StdinNode<'_> {}
|
||||
@@ -1,23 +1,24 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::time::Duration;
|
||||
|
||||
use os_std::syscall;
|
||||
os_std::custom_std_setup! {}
|
||||
|
||||
fn main() {
|
||||
let mut test = String::new();
|
||||
test.push('A');
|
||||
test.push('B');
|
||||
for _ in 0..100 {
|
||||
test.push('C');
|
||||
}
|
||||
// let mut input = String::new();
|
||||
// let mut file = syscall::open("/dev/fb0");
|
||||
// syscall::seek(&mut file, SeekFrom::End(-3));
|
||||
// syscall::write(&mut file, &[255; 6400 * 50]);
|
||||
syscall::sleep(Duration::from_secs_f64(2.0));
|
||||
let mut stdin = syscall::open("/dev/input/keyboard");
|
||||
let mut test = [0; 2];
|
||||
syscall::read(&mut stdin, &mut test);
|
||||
let mut file = syscall::open("/dev/tty0");
|
||||
syscall::write(&mut file, b"Hi !\nnice tty\x08");
|
||||
println!(
|
||||
"Hello from PIC program loaded dynamically with custom std and a better justfile, and syscalls ! {}",
|
||||
"Hello from PIC program loaded dynamically with custom std and a better justfile, and syscalls ! {:?}",
|
||||
test
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user