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