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