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 {
new(driver: Arc<TtyDriver>, index: usize) -> Arc<Self>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]
core(&self) -> &TtyCoreData71     pub fn core(&self) -> &TtyCoreData {
72         return &self.core;
73     }
74 
75     #[inline]
ldisc(&self) -> Arc<dyn TtyLineDiscipline>76     pub fn ldisc(&self) -> Arc<dyn TtyLineDiscipline> {
77         self.line_discipline.clone()
78     }
79 
write_without_serial(&self, buf: &[u8], nr: usize) -> Result<usize, SystemError>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 
reopen(&self) -> Result<(), SystemError>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]
set_port(&self, port: Arc<dyn TtyPort>)109     pub fn set_port(&self, port: Arc<dyn TtyPort>) {
110         *self.core.port.write() = Some(port);
111     }
112 
tty_start(&self)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 
tty_stop(&self)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 
tty_wakeup(&self)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 
tty_mode_ioctl(tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<usize, SystemError>144     pub fn tty_mode_ioctl(tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<usize, SystemError> {
145         let real_tty;
146         let core = tty.core();
147         if core.driver().tty_driver_type() == TtyDriverType::Pty
148             && core.driver().tty_driver_sub_type() == TtyDriverSubType::PtyMaster
149         {
150             real_tty = core.link().unwrap();
151         } else {
152             real_tty = tty;
153         }
154         match cmd {
155             TtyIoctlCmd::TCGETS => {
156                 let termios = PosixTermios::from_kernel_termios(real_tty.core.termios().clone());
157                 let mut user_writer = UserBufferWriter::new(
158                     VirtAddr::new(arg).as_ptr::<PosixTermios>(),
159                     core::mem::size_of::<PosixTermios>(),
160                     true,
161                 )?;
162 
163                 user_writer.copy_one_to_user(&termios, 0)?;
164                 return Ok(0);
165             }
166             TtyIoctlCmd::TCSETS => {
167                 return TtyCore::core_set_termios(
168                     real_tty,
169                     VirtAddr::new(arg),
170                     TtySetTermiosOpt::TERMIOS_OLD,
171                 );
172             }
173             TtyIoctlCmd::TCSETSW => {
174                 return TtyCore::core_set_termios(
175                     real_tty,
176                     VirtAddr::new(arg),
177                     TtySetTermiosOpt::TERMIOS_WAIT | TtySetTermiosOpt::TERMIOS_OLD,
178                 );
179             }
180             _ => {
181                 return Err(SystemError::ENOIOCTLCMD);
182             }
183         }
184     }
185 
core_set_termios( tty: Arc<TtyCore>, arg: VirtAddr, opt: TtySetTermiosOpt, ) -> Result<usize, SystemError>186     pub fn core_set_termios(
187         tty: Arc<TtyCore>,
188         arg: VirtAddr,
189         opt: TtySetTermiosOpt,
190     ) -> Result<usize, SystemError> {
191         #[allow(unused_assignments)]
192         // TERMIOS_TERMIO下会用到
193         let mut tmp_termios = tty.core().termios().clone();
194 
195         if opt.contains(TtySetTermiosOpt::TERMIOS_TERMIO) {
196             todo!()
197         } else {
198             let user_reader = UserBufferReader::new(
199                 arg.as_ptr::<PosixTermios>(),
200                 core::mem::size_of::<PosixTermios>(),
201                 true,
202             )?;
203 
204             let mut term = PosixTermios::default();
205             user_reader.copy_one_from_user(&mut term, 0)?;
206 
207             tmp_termios = term.to_kernel_termios();
208         }
209 
210         if opt.contains(TtySetTermiosOpt::TERMIOS_FLUSH) {
211             let ld = tty.ldisc();
212             let _ = ld.flush_buffer(tty.clone());
213         }
214 
215         if opt.contains(TtySetTermiosOpt::TERMIOS_WAIT) {
216             // TODO
217         }
218 
219         TtyCore::set_termios_next(tty, tmp_termios)?;
220         Ok(0)
221     }
222 
set_termios_next(tty: Arc<TtyCore>, new_termios: Termios) -> Result<(), SystemError>223     pub fn set_termios_next(tty: Arc<TtyCore>, new_termios: Termios) -> Result<(), SystemError> {
224         let mut termios = tty.core().termios_write();
225 
226         let old_termios = termios.clone();
227         *termios = new_termios;
228         let tmp = termios.control_mode;
229         termios.control_mode ^= (tmp ^ old_termios.control_mode) & ControlMode::ADDRB;
230 
231         let ret = tty.set_termios(tty.clone(), old_termios);
232         if ret.is_err() {
233             termios.control_mode &= ControlMode::HUPCL | ControlMode::CREAD | ControlMode::CLOCAL;
234             termios.control_mode |= old_termios.control_mode
235                 & !(ControlMode::HUPCL | ControlMode::CREAD | ControlMode::CLOCAL);
236             termios.input_speed = old_termios.input_speed;
237             termios.output_speed = old_termios.output_speed;
238         }
239 
240         drop(termios);
241         let ld = tty.ldisc();
242         ld.set_termios(tty, Some(old_termios))?;
243 
244         Ok(())
245     }
246 }
247 
248 #[derive(Debug)]
249 pub struct TtyContorlInfo {
250     /// 前台进程pid
251     pub session: Option<Pid>,
252     /// 前台进程组id
253     pub pgid: Option<Pid>,
254 
255     /// packet模式下使用,目前未用到
256     pub pktstatus: u8,
257     pub packet: bool,
258 }
259 
260 impl Default for TtyContorlInfo {
default() -> Self261     fn default() -> Self {
262         Self {
263             session: None,
264             pgid: None,
265             pktstatus: Default::default(),
266             packet: Default::default(),
267         }
268     }
269 }
270 
271 #[derive(Debug, Default)]
272 pub struct TtyCoreWriteData {
273     /// 写缓冲区
274     pub write_buf: Vec<u8>,
275     /// 写入数量
276     pub write_cnt: usize,
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: Option<Arc<TtyCore>>,
312     /// epitems
313     epitems: SpinLock<LinkedList<Arc<EPollItem>>>,
314 }
315 
316 impl TtyCoreData {
317     #[inline]
driver(&self) -> Arc<TtyDriver>318     pub fn driver(&self) -> Arc<TtyDriver> {
319         self.tty_driver.clone()
320     }
321 
322     #[inline]
flow_irqsave(&self) -> SpinLockGuard<TtyFlowState>323     pub fn flow_irqsave(&self) -> SpinLockGuard<TtyFlowState> {
324         self.flow.lock_irqsave()
325     }
326 
327     #[inline]
port(&self) -> Option<Arc<dyn TtyPort>>328     pub fn port(&self) -> Option<Arc<dyn TtyPort>> {
329         self.port.read().clone()
330     }
331 
332     #[inline]
index(&self) -> usize333     pub fn index(&self) -> usize {
334         self.index
335     }
336 
337     #[inline]
name(&self) -> String338     pub fn name(&self) -> String {
339         self.name.clone()
340     }
341 
342     #[inline]
flags(&self) -> TtyFlag343     pub fn flags(&self) -> TtyFlag {
344         self.flags.read_irqsave().clone()
345     }
346 
347     #[inline]
termios(&self) -> RwLockReadGuard<'_, Termios>348     pub fn termios(&self) -> RwLockReadGuard<'_, Termios> {
349         self.termios.read_irqsave()
350     }
351 
352     #[inline]
termios_write(&self) -> RwLockWriteGuard<Termios>353     pub fn termios_write(&self) -> RwLockWriteGuard<Termios> {
354         self.termios.write_irqsave()
355     }
356 
357     #[inline]
set_termios(&self, termios: Termios)358     pub fn set_termios(&self, termios: Termios) {
359         let mut termios_guard = self.termios_write();
360         *termios_guard = termios;
361     }
362 
363     #[inline]
add_count(&self)364     pub fn add_count(&self) {
365         self.count
366             .fetch_add(1, core::sync::atomic::Ordering::SeqCst);
367     }
368 
369     #[inline]
read_wq(&self) -> &EventWaitQueue370     pub fn read_wq(&self) -> &EventWaitQueue {
371         &self.read_wq
372     }
373 
374     #[inline]
write_wq(&self) -> &EventWaitQueue375     pub fn write_wq(&self) -> &EventWaitQueue {
376         &self.write_wq
377     }
378 
379     #[inline]
contorl_info_irqsave(&self) -> SpinLockGuard<TtyContorlInfo>380     pub fn contorl_info_irqsave(&self) -> SpinLockGuard<TtyContorlInfo> {
381         self.ctrl.lock_irqsave()
382     }
383 
384     #[inline]
window_size_upgradeable(&self) -> RwLockUpgradableGuard<WindowSize>385     pub fn window_size_upgradeable(&self) -> RwLockUpgradableGuard<WindowSize> {
386         self.window_size.upgradeable_read()
387     }
388 
389     #[inline]
window_size(&self) -> RwLockReadGuard<WindowSize>390     pub fn window_size(&self) -> RwLockReadGuard<WindowSize> {
391         self.window_size.read()
392     }
393 
394     #[inline]
is_closing(&self) -> bool395     pub fn is_closing(&self) -> bool {
396         self.closing.load(core::sync::atomic::Ordering::SeqCst)
397     }
398 
399     #[inline]
vc_data_irqsave(&self) -> SpinLockGuard<VirtualConsoleData>400     pub fn vc_data_irqsave(&self) -> SpinLockGuard<VirtualConsoleData> {
401         VIRT_CONSOLES[self.index].lock_irqsave()
402     }
403 
404     #[inline]
link(&self) -> Option<Arc<TtyCore>>405     pub fn link(&self) -> Option<Arc<TtyCore>> {
406         self.link.clone()
407     }
408 
409     #[inline]
add_epitem(&self, epitem: Arc<EPollItem>)410     pub fn add_epitem(&self, epitem: Arc<EPollItem>) {
411         self.epitems.lock().push_back(epitem)
412     }
413 }
414 
415 /// TTY 核心接口,不同的tty需要各自实现这个trait
416 pub trait TtyCoreFuncs: Debug + Send + Sync {}
417 
418 impl TtyOperation for TtyCore {
419     #[inline]
open(&self, tty: &TtyCoreData) -> Result<(), SystemError>420     fn open(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
421         return self.core().tty_driver.driver_funcs().open(tty);
422     }
423 
424     #[inline]
write_room(&self, tty: &TtyCoreData) -> usize425     fn write_room(&self, tty: &TtyCoreData) -> usize {
426         return self.core().tty_driver.driver_funcs().write_room(tty);
427     }
428 
429     #[inline]
write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError>430     fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError> {
431         send_to_default_serial8250_port(buf);
432         return self.core().tty_driver.driver_funcs().write(tty, buf, nr);
433     }
434 
435     #[inline]
flush_chars(&self, tty: &TtyCoreData)436     fn flush_chars(&self, tty: &TtyCoreData) {
437         self.core().tty_driver.driver_funcs().flush_chars(tty);
438     }
439 
440     #[inline]
put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError>441     fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError> {
442         return self.core().tty_driver.driver_funcs().put_char(tty, ch);
443     }
444 
445     #[inline]
install(&self, driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError>446     fn install(&self, driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> {
447         return self.core().tty_driver.driver_funcs().install(driver, tty);
448     }
449 
450     #[inline]
start(&self, tty: &TtyCoreData) -> Result<(), SystemError>451     fn start(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
452         return self.core().tty_driver.driver_funcs().start(tty);
453     }
454 
455     #[inline]
stop(&self, tty: &TtyCoreData) -> Result<(), SystemError>456     fn stop(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
457         return self.core().tty_driver.driver_funcs().stop(tty);
458     }
459 
460     #[inline]
ioctl(&self, tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<(), SystemError>461     fn ioctl(&self, tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<(), SystemError> {
462         return self.core().tty_driver.driver_funcs().ioctl(tty, cmd, arg);
463     }
464 
465     #[inline]
chars_in_buffer(&self) -> usize466     fn chars_in_buffer(&self) -> usize {
467         return self.core().tty_driver.driver_funcs().chars_in_buffer();
468     }
469 
470     #[inline]
set_termios(&self, tty: Arc<TtyCore>, old_termios: Termios) -> Result<(), SystemError>471     fn set_termios(&self, tty: Arc<TtyCore>, old_termios: Termios) -> Result<(), SystemError> {
472         return self
473             .core()
474             .tty_driver
475             .driver_funcs()
476             .set_termios(tty, old_termios);
477     }
478 }
479 
480 bitflags! {
481     pub struct TtyFlag: u32 {
482         /// 终端被节流
483         const THROTTLED		= 1 << 0;
484         /// 终端输入输出错误状态
485         const IO_ERROR		= 1 << 1;
486         /// 终端的其他一方已关闭
487         const OTHER_CLOSED	= 1 << 2;
488         /// 终端处于独占状态
489         const EXCLUSIVE		= 1 << 3;
490         /// 终端执行写唤醒操作
491         const DO_WRITE_WAKEUP	= 1 << 5;
492         /// 终端线路驱动程序已打开
493         const LDISC_OPEN		= 1 << 11;
494         /// 终端伪终端设备已锁定
495         const PTY_LOCK		= 1 << 16;
496         /// 终端禁用写分裂操作
497         const NO_WRITE_SPLIT	= 1 << 17;
498         /// 终端挂断(挂起)状态
499         const HUPPED		= 1 << 18;
500         /// 终端正在挂断(挂起)
501         const HUPPING		= 1 << 19;
502         /// 终端线路驱动程序正在更改
503         const LDISC_CHANGING	= 1 << 20;
504         /// 终端线路驱动程序已停止
505         const LDISC_HALTED	= 1 << 22;
506     }
507 }
508 
509 #[derive(Debug, PartialEq)]
510 pub enum EchoOperation {
511     /// 开始特殊操作。
512     Start,
513     /// 向后移动光标列。
514     MoveBackCol,
515     /// 设置规范模式下的列位置。
516     SetCanonCol,
517     /// 擦除制表符。
518     EraseTab,
519 
520     Undefined(u8),
521 }
522 
523 impl EchoOperation {
from_u8(num: u8) -> EchoOperation524     pub fn from_u8(num: u8) -> EchoOperation {
525         match num {
526             0xff => Self::Start,
527             0x80 => Self::MoveBackCol,
528             0x81 => Self::SetCanonCol,
529             0x82 => Self::EraseTab,
530             _ => Self::Undefined(num),
531         }
532     }
533 
to_u8(&self) -> u8534     pub fn to_u8(&self) -> u8 {
535         match *self {
536             EchoOperation::Start => 0xff,
537             EchoOperation::MoveBackCol => 0x80,
538             EchoOperation::SetCanonCol => 0x81,
539             EchoOperation::EraseTab => 0x82,
540             EchoOperation::Undefined(num) => num,
541         }
542     }
543 }
544 
545 pub struct TtyIoctlCmd;
546 
547 #[allow(dead_code)]
548 impl TtyIoctlCmd {
549     /// 获取终端参数
550     pub const TCGETS: u32 = 0x5401;
551     /// 设置终端参数
552     pub const TCSETS: u32 = 0x5402;
553     /// 设置终端参数并等待所有输出完成
554     pub const TCSETSW: u32 = 0x5403;
555     /// 设置终端参数并且等待所有输出完成,但在这之前将终端清空
556     pub const TCSETSF: u32 = 0x5404;
557     /// 获取终端参数
558     pub const TCGETA: u32 = 0x5405;
559     /// 设置终端参数
560     pub const TCSETA: u32 = 0x5406;
561     /// 设置终端参数并等待所有输出完成
562     pub const TCSETAW: u32 = 0x5407;
563     /// 设置终端参数并且等待所有输出完成,但在这之前将终端清空
564     pub const TCSETAF: u32 = 0x5408;
565     /// 发送零字节,等待所有输出完成
566     pub const TCSBRK: u32 = 0x5409;
567     /// 控制终端的流控
568     pub const TCXONC: u32 = 0x540A;
569     /// 刷新输入/输出缓冲区或者丢弃输入缓冲区
570     pub const TCFLSH: u32 = 0x540B;
571     /// 设置设备为独占模式
572     pub const TIOCEXCL: u32 = 0x540C;
573     /// 设置设备为非独占模式
574     pub const TIOCNXCL: u32 = 0x540D;
575     /// 设置当前进程的控制终端
576     pub const TIOCSCTTY: u32 = 0x540E;
577     /// 获取前台进程组
578     pub const TIOCGPGRP: u32 = 0x540F;
579     ///设置前台进程组
580     pub const TIOCSPGRP: u32 = 0x5410;
581     /// 获取输出队列的字节数
582     pub const TIOCOUTQ: u32 = 0x5411;
583     /// 模拟从终端输入字符
584     pub const TIOCSTI: u32 = 0x5412;
585     /// 获取窗口大小
586     pub const TIOCGWINSZ: u32 = 0x5413;
587     /// 设置窗口大小
588     pub const TIOCSWINSZ: u32 = 0x5414;
589     /// 获取终端控制信号的状态
590     pub const TIOCMGET: u32 = 0x5415;
591     /// 设置终端控制信号的位
592     pub const TIOCMBIS: u32 = 0x5416;
593     /// 清除终端控制信号的位
594     pub const TIOCMBIC: u32 = 0x5417;
595     /// 设置终端控制信号的状态
596     pub const TIOCMSET: u32 = 0x5418;
597     /// 获取软件载波状态
598     pub const TIOCGSOFTCAR: u32 = 0x5419;
599     /// 设置软件载波状态
600     pub const TIOCSSOFTCAR: u32 = 0x541A;
601     /// 获取输入队列的字节数
602     pub const FIONREAD: u32 = 0x541B;
603     /// Linux 特有命令
604     pub const TIOCLINUX: u32 = 0x541C;
605     /// 获取控制台设备
606     pub const TIOCCONS: u32 = 0x541D;
607     /// 获取串行设备参数
608     pub const TIOCGSERIAL: u32 = 0x541E;
609     /// 设置串行设备参数
610     pub const TIOCSSERIAL: u32 = 0x541F;
611     /// 设置套接字的报文模式
612     pub const TIOCPKT: u32 = 0x5420;
613     /// 设置非阻塞 I/O
614     pub const FIONBIO: u32 = 0x5421;
615     /// 清除控制终端
616     pub const TIOCNOTTY: u32 = 0x5422;
617     /// 设置终端线路驱动器
618     pub const TIOCSETD: u32 = 0x5423;
619     /// 获取终端线路驱动器
620     pub const TIOCGETD: u32 = 0x5424;
621     /// 发送终止条件
622     pub const TCSBRKP: u32 = 0x5425;
623     /// 开始发送零比特
624     pub const TIOCSBRK: u32 = 0x5427;
625     /// 停止发送零比特
626     pub const TIOCCBRK: u32 = 0x5428;
627     /// Return the session ID of FD
628     pub const TIOCGSID: u32 = 0x5429;
629 }
630