1 use alloc::{ 2 string::{String, ToString}, 3 sync::{Arc, Weak}, 4 }; 5 use system_error::SystemError; 6 use unified_init::macros::unified_init; 7 8 use crate::{ 9 arch::ipc::signal::Signal, 10 driver::{ 11 base::{ 12 char::CharDevice, 13 device::{ 14 bus::Bus, 15 device_number::{DeviceNumber, Major}, 16 device_register, 17 driver::Driver, 18 Device, DeviceKObjType, DeviceType, IdTable, 19 }, 20 kobject::{KObject, LockedKObjectState}, 21 kset::KSet, 22 }, 23 serial::serial_init, 24 }, 25 filesystem::{ 26 devfs::{devfs_register, DevFS, DeviceINode}, 27 kernfs::KernFSInode, 28 vfs::{file::FileMode, syscall::ModeType, FilePrivateData, FileType, IndexNode, Metadata}, 29 }, 30 init::initcall::INITCALL_DEVICE, 31 libs::rwlock::RwLock, 32 mm::VirtAddr, 33 net::event_poll::{EPollItem, EventPoll}, 34 process::ProcessManager, 35 syscall::user_access::{UserBufferReader, UserBufferWriter}, 36 }; 37 38 use super::{ 39 kthread::tty_flush_thread_init, 40 termios::WindowSize, 41 tty_core::{TtyCore, TtyFlag, TtyIoctlCmd}, 42 tty_driver::{TtyDriver, TtyDriverSubType, TtyDriverType, TtyOperation}, 43 tty_job_control::TtyJobCtrlManager, 44 virtual_terminal::vty_init, 45 }; 46 47 #[derive(Debug)] 48 pub struct InnerTtyDevice { 49 /// 当前设备所述的kset 50 kset: Option<Arc<KSet>>, 51 parent_kobj: Option<Weak<dyn KObject>>, 52 /// 当前设备所述的总线 53 bus: Option<Weak<dyn Bus>>, 54 inode: Option<Arc<KernFSInode>>, 55 driver: Option<Weak<dyn Driver>>, 56 can_match: bool, 57 58 metadata: Metadata, 59 } 60 61 impl InnerTtyDevice { 62 pub fn new() -> Self { 63 Self { 64 kset: None, 65 parent_kobj: None, 66 bus: None, 67 inode: None, 68 driver: None, 69 can_match: false, 70 metadata: Metadata::new(FileType::CharDevice, ModeType::from_bits_truncate(0o755)), 71 } 72 } 73 } 74 75 #[derive(Debug)] 76 #[cast_to([sync] Device)] 77 pub struct TtyDevice { 78 name: &'static str, 79 id_table: IdTable, 80 inner: RwLock<InnerTtyDevice>, 81 kobj_state: LockedKObjectState, 82 /// TTY所属的文件系统 83 fs: RwLock<Weak<DevFS>>, 84 } 85 86 impl TtyDevice { 87 pub fn new(name: &'static str, id_table: IdTable) -> Arc<TtyDevice> { 88 let dev_num = id_table.device_number(); 89 let dev = TtyDevice { 90 name, 91 id_table, 92 inner: RwLock::new(InnerTtyDevice::new()), 93 kobj_state: LockedKObjectState::new(None), 94 fs: RwLock::new(Weak::default()), 95 }; 96 97 dev.inner.write().metadata.raw_dev = dev_num; 98 99 Arc::new(dev) 100 } 101 } 102 103 impl IndexNode for TtyDevice { 104 fn open( 105 &self, 106 data: &mut crate::filesystem::vfs::FilePrivateData, 107 mode: &crate::filesystem::vfs::file::FileMode, 108 ) -> Result<(), SystemError> { 109 let dev_num = self.metadata()?.raw_dev; 110 111 let tty = TtyDriver::open_tty(dev_num)?; 112 113 // 设置privdata 114 *data = FilePrivateData::Tty(TtyFilePrivateData { 115 tty: tty.clone(), 116 mode: *mode, 117 }); 118 119 let ret = tty.open(tty.core()); 120 if ret.is_err() { 121 let err = ret.unwrap_err(); 122 if err == SystemError::ENOSYS { 123 return Err(SystemError::ENODEV); 124 } 125 return Err(err); 126 } 127 128 let driver = tty.core().driver(); 129 // 考虑noctty(当前tty) 130 if !(mode.contains(FileMode::O_NOCTTY) && dev_num == DeviceNumber::new(Major::TTY_MAJOR, 0) 131 || dev_num == DeviceNumber::new(Major::TTYAUX_MAJOR, 1) 132 || (driver.tty_driver_type() == TtyDriverType::Pty 133 && driver.tty_driver_sub_type() == TtyDriverSubType::PtyMaster)) 134 { 135 let pcb = ProcessManager::current_pcb(); 136 let pcb_tty = pcb.sig_info_irqsave().tty(); 137 if pcb_tty.is_none() && tty.core().contorl_info_irqsave().session.is_none() { 138 TtyJobCtrlManager::proc_set_tty(tty); 139 } 140 } 141 142 Ok(()) 143 } 144 145 fn read_at( 146 &self, 147 _offset: usize, 148 len: usize, 149 buf: &mut [u8], 150 data: &mut crate::filesystem::vfs::FilePrivateData, 151 ) -> Result<usize, system_error::SystemError> { 152 let (tty, mode) = if let FilePrivateData::Tty(tty_priv) = data { 153 (tty_priv.tty.clone(), tty_priv.mode) 154 } else { 155 return Err(SystemError::EIO); 156 }; 157 158 let ld = tty.ldisc(); 159 let mut offset = 0; 160 let mut cookie = false; 161 loop { 162 let mut size = if len > buf.len() { buf.len() } else { len }; 163 size = ld.read(tty.clone(), buf, size, &mut cookie, offset, mode)?; 164 // 没有更多数据 165 if size == 0 { 166 break; 167 } 168 169 offset += size; 170 171 // 缓冲区写满 172 if offset >= len { 173 break; 174 } 175 176 // 没有更多数据 177 if !cookie { 178 break; 179 } 180 } 181 182 return Ok(offset); 183 } 184 185 fn write_at( 186 &self, 187 _offset: usize, 188 len: usize, 189 buf: &[u8], 190 data: &mut crate::filesystem::vfs::FilePrivateData, 191 ) -> Result<usize, system_error::SystemError> { 192 let mut count = len; 193 let (tty, mode) = if let FilePrivateData::Tty(tty_priv) = data { 194 (tty_priv.tty.clone(), tty_priv.mode) 195 } else { 196 return Err(SystemError::EIO); 197 }; 198 199 let ld = tty.ldisc(); 200 let core = tty.core(); 201 let mut chunk = 2048; 202 if core.flags().contains(TtyFlag::NO_WRITE_SPLIT) { 203 chunk = 65536; 204 } 205 chunk = chunk.min(count); 206 207 let pcb = ProcessManager::current_pcb(); 208 let mut written = 0; 209 loop { 210 // 至少需要写多少 211 let size = chunk.min(count); 212 213 // 将数据从buf拷贝到writebuf 214 215 let ret = ld.write(tty.clone(), &buf[written..], size, mode)?; 216 217 written += ret; 218 count -= ret; 219 220 if count == 0 { 221 break; 222 } 223 224 if pcb.sig_info_irqsave().sig_pending().has_pending() { 225 return Err(SystemError::ERESTARTSYS); 226 } 227 } 228 229 if written > 0 { 230 // todo: 更新时间 231 } 232 233 Ok(written) 234 } 235 236 fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> { 237 todo!() 238 } 239 240 fn as_any_ref(&self) -> &dyn core::any::Any { 241 todo!() 242 } 243 244 fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, system_error::SystemError> { 245 todo!() 246 } 247 248 fn metadata(&self) -> Result<crate::filesystem::vfs::Metadata, SystemError> { 249 Ok(self.inner.read().metadata.clone()) 250 } 251 252 fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> { 253 Ok(()) 254 } 255 256 fn resize(&self, _len: usize) -> Result<(), SystemError> { 257 Ok(()) 258 } 259 260 fn ioctl(&self, cmd: u32, arg: usize, data: &FilePrivateData) -> Result<usize, SystemError> { 261 let (tty, _) = if let FilePrivateData::Tty(tty_priv) = data { 262 (tty_priv.tty.clone(), tty_priv.mode) 263 } else { 264 return Err(SystemError::EIO); 265 }; 266 267 match cmd { 268 TtyIoctlCmd::TIOCSETD 269 | TtyIoctlCmd::TIOCSBRK 270 | TtyIoctlCmd::TIOCCBRK 271 | TtyIoctlCmd::TCSBRK 272 | TtyIoctlCmd::TCSBRKP => { 273 TtyJobCtrlManager::tty_check_change(tty.clone(), Signal::SIGTTOU)?; 274 if cmd != TtyIoctlCmd::TIOCCBRK { 275 todo!() 276 } 277 } 278 EventPoll::ADD_EPOLLITEM => { 279 let _ = UserBufferReader::new( 280 arg as *const Arc<EPollItem>, 281 core::mem::size_of::<Arc<EPollItem>>(), 282 false, 283 )?; 284 let epitem = unsafe { &*(arg as *const Arc<EPollItem>) }; 285 286 let core = tty.core(); 287 288 core.add_epitem(epitem.clone()); 289 290 return Ok(0); 291 } 292 _ => {} 293 } 294 295 match cmd { 296 TtyIoctlCmd::TIOCGWINSZ => { 297 let core = tty.core(); 298 let winsize = *core.window_size(); 299 300 let mut user_writer = UserBufferWriter::new( 301 VirtAddr::new(arg).as_ptr::<WindowSize>(), 302 core::mem::size_of::<WindowSize>(), 303 true, 304 )?; 305 306 let err = user_writer.copy_one_to_user(&winsize, 0); 307 if err.is_err() { 308 return Err(SystemError::EFAULT); 309 } 310 return Ok(0); 311 } 312 _ => match TtyJobCtrlManager::job_ctrl_ioctl(tty.clone(), cmd, arg) { 313 Ok(_) => { 314 return Ok(0); 315 } 316 Err(e) => { 317 if e != SystemError::ENOIOCTLCMD { 318 return Err(e); 319 } 320 } 321 }, 322 } 323 324 match tty.ioctl(tty.clone(), cmd, arg) { 325 Ok(_) => { 326 return Ok(0); 327 } 328 Err(e) => { 329 if e != SystemError::ENOIOCTLCMD { 330 return Err(e); 331 } 332 } 333 } 334 tty.ldisc().ioctl(tty, cmd, arg)?; 335 336 Ok(0) 337 } 338 339 fn poll(&self, private_data: &FilePrivateData) -> Result<usize, SystemError> { 340 let (tty, _) = if let FilePrivateData::Tty(tty_priv) = private_data { 341 (tty_priv.tty.clone(), tty_priv.mode) 342 } else { 343 return Err(SystemError::EIO); 344 }; 345 346 tty.ldisc().poll(tty) 347 } 348 } 349 350 impl DeviceINode for TtyDevice { 351 fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) { 352 *self.fs.write() = fs; 353 } 354 } 355 356 impl KObject for TtyDevice { 357 fn as_any_ref(&self) -> &dyn core::any::Any { 358 self 359 } 360 361 fn set_inode(&self, inode: Option<Arc<crate::filesystem::kernfs::KernFSInode>>) { 362 self.inner.write().inode = inode; 363 } 364 365 fn inode(&self) -> Option<Arc<crate::filesystem::kernfs::KernFSInode>> { 366 self.inner.read().inode.clone() 367 } 368 369 fn parent(&self) -> Option<alloc::sync::Weak<dyn KObject>> { 370 self.inner.read().parent_kobj.clone() 371 } 372 373 fn set_parent(&self, parent: Option<alloc::sync::Weak<dyn KObject>>) { 374 self.inner.write().parent_kobj = parent 375 } 376 377 fn kset(&self) -> Option<Arc<crate::driver::base::kset::KSet>> { 378 self.inner.read().kset.clone() 379 } 380 381 fn set_kset(&self, kset: Option<Arc<crate::driver::base::kset::KSet>>) { 382 self.inner.write().kset = kset 383 } 384 385 fn kobj_type(&self) -> Option<&'static dyn crate::driver::base::kobject::KObjType> { 386 Some(&DeviceKObjType) 387 } 388 389 fn set_kobj_type(&self, _ktype: Option<&'static dyn crate::driver::base::kobject::KObjType>) {} 390 391 fn name(&self) -> alloc::string::String { 392 self.name.to_string() 393 } 394 395 fn set_name(&self, _name: alloc::string::String) { 396 // self.name = name 397 } 398 399 fn kobj_state( 400 &self, 401 ) -> crate::libs::rwlock::RwLockReadGuard<crate::driver::base::kobject::KObjectState> { 402 self.kobj_state.read() 403 } 404 405 fn kobj_state_mut( 406 &self, 407 ) -> crate::libs::rwlock::RwLockWriteGuard<crate::driver::base::kobject::KObjectState> { 408 self.kobj_state.write() 409 } 410 411 fn set_kobj_state(&self, state: crate::driver::base::kobject::KObjectState) { 412 *self.kobj_state.write() = state 413 } 414 } 415 416 impl Device for TtyDevice { 417 fn dev_type(&self) -> crate::driver::base::device::DeviceType { 418 DeviceType::Char 419 } 420 421 fn id_table(&self) -> crate::driver::base::device::IdTable { 422 self.id_table.clone() 423 } 424 425 fn set_bus(&self, bus: Option<alloc::sync::Weak<dyn crate::driver::base::device::bus::Bus>>) { 426 self.inner.write().bus = bus 427 } 428 429 fn set_class(&self, _class: Option<Arc<dyn crate::driver::base::class::Class>>) { 430 todo!() 431 } 432 433 fn driver(&self) -> Option<Arc<dyn crate::driver::base::device::driver::Driver>> { 434 self.inner.read().driver.clone()?.upgrade() 435 } 436 437 fn set_driver( 438 &self, 439 driver: Option<alloc::sync::Weak<dyn crate::driver::base::device::driver::Driver>>, 440 ) { 441 self.inner.write().driver = driver 442 } 443 444 fn is_dead(&self) -> bool { 445 false 446 } 447 448 fn can_match(&self) -> bool { 449 self.inner.read().can_match 450 } 451 452 fn set_can_match(&self, can_match: bool) { 453 self.inner.write().can_match = can_match 454 } 455 456 fn state_synced(&self) -> bool { 457 true 458 } 459 } 460 461 impl CharDevice for TtyDevice { 462 fn read(&self, _len: usize, _buf: &mut [u8]) -> Result<usize, SystemError> { 463 todo!() 464 } 465 466 fn write(&self, _len: usize, _buf: &[u8]) -> Result<usize, SystemError> { 467 todo!() 468 } 469 470 fn sync(&self) -> Result<(), SystemError> { 471 todo!() 472 } 473 } 474 475 #[derive(Debug, Clone)] 476 pub struct TtyFilePrivateData { 477 tty: Arc<TtyCore>, 478 mode: FileMode, 479 } 480 481 /// 初始化tty设备和console子设备 482 #[unified_init(INITCALL_DEVICE)] 483 #[inline(never)] 484 pub fn tty_init() -> Result<(), SystemError> { 485 let tty = TtyDevice::new( 486 "tty0", 487 IdTable::new( 488 String::from("tty0"), 489 Some(DeviceNumber::new(Major::TTY_MAJOR, 0)), 490 ), 491 ); 492 493 let console = TtyDevice::new( 494 "console", 495 IdTable::new( 496 String::from("console"), 497 Some(DeviceNumber::new(Major::TTYAUX_MAJOR, 1)), 498 ), 499 ); 500 501 // 注册tty设备 502 // CharDevOps::cdev_add( 503 // tty.clone() as Arc<dyn CharDevice>, 504 // IdTable::new( 505 // String::from("tty0"), 506 // Some(DeviceNumber::new(Major::TTYAUX_MAJOR, 0)), 507 // ), 508 // 1, 509 // )?; 510 511 // CharDevOps::register_chardev_region(DeviceNumber::new(Major::TTYAUX_MAJOR, 0), 1, "/dev/tty")?; 512 513 // 注册console设备 514 // CharDevOps::cdev_add( 515 // console.clone() as Arc<dyn CharDevice>, 516 // IdTable::new( 517 // String::from("console"), 518 // Some(DeviceNumber::new(Major::TTYAUX_MAJOR, 1)), 519 // ), 520 // 1, 521 // )?; 522 523 // CharDevOps::register_chardev_region(DeviceNumber::new(Major::TTYAUX_MAJOR, 1), 1, "/dev/tty")?; 524 525 // 将这两个设备注册到devfs,TODO:这里console设备应该与tty在一个设备group里面 526 device_register(tty.clone())?; 527 device_register(console.clone())?; 528 devfs_register(tty.name, tty)?; 529 devfs_register(console.name, console)?; 530 531 serial_init()?; 532 533 tty_flush_thread_init(); 534 return vty_init(); 535 } 536