1 use alloc::sync::{Arc, Weak}; 2 3 use crate::{ 4 filesystem::{ 5 devfs::{DeviceINode, DevFS}, 6 vfs::{file::FileMode, FilePrivateData, IndexNode}, 7 }, 8 include::bindings::bindings::{ECONNABORTED, EIO, ENOTSUP, EPERM}, 9 kerror, libs::rwlock::RwLock, 10 }; 11 12 use super::{TtyCore, TtyError, TtyFileFlag, TtyFilePrivateData}; 13 14 #[derive(Debug)] 15 pub struct TtyDevice { 16 core: TtyCore, 17 fs: RwLock<Weak<DevFS>> 18 19 } 20 21 impl TtyDevice { 22 pub fn new() -> Arc<TtyDevice> { 23 return Arc::new(TtyDevice { 24 core: TtyCore::new(), 25 fs: RwLock::new(Weak::default()), 26 }); 27 } 28 29 /// @brief 判断文件私有信息是否为TTY的私有信息 30 #[inline] 31 fn verify_file_private_data<'a>( 32 &self, 33 private_data: &'a mut FilePrivateData, 34 ) -> Result<&'a mut TtyFilePrivateData, i32> { 35 if let FilePrivateData::Tty(t) = private_data { 36 return Ok(t); 37 } 38 return Err(-(EIO as i32)); 39 } 40 } 41 42 impl DeviceINode for TtyDevice { 43 fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) { 44 *self.fs.write() = fs; 45 } 46 } 47 48 impl IndexNode for TtyDevice { 49 fn open(&self, data: &mut FilePrivateData, mode: &FileMode) -> Result<(), i32> { 50 let p = TtyFilePrivateData::default(); 51 *data = FilePrivateData::Tty(p); 52 return Ok(()); 53 } 54 55 fn read_at( 56 &self, 57 offset: usize, 58 len: usize, 59 buf: &mut [u8], 60 data: &mut crate::filesystem::vfs::FilePrivateData, 61 ) -> Result<usize, i32> { 62 let _data: &mut TtyFilePrivateData = match self.verify_file_private_data(data) { 63 Ok(t) => t, 64 Err(e) => { 65 kerror!("Try to read tty device, but file private data type mismatch!"); 66 return Err(e); 67 } 68 }; 69 70 // 读取stdin队列 71 let r: Result<usize, TtyError> = self.core.read_stdin(buf, true); 72 if r.is_ok() { 73 return Ok(r.unwrap()); 74 } 75 76 match r.unwrap_err() { 77 TtyError::EOF(n) => { 78 return Ok(n); 79 } 80 x => { 81 kerror!("Error occurred when reading tty, msg={x:?}"); 82 return Err(-(ECONNABORTED as i32)); 83 } 84 } 85 } 86 87 fn write_at( 88 &self, 89 offset: usize, 90 len: usize, 91 buf: &[u8], 92 data: &mut crate::filesystem::vfs::FilePrivateData, 93 ) -> Result<usize, i32> { 94 let data: &mut TtyFilePrivateData = match self.verify_file_private_data(data) { 95 Ok(t) => t, 96 Err(e) => { 97 kerror!("Try to write tty device, but file private data type mismatch!"); 98 return Err(e); 99 } 100 }; 101 102 // 根据当前文件是stdout还是stderr,选择不同的发送方式 103 let r: Result<usize, TtyError> = if data.flags.contains(TtyFileFlag::STDOUT) { 104 self.core.stdout(buf, true) 105 } else if data.flags.contains(TtyFileFlag::STDERR) { 106 self.core.stderr(buf, true) 107 } else { 108 return Err(-(EPERM as i32)); 109 }; 110 111 if r.is_ok() { 112 return Ok(r.unwrap()); 113 } 114 115 let r: TtyError = r.unwrap_err(); 116 kerror!("Error occurred when writing tty deivce. Error msg={r:?}"); 117 return Err(-(EIO as i32)); 118 } 119 120 fn poll(&self) -> Result<crate::filesystem::vfs::PollStatus, i32> { 121 return Err(-(ENOTSUP as i32)); 122 } 123 124 fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> { 125 return self.fs.read().upgrade().unwrap(); 126 } 127 128 fn as_any_ref(&self) -> &dyn core::any::Any { 129 self 130 } 131 132 fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, i32> { 133 return Err(-(ENOTSUP as i32)); 134 } 135 } 136