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