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