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