1 use alloc::{ 2 collections::BTreeMap, 3 string::{String, ToString}, 4 sync::{Arc, Weak}, 5 }; 6 7 use crate::{ 8 filesystem::{ 9 devfs::{devfs_register, DevFS, DeviceINode}, 10 vfs::{ 11 file::FileMode, syscall::ModeType, FilePrivateData, FileType, IndexNode, Metadata, 12 ROOT_INODE, 13 }, 14 }, 15 kerror, 16 libs::{ 17 lib_ui::textui::{textui_putchar, FontColor}, 18 rwlock::RwLock, 19 }, 20 syscall::SystemError, 21 }; 22 23 use super::{TtyCore, TtyError, TtyFileFlag, TtyFilePrivateData}; 24 25 lazy_static! { 26 /// 所有TTY设备的B树。用于根据名字,找到Arc<TtyDevice> 27 /// TODO: 待设备驱动模型完善,具有类似功能的机制后,删掉这里 28 pub static ref TTY_DEVICES: RwLock<BTreeMap<String, Arc<TtyDevice>>> = RwLock::new(BTreeMap::new()); 29 } 30 31 /// @brief TTY设备 32 #[derive(Debug)] 33 pub struct TtyDevice { 34 /// TTY核心 35 core: TtyCore, 36 /// TTY所属的文件系统 37 fs: RwLock<Weak<DevFS>>, 38 /// TTY设备私有信息 39 private_data: RwLock<TtyDevicePrivateData>, 40 } 41 42 #[derive(Debug)] 43 struct TtyDevicePrivateData { 44 /// TTY设备名(如tty1) 45 name: String, 46 /// TTY设备文件的元数据 47 metadata: Metadata, 48 // TODO: 增加指向输出端口连接的设备的指针 49 } 50 51 impl TtyDevice { 52 pub fn new(name: &str) -> Arc<TtyDevice> { 53 let result = Arc::new(TtyDevice { 54 core: TtyCore::new(), 55 fs: RwLock::new(Weak::default()), 56 private_data: TtyDevicePrivateData::new(name), 57 }); 58 // 默认开启输入回显 59 result.core.enable_echo(); 60 return result; 61 } 62 63 /// @brief 判断文件私有信息是否为TTY文件的私有信息 64 #[inline] 65 fn verify_file_private_data<'a>( 66 &self, 67 private_data: &'a mut FilePrivateData, 68 ) -> Result<&'a mut TtyFilePrivateData, SystemError> { 69 if let FilePrivateData::Tty(t) = private_data { 70 return Ok(t); 71 } 72 return Err(SystemError::EIO); 73 } 74 75 /// @brief 获取TTY设备名 76 #[inline] 77 pub fn name(&self) -> String { 78 return self.private_data.read().name.clone(); 79 } 80 81 /// @brief 检查TTY文件的读写参数是否合法 82 #[inline] 83 pub fn check_rw_param(&self, len: usize, buf: &[u8]) -> Result<(), SystemError> { 84 if len > buf.len() { 85 return Err(SystemError::EINVAL); 86 } 87 return Ok(()); 88 } 89 90 /// @brief 向TTY的输入端口导入数据 91 pub fn input(&self, buf: &[u8]) -> Result<usize, SystemError> { 92 let r: Result<usize, TtyError> = self.core.input(buf, false); 93 if r.is_ok() { 94 return Ok(r.unwrap()); 95 } 96 97 let r = r.unwrap_err(); 98 match r { 99 TtyError::BufferFull(x) => return Ok(x), 100 TtyError::Closed => return Err(SystemError::ENODEV), 101 e => { 102 kerror!("tty error occurred while writing data to its input port, msg={e:?}"); 103 return Err(SystemError::EBUSY); 104 } 105 } 106 } 107 } 108 109 impl DeviceINode for TtyDevice { 110 fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) { 111 *self.fs.write() = fs; 112 } 113 } 114 115 impl IndexNode for TtyDevice { 116 /// @brief 打开TTY设备 117 /// 118 /// @param data 文件私有信息 119 /// @param mode 打开模式 120 /// 121 /// TTY设备通过mode来确定这个文件到底是stdin/stdout/stderr 122 /// - mode的值为O_RDONLY时,表示这个文件是stdin 123 /// - mode的值为O_WRONLY时,表示这个文件是stdout 124 /// - mode的值为O_WRONLY | O_SYNC时,表示这个文件是stderr 125 fn open(&self, data: &mut FilePrivateData, mode: &FileMode) -> Result<(), SystemError> { 126 let mut p = TtyFilePrivateData::default(); 127 128 // 检查打开模式 129 let accmode = mode.accmode(); 130 if accmode == FileMode::O_RDONLY.accmode() { 131 p.flags.insert(TtyFileFlag::STDIN); 132 } else if accmode == FileMode::O_WRONLY.accmode() { 133 if mode.contains(FileMode::O_SYNC) { 134 p.flags.insert(TtyFileFlag::STDERR); 135 } else { 136 p.flags.insert(TtyFileFlag::STDOUT); 137 } 138 } else { 139 return Err(SystemError::EINVAL); 140 } 141 142 // 保存文件私有信息 143 *data = FilePrivateData::Tty(p); 144 return Ok(()); 145 } 146 147 fn read_at( 148 &self, 149 _offset: usize, 150 len: usize, 151 buf: &mut [u8], 152 data: &mut crate::filesystem::vfs::FilePrivateData, 153 ) -> Result<usize, SystemError> { 154 let _data: &mut TtyFilePrivateData = match self.verify_file_private_data(data) { 155 Ok(t) => t, 156 Err(e) => { 157 kerror!("Try to read tty device, but file private data type mismatch!"); 158 return Err(e); 159 } 160 }; 161 self.check_rw_param(len, buf)?; 162 163 // 读取stdin队列 164 let r: Result<usize, TtyError> = self.core.read_stdin(&mut buf[0..len], true); 165 if r.is_ok() { 166 return Ok(r.unwrap()); 167 } 168 169 match r.unwrap_err() { 170 TtyError::EOF(n) => { 171 return Ok(n); 172 } 173 174 x => { 175 kerror!("Error occurred when reading tty, msg={x:?}"); 176 return Err(SystemError::ECONNABORTED); 177 } 178 } 179 } 180 181 fn write_at( 182 &self, 183 _offset: usize, 184 len: usize, 185 buf: &[u8], 186 data: &mut crate::filesystem::vfs::FilePrivateData, 187 ) -> Result<usize, SystemError> { 188 let data: &mut TtyFilePrivateData = match self.verify_file_private_data(data) { 189 Ok(t) => t, 190 Err(e) => { 191 kerror!("Try to write tty device, but file private data type mismatch!"); 192 return Err(e); 193 } 194 }; 195 196 self.check_rw_param(len, buf)?; 197 198 // 根据当前文件是stdout还是stderr,选择不同的发送方式 199 let r: Result<usize, TtyError> = if data.flags.contains(TtyFileFlag::STDOUT) { 200 self.core.stdout(&buf[0..len], true) 201 } else if data.flags.contains(TtyFileFlag::STDERR) { 202 self.core.stderr(&buf[0..len], true) 203 } else { 204 return Err(SystemError::EPERM); 205 }; 206 207 if r.is_ok() { 208 self.sync().expect("Failed to sync tty device!"); 209 return Ok(r.unwrap()); 210 } 211 212 let r: TtyError = r.unwrap_err(); 213 kerror!("Error occurred when writing tty deivce. Error msg={r:?}"); 214 return Err(SystemError::EIO); 215 } 216 217 fn poll(&self) -> Result<crate::filesystem::vfs::PollStatus, SystemError> { 218 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 219 } 220 221 fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> { 222 return self.fs.read().upgrade().unwrap(); 223 } 224 225 fn as_any_ref(&self) -> &dyn core::any::Any { 226 self 227 } 228 229 fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> { 230 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 231 } 232 233 fn metadata(&self) -> Result<Metadata, SystemError> { 234 return Ok(self.private_data.read().metadata.clone()); 235 } 236 237 fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> { 238 return Ok(()); 239 } 240 241 fn sync(&self) -> Result<(), SystemError> { 242 // TODO: 引入IO重定向后,需要将输出重定向到对应的设备。 243 // 目前只是简单的输出到屏幕(为了实现的简便) 244 245 loop { 246 let mut buf = [0u8; 512]; 247 let r: Result<usize, TtyError> = self.core.output(&mut buf[0..511], false); 248 let len; 249 match r { 250 Ok(x) => { 251 len = x; 252 } 253 Err(TtyError::EOF(x)) | Err(TtyError::BufferEmpty(x)) => { 254 len = x; 255 } 256 _ => return Err(SystemError::EIO), 257 } 258 259 if len == 0 { 260 break; 261 } 262 // 输出到屏幕 263 264 for x in 0..len { 265 textui_putchar(buf[x] as char, FontColor::WHITE, FontColor::BLACK).ok(); 266 } 267 } 268 return Ok(()); 269 } 270 fn resize(&self, _len: usize) -> Result<(), SystemError> { 271 return Ok(()); 272 } 273 } 274 275 impl TtyDevicePrivateData { 276 pub fn new(name: &str) -> RwLock<Self> { 277 let mut metadata = Metadata::new(FileType::CharDevice, ModeType::from_bits_truncate(0o755)); 278 metadata.size = TtyCore::STDIN_BUF_SIZE as i64; 279 return RwLock::new(TtyDevicePrivateData { 280 name: name.to_string(), 281 metadata, 282 }); 283 } 284 } 285 286 /// @brief 导出到C的tty初始化函数 287 #[no_mangle] 288 pub extern "C" fn rs_tty_init() -> i32 { 289 let r = tty_init(); 290 if r.is_ok() { 291 return 0; 292 } else { 293 return r.unwrap_err().to_posix_errno(); 294 } 295 } 296 297 /// @brief 初始化TTY设备 298 pub fn tty_init() -> Result<(), SystemError> { 299 let tty: Arc<TtyDevice> = TtyDevice::new("tty0"); 300 let devfs_root_inode = ROOT_INODE().lookup("/dev"); 301 if devfs_root_inode.is_err() { 302 return Err(devfs_root_inode.unwrap_err()); 303 } 304 // 当前关闭键盘输入回显 305 // TODO: 完善Termios之后, 改为默认开启键盘输入回显. 306 tty.core.disable_echo(); 307 let guard = TTY_DEVICES.upgradeable_read(); 308 309 // 如果已经存在了这个设备 310 if guard.contains_key("tty0") { 311 return Err(SystemError::EEXIST); 312 } 313 314 let mut guard = guard.upgrade(); 315 316 guard.insert("tty0".to_string(), tty.clone()); 317 318 drop(guard); 319 320 let r = devfs_register(&tty.name(), tty); 321 if r.is_err() { 322 return Err(devfs_root_inode.unwrap_err()); 323 } 324 325 return Ok(()); 326 } 327