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