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