120e3152eSlogin use alloc::{ 220e3152eSlogin collections::BTreeMap, 320e3152eSlogin string::{String, ToString}, 420e3152eSlogin sync::{Arc, Weak}, 520e3152eSlogin }; 60d48c3c9Slogin 70d48c3c9Slogin use crate::{ 80d48c3c9Slogin filesystem::{ 920e3152eSlogin devfs::{devfs_register, DevFS, DeviceINode}, 1020e3152eSlogin vfs::{file::FileMode, FilePrivateData, FileType, IndexNode, Metadata, ROOT_INODE}, 110d48c3c9Slogin }, 12d7b31a96SGou Ngai kerror, 13abe3a6eaShanjiezhou libs::{ 14abe3a6eaShanjiezhou lib_ui::textui::{textui_putchar, FontColor}, 15abe3a6eaShanjiezhou rwlock::RwLock, 16abe3a6eaShanjiezhou }, 17ab5c8ca4Slogin syscall::SystemError, 180d48c3c9Slogin }; 190d48c3c9Slogin 200d48c3c9Slogin use super::{TtyCore, TtyError, TtyFileFlag, TtyFilePrivateData}; 210d48c3c9Slogin 2220e3152eSlogin lazy_static! { 2320e3152eSlogin /// 所有TTY设备的B树。用于根据名字,找到Arc<TtyDevice> 2420e3152eSlogin /// TODO: 待设备驱动模型完善,具有类似功能的机制后,删掉这里 2520e3152eSlogin pub static ref TTY_DEVICES: RwLock<BTreeMap<String, Arc<TtyDevice>>> = RwLock::new(BTreeMap::new()); 2620e3152eSlogin } 2720e3152eSlogin 2820e3152eSlogin /// @brief TTY设备 290d48c3c9Slogin #[derive(Debug)] 300d48c3c9Slogin pub struct TtyDevice { 3120e3152eSlogin /// TTY核心 320d48c3c9Slogin core: TtyCore, 3320e3152eSlogin /// TTY所属的文件系统 3420e3152eSlogin fs: RwLock<Weak<DevFS>>, 3520e3152eSlogin /// TTY设备私有信息 3620e3152eSlogin private_data: RwLock<TtyDevicePrivateData>, 3720e3152eSlogin } 380d48c3c9Slogin 3920e3152eSlogin #[derive(Debug)] 4020e3152eSlogin struct TtyDevicePrivateData { 4120e3152eSlogin /// TTY设备名(如tty1) 4220e3152eSlogin name: String, 4320e3152eSlogin /// TTY设备文件的元数据 4420e3152eSlogin metadata: Metadata, 4520e3152eSlogin // TODO: 增加指向输出端口连接的设备的指针 460d48c3c9Slogin } 470d48c3c9Slogin 480d48c3c9Slogin impl TtyDevice { 4920e3152eSlogin pub fn new(name: &str) -> Arc<TtyDevice> { 5020e3152eSlogin let result = Arc::new(TtyDevice { 510d48c3c9Slogin core: TtyCore::new(), 520d48c3c9Slogin fs: RwLock::new(Weak::default()), 5320e3152eSlogin private_data: TtyDevicePrivateData::new(name), 540d48c3c9Slogin }); 5520e3152eSlogin // 默认开启输入回显 5620e3152eSlogin result.core.enable_echo(); 5720e3152eSlogin return result; 580d48c3c9Slogin } 590d48c3c9Slogin 6020e3152eSlogin /// @brief 判断文件私有信息是否为TTY文件的私有信息 610d48c3c9Slogin #[inline] 620d48c3c9Slogin fn verify_file_private_data<'a>( 630d48c3c9Slogin &self, 640d48c3c9Slogin private_data: &'a mut FilePrivateData, 65676b8ef6SMork ) -> Result<&'a mut TtyFilePrivateData, SystemError> { 660d48c3c9Slogin if let FilePrivateData::Tty(t) = private_data { 670d48c3c9Slogin return Ok(t); 680d48c3c9Slogin } 69676b8ef6SMork return Err(SystemError::EIO); 700d48c3c9Slogin } 7120e3152eSlogin 7220e3152eSlogin /// @brief 获取TTY设备名 7320e3152eSlogin #[inline] 7420e3152eSlogin pub fn name(&self) -> String { 7520e3152eSlogin return self.private_data.read().name.clone(); 7620e3152eSlogin } 7720e3152eSlogin 7820e3152eSlogin /// @brief 检查TTY文件的读写参数是否合法 7920e3152eSlogin #[inline] 8020e3152eSlogin pub fn check_rw_param(&self, len: usize, buf: &[u8]) -> Result<(), SystemError> { 8120e3152eSlogin if len > buf.len() { 8220e3152eSlogin return Err(SystemError::EINVAL); 8320e3152eSlogin } 8420e3152eSlogin return Ok(()); 8520e3152eSlogin } 8620e3152eSlogin 8720e3152eSlogin /// @brief 向TTY的输入端口导入数据 8820e3152eSlogin pub fn input(&self, buf: &[u8]) -> Result<usize, SystemError> { 8920e3152eSlogin let r: Result<usize, TtyError> = self.core.input(buf, false); 9020e3152eSlogin if r.is_ok() { 9120e3152eSlogin return Ok(r.unwrap()); 9220e3152eSlogin } 9320e3152eSlogin 9420e3152eSlogin let r = r.unwrap_err(); 9520e3152eSlogin match r { 9620e3152eSlogin TtyError::BufferFull(x) => return Ok(x), 9720e3152eSlogin TtyError::Closed => return Err(SystemError::ENODEV), 9820e3152eSlogin e => { 9920e3152eSlogin kerror!("tty error occurred while writing data to its input port, msg={e:?}"); 10020e3152eSlogin return Err(SystemError::EBUSY); 10120e3152eSlogin } 10220e3152eSlogin } 10320e3152eSlogin } 1040d48c3c9Slogin } 1050d48c3c9Slogin 1060d48c3c9Slogin impl DeviceINode for TtyDevice { 1070d48c3c9Slogin fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) { 1080d48c3c9Slogin *self.fs.write() = fs; 1090d48c3c9Slogin } 1100d48c3c9Slogin } 1110d48c3c9Slogin 1120d48c3c9Slogin impl IndexNode for TtyDevice { 11320e3152eSlogin /// @brief 打开TTY设备 11420e3152eSlogin /// 11520e3152eSlogin /// @param data 文件私有信息 11620e3152eSlogin /// @param mode 打开模式 11720e3152eSlogin /// 11820e3152eSlogin /// TTY设备通过mode来确定这个文件到底是stdin/stdout/stderr 11920e3152eSlogin /// - mode的值为O_RDONLY时,表示这个文件是stdin 12020e3152eSlogin /// - mode的值为O_WRONLY时,表示这个文件是stdout 12120e3152eSlogin /// - mode的值为O_WRONLY | O_SYNC时,表示这个文件是stderr 122676b8ef6SMork fn open(&self, data: &mut FilePrivateData, mode: &FileMode) -> Result<(), SystemError> { 12320e3152eSlogin let mut p = TtyFilePrivateData::default(); 12420e3152eSlogin 12520e3152eSlogin // 检查打开模式 12620e3152eSlogin let accmode = mode.accmode(); 12720e3152eSlogin if accmode == FileMode::O_RDONLY.accmode() { 12820e3152eSlogin p.flags.insert(TtyFileFlag::STDIN); 12920e3152eSlogin } else if accmode == FileMode::O_WRONLY.accmode() { 13020e3152eSlogin if mode.contains(FileMode::O_SYNC) { 13120e3152eSlogin p.flags.insert(TtyFileFlag::STDERR); 13220e3152eSlogin } else { 13320e3152eSlogin p.flags.insert(TtyFileFlag::STDOUT); 13420e3152eSlogin } 13520e3152eSlogin } else { 13620e3152eSlogin return Err(SystemError::EINVAL); 13720e3152eSlogin } 13820e3152eSlogin 13920e3152eSlogin // 保存文件私有信息 1400d48c3c9Slogin *data = FilePrivateData::Tty(p); 1410d48c3c9Slogin return Ok(()); 1420d48c3c9Slogin } 1430d48c3c9Slogin 1440d48c3c9Slogin fn read_at( 1450d48c3c9Slogin &self, 14620e3152eSlogin _offset: usize, 1470d48c3c9Slogin len: usize, 1480d48c3c9Slogin buf: &mut [u8], 1490d48c3c9Slogin data: &mut crate::filesystem::vfs::FilePrivateData, 150676b8ef6SMork ) -> Result<usize, SystemError> { 1510d48c3c9Slogin let _data: &mut TtyFilePrivateData = match self.verify_file_private_data(data) { 1520d48c3c9Slogin Ok(t) => t, 1530d48c3c9Slogin Err(e) => { 1540d48c3c9Slogin kerror!("Try to read tty device, but file private data type mismatch!"); 1550d48c3c9Slogin return Err(e); 1560d48c3c9Slogin } 1570d48c3c9Slogin }; 15820e3152eSlogin self.check_rw_param(len, buf)?; 1590d48c3c9Slogin 1600d48c3c9Slogin // 读取stdin队列 16120e3152eSlogin let r: Result<usize, TtyError> = self.core.read_stdin(&mut buf[0..len], true); 1620d48c3c9Slogin if r.is_ok() { 1630d48c3c9Slogin return Ok(r.unwrap()); 1640d48c3c9Slogin } 1650d48c3c9Slogin 1660d48c3c9Slogin match r.unwrap_err() { 1670d48c3c9Slogin TtyError::EOF(n) => { 1680d48c3c9Slogin return Ok(n); 1690d48c3c9Slogin } 17020e3152eSlogin 1710d48c3c9Slogin x => { 1720d48c3c9Slogin kerror!("Error occurred when reading tty, msg={x:?}"); 173676b8ef6SMork return Err(SystemError::ECONNABORTED); 1740d48c3c9Slogin } 1750d48c3c9Slogin } 1760d48c3c9Slogin } 1770d48c3c9Slogin 1780d48c3c9Slogin fn write_at( 1790d48c3c9Slogin &self, 18020e3152eSlogin _offset: usize, 1810d48c3c9Slogin len: usize, 1820d48c3c9Slogin buf: &[u8], 1830d48c3c9Slogin data: &mut crate::filesystem::vfs::FilePrivateData, 184676b8ef6SMork ) -> Result<usize, SystemError> { 1850d48c3c9Slogin let data: &mut TtyFilePrivateData = match self.verify_file_private_data(data) { 1860d48c3c9Slogin Ok(t) => t, 1870d48c3c9Slogin Err(e) => { 1880d48c3c9Slogin kerror!("Try to write tty device, but file private data type mismatch!"); 1890d48c3c9Slogin return Err(e); 1900d48c3c9Slogin } 1910d48c3c9Slogin }; 1920d48c3c9Slogin 19320e3152eSlogin self.check_rw_param(len, buf)?; 19420e3152eSlogin 1950d48c3c9Slogin // 根据当前文件是stdout还是stderr,选择不同的发送方式 1960d48c3c9Slogin let r: Result<usize, TtyError> = if data.flags.contains(TtyFileFlag::STDOUT) { 19720e3152eSlogin self.core.stdout(&buf[0..len], true) 1980d48c3c9Slogin } else if data.flags.contains(TtyFileFlag::STDERR) { 19920e3152eSlogin self.core.stderr(&buf[0..len], true) 2000d48c3c9Slogin } else { 201676b8ef6SMork return Err(SystemError::EPERM); 2020d48c3c9Slogin }; 2030d48c3c9Slogin 2040d48c3c9Slogin if r.is_ok() { 20520e3152eSlogin self.sync().expect("Failed to sync tty device!"); 2060d48c3c9Slogin return Ok(r.unwrap()); 2070d48c3c9Slogin } 2080d48c3c9Slogin 2090d48c3c9Slogin let r: TtyError = r.unwrap_err(); 2100d48c3c9Slogin kerror!("Error occurred when writing tty deivce. Error msg={r:?}"); 211676b8ef6SMork return Err(SystemError::EIO); 2120d48c3c9Slogin } 2130d48c3c9Slogin 214676b8ef6SMork fn poll(&self) -> Result<crate::filesystem::vfs::PollStatus, SystemError> { 21579a452ceShoumkh return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 2160d48c3c9Slogin } 2170d48c3c9Slogin 2180d48c3c9Slogin fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> { 2190d48c3c9Slogin return self.fs.read().upgrade().unwrap(); 2200d48c3c9Slogin } 2210d48c3c9Slogin 2220d48c3c9Slogin fn as_any_ref(&self) -> &dyn core::any::Any { 2230d48c3c9Slogin self 2240d48c3c9Slogin } 2250d48c3c9Slogin 226676b8ef6SMork fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> { 22779a452ceShoumkh return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 2280d48c3c9Slogin } 22920e3152eSlogin 23020e3152eSlogin fn metadata(&self) -> Result<Metadata, SystemError> { 23120e3152eSlogin return Ok(self.private_data.read().metadata.clone()); 23220e3152eSlogin } 23320e3152eSlogin 23420e3152eSlogin fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> { 23520e3152eSlogin return Ok(()); 23620e3152eSlogin } 23720e3152eSlogin 23820e3152eSlogin fn sync(&self) -> Result<(), SystemError> { 23920e3152eSlogin // TODO: 引入IO重定向后,需要将输出重定向到对应的设备。 24020e3152eSlogin // 目前只是简单的输出到屏幕(为了实现的简便) 24120e3152eSlogin 24220e3152eSlogin loop { 24320e3152eSlogin let mut buf = [0u8; 512]; 244d7b31a96SGou Ngai let r: Result<usize, TtyError> = self.core.output(&mut buf[0..511], false); 24520e3152eSlogin let len; 24620e3152eSlogin match r { 24720e3152eSlogin Ok(x) => { 24820e3152eSlogin len = x; 24920e3152eSlogin } 25020e3152eSlogin Err(TtyError::EOF(x)) | Err(TtyError::BufferEmpty(x)) => { 25120e3152eSlogin len = x; 25220e3152eSlogin } 25320e3152eSlogin _ => return Err(SystemError::EIO), 25420e3152eSlogin } 25520e3152eSlogin 25620e3152eSlogin if len == 0 { 25720e3152eSlogin break; 25820e3152eSlogin } 25920e3152eSlogin // 输出到屏幕 260abe3a6eaShanjiezhou 261*11110997Shanjiezhou for x in 0..len { 262*11110997Shanjiezhou textui_putchar(buf[x] as char, FontColor::WHITE, FontColor::BLACK).ok(); 263d7b31a96SGou Ngai } 26420e3152eSlogin } 26520e3152eSlogin return Ok(()); 26620e3152eSlogin } 267*11110997Shanjiezhou fn resize(&self, _len: usize) -> Result<(), SystemError> { 268*11110997Shanjiezhou return Ok(()); 269*11110997Shanjiezhou } 27020e3152eSlogin } 27120e3152eSlogin 27220e3152eSlogin impl TtyDevicePrivateData { 27320e3152eSlogin pub fn new(name: &str) -> RwLock<Self> { 27420e3152eSlogin let mut metadata = Metadata::new(FileType::CharDevice, 0o755); 27520e3152eSlogin metadata.size = TtyCore::STDIN_BUF_SIZE as i64; 27620e3152eSlogin return RwLock::new(TtyDevicePrivateData { 27720e3152eSlogin name: name.to_string(), 27820e3152eSlogin metadata, 27920e3152eSlogin }); 28020e3152eSlogin } 28120e3152eSlogin } 28220e3152eSlogin 28320e3152eSlogin /// @brief 导出到C的tty初始化函数 28420e3152eSlogin #[no_mangle] 28520e3152eSlogin pub extern "C" fn rs_tty_init() -> i32 { 28620e3152eSlogin let r = tty_init(); 28720e3152eSlogin if r.is_ok() { 28820e3152eSlogin return 0; 28920e3152eSlogin } else { 29020e3152eSlogin return r.unwrap_err().to_posix_errno(); 29120e3152eSlogin } 29220e3152eSlogin } 29320e3152eSlogin 29420e3152eSlogin /// @brief 初始化TTY设备 29520e3152eSlogin pub fn tty_init() -> Result<(), SystemError> { 29620e3152eSlogin let tty: Arc<TtyDevice> = TtyDevice::new("tty0"); 29720e3152eSlogin let devfs_root_inode = ROOT_INODE().lookup("/dev"); 29820e3152eSlogin if devfs_root_inode.is_err() { 29920e3152eSlogin return Err(devfs_root_inode.unwrap_err()); 30020e3152eSlogin } 30120e3152eSlogin // 当前关闭键盘输入回显 30220e3152eSlogin // TODO: 完善Termios之后, 改为默认开启键盘输入回显. 30320e3152eSlogin tty.core.disable_echo(); 30420e3152eSlogin let guard = TTY_DEVICES.upgradeable_read(); 30520e3152eSlogin 30620e3152eSlogin // 如果已经存在了这个设备 30720e3152eSlogin if guard.contains_key("tty0") { 30820e3152eSlogin return Err(SystemError::EEXIST); 30920e3152eSlogin } 31020e3152eSlogin 31120e3152eSlogin let mut guard = guard.upgrade(); 31220e3152eSlogin 31320e3152eSlogin guard.insert("tty0".to_string(), tty.clone()); 31420e3152eSlogin 31520e3152eSlogin drop(guard); 31620e3152eSlogin 31720e3152eSlogin let r = devfs_register(&tty.name(), tty); 31820e3152eSlogin if r.is_err() { 31920e3152eSlogin return Err(devfs_root_inode.unwrap_err()); 32020e3152eSlogin } 32120e3152eSlogin 32220e3152eSlogin return Ok(()); 3230d48c3c9Slogin } 324