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