xref: /DragonOS/kernel/src/driver/tty/pty/unix98pty.rs (revision 4b0170bd6bb374d0e9699a0076cc23b976ad6db7)
1 use alloc::{string::ToString, sync::Arc};
2 use system_error::SystemError;
3 
4 use crate::{
5     driver::tty::{
6         termios::Termios,
7         tty_core::{TtyCore, TtyCoreData, TtyFlag, TtyIoctlCmd, TtyPacketStatus},
8         tty_device::TtyFilePrivateData,
9         tty_driver::{TtyDriver, TtyDriverPrivateData, TtyDriverSubType, TtyOperation},
10     },
11     filesystem::{
12         devpts::DevPtsFs,
13         vfs::{
14             file::FileMode, syscall::ModeType, FilePrivateData, FileType, MountFS, ROOT_INODE,
15             VFS_MAX_FOLLOW_SYMLINK_TIMES,
16         },
17     },
18     libs::spinlock::SpinLockGuard,
19     mm::VirtAddr,
20     net::event_poll::EPollEventType,
21     syscall::user_access::UserBufferWriter,
22 };
23 
24 use super::{ptm_driver, pts_driver, PtyCommon};
25 
26 pub const NR_UNIX98_PTY_MAX: u32 = 128;
27 
28 #[derive(Debug)]
29 pub struct Unix98PtyDriverInner;
30 
31 impl Unix98PtyDriverInner {
32     pub fn new() -> Self {
33         Self
34     }
35 }
36 
37 impl TtyOperation for Unix98PtyDriverInner {
38     fn install(&self, driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> {
39         PtyCommon::pty_common_install(driver, tty, false)
40     }
41 
42     fn open(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
43         PtyCommon::pty_common_open(tty)
44     }
45 
46     fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError> {
47         let to = tty.checked_link()?;
48 
49         if nr == 0 || tty.flow_irqsave().stopped {
50             return Ok(0);
51         }
52 
53         to.core().port().unwrap().receive_buf(buf, &[], nr)
54     }
55 
56     fn write_room(&self, tty: &TtyCoreData) -> usize {
57         // TODO 暂时
58         if tty.flow_irqsave().stopped {
59             return 0;
60         }
61 
62         8192
63     }
64 
65     fn flush_buffer(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
66         let to = tty.checked_link()?;
67 
68         let mut ctrl = to.core().contorl_info_irqsave();
69         ctrl.pktstatus.insert(TtyPacketStatus::TIOCPKT_FLUSHWRITE);
70 
71         to.core().read_wq().wakeup_all();
72 
73         Ok(())
74     }
75 
76     fn ioctl(&self, tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<(), SystemError> {
77         let core = tty.core();
78         if core.driver().tty_driver_sub_type() != TtyDriverSubType::PtyMaster {
79             return Err(SystemError::ENOSYS);
80         }
81 
82         match cmd {
83             TtyIoctlCmd::TIOCSPTLCK => {
84                 return PtyCommon::pty_set_lock(core, VirtAddr::new(arg));
85             }
86             TtyIoctlCmd::TIOCGPTLCK => {
87                 return PtyCommon::pty_get_lock(core, VirtAddr::new(arg));
88             }
89             TtyIoctlCmd::TIOCPKT => {
90                 return PtyCommon::pty_set_packet_mode(core, VirtAddr::new(arg));
91             }
92             TtyIoctlCmd::TIOCGPKT => {
93                 return PtyCommon::pty_get_packet_mode(core, VirtAddr::new(arg));
94             }
95             TtyIoctlCmd::TIOCGPTN => {
96                 let mut user_writer =
97                     UserBufferWriter::new(arg as *mut u32, core::mem::size_of::<u32>(), true)?;
98 
99                 return user_writer.copy_one_to_user(&(core.index() as u32), 0);
100             }
101             _ => {
102                 return Err(SystemError::ENOIOCTLCMD);
103             }
104         }
105     }
106 
107     fn set_termios(&self, tty: Arc<TtyCore>, _old_termios: Termios) -> Result<(), SystemError> {
108         let core = tty.core();
109         if core.driver().tty_driver_sub_type() != TtyDriverSubType::PtySlave {
110             return Err(SystemError::ENOSYS);
111         }
112         todo!()
113     }
114 
115     fn start(&self, core: &TtyCoreData) -> Result<(), SystemError> {
116         if core.driver().tty_driver_sub_type() != TtyDriverSubType::PtySlave {
117             return Err(SystemError::ENOSYS);
118         }
119 
120         let link = core.checked_link()?;
121 
122         let mut ctrl = core.contorl_info_irqsave();
123         ctrl.pktstatus.remove(TtyPacketStatus::TIOCPKT_STOP);
124         ctrl.pktstatus.insert(TtyPacketStatus::TIOCPKT_START);
125 
126         link.core()
127             .read_wq()
128             .wakeup_any(EPollEventType::EPOLLIN.bits() as u64);
129 
130         Ok(())
131     }
132 
133     fn stop(&self, core: &TtyCoreData) -> Result<(), SystemError> {
134         if core.driver().tty_driver_sub_type() != TtyDriverSubType::PtySlave {
135             return Err(SystemError::ENOSYS);
136         }
137 
138         let link = core.checked_link()?;
139 
140         let mut ctrl = core.contorl_info_irqsave();
141         ctrl.pktstatus.remove(TtyPacketStatus::TIOCPKT_START);
142         ctrl.pktstatus.insert(TtyPacketStatus::TIOCPKT_STOP);
143 
144         link.core()
145             .read_wq()
146             .wakeup_any(EPollEventType::EPOLLIN.bits() as u64);
147 
148         Ok(())
149     }
150 
151     fn flush_chars(&self, _tty: &TtyCoreData) {
152         // 不做处理
153     }
154 
155     fn lookup(
156         &self,
157         index: usize,
158         priv_data: TtyDriverPrivateData,
159     ) -> Result<Arc<TtyCore>, SystemError> {
160         if let TtyDriverPrivateData::Pty(false) = priv_data {
161             return pts_driver()
162                 .ttys()
163                 .get(&index)
164                 .cloned()
165                 .ok_or(SystemError::ENODEV);
166         }
167 
168         return Err(SystemError::ENOSYS);
169     }
170 
171     fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError> {
172         let driver = tty.core().driver();
173 
174         driver.ttys().remove(&tty.core().index());
175         if tty.core().driver().tty_driver_sub_type() == TtyDriverSubType::PtySlave {
176             let pts_root_inode =
177                 ROOT_INODE().lookup_follow_symlink("/dev/pts", VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
178             let _ = pts_root_inode.unlink(&tty.core().index().to_string());
179         }
180 
181         Ok(())
182     }
183 }
184 
185 pub fn ptmx_open(
186     mut data: SpinLockGuard<FilePrivateData>,
187     mode: &FileMode,
188 ) -> Result<(), SystemError> {
189     let pts_root_inode =
190         ROOT_INODE().lookup_follow_symlink("/dev/pts", VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
191 
192     let fs = pts_root_inode
193         .fs()
194         .as_any_ref()
195         .downcast_ref::<MountFS>()
196         .unwrap()
197         .inner_filesystem();
198     let fsinfo = fs.as_any_ref().downcast_ref::<DevPtsFs>().unwrap();
199 
200     let index = fsinfo.alloc_index()?;
201 
202     let tty = TtyDriver::init_tty_device(ptm_driver(), index)?;
203 
204     // 设置privdata
205     *data = FilePrivateData::Tty(TtyFilePrivateData {
206         tty: tty.clone(),
207         mode: *mode,
208     });
209 
210     let core = tty.core();
211     core.flags_write().insert(TtyFlag::PTY_LOCK);
212 
213     let _ = pts_root_inode.create(
214         &index.to_string(),
215         FileType::CharDevice,
216         ModeType::from_bits_truncate(0x666),
217     )?;
218 
219     ptm_driver().driver_funcs().open(core)?;
220 
221     Ok(())
222 }
223