xref: /DragonOS/kernel/src/driver/tty/tty_core.rs (revision f9fe30be89e89499aad4ef52b4648986bef5a7d8)
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 {
drop(&mut self)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 {
new(driver: Arc<TtyDriver>, index: usize) -> Arc<Self>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]
core(&self) -> &TtyCoreData89     pub fn core(&self) -> &TtyCoreData {
90         return &self.core;
91     }
92 
private_fields(&self) -> Option<Arc<dyn TtyCorePrivateField>>93     pub fn private_fields(&self) -> Option<Arc<dyn TtyCorePrivateField>> {
94         self.core.privete_fields.lock().clone()
95     }
96 
set_private_fields(&self, fields: Arc<dyn TtyCorePrivateField>)97     pub fn set_private_fields(&self, fields: Arc<dyn TtyCorePrivateField>) {
98         *self.core.privete_fields.lock() = Some(fields);
99     }
100 
101     #[inline]
ldisc(&self) -> Arc<dyn TtyLineDiscipline>102     pub fn ldisc(&self) -> Arc<dyn TtyLineDiscipline> {
103         self.line_discipline.clone()
104     }
105 
write_to_core(&self, buf: &[u8], nr: usize) -> Result<usize, SystemError>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 
reopen(&self) -> Result<(), SystemError>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]
set_port(&self, port: Arc<dyn TtyPort>)135     pub fn set_port(&self, port: Arc<dyn TtyPort>) {
136         *self.core.port.write() = Some(port);
137     }
138 
tty_start(&self)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 
tty_stop(&self)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 
tty_wakeup(&self)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 
tty_mode_ioctl(tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<usize, SystemError>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 
core_set_termios( tty: Arc<TtyCore>, arg: VirtAddr, opt: TtySetTermiosOpt, ) -> Result<usize, SystemError>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 
set_termios_next(tty: Arc<TtyCore>, new_termios: Termios) -> Result<(), SystemError>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 
tty_do_resize(&self, windowsize: WindowSize) -> Result<(), SystemError>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]
driver(&self) -> &Arc<TtyDriver>337     pub fn driver(&self) -> &Arc<TtyDriver> {
338         &self.tty_driver
339     }
340 
341     #[inline]
flow_irqsave(&self) -> SpinLockGuard<TtyFlowState>342     pub fn flow_irqsave(&self) -> SpinLockGuard<TtyFlowState> {
343         self.flow.lock_irqsave()
344     }
345 
346     #[inline]
port(&self) -> Option<Arc<dyn TtyPort>>347     pub fn port(&self) -> Option<Arc<dyn TtyPort>> {
348         self.port.read().clone()
349     }
350 
351     #[inline]
index(&self) -> usize352     pub fn index(&self) -> usize {
353         self.index
354     }
355 
356     #[inline]
name(&self) -> &String357     pub fn name(&self) -> &String {
358         &self.name
359     }
360 
device_number(&self) -> &DeviceNumber361     pub fn device_number(&self) -> &DeviceNumber {
362         &self.device_number
363     }
364 
365     #[inline]
flags(&self) -> TtyFlag366     pub fn flags(&self) -> TtyFlag {
367         *self.flags.read_irqsave()
368     }
369 
370     #[inline]
flags_write(&self) -> RwLockWriteGuard<'_, TtyFlag>371     pub fn flags_write(&self) -> RwLockWriteGuard<'_, TtyFlag> {
372         self.flags.write_irqsave()
373     }
374 
375     #[inline]
termios(&self) -> RwLockReadGuard<'_, Termios>376     pub fn termios(&self) -> RwLockReadGuard<'_, Termios> {
377         self.termios.read_irqsave()
378     }
379 
380     #[inline]
termios_write(&self) -> RwLockWriteGuard<Termios>381     pub fn termios_write(&self) -> RwLockWriteGuard<Termios> {
382         self.termios.write_irqsave()
383     }
384 
385     #[inline]
set_termios(&self, termios: Termios)386     pub fn set_termios(&self, termios: Termios) {
387         let mut termios_guard = self.termios_write();
388         *termios_guard = termios;
389     }
390 
391     #[inline]
count(&self) -> usize392     pub fn count(&self) -> usize {
393         self.count.load(Ordering::SeqCst)
394     }
395 
396     #[inline]
add_count(&self)397     pub fn add_count(&self) {
398         self.count
399             .fetch_add(1, core::sync::atomic::Ordering::SeqCst);
400     }
401 
402     #[inline]
read_wq(&self) -> &EventWaitQueue403     pub fn read_wq(&self) -> &EventWaitQueue {
404         &self.read_wq
405     }
406 
407     #[inline]
write_wq(&self) -> &EventWaitQueue408     pub fn write_wq(&self) -> &EventWaitQueue {
409         &self.write_wq
410     }
411 
412     #[inline]
contorl_info_irqsave(&self) -> SpinLockGuard<TtyContorlInfo>413     pub fn contorl_info_irqsave(&self) -> SpinLockGuard<TtyContorlInfo> {
414         self.ctrl.lock_irqsave()
415     }
416 
417     #[inline]
window_size_upgradeable(&self) -> RwLockUpgradableGuard<WindowSize>418     pub fn window_size_upgradeable(&self) -> RwLockUpgradableGuard<WindowSize> {
419         self.window_size.upgradeable_read()
420     }
421 
422     #[inline]
window_size(&self) -> RwLockReadGuard<WindowSize>423     pub fn window_size(&self) -> RwLockReadGuard<WindowSize> {
424         self.window_size.read()
425     }
426 
427     #[inline]
window_size_write(&self) -> RwLockWriteGuard<WindowSize>428     pub fn window_size_write(&self) -> RwLockWriteGuard<WindowSize> {
429         self.window_size.write()
430     }
431 
432     #[inline]
is_closing(&self) -> bool433     pub fn is_closing(&self) -> bool {
434         self.closing.load(core::sync::atomic::Ordering::SeqCst)
435     }
436 
437     #[inline]
vc_data(&self) -> Option<Arc<SpinLock<VirtualConsoleData>>>438     pub fn vc_data(&self) -> Option<Arc<SpinLock<VirtualConsoleData>>> {
439         vc_manager().get(self.vc_index()?).unwrap().vc_data()
440     }
441 
set_vc_index(&self, index: usize)442     pub fn set_vc_index(&self, index: usize) {
443         self.vc_index.store(index, Ordering::SeqCst);
444     }
445 
vc_index(&self) -> Option<usize>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]
link(&self) -> Option<Arc<TtyCore>>455     pub fn link(&self) -> Option<Arc<TtyCore>> {
456         self.link.read().upgrade()
457     }
458 
checked_link(&self) -> Result<Arc<TtyCore>, SystemError>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 
set_link(&self, link: Weak<TtyCore>)466     pub fn set_link(&self, link: Weak<TtyCore>) {
467         *self.link.write() = link;
468     }
469 
init_termios(&self)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]
add_epitem(&self, epitem: Arc<EPollItem>)489     pub fn add_epitem(&self, epitem: Arc<EPollItem>) {
490         self.epitems.lock().push_back(epitem)
491     }
492 
eptiems(&self) -> &SpinLock<LinkedList<Arc<EPollItem>>>493     pub fn eptiems(&self) -> &SpinLock<LinkedList<Arc<EPollItem>>> {
494         &self.epitems
495     }
496 
do_write(&self, buf: &[u8], mut nr: usize) -> Result<usize, SystemError>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]
open(&self, tty: &TtyCoreData) -> Result<(), SystemError>551     fn open(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
552         return self.core().tty_driver.driver_funcs().open(tty);
553     }
554 
555     #[inline]
write_room(&self, tty: &TtyCoreData) -> usize556     fn write_room(&self, tty: &TtyCoreData) -> usize {
557         return self.core().tty_driver.driver_funcs().write_room(tty);
558     }
559 
560     #[inline]
write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError>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]
flush_chars(&self, tty: &TtyCoreData)566     fn flush_chars(&self, tty: &TtyCoreData) {
567         self.core().tty_driver.driver_funcs().flush_chars(tty);
568     }
569 
570     #[inline]
put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError>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]
install(&self, driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError>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]
start(&self, tty: &TtyCoreData) -> Result<(), SystemError>581     fn start(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
582         return self.core().tty_driver.driver_funcs().start(tty);
583     }
584 
585     #[inline]
stop(&self, tty: &TtyCoreData) -> Result<(), SystemError>586     fn stop(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
587         return self.core().tty_driver.driver_funcs().stop(tty);
588     }
589 
590     #[inline]
ioctl(&self, tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<(), SystemError>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]
chars_in_buffer(&self) -> usize596     fn chars_in_buffer(&self) -> usize {
597         return self.core().tty_driver.driver_funcs().chars_in_buffer();
598     }
599 
600     #[inline]
set_termios(&self, tty: Arc<TtyCore>, old_termios: Termios) -> Result<(), SystemError>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 
close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError>609     fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError> {
610         self.core().tty_driver.driver_funcs().close(tty)
611     }
612 
resize(&self, tty: Arc<TtyCore>, winsize: WindowSize) -> Result<(), SystemError>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 {
from_u8(num: u8) -> EchoOperation675     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 
to_u8(&self) -> u8685     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