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