1 use core::{ 2 fmt::Debug, 3 sync::atomic::{AtomicBool, AtomicUsize, Ordering}, 4 }; 5 6 use alloc::{ 7 collections::LinkedList, 8 string::String, 9 sync::{Arc, Weak}, 10 vec::Vec, 11 }; 12 use system_error::SystemError; 13 14 use crate::{ 15 driver::serial::serial8250::send_to_default_serial8250_port, 16 libs::{ 17 rwlock::{RwLock, RwLockReadGuard, RwLockUpgradableGuard, RwLockWriteGuard}, 18 spinlock::{SpinLock, SpinLockGuard}, 19 wait_queue::EventWaitQueue, 20 }, 21 mm::VirtAddr, 22 net::event_poll::{EPollEventType, EPollItem}, 23 process::Pid, 24 syscall::user_access::{UserBufferReader, UserBufferWriter}, 25 }; 26 27 use super::{ 28 termios::{ControlMode, PosixTermios, Termios, TtySetTermiosOpt, WindowSize}, 29 tty_driver::{TtyDriver, TtyDriverSubType, TtyDriverType, TtyOperation}, 30 tty_ldisc::{ 31 ntty::{NTtyData, NTtyLinediscipline}, 32 TtyLineDiscipline, 33 }, 34 tty_port::TtyPort, 35 virtual_terminal::{virtual_console::VirtualConsoleData, VIRT_CONSOLES}, 36 }; 37 38 #[derive(Debug)] 39 pub struct TtyCore { 40 core: TtyCoreData, 41 /// 线路规程函数集 42 line_discipline: Arc<dyn TtyLineDiscipline>, 43 } 44 45 impl TtyCore { 46 pub fn new(driver: Arc<TtyDriver>, index: usize) -> Arc<Self> { 47 let name = driver.tty_line_name(index); 48 let termios = driver.init_termios(); 49 let core = TtyCoreData { 50 tty_driver: driver, 51 termios: RwLock::new(termios), 52 name, 53 flags: RwLock::new(TtyFlag::empty()), 54 count: AtomicUsize::new(0), 55 window_size: RwLock::new(WindowSize::default()), 56 read_wq: EventWaitQueue::new(), 57 write_wq: EventWaitQueue::new(), 58 port: RwLock::new(None), 59 index, 60 ctrl: SpinLock::new(TtyContorlInfo::default()), 61 closing: AtomicBool::new(false), 62 flow: SpinLock::new(TtyFlowState::default()), 63 link: RwLock::default(), 64 epitems: SpinLock::new(LinkedList::new()), 65 }; 66 67 return Arc::new(Self { 68 core, 69 line_discipline: Arc::new(NTtyLinediscipline { 70 data: SpinLock::new(NTtyData::new()), 71 }), 72 }); 73 } 74 75 #[inline] 76 pub fn core(&self) -> &TtyCoreData { 77 return &self.core; 78 } 79 80 #[inline] 81 pub fn ldisc(&self) -> Arc<dyn TtyLineDiscipline> { 82 self.line_discipline.clone() 83 } 84 85 pub fn write_without_serial(&self, buf: &[u8], nr: usize) -> Result<usize, SystemError> { 86 self.core 87 .driver() 88 .driver_funcs() 89 .write(self.core(), buf, nr) 90 } 91 92 pub fn reopen(&self) -> Result<(), SystemError> { 93 let tty_core = self.core(); 94 let driver = tty_core.driver(); 95 96 if driver.tty_driver_type() == TtyDriverType::Pty 97 && driver.tty_driver_sub_type() == TtyDriverSubType::PtyMaster 98 { 99 return Err(SystemError::EIO); 100 } 101 102 // if *tty_core.count.read() == 0 { 103 // return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 104 // } 105 106 // TODO 判断flags 107 108 tty_core.add_count(); 109 110 Ok(()) 111 } 112 113 #[inline] 114 pub fn set_port(&self, port: Arc<dyn TtyPort>) { 115 *self.core.port.write() = Some(port); 116 } 117 118 pub fn tty_start(&self) { 119 let mut flow = self.core.flow.lock_irqsave(); 120 if !flow.stopped || flow.tco_stopped { 121 return; 122 } 123 124 flow.stopped = false; 125 let _ = self.start(self.core()); 126 self.tty_wakeup(); 127 } 128 129 pub fn tty_stop(&self) { 130 let mut flow = self.core.flow.lock_irqsave(); 131 if flow.stopped { 132 return; 133 } 134 flow.stopped = true; 135 136 let _ = self.stop(self.core()); 137 } 138 139 pub fn tty_wakeup(&self) { 140 if self.core.flags().contains(TtyFlag::DO_WRITE_WAKEUP) { 141 let _ = self.ldisc().write_wakeup(self.core()); 142 } 143 144 self.core() 145 .write_wq 146 .wakeup_any(EPollEventType::EPOLLOUT.bits() as u64); 147 } 148 149 pub fn tty_mode_ioctl(tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<usize, SystemError> { 150 let core = tty.core(); 151 let real_tty = if core.driver().tty_driver_type() == TtyDriverType::Pty 152 && core.driver().tty_driver_sub_type() == TtyDriverSubType::PtyMaster 153 { 154 core.link().unwrap() 155 } else { 156 tty 157 }; 158 match cmd { 159 TtyIoctlCmd::TCGETS => { 160 let termios = PosixTermios::from_kernel_termios(*real_tty.core.termios()); 161 let mut user_writer = UserBufferWriter::new( 162 VirtAddr::new(arg).as_ptr::<PosixTermios>(), 163 core::mem::size_of::<PosixTermios>(), 164 true, 165 )?; 166 167 user_writer.copy_one_to_user(&termios, 0)?; 168 return Ok(0); 169 } 170 TtyIoctlCmd::TCSETS => { 171 return TtyCore::core_set_termios( 172 real_tty, 173 VirtAddr::new(arg), 174 TtySetTermiosOpt::TERMIOS_OLD, 175 ); 176 } 177 TtyIoctlCmd::TCSETSW => { 178 return TtyCore::core_set_termios( 179 real_tty, 180 VirtAddr::new(arg), 181 TtySetTermiosOpt::TERMIOS_WAIT | TtySetTermiosOpt::TERMIOS_OLD, 182 ); 183 } 184 _ => { 185 return Err(SystemError::ENOIOCTLCMD); 186 } 187 } 188 } 189 190 pub fn core_set_termios( 191 tty: Arc<TtyCore>, 192 arg: VirtAddr, 193 opt: TtySetTermiosOpt, 194 ) -> Result<usize, SystemError> { 195 #[allow(unused_assignments)] 196 // TERMIOS_TERMIO下会用到 197 let mut tmp_termios = *tty.core().termios(); 198 199 if opt.contains(TtySetTermiosOpt::TERMIOS_TERMIO) { 200 todo!() 201 } else { 202 let user_reader = UserBufferReader::new( 203 arg.as_ptr::<PosixTermios>(), 204 core::mem::size_of::<PosixTermios>(), 205 true, 206 )?; 207 208 let mut term = PosixTermios::default(); 209 user_reader.copy_one_from_user(&mut term, 0)?; 210 211 tmp_termios = term.to_kernel_termios(); 212 } 213 214 if opt.contains(TtySetTermiosOpt::TERMIOS_FLUSH) { 215 let ld = tty.ldisc(); 216 let _ = ld.flush_buffer(tty.clone()); 217 } 218 219 if opt.contains(TtySetTermiosOpt::TERMIOS_WAIT) { 220 // TODO 221 } 222 223 TtyCore::set_termios_next(tty, tmp_termios)?; 224 Ok(0) 225 } 226 227 pub fn set_termios_next(tty: Arc<TtyCore>, new_termios: Termios) -> Result<(), SystemError> { 228 let mut termios = tty.core().termios_write(); 229 230 let old_termios = *termios; 231 *termios = new_termios; 232 let tmp = termios.control_mode; 233 termios.control_mode ^= (tmp ^ old_termios.control_mode) & ControlMode::ADDRB; 234 235 let ret = tty.set_termios(tty.clone(), old_termios); 236 if ret.is_err() { 237 termios.control_mode &= ControlMode::HUPCL | ControlMode::CREAD | ControlMode::CLOCAL; 238 termios.control_mode |= old_termios.control_mode 239 & !(ControlMode::HUPCL | ControlMode::CREAD | ControlMode::CLOCAL); 240 termios.input_speed = old_termios.input_speed; 241 termios.output_speed = old_termios.output_speed; 242 } 243 244 drop(termios); 245 let ld = tty.ldisc(); 246 ld.set_termios(tty, Some(old_termios))?; 247 248 Ok(()) 249 } 250 } 251 252 #[derive(Debug, Default)] 253 pub struct TtyContorlInfo { 254 /// 前台进程pid 255 pub session: Option<Pid>, 256 /// 前台进程组id 257 pub pgid: Option<Pid>, 258 259 /// packet模式下使用,目前未用到 260 pub pktstatus: TtyPacketStatus, 261 pub packet: bool, 262 } 263 264 #[derive(Debug, Default)] 265 pub struct TtyCoreWriteData { 266 /// 写缓冲区 267 pub write_buf: Vec<u8>, 268 /// 写入数量 269 pub write_cnt: usize, 270 } 271 272 #[derive(Debug, Default)] 273 pub struct TtyFlowState { 274 /// 表示流控是否被停止 275 pub stopped: bool, 276 /// 表示 TCO(Transmit Continuous Operation)流控是否被停止 277 pub tco_stopped: bool, 278 } 279 280 #[derive(Debug)] 281 pub struct TtyCoreData { 282 tty_driver: Arc<TtyDriver>, 283 termios: RwLock<Termios>, 284 name: String, 285 flags: RwLock<TtyFlag>, 286 /// 在初始化时即确定不会更改,所以这里不用加锁 287 index: usize, 288 count: AtomicUsize, 289 /// 窗口大小 290 window_size: RwLock<WindowSize>, 291 /// 读等待队列 292 read_wq: EventWaitQueue, 293 /// 写等待队列 294 write_wq: EventWaitQueue, 295 /// 端口 296 port: RwLock<Option<Arc<dyn TtyPort>>>, 297 /// 前台进程 298 ctrl: SpinLock<TtyContorlInfo>, 299 /// 是否正在关闭 300 closing: AtomicBool, 301 /// 流控状态 302 flow: SpinLock<TtyFlowState>, 303 /// 链接tty 304 link: RwLock<Weak<TtyCore>>, 305 /// epitems 306 epitems: SpinLock<LinkedList<Arc<EPollItem>>>, 307 } 308 309 impl TtyCoreData { 310 #[inline] 311 pub fn driver(&self) -> Arc<TtyDriver> { 312 self.tty_driver.clone() 313 } 314 315 #[inline] 316 pub fn flow_irqsave(&self) -> SpinLockGuard<TtyFlowState> { 317 self.flow.lock_irqsave() 318 } 319 320 #[inline] 321 pub fn port(&self) -> Option<Arc<dyn TtyPort>> { 322 self.port.read().clone() 323 } 324 325 #[inline] 326 pub fn index(&self) -> usize { 327 self.index 328 } 329 330 #[inline] 331 pub fn name(&self) -> String { 332 self.name.clone() 333 } 334 335 #[inline] 336 pub fn flags(&self) -> TtyFlag { 337 *self.flags.read_irqsave() 338 } 339 340 #[inline] 341 pub fn flags_write(&self) -> RwLockWriteGuard<'_, TtyFlag> { 342 self.flags.write_irqsave() 343 } 344 345 #[inline] 346 pub fn termios(&self) -> RwLockReadGuard<'_, Termios> { 347 self.termios.read_irqsave() 348 } 349 350 #[inline] 351 pub fn termios_write(&self) -> RwLockWriteGuard<Termios> { 352 self.termios.write_irqsave() 353 } 354 355 #[inline] 356 pub fn set_termios(&self, termios: Termios) { 357 let mut termios_guard = self.termios_write(); 358 *termios_guard = termios; 359 } 360 361 #[inline] 362 pub fn count(&self) -> usize { 363 self.count.load(Ordering::SeqCst) 364 } 365 366 #[inline] 367 pub fn add_count(&self) { 368 self.count 369 .fetch_add(1, core::sync::atomic::Ordering::SeqCst); 370 } 371 372 #[inline] 373 pub fn read_wq(&self) -> &EventWaitQueue { 374 &self.read_wq 375 } 376 377 #[inline] 378 pub fn write_wq(&self) -> &EventWaitQueue { 379 &self.write_wq 380 } 381 382 #[inline] 383 pub fn contorl_info_irqsave(&self) -> SpinLockGuard<TtyContorlInfo> { 384 self.ctrl.lock_irqsave() 385 } 386 387 #[inline] 388 pub fn window_size_upgradeable(&self) -> RwLockUpgradableGuard<WindowSize> { 389 self.window_size.upgradeable_read() 390 } 391 392 #[inline] 393 pub fn window_size(&self) -> RwLockReadGuard<WindowSize> { 394 self.window_size.read() 395 } 396 397 #[inline] 398 pub fn is_closing(&self) -> bool { 399 self.closing.load(core::sync::atomic::Ordering::SeqCst) 400 } 401 402 #[inline] 403 pub fn vc_data_irqsave(&self) -> SpinLockGuard<VirtualConsoleData> { 404 VIRT_CONSOLES[self.index].lock_irqsave() 405 } 406 407 #[inline] 408 pub fn link(&self) -> Option<Arc<TtyCore>> { 409 self.link.read().upgrade() 410 } 411 412 pub fn checked_link(&self) -> Result<Arc<TtyCore>, SystemError> { 413 if let Some(link) = self.link() { 414 return Ok(link); 415 } 416 return Err(SystemError::ENODEV); 417 } 418 419 pub fn set_link(&self, link: Weak<TtyCore>) { 420 *self.link.write() = link; 421 } 422 423 pub fn init_termios(&self) { 424 let tty_index = self.index(); 425 let driver = self.driver(); 426 // 初始化termios 427 if !driver 428 .flags() 429 .contains(super::tty_driver::TtyDriverFlag::TTY_DRIVER_RESET_TERMIOS) 430 { 431 // 先查看是否有已经保存的termios 432 if let Some(t) = driver.saved_termios().get(tty_index) { 433 let mut termios = *t; 434 termios.line = driver.init_termios().line; 435 self.set_termios(termios); 436 } 437 } 438 // TODO:设置termios波特率? 439 } 440 441 #[inline] 442 pub fn add_epitem(&self, epitem: Arc<EPollItem>) { 443 self.epitems.lock().push_back(epitem) 444 } 445 } 446 447 /// TTY 核心接口,不同的tty需要各自实现这个trait 448 pub trait TtyCoreFuncs: Debug + Send + Sync {} 449 450 impl TtyOperation for TtyCore { 451 #[inline] 452 fn open(&self, tty: &TtyCoreData) -> Result<(), SystemError> { 453 return self.core().tty_driver.driver_funcs().open(tty); 454 } 455 456 #[inline] 457 fn write_room(&self, tty: &TtyCoreData) -> usize { 458 return self.core().tty_driver.driver_funcs().write_room(tty); 459 } 460 461 #[inline] 462 fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError> { 463 send_to_default_serial8250_port(buf); 464 return self.core().tty_driver.driver_funcs().write(tty, buf, nr); 465 } 466 467 #[inline] 468 fn flush_chars(&self, tty: &TtyCoreData) { 469 self.core().tty_driver.driver_funcs().flush_chars(tty); 470 } 471 472 #[inline] 473 fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError> { 474 return self.core().tty_driver.driver_funcs().put_char(tty, ch); 475 } 476 477 #[inline] 478 fn install(&self, driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> { 479 return self.core().tty_driver.driver_funcs().install(driver, tty); 480 } 481 482 #[inline] 483 fn start(&self, tty: &TtyCoreData) -> Result<(), SystemError> { 484 return self.core().tty_driver.driver_funcs().start(tty); 485 } 486 487 #[inline] 488 fn stop(&self, tty: &TtyCoreData) -> Result<(), SystemError> { 489 return self.core().tty_driver.driver_funcs().stop(tty); 490 } 491 492 #[inline] 493 fn ioctl(&self, tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<(), SystemError> { 494 return self.core().tty_driver.driver_funcs().ioctl(tty, cmd, arg); 495 } 496 497 #[inline] 498 fn chars_in_buffer(&self) -> usize { 499 return self.core().tty_driver.driver_funcs().chars_in_buffer(); 500 } 501 502 #[inline] 503 fn set_termios(&self, tty: Arc<TtyCore>, old_termios: Termios) -> Result<(), SystemError> { 504 return self 505 .core() 506 .tty_driver 507 .driver_funcs() 508 .set_termios(tty, old_termios); 509 } 510 511 fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError> { 512 self.core().tty_driver.driver_funcs().close(tty) 513 } 514 } 515 516 bitflags! { 517 pub struct TtyFlag: u32 { 518 /// 终端被节流 519 const THROTTLED = 1 << 0; 520 /// 终端输入输出错误状态 521 const IO_ERROR = 1 << 1; 522 /// 终端的其他一方已关闭 523 const OTHER_CLOSED = 1 << 2; 524 /// 终端处于独占状态 525 const EXCLUSIVE = 1 << 3; 526 /// 终端执行写唤醒操作 527 const DO_WRITE_WAKEUP = 1 << 5; 528 /// 终端线路驱动程序已打开 529 const LDISC_OPEN = 1 << 11; 530 /// 终端伪终端设备已锁定 531 const PTY_LOCK = 1 << 16; 532 /// 终端禁用写分裂操作 533 const NO_WRITE_SPLIT = 1 << 17; 534 /// 终端挂断(挂起)状态 535 const HUPPED = 1 << 18; 536 /// 终端正在挂断(挂起) 537 const HUPPING = 1 << 19; 538 /// 终端线路驱动程序正在更改 539 const LDISC_CHANGING = 1 << 20; 540 /// 终端线路驱动程序已停止 541 const LDISC_HALTED = 1 << 22; 542 } 543 544 #[derive(Default)] 545 pub struct TtyPacketStatus: u8 { 546 /* Used for packet mode */ 547 const TIOCPKT_DATA = 0; 548 const TIOCPKT_FLUSHREAD = 1; 549 const TIOCPKT_FLUSHWRITE = 2; 550 const TIOCPKT_STOP = 4; 551 const TIOCPKT_START = 8; 552 const TIOCPKT_NOSTOP = 16; 553 const TIOCPKT_DOSTOP = 32; 554 const TIOCPKT_IOCTL = 64; 555 } 556 } 557 558 #[derive(Debug, PartialEq)] 559 pub enum EchoOperation { 560 /// 开始特殊操作。 561 Start, 562 /// 向后移动光标列。 563 MoveBackCol, 564 /// 设置规范模式下的列位置。 565 SetCanonCol, 566 /// 擦除制表符。 567 EraseTab, 568 569 Undefined(u8), 570 } 571 572 impl EchoOperation { 573 pub fn from_u8(num: u8) -> EchoOperation { 574 match num { 575 0xff => Self::Start, 576 0x80 => Self::MoveBackCol, 577 0x81 => Self::SetCanonCol, 578 0x82 => Self::EraseTab, 579 _ => Self::Undefined(num), 580 } 581 } 582 583 pub fn to_u8(&self) -> u8 { 584 match *self { 585 EchoOperation::Start => 0xff, 586 EchoOperation::MoveBackCol => 0x80, 587 EchoOperation::SetCanonCol => 0x81, 588 EchoOperation::EraseTab => 0x82, 589 EchoOperation::Undefined(num) => num, 590 } 591 } 592 } 593 594 pub struct TtyIoctlCmd; 595 596 #[allow(dead_code)] 597 impl TtyIoctlCmd { 598 /// 获取终端参数 599 pub const TCGETS: u32 = 0x5401; 600 /// 设置终端参数 601 pub const TCSETS: u32 = 0x5402; 602 /// 设置终端参数并等待所有输出完成 603 pub const TCSETSW: u32 = 0x5403; 604 /// 设置终端参数并且等待所有输出完成,但在这之前将终端清空 605 pub const TCSETSF: u32 = 0x5404; 606 /// 获取终端参数 607 pub const TCGETA: u32 = 0x5405; 608 /// 设置终端参数 609 pub const TCSETA: u32 = 0x5406; 610 /// 设置终端参数并等待所有输出完成 611 pub const TCSETAW: u32 = 0x5407; 612 /// 设置终端参数并且等待所有输出完成,但在这之前将终端清空 613 pub const TCSETAF: u32 = 0x5408; 614 /// 发送零字节,等待所有输出完成 615 pub const TCSBRK: u32 = 0x5409; 616 /// 控制终端的流控 617 pub const TCXONC: u32 = 0x540A; 618 /// 刷新输入/输出缓冲区或者丢弃输入缓冲区 619 pub const TCFLSH: u32 = 0x540B; 620 /// 设置设备为独占模式 621 pub const TIOCEXCL: u32 = 0x540C; 622 /// 设置设备为非独占模式 623 pub const TIOCNXCL: u32 = 0x540D; 624 /// 设置当前进程的控制终端 625 pub const TIOCSCTTY: u32 = 0x540E; 626 /// 获取前台进程组 627 pub const TIOCGPGRP: u32 = 0x540F; 628 ///设置前台进程组 629 pub const TIOCSPGRP: u32 = 0x5410; 630 /// 获取输出队列的字节数 631 pub const TIOCOUTQ: u32 = 0x5411; 632 /// 模拟从终端输入字符 633 pub const TIOCSTI: u32 = 0x5412; 634 /// 获取窗口大小 635 pub const TIOCGWINSZ: u32 = 0x5413; 636 /// 设置窗口大小 637 pub const TIOCSWINSZ: u32 = 0x5414; 638 /// 获取终端控制信号的状态 639 pub const TIOCMGET: u32 = 0x5415; 640 /// 设置终端控制信号的位 641 pub const TIOCMBIS: u32 = 0x5416; 642 /// 清除终端控制信号的位 643 pub const TIOCMBIC: u32 = 0x5417; 644 /// 设置终端控制信号的状态 645 pub const TIOCMSET: u32 = 0x5418; 646 /// 获取软件载波状态 647 pub const TIOCGSOFTCAR: u32 = 0x5419; 648 /// 设置软件载波状态 649 pub const TIOCSSOFTCAR: u32 = 0x541A; 650 /// 获取输入队列的字节数 651 pub const FIONREAD: u32 = 0x541B; 652 /// Linux 特有命令 653 pub const TIOCLINUX: u32 = 0x541C; 654 /// 获取控制台设备 655 pub const TIOCCONS: u32 = 0x541D; 656 /// 获取串行设备参数 657 pub const TIOCGSERIAL: u32 = 0x541E; 658 /// 设置串行设备参数 659 pub const TIOCSSERIAL: u32 = 0x541F; 660 /// 设置套接字的报文模式 661 pub const TIOCPKT: u32 = 0x5420; 662 /// 设置非阻塞 I/O 663 pub const FIONBIO: u32 = 0x5421; 664 /// 清除控制终端 665 pub const TIOCNOTTY: u32 = 0x5422; 666 /// 设置终端线路驱动器 667 pub const TIOCSETD: u32 = 0x5423; 668 /// 获取终端线路驱动器 669 pub const TIOCGETD: u32 = 0x5424; 670 /// 发送终止条件 671 pub const TCSBRKP: u32 = 0x5425; 672 /// 开始发送零比特 673 pub const TIOCSBRK: u32 = 0x5427; 674 /// 停止发送零比特 675 pub const TIOCCBRK: u32 = 0x5428; 676 /// Return the session ID of FD 677 pub const TIOCGSID: u32 = 0x5429; 678 /// 设置ptl锁标记 679 pub const TIOCSPTLCK: u32 = 0x40045431; 680 /// 获取ptl锁标记 681 pub const TIOCGPTLCK: u32 = 0x80045439; 682 /// 获取packet标记 683 pub const TIOCGPKT: u32 = 0x80045438; 684 /// 获取pts index 685 pub const TIOCGPTN: u32 = 0x80045430; 686 } 687