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