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