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