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