1*20e3152eSlogin use alloc::{ 2*20e3152eSlogin collections::BTreeMap, 3*20e3152eSlogin string::{String, ToString}, 4*20e3152eSlogin sync::{Arc, Weak}, 5*20e3152eSlogin }; 60d48c3c9Slogin 70d48c3c9Slogin use crate::{ 80d48c3c9Slogin filesystem::{ 9*20e3152eSlogin devfs::{devfs_register, DevFS, DeviceINode}, 10*20e3152eSlogin vfs::{file::FileMode, FilePrivateData, FileType, IndexNode, Metadata, ROOT_INODE}, 110d48c3c9Slogin }, 12*20e3152eSlogin include::bindings::bindings::{printk_color, textui_putchar, BLACK, WHITE}, 13*20e3152eSlogin kdebug, kerror, 14*20e3152eSlogin libs::rwlock::RwLock, 15*20e3152eSlogin print, 16*20e3152eSlogin syscall::SystemError, 170d48c3c9Slogin }; 180d48c3c9Slogin 190d48c3c9Slogin use super::{TtyCore, TtyError, TtyFileFlag, TtyFilePrivateData}; 200d48c3c9Slogin 21*20e3152eSlogin lazy_static! { 22*20e3152eSlogin /// 所有TTY设备的B树。用于根据名字,找到Arc<TtyDevice> 23*20e3152eSlogin /// TODO: 待设备驱动模型完善,具有类似功能的机制后,删掉这里 24*20e3152eSlogin pub static ref TTY_DEVICES: RwLock<BTreeMap<String, Arc<TtyDevice>>> = RwLock::new(BTreeMap::new()); 25*20e3152eSlogin } 26*20e3152eSlogin 27*20e3152eSlogin /// @brief TTY设备 280d48c3c9Slogin #[derive(Debug)] 290d48c3c9Slogin pub struct TtyDevice { 30*20e3152eSlogin /// TTY核心 310d48c3c9Slogin core: TtyCore, 32*20e3152eSlogin /// TTY所属的文件系统 33*20e3152eSlogin fs: RwLock<Weak<DevFS>>, 34*20e3152eSlogin /// TTY设备私有信息 35*20e3152eSlogin private_data: RwLock<TtyDevicePrivateData>, 36*20e3152eSlogin } 370d48c3c9Slogin 38*20e3152eSlogin #[derive(Debug)] 39*20e3152eSlogin struct TtyDevicePrivateData { 40*20e3152eSlogin /// TTY设备名(如tty1) 41*20e3152eSlogin name: String, 42*20e3152eSlogin /// TTY设备文件的元数据 43*20e3152eSlogin metadata: Metadata, 44*20e3152eSlogin // TODO: 增加指向输出端口连接的设备的指针 450d48c3c9Slogin } 460d48c3c9Slogin 470d48c3c9Slogin impl TtyDevice { 48*20e3152eSlogin pub fn new(name: &str) -> Arc<TtyDevice> { 49*20e3152eSlogin let result = Arc::new(TtyDevice { 500d48c3c9Slogin core: TtyCore::new(), 510d48c3c9Slogin fs: RwLock::new(Weak::default()), 52*20e3152eSlogin private_data: TtyDevicePrivateData::new(name), 530d48c3c9Slogin }); 54*20e3152eSlogin // 默认开启输入回显 55*20e3152eSlogin result.core.enable_echo(); 56*20e3152eSlogin return result; 570d48c3c9Slogin } 580d48c3c9Slogin 59*20e3152eSlogin /// @brief 判断文件私有信息是否为TTY文件的私有信息 600d48c3c9Slogin #[inline] 610d48c3c9Slogin fn verify_file_private_data<'a>( 620d48c3c9Slogin &self, 630d48c3c9Slogin private_data: &'a mut FilePrivateData, 64676b8ef6SMork ) -> Result<&'a mut TtyFilePrivateData, SystemError> { 650d48c3c9Slogin if let FilePrivateData::Tty(t) = private_data { 660d48c3c9Slogin return Ok(t); 670d48c3c9Slogin } 68676b8ef6SMork return Err(SystemError::EIO); 690d48c3c9Slogin } 70*20e3152eSlogin 71*20e3152eSlogin /// @brief 获取TTY设备名 72*20e3152eSlogin #[inline] 73*20e3152eSlogin pub fn name(&self) -> String { 74*20e3152eSlogin return self.private_data.read().name.clone(); 75*20e3152eSlogin } 76*20e3152eSlogin 77*20e3152eSlogin /// @brief 检查TTY文件的读写参数是否合法 78*20e3152eSlogin #[inline] 79*20e3152eSlogin pub fn check_rw_param(&self, len: usize, buf: &[u8]) -> Result<(), SystemError> { 80*20e3152eSlogin if len > buf.len() { 81*20e3152eSlogin return Err(SystemError::EINVAL); 82*20e3152eSlogin } 83*20e3152eSlogin return Ok(()); 84*20e3152eSlogin } 85*20e3152eSlogin 86*20e3152eSlogin /// @brief 向TTY的输入端口导入数据 87*20e3152eSlogin pub fn input(&self, buf: &[u8]) -> Result<usize, SystemError> { 88*20e3152eSlogin let r: Result<usize, TtyError> = self.core.input(buf, false); 89*20e3152eSlogin if r.is_ok() { 90*20e3152eSlogin return Ok(r.unwrap()); 91*20e3152eSlogin } 92*20e3152eSlogin 93*20e3152eSlogin let r = r.unwrap_err(); 94*20e3152eSlogin match r { 95*20e3152eSlogin TtyError::BufferFull(x) => return Ok(x), 96*20e3152eSlogin TtyError::Closed => return Err(SystemError::ENODEV), 97*20e3152eSlogin e => { 98*20e3152eSlogin kerror!("tty error occurred while writing data to its input port, msg={e:?}"); 99*20e3152eSlogin return Err(SystemError::EBUSY); 100*20e3152eSlogin } 101*20e3152eSlogin } 102*20e3152eSlogin } 1030d48c3c9Slogin } 1040d48c3c9Slogin 1050d48c3c9Slogin impl DeviceINode for TtyDevice { 1060d48c3c9Slogin fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) { 1070d48c3c9Slogin *self.fs.write() = fs; 1080d48c3c9Slogin } 1090d48c3c9Slogin } 1100d48c3c9Slogin 1110d48c3c9Slogin impl IndexNode for TtyDevice { 112*20e3152eSlogin /// @brief 打开TTY设备 113*20e3152eSlogin /// 114*20e3152eSlogin /// @param data 文件私有信息 115*20e3152eSlogin /// @param mode 打开模式 116*20e3152eSlogin /// 117*20e3152eSlogin /// TTY设备通过mode来确定这个文件到底是stdin/stdout/stderr 118*20e3152eSlogin /// - mode的值为O_RDONLY时,表示这个文件是stdin 119*20e3152eSlogin /// - mode的值为O_WRONLY时,表示这个文件是stdout 120*20e3152eSlogin /// - mode的值为O_WRONLY | O_SYNC时,表示这个文件是stderr 121676b8ef6SMork fn open(&self, data: &mut FilePrivateData, mode: &FileMode) -> Result<(), SystemError> { 122*20e3152eSlogin let mut p = TtyFilePrivateData::default(); 123*20e3152eSlogin 124*20e3152eSlogin // 检查打开模式 125*20e3152eSlogin let accmode = mode.accmode(); 126*20e3152eSlogin if accmode == FileMode::O_RDONLY.accmode() { 127*20e3152eSlogin p.flags.insert(TtyFileFlag::STDIN); 128*20e3152eSlogin } else if accmode == FileMode::O_WRONLY.accmode() { 129*20e3152eSlogin if mode.contains(FileMode::O_SYNC) { 130*20e3152eSlogin p.flags.insert(TtyFileFlag::STDERR); 131*20e3152eSlogin } else { 132*20e3152eSlogin p.flags.insert(TtyFileFlag::STDOUT); 133*20e3152eSlogin } 134*20e3152eSlogin } else { 135*20e3152eSlogin return Err(SystemError::EINVAL); 136*20e3152eSlogin } 137*20e3152eSlogin 138*20e3152eSlogin // 保存文件私有信息 1390d48c3c9Slogin *data = FilePrivateData::Tty(p); 1400d48c3c9Slogin return Ok(()); 1410d48c3c9Slogin } 1420d48c3c9Slogin 1430d48c3c9Slogin fn read_at( 1440d48c3c9Slogin &self, 145*20e3152eSlogin _offset: usize, 1460d48c3c9Slogin len: usize, 1470d48c3c9Slogin buf: &mut [u8], 1480d48c3c9Slogin data: &mut crate::filesystem::vfs::FilePrivateData, 149676b8ef6SMork ) -> Result<usize, SystemError> { 1500d48c3c9Slogin let _data: &mut TtyFilePrivateData = match self.verify_file_private_data(data) { 1510d48c3c9Slogin Ok(t) => t, 1520d48c3c9Slogin Err(e) => { 1530d48c3c9Slogin kerror!("Try to read tty device, but file private data type mismatch!"); 1540d48c3c9Slogin return Err(e); 1550d48c3c9Slogin } 1560d48c3c9Slogin }; 157*20e3152eSlogin self.check_rw_param(len, buf)?; 1580d48c3c9Slogin 1590d48c3c9Slogin // 读取stdin队列 160*20e3152eSlogin let r: Result<usize, TtyError> = self.core.read_stdin(&mut buf[0..len], true); 1610d48c3c9Slogin if r.is_ok() { 1620d48c3c9Slogin return Ok(r.unwrap()); 1630d48c3c9Slogin } 1640d48c3c9Slogin 1650d48c3c9Slogin match r.unwrap_err() { 1660d48c3c9Slogin TtyError::EOF(n) => { 1670d48c3c9Slogin return Ok(n); 1680d48c3c9Slogin } 169*20e3152eSlogin 1700d48c3c9Slogin x => { 1710d48c3c9Slogin kerror!("Error occurred when reading tty, msg={x:?}"); 172676b8ef6SMork return Err(SystemError::ECONNABORTED); 1730d48c3c9Slogin } 1740d48c3c9Slogin } 1750d48c3c9Slogin } 1760d48c3c9Slogin 1770d48c3c9Slogin fn write_at( 1780d48c3c9Slogin &self, 179*20e3152eSlogin _offset: usize, 1800d48c3c9Slogin len: usize, 1810d48c3c9Slogin buf: &[u8], 1820d48c3c9Slogin data: &mut crate::filesystem::vfs::FilePrivateData, 183676b8ef6SMork ) -> Result<usize, SystemError> { 1840d48c3c9Slogin let data: &mut TtyFilePrivateData = match self.verify_file_private_data(data) { 1850d48c3c9Slogin Ok(t) => t, 1860d48c3c9Slogin Err(e) => { 1870d48c3c9Slogin kerror!("Try to write tty device, but file private data type mismatch!"); 1880d48c3c9Slogin return Err(e); 1890d48c3c9Slogin } 1900d48c3c9Slogin }; 1910d48c3c9Slogin 192*20e3152eSlogin self.check_rw_param(len, buf)?; 193*20e3152eSlogin 1940d48c3c9Slogin // 根据当前文件是stdout还是stderr,选择不同的发送方式 1950d48c3c9Slogin let r: Result<usize, TtyError> = if data.flags.contains(TtyFileFlag::STDOUT) { 196*20e3152eSlogin self.core.stdout(&buf[0..len], true) 1970d48c3c9Slogin } else if data.flags.contains(TtyFileFlag::STDERR) { 198*20e3152eSlogin self.core.stderr(&buf[0..len], true) 1990d48c3c9Slogin } else { 200676b8ef6SMork return Err(SystemError::EPERM); 2010d48c3c9Slogin }; 2020d48c3c9Slogin 2030d48c3c9Slogin if r.is_ok() { 204*20e3152eSlogin self.sync().expect("Failed to sync tty device!"); 2050d48c3c9Slogin return Ok(r.unwrap()); 2060d48c3c9Slogin } 2070d48c3c9Slogin 2080d48c3c9Slogin let r: TtyError = r.unwrap_err(); 2090d48c3c9Slogin kerror!("Error occurred when writing tty deivce. Error msg={r:?}"); 210676b8ef6SMork return Err(SystemError::EIO); 2110d48c3c9Slogin } 2120d48c3c9Slogin 213676b8ef6SMork fn poll(&self) -> Result<crate::filesystem::vfs::PollStatus, SystemError> { 214676b8ef6SMork return Err(SystemError::ENOTSUP); 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> { 226676b8ef6SMork return Err(SystemError::ENOTSUP); 2270d48c3c9Slogin } 228*20e3152eSlogin 229*20e3152eSlogin fn metadata(&self) -> Result<Metadata, SystemError> { 230*20e3152eSlogin return Ok(self.private_data.read().metadata.clone()); 231*20e3152eSlogin } 232*20e3152eSlogin 233*20e3152eSlogin fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> { 234*20e3152eSlogin return Ok(()); 235*20e3152eSlogin } 236*20e3152eSlogin 237*20e3152eSlogin fn sync(&self) -> Result<(), SystemError> { 238*20e3152eSlogin // TODO: 引入IO重定向后,需要将输出重定向到对应的设备。 239*20e3152eSlogin // 目前只是简单的输出到屏幕(为了实现的简便) 240*20e3152eSlogin 241*20e3152eSlogin loop { 242*20e3152eSlogin let mut buf = [0u8; 512]; 243*20e3152eSlogin let r: Result<usize, TtyError> = self.core.read_output(&mut buf[0..511], false); 244*20e3152eSlogin let len; 245*20e3152eSlogin match r { 246*20e3152eSlogin Ok(x) => { 247*20e3152eSlogin len = x; 248*20e3152eSlogin } 249*20e3152eSlogin Err(TtyError::EOF(x)) | Err(TtyError::BufferEmpty(x)) => { 250*20e3152eSlogin len = x; 251*20e3152eSlogin } 252*20e3152eSlogin _ => return Err(SystemError::EIO), 253*20e3152eSlogin } 254*20e3152eSlogin 255*20e3152eSlogin if len == 0 { 256*20e3152eSlogin break; 257*20e3152eSlogin } 258*20e3152eSlogin // 输出到屏幕 259*20e3152eSlogin print!("{}", unsafe { 260*20e3152eSlogin core::str::from_utf8_unchecked(&buf[0..len]) 261*20e3152eSlogin }); 262*20e3152eSlogin } 263*20e3152eSlogin return Ok(()); 264*20e3152eSlogin } 265*20e3152eSlogin } 266*20e3152eSlogin 267*20e3152eSlogin impl TtyDevicePrivateData { 268*20e3152eSlogin pub fn new(name: &str) -> RwLock<Self> { 269*20e3152eSlogin let mut metadata = Metadata::new(FileType::CharDevice, 0o755); 270*20e3152eSlogin metadata.size = TtyCore::STDIN_BUF_SIZE as i64; 271*20e3152eSlogin return RwLock::new(TtyDevicePrivateData { 272*20e3152eSlogin name: name.to_string(), 273*20e3152eSlogin metadata, 274*20e3152eSlogin }); 275*20e3152eSlogin } 276*20e3152eSlogin } 277*20e3152eSlogin 278*20e3152eSlogin /// @brief 导出到C的tty初始化函数 279*20e3152eSlogin #[no_mangle] 280*20e3152eSlogin pub extern "C" fn rs_tty_init() -> i32 { 281*20e3152eSlogin let r = tty_init(); 282*20e3152eSlogin if r.is_ok() { 283*20e3152eSlogin return 0; 284*20e3152eSlogin } else { 285*20e3152eSlogin return r.unwrap_err().to_posix_errno(); 286*20e3152eSlogin } 287*20e3152eSlogin } 288*20e3152eSlogin 289*20e3152eSlogin /// @brief 初始化TTY设备 290*20e3152eSlogin pub fn tty_init() -> Result<(), SystemError> { 291*20e3152eSlogin let tty: Arc<TtyDevice> = TtyDevice::new("tty0"); 292*20e3152eSlogin let devfs_root_inode = ROOT_INODE().lookup("/dev"); 293*20e3152eSlogin if devfs_root_inode.is_err() { 294*20e3152eSlogin return Err(devfs_root_inode.unwrap_err()); 295*20e3152eSlogin } 296*20e3152eSlogin // 当前关闭键盘输入回显 297*20e3152eSlogin // TODO: 完善Termios之后, 改为默认开启键盘输入回显. 298*20e3152eSlogin tty.core.disable_echo(); 299*20e3152eSlogin let guard = TTY_DEVICES.upgradeable_read(); 300*20e3152eSlogin 301*20e3152eSlogin // 如果已经存在了这个设备 302*20e3152eSlogin if guard.contains_key("tty0") { 303*20e3152eSlogin return Err(SystemError::EEXIST); 304*20e3152eSlogin } 305*20e3152eSlogin 306*20e3152eSlogin let mut guard = guard.upgrade(); 307*20e3152eSlogin 308*20e3152eSlogin guard.insert("tty0".to_string(), tty.clone()); 309*20e3152eSlogin 310*20e3152eSlogin drop(guard); 311*20e3152eSlogin 312*20e3152eSlogin let r = devfs_register(&tty.name(), tty); 313*20e3152eSlogin if r.is_err() { 314*20e3152eSlogin return Err(devfs_root_inode.unwrap_err()); 315*20e3152eSlogin } 316*20e3152eSlogin 317*20e3152eSlogin return Ok(()); 3180d48c3c9Slogin } 319