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