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