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