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 include::bindings::bindings::{textui_putchar, BLACK, WHITE}, 13d7b31a96SGou Ngai kerror, 1420e3152eSlogin libs::rwlock::RwLock, 1520e3152eSlogin syscall::SystemError, 160d48c3c9Slogin }; 170d48c3c9Slogin 180d48c3c9Slogin use super::{TtyCore, TtyError, TtyFileFlag, TtyFilePrivateData}; 190d48c3c9Slogin 2020e3152eSlogin lazy_static! { 2120e3152eSlogin /// 所有TTY设备的B树。用于根据名字,找到Arc<TtyDevice> 2220e3152eSlogin /// TODO: 待设备驱动模型完善,具有类似功能的机制后,删掉这里 2320e3152eSlogin pub static ref TTY_DEVICES: RwLock<BTreeMap<String, Arc<TtyDevice>>> = RwLock::new(BTreeMap::new()); 2420e3152eSlogin } 2520e3152eSlogin 2620e3152eSlogin /// @brief TTY设备 270d48c3c9Slogin #[derive(Debug)] 280d48c3c9Slogin pub struct TtyDevice { 2920e3152eSlogin /// TTY核心 300d48c3c9Slogin core: TtyCore, 3120e3152eSlogin /// TTY所属的文件系统 3220e3152eSlogin fs: RwLock<Weak<DevFS>>, 3320e3152eSlogin /// TTY设备私有信息 3420e3152eSlogin private_data: RwLock<TtyDevicePrivateData>, 3520e3152eSlogin } 360d48c3c9Slogin 3720e3152eSlogin #[derive(Debug)] 3820e3152eSlogin struct TtyDevicePrivateData { 3920e3152eSlogin /// TTY设备名(如tty1) 4020e3152eSlogin name: String, 4120e3152eSlogin /// TTY设备文件的元数据 4220e3152eSlogin metadata: Metadata, 4320e3152eSlogin // TODO: 增加指向输出端口连接的设备的指针 440d48c3c9Slogin } 450d48c3c9Slogin 460d48c3c9Slogin impl TtyDevice { 4720e3152eSlogin pub fn new(name: &str) -> Arc<TtyDevice> { 4820e3152eSlogin let result = Arc::new(TtyDevice { 490d48c3c9Slogin core: TtyCore::new(), 500d48c3c9Slogin fs: RwLock::new(Weak::default()), 5120e3152eSlogin private_data: TtyDevicePrivateData::new(name), 520d48c3c9Slogin }); 5320e3152eSlogin // 默认开启输入回显 5420e3152eSlogin result.core.enable_echo(); 5520e3152eSlogin return result; 560d48c3c9Slogin } 570d48c3c9Slogin 5820e3152eSlogin /// @brief 判断文件私有信息是否为TTY文件的私有信息 590d48c3c9Slogin #[inline] 600d48c3c9Slogin fn verify_file_private_data<'a>( 610d48c3c9Slogin &self, 620d48c3c9Slogin private_data: &'a mut FilePrivateData, 63676b8ef6SMork ) -> Result<&'a mut TtyFilePrivateData, SystemError> { 640d48c3c9Slogin if let FilePrivateData::Tty(t) = private_data { 650d48c3c9Slogin return Ok(t); 660d48c3c9Slogin } 67676b8ef6SMork return Err(SystemError::EIO); 680d48c3c9Slogin } 6920e3152eSlogin 7020e3152eSlogin /// @brief 获取TTY设备名 7120e3152eSlogin #[inline] 7220e3152eSlogin pub fn name(&self) -> String { 7320e3152eSlogin return self.private_data.read().name.clone(); 7420e3152eSlogin } 7520e3152eSlogin 7620e3152eSlogin /// @brief 检查TTY文件的读写参数是否合法 7720e3152eSlogin #[inline] 7820e3152eSlogin pub fn check_rw_param(&self, len: usize, buf: &[u8]) -> Result<(), SystemError> { 7920e3152eSlogin if len > buf.len() { 8020e3152eSlogin return Err(SystemError::EINVAL); 8120e3152eSlogin } 8220e3152eSlogin return Ok(()); 8320e3152eSlogin } 8420e3152eSlogin 8520e3152eSlogin /// @brief 向TTY的输入端口导入数据 8620e3152eSlogin pub fn input(&self, buf: &[u8]) -> Result<usize, SystemError> { 8720e3152eSlogin let r: Result<usize, TtyError> = self.core.input(buf, false); 8820e3152eSlogin if r.is_ok() { 8920e3152eSlogin return Ok(r.unwrap()); 9020e3152eSlogin } 9120e3152eSlogin 9220e3152eSlogin let r = r.unwrap_err(); 9320e3152eSlogin match r { 9420e3152eSlogin TtyError::BufferFull(x) => return Ok(x), 9520e3152eSlogin TtyError::Closed => return Err(SystemError::ENODEV), 9620e3152eSlogin e => { 9720e3152eSlogin kerror!("tty error occurred while writing data to its input port, msg={e:?}"); 9820e3152eSlogin return Err(SystemError::EBUSY); 9920e3152eSlogin } 10020e3152eSlogin } 10120e3152eSlogin } 1020d48c3c9Slogin } 1030d48c3c9Slogin 1040d48c3c9Slogin impl DeviceINode for TtyDevice { 1050d48c3c9Slogin fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) { 1060d48c3c9Slogin *self.fs.write() = fs; 1070d48c3c9Slogin } 1080d48c3c9Slogin } 1090d48c3c9Slogin 1100d48c3c9Slogin impl IndexNode for TtyDevice { 11120e3152eSlogin /// @brief 打开TTY设备 11220e3152eSlogin /// 11320e3152eSlogin /// @param data 文件私有信息 11420e3152eSlogin /// @param mode 打开模式 11520e3152eSlogin /// 11620e3152eSlogin /// TTY设备通过mode来确定这个文件到底是stdin/stdout/stderr 11720e3152eSlogin /// - mode的值为O_RDONLY时,表示这个文件是stdin 11820e3152eSlogin /// - mode的值为O_WRONLY时,表示这个文件是stdout 11920e3152eSlogin /// - mode的值为O_WRONLY | O_SYNC时,表示这个文件是stderr 120676b8ef6SMork fn open(&self, data: &mut FilePrivateData, mode: &FileMode) -> Result<(), SystemError> { 12120e3152eSlogin let mut p = TtyFilePrivateData::default(); 12220e3152eSlogin 12320e3152eSlogin // 检查打开模式 12420e3152eSlogin let accmode = mode.accmode(); 12520e3152eSlogin if accmode == FileMode::O_RDONLY.accmode() { 12620e3152eSlogin p.flags.insert(TtyFileFlag::STDIN); 12720e3152eSlogin } else if accmode == FileMode::O_WRONLY.accmode() { 12820e3152eSlogin if mode.contains(FileMode::O_SYNC) { 12920e3152eSlogin p.flags.insert(TtyFileFlag::STDERR); 13020e3152eSlogin } else { 13120e3152eSlogin p.flags.insert(TtyFileFlag::STDOUT); 13220e3152eSlogin } 13320e3152eSlogin } else { 13420e3152eSlogin return Err(SystemError::EINVAL); 13520e3152eSlogin } 13620e3152eSlogin 13720e3152eSlogin // 保存文件私有信息 1380d48c3c9Slogin *data = FilePrivateData::Tty(p); 1390d48c3c9Slogin return Ok(()); 1400d48c3c9Slogin } 1410d48c3c9Slogin 1420d48c3c9Slogin fn read_at( 1430d48c3c9Slogin &self, 14420e3152eSlogin _offset: usize, 1450d48c3c9Slogin len: usize, 1460d48c3c9Slogin buf: &mut [u8], 1470d48c3c9Slogin data: &mut crate::filesystem::vfs::FilePrivateData, 148676b8ef6SMork ) -> Result<usize, SystemError> { 1490d48c3c9Slogin let _data: &mut TtyFilePrivateData = match self.verify_file_private_data(data) { 1500d48c3c9Slogin Ok(t) => t, 1510d48c3c9Slogin Err(e) => { 1520d48c3c9Slogin kerror!("Try to read tty device, but file private data type mismatch!"); 1530d48c3c9Slogin return Err(e); 1540d48c3c9Slogin } 1550d48c3c9Slogin }; 15620e3152eSlogin self.check_rw_param(len, buf)?; 1570d48c3c9Slogin 1580d48c3c9Slogin // 读取stdin队列 15920e3152eSlogin let r: Result<usize, TtyError> = self.core.read_stdin(&mut buf[0..len], true); 1600d48c3c9Slogin if r.is_ok() { 1610d48c3c9Slogin return Ok(r.unwrap()); 1620d48c3c9Slogin } 1630d48c3c9Slogin 1640d48c3c9Slogin match r.unwrap_err() { 1650d48c3c9Slogin TtyError::EOF(n) => { 1660d48c3c9Slogin return Ok(n); 1670d48c3c9Slogin } 16820e3152eSlogin 1690d48c3c9Slogin x => { 1700d48c3c9Slogin kerror!("Error occurred when reading tty, msg={x:?}"); 171676b8ef6SMork return Err(SystemError::ECONNABORTED); 1720d48c3c9Slogin } 1730d48c3c9Slogin } 1740d48c3c9Slogin } 1750d48c3c9Slogin 1760d48c3c9Slogin fn write_at( 1770d48c3c9Slogin &self, 17820e3152eSlogin _offset: usize, 1790d48c3c9Slogin len: usize, 1800d48c3c9Slogin buf: &[u8], 1810d48c3c9Slogin data: &mut crate::filesystem::vfs::FilePrivateData, 182676b8ef6SMork ) -> Result<usize, SystemError> { 1830d48c3c9Slogin let data: &mut TtyFilePrivateData = match self.verify_file_private_data(data) { 1840d48c3c9Slogin Ok(t) => t, 1850d48c3c9Slogin Err(e) => { 1860d48c3c9Slogin kerror!("Try to write tty device, but file private data type mismatch!"); 1870d48c3c9Slogin return Err(e); 1880d48c3c9Slogin } 1890d48c3c9Slogin }; 1900d48c3c9Slogin 19120e3152eSlogin self.check_rw_param(len, buf)?; 19220e3152eSlogin 1930d48c3c9Slogin // 根据当前文件是stdout还是stderr,选择不同的发送方式 1940d48c3c9Slogin let r: Result<usize, TtyError> = if data.flags.contains(TtyFileFlag::STDOUT) { 19520e3152eSlogin self.core.stdout(&buf[0..len], true) 1960d48c3c9Slogin } else if data.flags.contains(TtyFileFlag::STDERR) { 19720e3152eSlogin self.core.stderr(&buf[0..len], true) 1980d48c3c9Slogin } else { 199676b8ef6SMork return Err(SystemError::EPERM); 2000d48c3c9Slogin }; 2010d48c3c9Slogin 2020d48c3c9Slogin if r.is_ok() { 20320e3152eSlogin self.sync().expect("Failed to sync tty device!"); 2040d48c3c9Slogin return Ok(r.unwrap()); 2050d48c3c9Slogin } 2060d48c3c9Slogin 2070d48c3c9Slogin let r: TtyError = r.unwrap_err(); 2080d48c3c9Slogin kerror!("Error occurred when writing tty deivce. Error msg={r:?}"); 209676b8ef6SMork return Err(SystemError::EIO); 2100d48c3c9Slogin } 2110d48c3c9Slogin 212676b8ef6SMork fn poll(&self) -> Result<crate::filesystem::vfs::PollStatus, SystemError> { 213*79a452ceShoumkh return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 2140d48c3c9Slogin } 2150d48c3c9Slogin 2160d48c3c9Slogin fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> { 2170d48c3c9Slogin return self.fs.read().upgrade().unwrap(); 2180d48c3c9Slogin } 2190d48c3c9Slogin 2200d48c3c9Slogin fn as_any_ref(&self) -> &dyn core::any::Any { 2210d48c3c9Slogin self 2220d48c3c9Slogin } 2230d48c3c9Slogin 224676b8ef6SMork fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> { 225*79a452ceShoumkh return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 2260d48c3c9Slogin } 22720e3152eSlogin 22820e3152eSlogin fn metadata(&self) -> Result<Metadata, SystemError> { 22920e3152eSlogin return Ok(self.private_data.read().metadata.clone()); 23020e3152eSlogin } 23120e3152eSlogin 23220e3152eSlogin fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> { 23320e3152eSlogin return Ok(()); 23420e3152eSlogin } 23520e3152eSlogin 23620e3152eSlogin fn sync(&self) -> Result<(), SystemError> { 23720e3152eSlogin // TODO: 引入IO重定向后,需要将输出重定向到对应的设备。 23820e3152eSlogin // 目前只是简单的输出到屏幕(为了实现的简便) 23920e3152eSlogin 24020e3152eSlogin loop { 24120e3152eSlogin let mut buf = [0u8; 512]; 242d7b31a96SGou Ngai let r: Result<usize, TtyError> = self.core.output(&mut buf[0..511], false); 24320e3152eSlogin let len; 24420e3152eSlogin match r { 24520e3152eSlogin Ok(x) => { 24620e3152eSlogin len = x; 24720e3152eSlogin } 24820e3152eSlogin Err(TtyError::EOF(x)) | Err(TtyError::BufferEmpty(x)) => { 24920e3152eSlogin len = x; 25020e3152eSlogin } 25120e3152eSlogin _ => return Err(SystemError::EIO), 25220e3152eSlogin } 25320e3152eSlogin 25420e3152eSlogin if len == 0 { 25520e3152eSlogin break; 25620e3152eSlogin } 25720e3152eSlogin // 输出到屏幕 258d7b31a96SGou Ngai unsafe { 259d7b31a96SGou Ngai for x in buf { 260d7b31a96SGou Ngai textui_putchar(x as u16, WHITE, BLACK); 261d7b31a96SGou Ngai } 262d7b31a96SGou Ngai } 26320e3152eSlogin } 26420e3152eSlogin return Ok(()); 26520e3152eSlogin } 26620e3152eSlogin } 26720e3152eSlogin 26820e3152eSlogin impl TtyDevicePrivateData { 26920e3152eSlogin pub fn new(name: &str) -> RwLock<Self> { 27020e3152eSlogin let mut metadata = Metadata::new(FileType::CharDevice, 0o755); 27120e3152eSlogin metadata.size = TtyCore::STDIN_BUF_SIZE as i64; 27220e3152eSlogin return RwLock::new(TtyDevicePrivateData { 27320e3152eSlogin name: name.to_string(), 27420e3152eSlogin metadata, 27520e3152eSlogin }); 27620e3152eSlogin } 27720e3152eSlogin } 27820e3152eSlogin 27920e3152eSlogin /// @brief 导出到C的tty初始化函数 28020e3152eSlogin #[no_mangle] 28120e3152eSlogin pub extern "C" fn rs_tty_init() -> i32 { 28220e3152eSlogin let r = tty_init(); 28320e3152eSlogin if r.is_ok() { 28420e3152eSlogin return 0; 28520e3152eSlogin } else { 28620e3152eSlogin return r.unwrap_err().to_posix_errno(); 28720e3152eSlogin } 28820e3152eSlogin } 28920e3152eSlogin 29020e3152eSlogin /// @brief 初始化TTY设备 29120e3152eSlogin pub fn tty_init() -> Result<(), SystemError> { 29220e3152eSlogin let tty: Arc<TtyDevice> = TtyDevice::new("tty0"); 29320e3152eSlogin let devfs_root_inode = ROOT_INODE().lookup("/dev"); 29420e3152eSlogin if devfs_root_inode.is_err() { 29520e3152eSlogin return Err(devfs_root_inode.unwrap_err()); 29620e3152eSlogin } 29720e3152eSlogin // 当前关闭键盘输入回显 29820e3152eSlogin // TODO: 完善Termios之后, 改为默认开启键盘输入回显. 29920e3152eSlogin tty.core.disable_echo(); 30020e3152eSlogin let guard = TTY_DEVICES.upgradeable_read(); 30120e3152eSlogin 30220e3152eSlogin // 如果已经存在了这个设备 30320e3152eSlogin if guard.contains_key("tty0") { 30420e3152eSlogin return Err(SystemError::EEXIST); 30520e3152eSlogin } 30620e3152eSlogin 30720e3152eSlogin let mut guard = guard.upgrade(); 30820e3152eSlogin 30920e3152eSlogin guard.insert("tty0".to_string(), tty.clone()); 31020e3152eSlogin 31120e3152eSlogin drop(guard); 31220e3152eSlogin 31320e3152eSlogin let r = devfs_register(&tty.name(), tty); 31420e3152eSlogin if r.is_err() { 31520e3152eSlogin return Err(devfs_root_inode.unwrap_err()); 31620e3152eSlogin } 31720e3152eSlogin 31820e3152eSlogin return Ok(()); 3190d48c3c9Slogin } 320