use core::{ cell::{LazyCell, RefCell}, sync::atomic::AtomicBool, }; use alloc::{boxed::Box, rc::Rc}; use io::{IoBase, Read, Seek, Write}; use crate::{ data_structures::circular_buffer::CircularBuffer, virtual_console::VirtualConsole, virtual_fs::{VirtualFileSystem, VirtualNode}, }; pub const TTY_BUFFER_SIZE: usize = 4096; // 4Ko pub static mut TTY0: LazyCell = LazyCell::new(|| { let tty = Tty::new(); TTY_INITIALIZED.store(true, core::sync::atomic::Ordering::Relaxed); tty }); pub static TTY_INITIALIZED: AtomicBool = AtomicBool::new(false); #[derive(Debug, Clone)] pub struct Tty { pub buffer: Rc>>, console: Rc>, } impl Tty { pub fn new() -> Self { Self { buffer: RefCell::new(CircularBuffer::new()).into(), console: RefCell::new(VirtualConsole::new()).into(), } } pub fn new_node(&'_ self) -> TtyNode<'_> { TtyNode { tty: self } } } #[derive(Debug)] pub struct TtyNode<'a> { tty: &'a Tty, } impl VirtualFileSystem for Tty { fn open( &mut self, path: &bffs::path::Path, ) -> Result, ()> { if !path.is_empty() { Err(()) } else { Ok(Box::new(self.new_node())) } } } impl IoBase for TtyNode<'_> { type Error = (); } impl Read for TtyNode<'_> { fn read(&mut self, buf: &mut [u8]) -> Result { let mut buffer = self.tty.buffer.borrow_mut(); let max_len = buffer.len(); (0..buf.len().min(max_len)).for_each(|i| { buf[i] = buffer.pop().unwrap(); }); Ok(buf.len().min(max_len)) } } impl Seek for TtyNode<'_> { fn seek(&mut self, _pos: io::SeekFrom) -> Result { unimplemented!() } } impl Write for TtyNode<'_> { fn write(&mut self, buf: &[u8]) -> Result { critical_section::with(|_| { self.tty .console .borrow_mut() .write_str(str::from_utf8(buf).unwrap()); }); Ok(buf.len()) } fn flush(&mut self) -> Result<(), Self::Error> { todo!() } } impl VirtualNode for TtyNode<'_> {}