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