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