xref: /DragonOS/kernel/src/driver/tty/tty_device.rs (revision 52da9a59374752b4d01907b052135a0d317781dd)
1 use alloc::{
2     string::{String, ToString},
3     sync::{Arc, Weak},
4 };
5 use system_error::SystemError;
6 use unified_init::macros::unified_init;
7 
8 use crate::{
9     arch::ipc::signal::Signal,
10     driver::{
11         base::{
12             char::CharDevice,
13             device::{
14                 bus::Bus,
15                 device_number::{DeviceNumber, Major},
16                 device_register,
17                 driver::Driver,
18                 Device, DeviceKObjType, DeviceType, IdTable,
19             },
20             kobject::{KObject, LockedKObjectState},
21             kset::KSet,
22         },
23         serial::serial_init,
24     },
25     filesystem::{
26         devfs::{devfs_register, DevFS, DeviceINode},
27         kernfs::KernFSInode,
28         vfs::{file::FileMode, syscall::ModeType, FilePrivateData, FileType, IndexNode, Metadata},
29     },
30     init::initcall::INITCALL_DEVICE,
31     libs::rwlock::RwLock,
32     mm::VirtAddr,
33     process::ProcessManager,
34     syscall::user_access::UserBufferWriter,
35 };
36 
37 use super::{
38     termios::WindowSize,
39     tty_core::{TtyCore, TtyFlag, TtyIoctlCmd},
40     tty_driver::{TtyDriver, TtyDriverSubType, TtyDriverType, TtyOperation},
41     tty_job_control::TtyJobCtrlManager,
42     virtual_terminal::vty_init,
43 };
44 
45 #[derive(Debug)]
46 pub struct InnerTtyDevice {
47     /// 当前设备所述的kset
48     kset: Option<Arc<KSet>>,
49     parent_kobj: Option<Weak<dyn KObject>>,
50     /// 当前设备所述的总线
51     bus: Option<Weak<dyn Bus>>,
52     inode: Option<Arc<KernFSInode>>,
53     driver: Option<Weak<dyn Driver>>,
54     can_match: bool,
55 
56     metadata: Metadata,
57 }
58 
59 impl InnerTtyDevice {
60     pub fn new() -> Self {
61         Self {
62             kset: None,
63             parent_kobj: None,
64             bus: None,
65             inode: None,
66             driver: None,
67             can_match: false,
68             metadata: Metadata::new(FileType::CharDevice, ModeType::from_bits_truncate(0o755)),
69         }
70     }
71 }
72 
73 #[derive(Debug)]
74 #[cast_to([sync] Device)]
75 pub struct TtyDevice {
76     name: &'static str,
77     id_table: IdTable,
78     inner: RwLock<InnerTtyDevice>,
79     kobj_state: LockedKObjectState,
80     /// TTY所属的文件系统
81     fs: RwLock<Weak<DevFS>>,
82 }
83 
84 impl TtyDevice {
85     pub fn new(name: &'static str, id_table: IdTable) -> Arc<TtyDevice> {
86         let dev_num = id_table.device_number();
87         let dev = TtyDevice {
88             name,
89             id_table,
90             inner: RwLock::new(InnerTtyDevice::new()),
91             kobj_state: LockedKObjectState::new(None),
92             fs: RwLock::new(Weak::default()),
93         };
94 
95         dev.inner.write().metadata.raw_dev = dev_num;
96 
97         Arc::new(dev)
98     }
99 }
100 
101 impl IndexNode for TtyDevice {
102     fn open(
103         &self,
104         data: &mut crate::filesystem::vfs::FilePrivateData,
105         mode: &crate::filesystem::vfs::file::FileMode,
106     ) -> Result<(), SystemError> {
107         let dev_num = self.metadata()?.raw_dev;
108 
109         let tty = TtyDriver::open_tty(dev_num)?;
110 
111         // 设置privdata
112         *data = FilePrivateData::Tty(TtyFilePrivateData {
113             tty: tty.clone(),
114             mode: *mode,
115         });
116 
117         let ret = tty.open(tty.core());
118         if ret.is_err() {
119             let err = ret.unwrap_err();
120             if err == SystemError::ENOSYS {
121                 return Err(SystemError::ENODEV);
122             }
123             return Err(err);
124         }
125 
126         let driver = tty.core().driver();
127         // 考虑noctty(当前tty)
128         if !(mode.contains(FileMode::O_NOCTTY) && dev_num == DeviceNumber::new(Major::TTY_MAJOR, 0)
129             || dev_num == DeviceNumber::new(Major::TTYAUX_MAJOR, 1)
130             || (driver.tty_driver_type() == TtyDriverType::Pty
131                 && driver.tty_driver_sub_type() == TtyDriverSubType::PtyMaster))
132         {
133             let pcb = ProcessManager::current_pcb();
134             let pcb_tty = pcb.sig_info().tty();
135             if pcb_tty.is_none() && tty.core().contorl_info_irqsave().session.is_none() {
136                 TtyJobCtrlManager::proc_set_tty(tty);
137             }
138         }
139 
140         Ok(())
141     }
142 
143     fn read_at(
144         &self,
145         _offset: usize,
146         len: usize,
147         buf: &mut [u8],
148         data: &mut crate::filesystem::vfs::FilePrivateData,
149     ) -> Result<usize, system_error::SystemError> {
150         let (tty, mode) = if let FilePrivateData::Tty(tty_priv) = data {
151             (tty_priv.tty.clone(), tty_priv.mode)
152         } else {
153             return Err(SystemError::EIO);
154         };
155 
156         let ld = tty.ldisc();
157         let mut offset = 0;
158         let mut cookie = false;
159         loop {
160             let mut size = if len > buf.len() { buf.len() } else { len };
161             size = ld.read(tty.clone(), buf, size, &mut cookie, offset, mode)?;
162             // 没有更多数据
163             if size == 0 {
164                 break;
165             }
166 
167             offset += size;
168 
169             // 缓冲区写满
170             if offset >= len {
171                 break;
172             }
173 
174             // 没有更多数据
175             if !cookie {
176                 break;
177             }
178         }
179 
180         return Ok(offset);
181     }
182 
183     fn write_at(
184         &self,
185         _offset: usize,
186         len: usize,
187         buf: &[u8],
188         data: &mut crate::filesystem::vfs::FilePrivateData,
189     ) -> Result<usize, system_error::SystemError> {
190         let mut count = len;
191         let (tty, mode) = if let FilePrivateData::Tty(tty_priv) = data {
192             (tty_priv.tty.clone(), tty_priv.mode)
193         } else {
194             return Err(SystemError::EIO);
195         };
196 
197         let ld = tty.ldisc();
198         let core = tty.core();
199         let mut chunk = 2048;
200         if core.flags().contains(TtyFlag::NO_WRITE_SPLIT) {
201             chunk = 65536;
202         }
203         chunk = chunk.min(count);
204 
205         let pcb = ProcessManager::current_pcb();
206         let mut written = 0;
207         loop {
208             // 至少需要写多少
209             let size = chunk.min(count);
210 
211             // 将数据从buf拷贝到writebuf
212 
213             let ret = ld.write(tty.clone(), buf, size, mode)?;
214 
215             written += ret;
216             count -= ret;
217 
218             if count == 0 {
219                 break;
220             }
221 
222             if pcb.sig_info().sig_pending().has_pending() {
223                 return Err(SystemError::ERESTARTSYS);
224             }
225         }
226 
227         if written > 0 {
228             // todo: 更新时间
229         }
230 
231         Ok(written)
232     }
233 
234     fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
235         todo!()
236     }
237 
238     fn as_any_ref(&self) -> &dyn core::any::Any {
239         todo!()
240     }
241 
242     fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, system_error::SystemError> {
243         todo!()
244     }
245 
246     fn metadata(&self) -> Result<crate::filesystem::vfs::Metadata, SystemError> {
247         Ok(self.inner.read().metadata.clone())
248     }
249 
250     fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
251         Ok(())
252     }
253 
254     fn resize(&self, _len: usize) -> Result<(), SystemError> {
255         Ok(())
256     }
257 
258     fn ioctl(&self, cmd: u32, arg: usize, data: &FilePrivateData) -> Result<usize, SystemError> {
259         let (tty, _) = if let FilePrivateData::Tty(tty_priv) = data {
260             (tty_priv.tty.clone(), tty_priv.mode)
261         } else {
262             return Err(SystemError::EIO);
263         };
264 
265         match cmd {
266             TtyIoctlCmd::TIOCSETD
267             | TtyIoctlCmd::TIOCSBRK
268             | TtyIoctlCmd::TIOCCBRK
269             | TtyIoctlCmd::TCSBRK
270             | TtyIoctlCmd::TCSBRKP => {
271                 TtyJobCtrlManager::tty_check_change(tty.clone(), Signal::SIGTTOU)?;
272                 if cmd != TtyIoctlCmd::TIOCCBRK {
273                     todo!()
274                 }
275             }
276             _ => {}
277         }
278 
279         match cmd {
280             TtyIoctlCmd::TIOCGWINSZ => {
281                 let core = tty.core();
282                 let winsize = *core.window_size();
283 
284                 let mut user_writer = UserBufferWriter::new(
285                     VirtAddr::new(arg).as_ptr::<WindowSize>(),
286                     core::mem::size_of::<WindowSize>(),
287                     true,
288                 )?;
289 
290                 let err = user_writer.copy_one_to_user(&winsize, 0);
291                 if err.is_err() {
292                     return Err(SystemError::EFAULT);
293                 }
294                 return Ok(0);
295             }
296             _ => match TtyJobCtrlManager::job_ctrl_ioctl(tty.clone(), cmd, arg) {
297                 Ok(_) => {
298                     return Ok(0);
299                 }
300                 Err(e) => {
301                     if e != SystemError::ENOIOCTLCMD {
302                         return Err(e);
303                     }
304                 }
305             },
306         }
307 
308         match tty.ioctl(tty.clone(), cmd, arg) {
309             Ok(_) => {
310                 return Ok(0);
311             }
312             Err(e) => {
313                 if e != SystemError::ENOIOCTLCMD {
314                     return Err(e);
315                 }
316             }
317         }
318         tty.ldisc().ioctl(tty, cmd, arg)?;
319 
320         Ok(0)
321     }
322 }
323 
324 impl DeviceINode for TtyDevice {
325     fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) {
326         *self.fs.write() = fs;
327     }
328 }
329 
330 impl KObject for TtyDevice {
331     fn as_any_ref(&self) -> &dyn core::any::Any {
332         self
333     }
334 
335     fn set_inode(&self, inode: Option<Arc<crate::filesystem::kernfs::KernFSInode>>) {
336         self.inner.write().inode = inode;
337     }
338 
339     fn inode(&self) -> Option<Arc<crate::filesystem::kernfs::KernFSInode>> {
340         self.inner.read().inode.clone()
341     }
342 
343     fn parent(&self) -> Option<alloc::sync::Weak<dyn KObject>> {
344         self.inner.read().parent_kobj.clone()
345     }
346 
347     fn set_parent(&self, parent: Option<alloc::sync::Weak<dyn KObject>>) {
348         self.inner.write().parent_kobj = parent
349     }
350 
351     fn kset(&self) -> Option<Arc<crate::driver::base::kset::KSet>> {
352         self.inner.read().kset.clone()
353     }
354 
355     fn set_kset(&self, kset: Option<Arc<crate::driver::base::kset::KSet>>) {
356         self.inner.write().kset = kset
357     }
358 
359     fn kobj_type(&self) -> Option<&'static dyn crate::driver::base::kobject::KObjType> {
360         Some(&DeviceKObjType)
361     }
362 
363     fn set_kobj_type(&self, _ktype: Option<&'static dyn crate::driver::base::kobject::KObjType>) {}
364 
365     fn name(&self) -> alloc::string::String {
366         self.name.to_string()
367     }
368 
369     fn set_name(&self, _name: alloc::string::String) {
370         // self.name = name
371     }
372 
373     fn kobj_state(
374         &self,
375     ) -> crate::libs::rwlock::RwLockReadGuard<crate::driver::base::kobject::KObjectState> {
376         self.kobj_state.read()
377     }
378 
379     fn kobj_state_mut(
380         &self,
381     ) -> crate::libs::rwlock::RwLockWriteGuard<crate::driver::base::kobject::KObjectState> {
382         self.kobj_state.write()
383     }
384 
385     fn set_kobj_state(&self, state: crate::driver::base::kobject::KObjectState) {
386         *self.kobj_state.write() = state
387     }
388 }
389 
390 impl Device for TtyDevice {
391     fn dev_type(&self) -> crate::driver::base::device::DeviceType {
392         DeviceType::Char
393     }
394 
395     fn id_table(&self) -> crate::driver::base::device::IdTable {
396         self.id_table.clone()
397     }
398 
399     fn set_bus(&self, bus: Option<alloc::sync::Weak<dyn crate::driver::base::device::bus::Bus>>) {
400         self.inner.write().bus = bus
401     }
402 
403     fn set_class(&self, _class: Option<Arc<dyn crate::driver::base::class::Class>>) {
404         todo!()
405     }
406 
407     fn driver(&self) -> Option<Arc<dyn crate::driver::base::device::driver::Driver>> {
408         self.inner.read().driver.clone()?.upgrade()
409     }
410 
411     fn set_driver(
412         &self,
413         driver: Option<alloc::sync::Weak<dyn crate::driver::base::device::driver::Driver>>,
414     ) {
415         self.inner.write().driver = driver
416     }
417 
418     fn is_dead(&self) -> bool {
419         false
420     }
421 
422     fn can_match(&self) -> bool {
423         self.inner.read().can_match
424     }
425 
426     fn set_can_match(&self, can_match: bool) {
427         self.inner.write().can_match = can_match
428     }
429 
430     fn state_synced(&self) -> bool {
431         true
432     }
433 }
434 
435 impl CharDevice for TtyDevice {
436     fn read(&self, _len: usize, _buf: &mut [u8]) -> Result<usize, SystemError> {
437         todo!()
438     }
439 
440     fn write(&self, _len: usize, _buf: &[u8]) -> Result<usize, SystemError> {
441         todo!()
442     }
443 
444     fn sync(&self) -> Result<(), SystemError> {
445         todo!()
446     }
447 }
448 
449 #[derive(Debug, Clone)]
450 pub struct TtyFilePrivateData {
451     tty: Arc<TtyCore>,
452     mode: FileMode,
453 }
454 
455 /// 初始化tty设备和console子设备
456 #[unified_init(INITCALL_DEVICE)]
457 #[inline(never)]
458 pub fn tty_init() -> Result<(), SystemError> {
459     let tty = TtyDevice::new(
460         "tty0",
461         IdTable::new(
462             String::from("tty0"),
463             Some(DeviceNumber::new(Major::TTY_MAJOR, 0)),
464         ),
465     );
466 
467     let console = TtyDevice::new(
468         "console",
469         IdTable::new(
470             String::from("console"),
471             Some(DeviceNumber::new(Major::TTYAUX_MAJOR, 1)),
472         ),
473     );
474 
475     // 注册tty设备
476     // CharDevOps::cdev_add(
477     //     tty.clone() as Arc<dyn CharDevice>,
478     // IdTable::new(
479     //     String::from("tty0"),
480     //     Some(DeviceNumber::new(Major::TTYAUX_MAJOR, 0)),
481     // ),
482     //     1,
483     // )?;
484 
485     // CharDevOps::register_chardev_region(DeviceNumber::new(Major::TTYAUX_MAJOR, 0), 1, "/dev/tty")?;
486 
487     // 注册console设备
488     // CharDevOps::cdev_add(
489     //     console.clone() as Arc<dyn CharDevice>,
490     //     IdTable::new(
491     //         String::from("console"),
492     //         Some(DeviceNumber::new(Major::TTYAUX_MAJOR, 1)),
493     //     ),
494     //     1,
495     // )?;
496 
497     // CharDevOps::register_chardev_region(DeviceNumber::new(Major::TTYAUX_MAJOR, 1), 1, "/dev/tty")?;
498 
499     // 将这两个设备注册到devfs,TODO:这里console设备应该与tty在一个设备group里面
500     device_register(tty.clone())?;
501     device_register(console.clone())?;
502     devfs_register(tty.name, tty)?;
503     devfs_register(console.name, console)?;
504 
505     serial_init()?;
506     return vty_init();
507 }
508