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