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