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, DrawRegion}, 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_to_core(&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 pub fn eptiems(&self) -> &SpinLock<LinkedList<Arc<EPollItem>>> { 494 &self.epitems 495 } 496 497 pub fn do_write(&self, buf: &[u8], mut nr: usize) -> Result<usize, SystemError> { 498 // 关闭中断 499 if let Some(vc_data) = self.vc_data() { 500 let mut vc_data_guard = vc_data.lock_irqsave(); 501 let mut offset = 0; 502 503 // 这个参数是用来扫描unicode字符的,但是这部分目前未完成,先写着 504 let mut rescan = false; 505 let mut ch: u32 = 0; 506 507 let mut draw = DrawRegion::default(); 508 509 // 首先隐藏光标再写 510 vc_data_guard.hide_cursor(); 511 512 while nr != 0 { 513 if !rescan { 514 ch = buf[offset] as u32; 515 offset += 1; 516 nr -= 1; 517 } 518 519 let (tc, rescan_last) = vc_data_guard.translate(&mut ch); 520 if tc.is_none() { 521 // 表示未转换完成 522 continue; 523 } 524 525 let tc = tc.unwrap(); 526 rescan = rescan_last; 527 528 if vc_data_guard.is_control(tc, ch) { 529 vc_data_guard.flush(&mut draw); 530 vc_data_guard.do_control(ch); 531 continue; 532 } 533 534 if !vc_data_guard.console_write_normal(tc, ch, &mut draw) { 535 continue; 536 } 537 } 538 539 vc_data_guard.flush(&mut draw); 540 541 // TODO: notify update 542 return Ok(offset); 543 } else { 544 return Ok(0); 545 } 546 } 547 } 548 549 impl TtyOperation for TtyCore { 550 #[inline] 551 fn open(&self, tty: &TtyCoreData) -> Result<(), SystemError> { 552 return self.core().tty_driver.driver_funcs().open(tty); 553 } 554 555 #[inline] 556 fn write_room(&self, tty: &TtyCoreData) -> usize { 557 return self.core().tty_driver.driver_funcs().write_room(tty); 558 } 559 560 #[inline] 561 fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError> { 562 return self.core().tty_driver.driver_funcs().write(tty, buf, nr); 563 } 564 565 #[inline] 566 fn flush_chars(&self, tty: &TtyCoreData) { 567 self.core().tty_driver.driver_funcs().flush_chars(tty); 568 } 569 570 #[inline] 571 fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError> { 572 return self.core().tty_driver.driver_funcs().put_char(tty, ch); 573 } 574 575 #[inline] 576 fn install(&self, driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> { 577 return self.core().tty_driver.driver_funcs().install(driver, tty); 578 } 579 580 #[inline] 581 fn start(&self, tty: &TtyCoreData) -> Result<(), SystemError> { 582 return self.core().tty_driver.driver_funcs().start(tty); 583 } 584 585 #[inline] 586 fn stop(&self, tty: &TtyCoreData) -> Result<(), SystemError> { 587 return self.core().tty_driver.driver_funcs().stop(tty); 588 } 589 590 #[inline] 591 fn ioctl(&self, tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<(), SystemError> { 592 return self.core().tty_driver.driver_funcs().ioctl(tty, cmd, arg); 593 } 594 595 #[inline] 596 fn chars_in_buffer(&self) -> usize { 597 return self.core().tty_driver.driver_funcs().chars_in_buffer(); 598 } 599 600 #[inline] 601 fn set_termios(&self, tty: Arc<TtyCore>, old_termios: Termios) -> Result<(), SystemError> { 602 return self 603 .core() 604 .tty_driver 605 .driver_funcs() 606 .set_termios(tty, old_termios); 607 } 608 609 fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError> { 610 self.core().tty_driver.driver_funcs().close(tty) 611 } 612 613 fn resize(&self, tty: Arc<TtyCore>, winsize: WindowSize) -> Result<(), SystemError> { 614 self.core.tty_driver.driver_funcs().resize(tty, winsize) 615 } 616 } 617 618 bitflags! { 619 pub struct TtyFlag: u32 { 620 /// 终端被节流 621 const THROTTLED = 1 << 0; 622 /// 终端输入输出错误状态 623 const IO_ERROR = 1 << 1; 624 /// 终端的其他一方已关闭 625 const OTHER_CLOSED = 1 << 2; 626 /// 终端处于独占状态 627 const EXCLUSIVE = 1 << 3; 628 /// 终端执行写唤醒操作 629 const DO_WRITE_WAKEUP = 1 << 5; 630 /// 终端线路驱动程序已打开 631 const LDISC_OPEN = 1 << 11; 632 /// 终端伪终端设备已锁定 633 const PTY_LOCK = 1 << 16; 634 /// 终端禁用写分裂操作 635 const NO_WRITE_SPLIT = 1 << 17; 636 /// 终端挂断(挂起)状态 637 const HUPPED = 1 << 18; 638 /// 终端正在挂断(挂起) 639 const HUPPING = 1 << 19; 640 /// 终端线路驱动程序正在更改 641 const LDISC_CHANGING = 1 << 20; 642 /// 终端线路驱动程序已停止 643 const LDISC_HALTED = 1 << 22; 644 } 645 646 #[derive(Default)] 647 pub struct TtyPacketStatus: u8 { 648 /* Used for packet mode */ 649 const TIOCPKT_DATA = 0; 650 const TIOCPKT_FLUSHREAD = 1; 651 const TIOCPKT_FLUSHWRITE = 2; 652 const TIOCPKT_STOP = 4; 653 const TIOCPKT_START = 8; 654 const TIOCPKT_NOSTOP = 16; 655 const TIOCPKT_DOSTOP = 32; 656 const TIOCPKT_IOCTL = 64; 657 } 658 } 659 660 #[derive(Debug, PartialEq)] 661 pub enum EchoOperation { 662 /// 开始特殊操作。 663 Start, 664 /// 向后移动光标列。 665 MoveBackCol, 666 /// 设置规范模式下的列位置。 667 SetCanonCol, 668 /// 擦除制表符。 669 EraseTab, 670 671 Undefined(u8), 672 } 673 674 impl EchoOperation { 675 pub fn from_u8(num: u8) -> EchoOperation { 676 match num { 677 0xff => Self::Start, 678 0x80 => Self::MoveBackCol, 679 0x81 => Self::SetCanonCol, 680 0x82 => Self::EraseTab, 681 _ => Self::Undefined(num), 682 } 683 } 684 685 pub fn to_u8(&self) -> u8 { 686 match *self { 687 EchoOperation::Start => 0xff, 688 EchoOperation::MoveBackCol => 0x80, 689 EchoOperation::SetCanonCol => 0x81, 690 EchoOperation::EraseTab => 0x82, 691 EchoOperation::Undefined(num) => num, 692 } 693 } 694 } 695 696 pub struct TtyIoctlCmd; 697 698 #[allow(dead_code)] 699 impl TtyIoctlCmd { 700 /// 获取终端参数 701 pub const TCGETS: u32 = 0x5401; 702 /// 设置终端参数 703 pub const TCSETS: u32 = 0x5402; 704 /// 设置终端参数并等待所有输出完成 705 pub const TCSETSW: u32 = 0x5403; 706 /// 设置终端参数并且等待所有输出完成,但在这之前将终端清空 707 pub const TCSETSF: u32 = 0x5404; 708 /// 获取终端参数 709 pub const TCGETA: u32 = 0x5405; 710 /// 设置终端参数 711 pub const TCSETA: u32 = 0x5406; 712 /// 设置终端参数并等待所有输出完成 713 pub const TCSETAW: u32 = 0x5407; 714 /// 设置终端参数并且等待所有输出完成,但在这之前将终端清空 715 pub const TCSETAF: u32 = 0x5408; 716 /// 发送零字节,等待所有输出完成 717 pub const TCSBRK: u32 = 0x5409; 718 /// 控制终端的流控 719 pub const TCXONC: u32 = 0x540A; 720 /// 刷新输入/输出缓冲区或者丢弃输入缓冲区 721 pub const TCFLSH: u32 = 0x540B; 722 /// 设置设备为独占模式 723 pub const TIOCEXCL: u32 = 0x540C; 724 /// 设置设备为非独占模式 725 pub const TIOCNXCL: u32 = 0x540D; 726 /// 设置当前进程的控制终端 727 pub const TIOCSCTTY: u32 = 0x540E; 728 /// 获取前台进程组 729 pub const TIOCGPGRP: u32 = 0x540F; 730 ///设置前台进程组 731 pub const TIOCSPGRP: u32 = 0x5410; 732 /// 获取输出队列的字节数 733 pub const TIOCOUTQ: u32 = 0x5411; 734 /// 模拟从终端输入字符 735 pub const TIOCSTI: u32 = 0x5412; 736 /// 获取窗口大小 737 pub const TIOCGWINSZ: u32 = 0x5413; 738 /// 设置窗口大小 739 pub const TIOCSWINSZ: u32 = 0x5414; 740 /// 获取终端控制信号的状态 741 pub const TIOCMGET: u32 = 0x5415; 742 /// 设置终端控制信号的位 743 pub const TIOCMBIS: u32 = 0x5416; 744 /// 清除终端控制信号的位 745 pub const TIOCMBIC: u32 = 0x5417; 746 /// 设置终端控制信号的状态 747 pub const TIOCMSET: u32 = 0x5418; 748 /// 获取软件载波状态 749 pub const TIOCGSOFTCAR: u32 = 0x5419; 750 /// 设置软件载波状态 751 pub const TIOCSSOFTCAR: u32 = 0x541A; 752 /// 获取输入队列的字节数 753 pub const FIONREAD: u32 = 0x541B; 754 /// Linux 特有命令 755 pub const TIOCLINUX: u32 = 0x541C; 756 /// 获取控制台设备 757 pub const TIOCCONS: u32 = 0x541D; 758 /// 获取串行设备参数 759 pub const TIOCGSERIAL: u32 = 0x541E; 760 /// 设置串行设备参数 761 pub const TIOCSSERIAL: u32 = 0x541F; 762 /// 设置套接字的报文模式 763 pub const TIOCPKT: u32 = 0x5420; 764 /// 设置非阻塞 I/O 765 pub const FIONBIO: u32 = 0x5421; 766 /// 清除控制终端 767 pub const TIOCNOTTY: u32 = 0x5422; 768 /// 设置终端线路驱动器 769 pub const TIOCSETD: u32 = 0x5423; 770 /// 获取终端线路驱动器 771 pub const TIOCGETD: u32 = 0x5424; 772 /// 发送终止条件 773 pub const TCSBRKP: u32 = 0x5425; 774 /// 开始发送零比特 775 pub const TIOCSBRK: u32 = 0x5427; 776 /// 停止发送零比特 777 pub const TIOCCBRK: u32 = 0x5428; 778 /// Return the session ID of FD 779 pub const TIOCGSID: u32 = 0x5429; 780 /// 设置ptl锁标记 781 pub const TIOCSPTLCK: u32 = 0x40045431; 782 /// 获取ptl锁标记 783 pub const TIOCGPTLCK: u32 = 0x80045439; 784 /// 获取packet标记 785 pub const TIOCGPKT: u32 = 0x80045438; 786 /// 获取pts index 787 pub const TIOCGPTN: u32 = 0x80045430; 788 } 789