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