120e3152eSlogin use alloc::{ 220e3152eSlogin collections::BTreeMap, 320e3152eSlogin string::{String, ToString}, 420e3152eSlogin sync::{Arc, Weak}, 520e3152eSlogin }; 6*91e9d4abSLoGin use system_error::SystemError; 70d48c3c9Slogin 80d48c3c9Slogin use crate::{ 90d48c3c9Slogin filesystem::{ 1020e3152eSlogin devfs::{devfs_register, DevFS, DeviceINode}, 116b4e7a29SLoGin vfs::{ 126b4e7a29SLoGin file::FileMode, syscall::ModeType, FilePrivateData, FileType, IndexNode, Metadata, 136b4e7a29SLoGin ROOT_INODE, 146b4e7a29SLoGin }, 150d48c3c9Slogin }, 16d7b31a96SGou Ngai kerror, 17abe3a6eaShanjiezhou libs::{ 18abe3a6eaShanjiezhou lib_ui::textui::{textui_putchar, FontColor}, 19abe3a6eaShanjiezhou rwlock::RwLock, 20abe3a6eaShanjiezhou }, 210d48c3c9Slogin }; 220d48c3c9Slogin 23a03c4f9dSLoGin use super::{serial::serial_init, TtyCore, TtyError, TtyFileFlag, TtyFilePrivateData}; 240d48c3c9Slogin 2520e3152eSlogin lazy_static! { 2620e3152eSlogin /// 所有TTY设备的B树。用于根据名字,找到Arc<TtyDevice> 2720e3152eSlogin /// TODO: 待设备驱动模型完善,具有类似功能的机制后,删掉这里 2820e3152eSlogin pub static ref TTY_DEVICES: RwLock<BTreeMap<String, Arc<TtyDevice>>> = RwLock::new(BTreeMap::new()); 2920e3152eSlogin } 3020e3152eSlogin 3120e3152eSlogin /// @brief TTY设备 320d48c3c9Slogin #[derive(Debug)] 330d48c3c9Slogin pub struct TtyDevice { 3420e3152eSlogin /// TTY核心 350d48c3c9Slogin core: TtyCore, 3620e3152eSlogin /// TTY所属的文件系统 3720e3152eSlogin fs: RwLock<Weak<DevFS>>, 3820e3152eSlogin /// TTY设备私有信息 3920e3152eSlogin private_data: RwLock<TtyDevicePrivateData>, 4020e3152eSlogin } 410d48c3c9Slogin 4220e3152eSlogin #[derive(Debug)] 4320e3152eSlogin struct TtyDevicePrivateData { 4420e3152eSlogin /// TTY设备名(如tty1) 4520e3152eSlogin name: String, 4620e3152eSlogin /// TTY设备文件的元数据 4720e3152eSlogin metadata: Metadata, 4820e3152eSlogin // TODO: 增加指向输出端口连接的设备的指针 490d48c3c9Slogin } 500d48c3c9Slogin 510d48c3c9Slogin impl TtyDevice { 5220e3152eSlogin pub fn new(name: &str) -> Arc<TtyDevice> { 5320e3152eSlogin let result = Arc::new(TtyDevice { 540d48c3c9Slogin core: TtyCore::new(), 550d48c3c9Slogin fs: RwLock::new(Weak::default()), 5620e3152eSlogin private_data: TtyDevicePrivateData::new(name), 570d48c3c9Slogin }); 5820e3152eSlogin // 默认开启输入回显 5920e3152eSlogin result.core.enable_echo(); 6020e3152eSlogin return result; 610d48c3c9Slogin } 620d48c3c9Slogin 6320e3152eSlogin /// @brief 判断文件私有信息是否为TTY文件的私有信息 640d48c3c9Slogin #[inline] 650d48c3c9Slogin fn verify_file_private_data<'a>( 660d48c3c9Slogin &self, 670d48c3c9Slogin private_data: &'a mut FilePrivateData, 68676b8ef6SMork ) -> Result<&'a mut TtyFilePrivateData, SystemError> { 690d48c3c9Slogin if let FilePrivateData::Tty(t) = private_data { 700d48c3c9Slogin return Ok(t); 710d48c3c9Slogin } 72676b8ef6SMork return Err(SystemError::EIO); 730d48c3c9Slogin } 7420e3152eSlogin 7520e3152eSlogin /// @brief 获取TTY设备名 7620e3152eSlogin #[inline] 7720e3152eSlogin pub fn name(&self) -> String { 7820e3152eSlogin return self.private_data.read().name.clone(); 7920e3152eSlogin } 8020e3152eSlogin 8120e3152eSlogin /// @brief 检查TTY文件的读写参数是否合法 8220e3152eSlogin #[inline] 8320e3152eSlogin pub fn check_rw_param(&self, len: usize, buf: &[u8]) -> Result<(), SystemError> { 8420e3152eSlogin if len > buf.len() { 8520e3152eSlogin return Err(SystemError::EINVAL); 8620e3152eSlogin } 8720e3152eSlogin return Ok(()); 8820e3152eSlogin } 8920e3152eSlogin 9020e3152eSlogin /// @brief 向TTY的输入端口导入数据 9120e3152eSlogin pub fn input(&self, buf: &[u8]) -> Result<usize, SystemError> { 9220e3152eSlogin let r: Result<usize, TtyError> = self.core.input(buf, false); 9320e3152eSlogin if r.is_ok() { 9420e3152eSlogin return Ok(r.unwrap()); 9520e3152eSlogin } 9620e3152eSlogin 9720e3152eSlogin let r = r.unwrap_err(); 9820e3152eSlogin match r { 9920e3152eSlogin TtyError::BufferFull(x) => return Ok(x), 10020e3152eSlogin TtyError::Closed => return Err(SystemError::ENODEV), 10120e3152eSlogin e => { 10220e3152eSlogin kerror!("tty error occurred while writing data to its input port, msg={e:?}"); 10320e3152eSlogin return Err(SystemError::EBUSY); 10420e3152eSlogin } 10520e3152eSlogin } 10620e3152eSlogin } 1070d48c3c9Slogin } 1080d48c3c9Slogin 1090d48c3c9Slogin impl DeviceINode for TtyDevice { 1100d48c3c9Slogin fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) { 1110d48c3c9Slogin *self.fs.write() = fs; 1120d48c3c9Slogin } 1130d48c3c9Slogin } 1140d48c3c9Slogin 1150d48c3c9Slogin impl IndexNode for TtyDevice { 11620e3152eSlogin /// @brief 打开TTY设备 11720e3152eSlogin /// 11820e3152eSlogin /// @param data 文件私有信息 11920e3152eSlogin /// @param mode 打开模式 12020e3152eSlogin /// 12120e3152eSlogin /// TTY设备通过mode来确定这个文件到底是stdin/stdout/stderr 12220e3152eSlogin /// - mode的值为O_RDONLY时,表示这个文件是stdin 12320e3152eSlogin /// - mode的值为O_WRONLY时,表示这个文件是stdout 12420e3152eSlogin /// - mode的值为O_WRONLY | O_SYNC时,表示这个文件是stderr 125676b8ef6SMork fn open(&self, data: &mut FilePrivateData, mode: &FileMode) -> Result<(), SystemError> { 12620e3152eSlogin let mut p = TtyFilePrivateData::default(); 12720e3152eSlogin 12820e3152eSlogin // 检查打开模式 12920e3152eSlogin let accmode = mode.accmode(); 13020e3152eSlogin if accmode == FileMode::O_RDONLY.accmode() { 13120e3152eSlogin p.flags.insert(TtyFileFlag::STDIN); 13220e3152eSlogin } else if accmode == FileMode::O_WRONLY.accmode() { 13320e3152eSlogin if mode.contains(FileMode::O_SYNC) { 13420e3152eSlogin p.flags.insert(TtyFileFlag::STDERR); 13520e3152eSlogin } else { 13620e3152eSlogin p.flags.insert(TtyFileFlag::STDOUT); 13720e3152eSlogin } 13820e3152eSlogin } else { 13920e3152eSlogin return Err(SystemError::EINVAL); 14020e3152eSlogin } 14120e3152eSlogin 14220e3152eSlogin // 保存文件私有信息 1430d48c3c9Slogin *data = FilePrivateData::Tty(p); 1440d48c3c9Slogin return Ok(()); 1450d48c3c9Slogin } 1460d48c3c9Slogin 1470d48c3c9Slogin fn read_at( 1480d48c3c9Slogin &self, 14920e3152eSlogin _offset: usize, 1500d48c3c9Slogin len: usize, 1510d48c3c9Slogin buf: &mut [u8], 1520d48c3c9Slogin data: &mut crate::filesystem::vfs::FilePrivateData, 153676b8ef6SMork ) -> Result<usize, SystemError> { 1540d48c3c9Slogin let _data: &mut TtyFilePrivateData = match self.verify_file_private_data(data) { 1550d48c3c9Slogin Ok(t) => t, 1560d48c3c9Slogin Err(e) => { 1570d48c3c9Slogin kerror!("Try to read tty device, but file private data type mismatch!"); 1580d48c3c9Slogin return Err(e); 1590d48c3c9Slogin } 1600d48c3c9Slogin }; 16120e3152eSlogin self.check_rw_param(len, buf)?; 1620d48c3c9Slogin 1630d48c3c9Slogin // 读取stdin队列 16420e3152eSlogin let r: Result<usize, TtyError> = self.core.read_stdin(&mut buf[0..len], true); 1650d48c3c9Slogin if r.is_ok() { 1660d48c3c9Slogin return Ok(r.unwrap()); 1670d48c3c9Slogin } 1680d48c3c9Slogin 1690d48c3c9Slogin match r.unwrap_err() { 1700d48c3c9Slogin TtyError::EOF(n) => { 1710d48c3c9Slogin return Ok(n); 1720d48c3c9Slogin } 17320e3152eSlogin 1740d48c3c9Slogin x => { 1750d48c3c9Slogin kerror!("Error occurred when reading tty, msg={x:?}"); 176676b8ef6SMork return Err(SystemError::ECONNABORTED); 1770d48c3c9Slogin } 1780d48c3c9Slogin } 1790d48c3c9Slogin } 1800d48c3c9Slogin 1810d48c3c9Slogin fn write_at( 1820d48c3c9Slogin &self, 18320e3152eSlogin _offset: usize, 1840d48c3c9Slogin len: usize, 1850d48c3c9Slogin buf: &[u8], 1860d48c3c9Slogin data: &mut crate::filesystem::vfs::FilePrivateData, 187676b8ef6SMork ) -> Result<usize, SystemError> { 1880d48c3c9Slogin let data: &mut TtyFilePrivateData = match self.verify_file_private_data(data) { 1890d48c3c9Slogin Ok(t) => t, 1900d48c3c9Slogin Err(e) => { 1910d48c3c9Slogin kerror!("Try to write tty device, but file private data type mismatch!"); 1920d48c3c9Slogin return Err(e); 1930d48c3c9Slogin } 1940d48c3c9Slogin }; 1950d48c3c9Slogin 19620e3152eSlogin self.check_rw_param(len, buf)?; 19720e3152eSlogin 1980d48c3c9Slogin // 根据当前文件是stdout还是stderr,选择不同的发送方式 1990d48c3c9Slogin let r: Result<usize, TtyError> = if data.flags.contains(TtyFileFlag::STDOUT) { 20020e3152eSlogin self.core.stdout(&buf[0..len], true) 2010d48c3c9Slogin } else if data.flags.contains(TtyFileFlag::STDERR) { 20220e3152eSlogin self.core.stderr(&buf[0..len], true) 2030d48c3c9Slogin } else { 204676b8ef6SMork return Err(SystemError::EPERM); 2050d48c3c9Slogin }; 2060d48c3c9Slogin 2070d48c3c9Slogin if r.is_ok() { 20820e3152eSlogin self.sync().expect("Failed to sync tty device!"); 2090d48c3c9Slogin return Ok(r.unwrap()); 2100d48c3c9Slogin } 2110d48c3c9Slogin 2120d48c3c9Slogin let r: TtyError = r.unwrap_err(); 2130d48c3c9Slogin kerror!("Error occurred when writing tty deivce. Error msg={r:?}"); 214676b8ef6SMork return Err(SystemError::EIO); 2150d48c3c9Slogin } 2160d48c3c9Slogin 2170d48c3c9Slogin fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> { 2180d48c3c9Slogin return self.fs.read().upgrade().unwrap(); 2190d48c3c9Slogin } 2200d48c3c9Slogin 2210d48c3c9Slogin fn as_any_ref(&self) -> &dyn core::any::Any { 2220d48c3c9Slogin self 2230d48c3c9Slogin } 2240d48c3c9Slogin 225676b8ef6SMork fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> { 22679a452ceShoumkh return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 2270d48c3c9Slogin } 22820e3152eSlogin 22920e3152eSlogin fn metadata(&self) -> Result<Metadata, SystemError> { 23020e3152eSlogin return Ok(self.private_data.read().metadata.clone()); 23120e3152eSlogin } 23220e3152eSlogin 23320e3152eSlogin fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> { 23420e3152eSlogin return Ok(()); 23520e3152eSlogin } 23620e3152eSlogin 23720e3152eSlogin fn sync(&self) -> Result<(), SystemError> { 23820e3152eSlogin // TODO: 引入IO重定向后,需要将输出重定向到对应的设备。 23920e3152eSlogin // 目前只是简单的输出到屏幕(为了实现的简便) 24020e3152eSlogin 24120e3152eSlogin loop { 24220e3152eSlogin let mut buf = [0u8; 512]; 243d7b31a96SGou Ngai let r: Result<usize, TtyError> = self.core.output(&mut buf[0..511], false); 24420e3152eSlogin let len; 24520e3152eSlogin match r { 24620e3152eSlogin Ok(x) => { 24720e3152eSlogin len = x; 24820e3152eSlogin } 24920e3152eSlogin Err(TtyError::EOF(x)) | Err(TtyError::BufferEmpty(x)) => { 25020e3152eSlogin len = x; 25120e3152eSlogin } 25220e3152eSlogin _ => return Err(SystemError::EIO), 25320e3152eSlogin } 25420e3152eSlogin 25520e3152eSlogin if len == 0 { 25620e3152eSlogin break; 25720e3152eSlogin } 25820e3152eSlogin // 输出到屏幕 259abe3a6eaShanjiezhou 26011110997Shanjiezhou for x in 0..len { 26111110997Shanjiezhou textui_putchar(buf[x] as char, FontColor::WHITE, FontColor::BLACK).ok(); 262d7b31a96SGou Ngai } 26320e3152eSlogin } 26420e3152eSlogin return Ok(()); 26520e3152eSlogin } 26611110997Shanjiezhou fn resize(&self, _len: usize) -> Result<(), SystemError> { 26711110997Shanjiezhou return Ok(()); 26811110997Shanjiezhou } 26920e3152eSlogin } 27020e3152eSlogin 27120e3152eSlogin impl TtyDevicePrivateData { 27220e3152eSlogin pub fn new(name: &str) -> RwLock<Self> { 2736b4e7a29SLoGin let mut metadata = Metadata::new(FileType::CharDevice, ModeType::from_bits_truncate(0o755)); 27420e3152eSlogin metadata.size = TtyCore::STDIN_BUF_SIZE as i64; 27520e3152eSlogin return RwLock::new(TtyDevicePrivateData { 27620e3152eSlogin name: name.to_string(), 27720e3152eSlogin metadata, 27820e3152eSlogin }); 27920e3152eSlogin } 28020e3152eSlogin } 28120e3152eSlogin 28220e3152eSlogin /// @brief 初始化TTY设备 28320e3152eSlogin pub fn tty_init() -> Result<(), SystemError> { 28420e3152eSlogin let tty: Arc<TtyDevice> = TtyDevice::new("tty0"); 28520e3152eSlogin let devfs_root_inode = ROOT_INODE().lookup("/dev"); 28620e3152eSlogin if devfs_root_inode.is_err() { 28720e3152eSlogin return Err(devfs_root_inode.unwrap_err()); 28820e3152eSlogin } 28920e3152eSlogin // 当前关闭键盘输入回显 29020e3152eSlogin // TODO: 完善Termios之后, 改为默认开启键盘输入回显. 29120e3152eSlogin tty.core.disable_echo(); 29220e3152eSlogin let guard = TTY_DEVICES.upgradeable_read(); 29320e3152eSlogin 29420e3152eSlogin // 如果已经存在了这个设备 29520e3152eSlogin if guard.contains_key("tty0") { 29620e3152eSlogin return Err(SystemError::EEXIST); 29720e3152eSlogin } 29820e3152eSlogin 29920e3152eSlogin let mut guard = guard.upgrade(); 30020e3152eSlogin 30120e3152eSlogin guard.insert("tty0".to_string(), tty.clone()); 30220e3152eSlogin 30320e3152eSlogin drop(guard); 30420e3152eSlogin 30520e3152eSlogin let r = devfs_register(&tty.name(), tty); 30620e3152eSlogin if r.is_err() { 30720e3152eSlogin return Err(devfs_root_inode.unwrap_err()); 30820e3152eSlogin } 30920e3152eSlogin 310a03c4f9dSLoGin serial_init()?; 31120e3152eSlogin return Ok(()); 3120d48c3c9Slogin } 313