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