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