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