xref: /DragonOS/kernel/src/driver/tty/mod.rs (revision c75ef4e2126c180bf04c08635ffa5a278619c035)
1 use core::intrinsics::unlikely;
2 
3 use alloc::string::String;
4 
5 use kdepends::thingbuf::mpsc::{
6     self,
7     errors::{TryRecvError, TrySendError},
8 };
9 
10 use crate::libs::rwlock::RwLock;
11 
12 pub mod init;
13 pub mod serial;
14 pub mod tty_device;
15 pub mod tty_driver;
16 pub mod vt;
17 
18 bitflags! {
19     pub struct TtyCoreState: u32{
20         /// 在读取stdin缓冲区时,由于队列为空,有读者被阻塞
21         const BLOCK_AT_STDIN_READ = (1 << 0);
22         /// 开启输入回显。
23         const ECHO_ON = (1 << 1);
24     }
25 
26     #[derive(Default)]
27     pub struct TtyFileFlag:u32{
28         /// 当前文件是stdin文件
29         const STDIN = (1 << 0);
30         /// 当前文件是stdout文件
31         const STDOUT = (1 << 1);
32         /// 当前文件是stderr文件
33         const STDERR = (1 << 2);
34     }
35 }
36 
37 /// @brief tty文件的私有信息
38 #[derive(Debug, Default, Clone)]
39 pub struct TtyFilePrivateData {
40     flags: TtyFileFlag,
41 }
42 
43 /// @brief tty设备的核心功能结构体。在此结构体的基础上,衍生出TTY/PTY/PTS
44 ///
45 /// 每个TTY Core有5个端口:
46 /// - stdin:连接到一个活动进程的stdin文件描述符
47 /// - stdout:连接到多个进程的stdout文件描述符
48 /// - stderr:连接到多个进程的stdout文件描述符
49 /// - 输入端口:向tty设备输入数据的接口。输入到该接口的数据,将被导向stdin接口。
50 ///     如果开启了回显,那么,数据也将同时被导向输出端
51 /// - 输出端口:tty设备对外输出数据的端口。从stdout、stderr输入的数据,将会被导向此端口。
52 ///             此端口可以连接到屏幕、文件、或者是另一个tty core的输入端口。如果开启了
53 ///             输入数据回显,那么,输入端口的数据,将会被同时导向此端口,以及stdin端口
54 #[derive(Debug)]
55 struct TtyCore {
56     /// stdin的mpsc队列输入输出端
57     stdin_rx: mpsc::Receiver<u8>,
58     stdin_tx: mpsc::Sender<u8>,
59     /// 输出的mpsc队列输入输出端
60     output_rx: mpsc::Receiver<u8>,
61     output_tx: mpsc::Sender<u8>,
62     // 前台进程,以后改成前台进程组
63     // front_job: Option<Pid>,
64     /// tty核心的状态
65     state: RwLock<TtyCoreState>,
66 }
67 
68 #[derive(Debug)]
69 #[allow(dead_code)]
70 pub enum TtyError {
71     /// 缓冲区满,返回成功传送的字节数
72     BufferFull(usize),
73     /// 缓冲区空,返回成功传送的字节数
74     BufferEmpty(usize),
75     /// 设备已经被关闭
76     Closed,
77     /// End of file(已经读取的字符数,包含eof)
78     EOF(usize),
79     /// 接收到信号终止
80     Stopped(usize),
81     Unknown(String),
82 }
83 
84 impl TtyCore {
85     // 各个缓冲区的大小
86     pub const STDIN_BUF_SIZE: usize = 4096;
87     pub const OUTPUT_BUF_SIZE: usize = 4096;
88 
89     /// @brief 创建一个TTY核心组件
90     pub fn new() -> TtyCore {
91         let (stdin_tx, stdin_rx) = mpsc::channel::<u8>(Self::STDIN_BUF_SIZE);
92         let (output_tx, output_rx) = mpsc::channel::<u8>(Self::OUTPUT_BUF_SIZE);
93         let state: RwLock<TtyCoreState> = RwLock::new(TtyCoreState { bits: 0 });
94 
95         return TtyCore {
96             stdin_rx,
97             stdin_tx,
98             output_rx,
99             output_tx,
100             state,
101         };
102     }
103 
104     /// @brief 向tty的输入端口输入数据
105     ///
106     /// @param buf 输入数据
107     ///
108     /// @param block 是否允许阻塞
109     ///
110     /// @return Ok(成功传送的字节数)
111     /// @return Err(TtyError) 内部错误信息
112     pub fn input(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> {
113         let val = self.write_stdin(buf, block)?;
114         // 如果开启了输入回显,那么就写一份到输出缓冲区
115         if self.echo_enabled() {
116             self.write_output(&buf[0..val], true)?;
117         }
118         return Ok(val);
119     }
120 
121     /// @brief 从tty的输出端口读出数据
122     ///
123     /// @param buf 输出缓冲区
124     ///
125     /// @return Ok(成功传送的字节数)
126     /// @return Err(TtyError) 内部错误信息
127     #[inline]
128     pub fn output(&self, buf: &mut [u8], block: bool) -> Result<usize, TtyError> {
129         return self.read_output(buf, block);
130     }
131 
132     /// @brief tty的stdout接口
133     ///
134     /// @param buf 输入缓冲区
135     ///
136     /// @return Ok(成功传送的字节数)
137     /// @return Err(TtyError) 内部错误信息
138     #[inline]
139     pub fn stdout(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> {
140         return self.write_output(buf, block);
141     }
142 
143     /// @brief tty的stderr接口
144     ///
145     /// @param buf 输入缓冲区
146     ///
147     /// @return Ok(成功传送的字节数)
148     /// @return Err(TtyError) 内部错误信息
149     #[inline]
150     pub fn stderr(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> {
151         return self.write_output(buf, block);
152     }
153 
154     /// @brief 读取TTY的stdin缓冲区
155     ///
156     /// @param buf 读取到的位置
157     /// @param block 是否阻塞读
158     ///
159     /// @return Ok(成功读取的字节数)
160     /// @return Err(TtyError) 内部错误信息
161     pub fn read_stdin(&self, buf: &mut [u8], block: bool) -> Result<usize, TtyError> {
162         // TODO: 增加对EOF的处理
163         let mut cnt = 0;
164         while cnt < buf.len() {
165             let val: Result<mpsc::RecvRef<u8>, TryRecvError> = self.stdin_rx.try_recv_ref();
166             if let Err(err) = val {
167                 match err {
168                     TryRecvError::Closed => return Err(TtyError::Closed),
169                     TryRecvError::Empty => {
170                         if block {
171                             continue;
172                         } else {
173                             return Ok(cnt);
174                         }
175                     }
176                     _ => return Err(TtyError::Unknown(format!("{err:?}"))),
177                 }
178             } else {
179                 let x = *val.unwrap();
180                 buf[cnt] = x;
181                 cnt += 1;
182 
183                 if unlikely(self.stdin_should_return(x)) {
184                     return Ok(cnt);
185                 }
186             }
187         }
188         return Ok(cnt);
189     }
190 
191     fn stdin_should_return(&self, c: u8) -> bool {
192         // 如果是换行符或者是ctrl+d,那么就应该返回
193         return c == b'\n' || c == 4;
194     }
195 
196     /// @brief 向stdin缓冲区内写入数据
197     ///
198     /// @param buf 输入缓冲区
199     ///
200     /// @param block 当缓冲区满的时候,是否阻塞
201     ///
202     /// @return Ok(成功传送的字节数)
203     /// @return Err(BufferFull(成功传送的字节数)) 缓冲区满,成功传送的字节数
204     /// @return Err(TtyError) 内部错误信息
205     fn write_stdin(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> {
206         let mut cnt = 0;
207         while cnt < buf.len() {
208             let r: Result<mpsc::SendRef<u8>, TrySendError> = self.stdin_tx.try_send_ref();
209             if let Err(e) = r {
210                 match e {
211                     TrySendError::Closed(_) => return Err(TtyError::Closed),
212                     TrySendError::Full(_) => {
213                         if block {
214                             continue;
215                         } else {
216                             return Err(TtyError::BufferFull(cnt));
217                         }
218                     }
219                     _ => return Err(TtyError::Unknown(format!("{e:?}"))),
220                 }
221             } else {
222                 *r.unwrap() = buf[cnt];
223                 cnt += 1;
224             }
225         }
226 
227         return Ok(cnt);
228     }
229 
230     /// @brief 读取TTY的output缓冲区
231     ///
232     /// @param buf 读取到的位置
233     /// @param block 是否阻塞读
234     ///
235     /// @return Ok(成功读取的字节数)
236     /// @return Err(TtyError) 内部错误信息
237     fn read_output(&self, buf: &mut [u8], block: bool) -> Result<usize, TtyError> {
238         let mut cnt = 0;
239         while cnt < buf.len() {
240             let val: Result<mpsc::RecvRef<u8>, TryRecvError> = self.output_rx.try_recv_ref();
241             if let Err(err) = val {
242                 match err {
243                     TryRecvError::Closed => return Err(TtyError::Closed),
244                     TryRecvError::Empty => {
245                         if block {
246                             continue;
247                         } else {
248                             return Ok(cnt);
249                         }
250                     }
251                     _ => return Err(TtyError::Unknown(format!("{err:?}"))),
252                 }
253             } else {
254                 buf[cnt] = *val.unwrap();
255                 cnt += 1;
256             }
257         }
258         return Ok(cnt);
259     }
260 
261     /// @brief 向output缓冲区内写入数据
262     ///
263     /// @param buf 输入缓冲区
264     ///
265     /// @param block 当缓冲区满的时候,是否阻塞
266     ///
267     /// @return Ok(成功传送的字节数)
268     /// @return Err(BufferFull(成功传送的字节数)) 缓冲区满,成功传送的字节数
269     /// @return Err(TtyError) 内部错误信息
270     fn write_output(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> {
271         let mut cnt = 0;
272         while cnt < buf.len() {
273             let r: Result<mpsc::SendRef<u8>, TrySendError> = self.output_tx.try_send_ref();
274             if let Err(e) = r {
275                 match e {
276                     TrySendError::Closed(_) => return Err(TtyError::Closed),
277                     TrySendError::Full(_) => {
278                         if block {
279                             continue;
280                         } else {
281                             return Err(TtyError::BufferFull(cnt));
282                         }
283                     }
284                     _ => return Err(TtyError::Unknown(format!("{e:?}"))),
285                 }
286             } else {
287                 // TODO: 在这里考虑增加对信号发送的处理
288                 // if buf[cnt] == 3 {
289                 //     let pid = ProcessManager::current_pcb().pid();
290                 //     Signal::SIGKILL.send_signal_info(
291                 //         Some(&mut SigInfo::new(
292                 //             Signal::SIGKILL,
293                 //             0,
294                 //             SigCode::SI_USER,
295                 //             SigType::Kill(pid),
296                 //         )),
297                 //         pid,
298                 //     );
299                 //     return Err(TtyError::Stopped(cnt));
300                 // }
301                 *r.unwrap() = buf[cnt];
302                 cnt += 1;
303             }
304         }
305         return Ok(cnt);
306     }
307 
308     /// @brief 开启tty输入回显(也就是将输入数据传送一份到输出缓冲区)
309     #[inline]
310     pub fn enable_echo(&self) {
311         self.state.write().set(TtyCoreState::ECHO_ON, true);
312     }
313 
314     /// @brief 关闭输入回显
315     #[inline]
316     #[allow(dead_code)]
317     pub fn disable_echo(&self) {
318         self.state.write().set(TtyCoreState::ECHO_ON, false);
319     }
320 
321     /// @brief 判断当前tty核心,是否开启了输入回显
322     ///
323     /// @return true 开启了输入回显
324     ///
325     /// @return false 未开启输入回显
326     #[inline]
327     #[allow(dead_code)]
328     pub fn echo_enabled(&self) -> bool {
329         return self.state.read().contains(TtyCoreState::ECHO_ON);
330     }
331 }
332 
333 // ======= 以下代码考虑了“缓冲区满,然后睡眠,当缓冲区有空位就唤醒”的逻辑。
334 // 但是由于在开发过程中的调整,并且由于数据结构发生变化,因此暂时不实现上述优化,因此先注释。
335 //
336 // @brief 读取TTY的stdin缓冲区
337 //
338 // @param buf 读取到的位置
339 // @param block 是否阻塞读
340 //
341 // @return Ok(成功读取的字节数)
342 // @return Err(TtyError) 内部错误信息
343 // pub fn read_stdin(&mut self, buf: &mut [u8], block: bool) -> Result<usize, TtyError> {
344 //     let mut cnt = 0;
345 //     loop{
346 //         if cnt == buf.len(){
347 //             break;
348 //         }
349 //         let val:Option<u8> = self.stdin_queue.dequeue();
350 //         // 如果没读到
351 //         if val.is_none() {
352 //             // 如果阻塞读
353 //             if block {
354 //                 let state_guard: RwLockUpgradableGuard<TtyCoreState> =
355 //                     self.state.upgradeable_read();
356 //                 // 判断是否有进程正在stdin上睡眠,如果有,则忙等读
357 //                 // 理论上,这种情况应该不存在,因为stdin是单读者的
358 //                 if state_guard.contains(TtyCoreState::BLOCK_AT_STDIN_READ) {
359 //                     kwarn!("Read stdin: Process {} want to read its' stdin, but previous process {} is sleeping on the stdin.", current_pcb().pid, self.stdin_waiter.read().as_ref().unwrap().pid);
360 //                     drop(state_guard);
361 //                     Self::ringbuf_spin_dequeue(&mut buf[cnt], &mut self.stdin_queue);
362 //                     cnt += 1;
363 //                 } else {
364 //                     // 正常情况,阻塞读,将当前进程休眠
365 //                     let mut state_guard: RwLockWriteGuard<TtyCoreState> = state_guard.upgrade();
366 //                     let mut stdin_waiter_guard: RwLockWriteGuard<
367 //                         Option<&mut process_control_block>,
368 //                     > = self.stdin_waiter.write();
369 
370 //                     // 由于输入数据到stdin的时候,必须先获得state guard的读锁。而这里我们已经获取了state的写锁。
371 //                     // 因此可以保证,此时没有新的数据会进入stdin_queue. 因此再次尝试读取stdin_queue
372 //                     let val:Option<u8> = self.stdin_queue.dequeue();
373 //                     // 读到数据,不用睡眠
374 //                     if val.is_some(){
375 //                         buf[cnt] = val.unwrap();
376 //                         cnt += 1;
377 //                         continue;
378 //                     }
379 //                     // 没读到数据,准备睡眠
380 
381 //                     // 设置等待标志位
382 //                     state_guard.set(TtyCoreState::BLOCK_AT_STDIN_READ, true);
383 
384 //                     // 将当前进程标记为被其他机制管理
385 //                     unsafe {
386 //                         current_pcb().mark_sleep_interruptible();
387 //                     }
388 
389 //                     *stdin_waiter_guard = Some(current_pcb());
390 //                     drop(stdin_waiter_guard);
391 //                     drop(state_guard);
392 //                     sched();
393 //                     continue;
394 //                 }
395 //             } else {
396 //                 // 非阻塞读,没读到就直接返回了
397 //                 return Ok(cnt);
398 //             }
399 //         }else{
400 //             buf[cnt] = val.unwrap();
401 //             cnt += 1;
402 //         }
403 //     }
404 
405 //     return Ok(cnt);
406 // }
407 
408 // fn write_stdin(&self)
409 
410 // /// @brief 非休眠的,自旋地读队列,直到有元素被读出来
411 // fn ringbuf_spin_dequeue(dst: &mut u8, queue: &mut AllocRingBuffer<u8>) {
412 //     loop {
413 //         if let Some(val) = queue.dequeue() {
414 //             *dst = val;
415 //             return;
416 //         }
417 //     }
418 // }
419