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