tty_device.rs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. use alloc::{
  2. collections::BTreeMap,
  3. string::{String, ToString},
  4. sync::{Arc, Weak},
  5. };
  6. use crate::{
  7. filesystem::{
  8. devfs::{devfs_register, DevFS, DeviceINode},
  9. vfs::{file::FileMode, FilePrivateData, FileType, IndexNode, Metadata, ROOT_INODE},
  10. },
  11. include::bindings::bindings::{textui_putchar, BLACK, WHITE},
  12. kerror,
  13. libs::rwlock::RwLock,
  14. syscall::SystemError,
  15. };
  16. use super::{TtyCore, TtyError, TtyFileFlag, TtyFilePrivateData};
  17. lazy_static! {
  18. /// 所有TTY设备的B树。用于根据名字,找到Arc<TtyDevice>
  19. /// TODO: 待设备驱动模型完善,具有类似功能的机制后,删掉这里
  20. pub static ref TTY_DEVICES: RwLock<BTreeMap<String, Arc<TtyDevice>>> = RwLock::new(BTreeMap::new());
  21. }
  22. /// @brief TTY设备
  23. #[derive(Debug)]
  24. pub struct TtyDevice {
  25. /// TTY核心
  26. core: TtyCore,
  27. /// TTY所属的文件系统
  28. fs: RwLock<Weak<DevFS>>,
  29. /// TTY设备私有信息
  30. private_data: RwLock<TtyDevicePrivateData>,
  31. }
  32. #[derive(Debug)]
  33. struct TtyDevicePrivateData {
  34. /// TTY设备名(如tty1)
  35. name: String,
  36. /// TTY设备文件的元数据
  37. metadata: Metadata,
  38. // TODO: 增加指向输出端口连接的设备的指针
  39. }
  40. impl TtyDevice {
  41. pub fn new(name: &str) -> Arc<TtyDevice> {
  42. let result = Arc::new(TtyDevice {
  43. core: TtyCore::new(),
  44. fs: RwLock::new(Weak::default()),
  45. private_data: TtyDevicePrivateData::new(name),
  46. });
  47. // 默认开启输入回显
  48. result.core.enable_echo();
  49. return result;
  50. }
  51. /// @brief 判断文件私有信息是否为TTY文件的私有信息
  52. #[inline]
  53. fn verify_file_private_data<'a>(
  54. &self,
  55. private_data: &'a mut FilePrivateData,
  56. ) -> Result<&'a mut TtyFilePrivateData, SystemError> {
  57. if let FilePrivateData::Tty(t) = private_data {
  58. return Ok(t);
  59. }
  60. return Err(SystemError::EIO);
  61. }
  62. /// @brief 获取TTY设备名
  63. #[inline]
  64. pub fn name(&self) -> String {
  65. return self.private_data.read().name.clone();
  66. }
  67. /// @brief 检查TTY文件的读写参数是否合法
  68. #[inline]
  69. pub fn check_rw_param(&self, len: usize, buf: &[u8]) -> Result<(), SystemError> {
  70. if len > buf.len() {
  71. return Err(SystemError::EINVAL);
  72. }
  73. return Ok(());
  74. }
  75. /// @brief 向TTY的输入端口导入数据
  76. pub fn input(&self, buf: &[u8]) -> Result<usize, SystemError> {
  77. let r: Result<usize, TtyError> = self.core.input(buf, false);
  78. if r.is_ok() {
  79. return Ok(r.unwrap());
  80. }
  81. let r = r.unwrap_err();
  82. match r {
  83. TtyError::BufferFull(x) => return Ok(x),
  84. TtyError::Closed => return Err(SystemError::ENODEV),
  85. e => {
  86. kerror!("tty error occurred while writing data to its input port, msg={e:?}");
  87. return Err(SystemError::EBUSY);
  88. }
  89. }
  90. }
  91. }
  92. impl DeviceINode for TtyDevice {
  93. fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) {
  94. *self.fs.write() = fs;
  95. }
  96. }
  97. impl IndexNode for TtyDevice {
  98. /// @brief 打开TTY设备
  99. ///
  100. /// @param data 文件私有信息
  101. /// @param mode 打开模式
  102. ///
  103. /// TTY设备通过mode来确定这个文件到底是stdin/stdout/stderr
  104. /// - mode的值为O_RDONLY时,表示这个文件是stdin
  105. /// - mode的值为O_WRONLY时,表示这个文件是stdout
  106. /// - mode的值为O_WRONLY | O_SYNC时,表示这个文件是stderr
  107. fn open(&self, data: &mut FilePrivateData, mode: &FileMode) -> Result<(), SystemError> {
  108. let mut p = TtyFilePrivateData::default();
  109. // 检查打开模式
  110. let accmode = mode.accmode();
  111. if accmode == FileMode::O_RDONLY.accmode() {
  112. p.flags.insert(TtyFileFlag::STDIN);
  113. } else if accmode == FileMode::O_WRONLY.accmode() {
  114. if mode.contains(FileMode::O_SYNC) {
  115. p.flags.insert(TtyFileFlag::STDERR);
  116. } else {
  117. p.flags.insert(TtyFileFlag::STDOUT);
  118. }
  119. } else {
  120. return Err(SystemError::EINVAL);
  121. }
  122. // 保存文件私有信息
  123. *data = FilePrivateData::Tty(p);
  124. return Ok(());
  125. }
  126. fn read_at(
  127. &self,
  128. _offset: usize,
  129. len: usize,
  130. buf: &mut [u8],
  131. data: &mut crate::filesystem::vfs::FilePrivateData,
  132. ) -> Result<usize, SystemError> {
  133. let _data: &mut TtyFilePrivateData = match self.verify_file_private_data(data) {
  134. Ok(t) => t,
  135. Err(e) => {
  136. kerror!("Try to read tty device, but file private data type mismatch!");
  137. return Err(e);
  138. }
  139. };
  140. self.check_rw_param(len, buf)?;
  141. // 读取stdin队列
  142. let r: Result<usize, TtyError> = self.core.read_stdin(&mut buf[0..len], true);
  143. if r.is_ok() {
  144. return Ok(r.unwrap());
  145. }
  146. match r.unwrap_err() {
  147. TtyError::EOF(n) => {
  148. return Ok(n);
  149. }
  150. x => {
  151. kerror!("Error occurred when reading tty, msg={x:?}");
  152. return Err(SystemError::ECONNABORTED);
  153. }
  154. }
  155. }
  156. fn write_at(
  157. &self,
  158. _offset: usize,
  159. len: usize,
  160. buf: &[u8],
  161. data: &mut crate::filesystem::vfs::FilePrivateData,
  162. ) -> Result<usize, SystemError> {
  163. let data: &mut TtyFilePrivateData = match self.verify_file_private_data(data) {
  164. Ok(t) => t,
  165. Err(e) => {
  166. kerror!("Try to write tty device, but file private data type mismatch!");
  167. return Err(e);
  168. }
  169. };
  170. self.check_rw_param(len, buf)?;
  171. // 根据当前文件是stdout还是stderr,选择不同的发送方式
  172. let r: Result<usize, TtyError> = if data.flags.contains(TtyFileFlag::STDOUT) {
  173. self.core.stdout(&buf[0..len], true)
  174. } else if data.flags.contains(TtyFileFlag::STDERR) {
  175. self.core.stderr(&buf[0..len], true)
  176. } else {
  177. return Err(SystemError::EPERM);
  178. };
  179. if r.is_ok() {
  180. self.sync().expect("Failed to sync tty device!");
  181. return Ok(r.unwrap());
  182. }
  183. let r: TtyError = r.unwrap_err();
  184. kerror!("Error occurred when writing tty deivce. Error msg={r:?}");
  185. return Err(SystemError::EIO);
  186. }
  187. fn poll(&self) -> Result<crate::filesystem::vfs::PollStatus, SystemError> {
  188. return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
  189. }
  190. fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
  191. return self.fs.read().upgrade().unwrap();
  192. }
  193. fn as_any_ref(&self) -> &dyn core::any::Any {
  194. self
  195. }
  196. fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> {
  197. return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
  198. }
  199. fn metadata(&self) -> Result<Metadata, SystemError> {
  200. return Ok(self.private_data.read().metadata.clone());
  201. }
  202. fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
  203. return Ok(());
  204. }
  205. fn sync(&self) -> Result<(), SystemError> {
  206. // TODO: 引入IO重定向后,需要将输出重定向到对应的设备。
  207. // 目前只是简单的输出到屏幕(为了实现的简便)
  208. loop {
  209. let mut buf = [0u8; 512];
  210. let r: Result<usize, TtyError> = self.core.output(&mut buf[0..511], false);
  211. let len;
  212. match r {
  213. Ok(x) => {
  214. len = x;
  215. }
  216. Err(TtyError::EOF(x)) | Err(TtyError::BufferEmpty(x)) => {
  217. len = x;
  218. }
  219. _ => return Err(SystemError::EIO),
  220. }
  221. if len == 0 {
  222. break;
  223. }
  224. // 输出到屏幕
  225. unsafe {
  226. for x in buf {
  227. textui_putchar(x as u16, WHITE, BLACK);
  228. }
  229. }
  230. }
  231. return Ok(());
  232. }
  233. }
  234. impl TtyDevicePrivateData {
  235. pub fn new(name: &str) -> RwLock<Self> {
  236. let mut metadata = Metadata::new(FileType::CharDevice, 0o755);
  237. metadata.size = TtyCore::STDIN_BUF_SIZE as i64;
  238. return RwLock::new(TtyDevicePrivateData {
  239. name: name.to_string(),
  240. metadata,
  241. });
  242. }
  243. }
  244. /// @brief 导出到C的tty初始化函数
  245. #[no_mangle]
  246. pub extern "C" fn rs_tty_init() -> i32 {
  247. let r = tty_init();
  248. if r.is_ok() {
  249. return 0;
  250. } else {
  251. return r.unwrap_err().to_posix_errno();
  252. }
  253. }
  254. /// @brief 初始化TTY设备
  255. pub fn tty_init() -> Result<(), SystemError> {
  256. let tty: Arc<TtyDevice> = TtyDevice::new("tty0");
  257. let devfs_root_inode = ROOT_INODE().lookup("/dev");
  258. if devfs_root_inode.is_err() {
  259. return Err(devfs_root_inode.unwrap_err());
  260. }
  261. // 当前关闭键盘输入回显
  262. // TODO: 完善Termios之后, 改为默认开启键盘输入回显.
  263. tty.core.disable_echo();
  264. let guard = TTY_DEVICES.upgradeable_read();
  265. // 如果已经存在了这个设备
  266. if guard.contains_key("tty0") {
  267. return Err(SystemError::EEXIST);
  268. }
  269. let mut guard = guard.upgrade();
  270. guard.insert("tty0".to_string(), tty.clone());
  271. drop(guard);
  272. let r = devfs_register(&tty.name(), tty);
  273. if r.is_err() {
  274. return Err(devfs_root_inode.unwrap_err());
  275. }
  276. return Ok(());
  277. }