1 use alloc::{string::ToString, sync::Arc};
2 use system_error::SystemError;
3
4 use crate::{
5 driver::tty::{
6 termios::{ControlCharIndex, ControlMode, InputMode, LocalMode, 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 {
new() -> Self32 pub fn new() -> Self {
33 Self
34 }
35 }
36
37 impl TtyOperation for Unix98PtyDriverInner {
install(&self, driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError>38 fn install(&self, driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> {
39 PtyCommon::pty_common_install(driver, tty, false)
40 }
41
open(&self, tty: &TtyCoreData) -> Result<(), SystemError>42 fn open(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
43 PtyCommon::pty_common_open(tty)
44 }
45
write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError>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
write_room(&self, tty: &TtyCoreData) -> usize56 fn write_room(&self, tty: &TtyCoreData) -> usize {
57 // TODO 暂时
58 if tty.flow_irqsave().stopped {
59 return 0;
60 }
61
62 8192
63 }
64
flush_buffer(&self, tty: &TtyCoreData) -> Result<(), SystemError>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
ioctl(&self, tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<(), SystemError>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::ENOIOCTLCMD);
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
set_termios(&self, tty: Arc<TtyCore>, old_termios: Termios) -> Result<(), SystemError>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
113 let core = tty.core();
114 if let Some(link) = core.link() {
115 let link = link.core();
116 if link.contorl_info_irqsave().packet {
117 let curr_termios = *core.termios();
118 let extproc = old_termios.local_mode.contains(LocalMode::EXTPROC)
119 | curr_termios.local_mode.contains(LocalMode::EXTPROC);
120
121 let old_flow = old_termios.input_mode.contains(InputMode::IXON)
122 && old_termios.control_characters[ControlCharIndex::VSTOP] == 0o023
123 && old_termios.control_characters[ControlCharIndex::VSTART] == 0o021;
124
125 let new_flow = curr_termios.input_mode.contains(InputMode::IXON)
126 && curr_termios.control_characters[ControlCharIndex::VSTOP] == 0o023
127 && curr_termios.control_characters[ControlCharIndex::VSTART] == 0o021;
128
129 if old_flow != new_flow || extproc {
130 let mut ctrl = core.contorl_info_irqsave();
131 if old_flow != new_flow {
132 ctrl.pktstatus.remove(
133 TtyPacketStatus::TIOCPKT_DOSTOP | TtyPacketStatus::TIOCPKT_NOSTOP,
134 );
135
136 if new_flow {
137 ctrl.pktstatus.insert(TtyPacketStatus::TIOCPKT_DOSTOP);
138 } else {
139 ctrl.pktstatus.insert(TtyPacketStatus::TIOCPKT_NOSTOP);
140 }
141 }
142
143 if extproc {
144 ctrl.pktstatus.insert(TtyPacketStatus::TIOCPKT_IOCTL);
145 }
146
147 link.read_wq().wakeup_all();
148 }
149 }
150 }
151 let mut termois = core.termios_write();
152 termois
153 .control_mode
154 .remove(ControlMode::CSIZE | ControlMode::PARENB);
155 termois
156 .control_mode
157 .insert(ControlMode::CS8 | ControlMode::CREAD);
158 Ok(())
159 }
160
start(&self, core: &TtyCoreData) -> Result<(), SystemError>161 fn start(&self, core: &TtyCoreData) -> Result<(), SystemError> {
162 if core.driver().tty_driver_sub_type() != TtyDriverSubType::PtySlave {
163 return Err(SystemError::ENOSYS);
164 }
165
166 let link = core.checked_link()?;
167
168 let mut ctrl = core.contorl_info_irqsave();
169 ctrl.pktstatus.remove(TtyPacketStatus::TIOCPKT_STOP);
170 ctrl.pktstatus.insert(TtyPacketStatus::TIOCPKT_START);
171
172 link.core()
173 .read_wq()
174 .wakeup_any(EPollEventType::EPOLLIN.bits() as u64);
175
176 Ok(())
177 }
178
stop(&self, core: &TtyCoreData) -> Result<(), SystemError>179 fn stop(&self, core: &TtyCoreData) -> Result<(), SystemError> {
180 if core.driver().tty_driver_sub_type() != TtyDriverSubType::PtySlave {
181 return Err(SystemError::ENOSYS);
182 }
183
184 let link = core.checked_link()?;
185
186 let mut ctrl = core.contorl_info_irqsave();
187 ctrl.pktstatus.remove(TtyPacketStatus::TIOCPKT_START);
188 ctrl.pktstatus.insert(TtyPacketStatus::TIOCPKT_STOP);
189
190 link.core()
191 .read_wq()
192 .wakeup_any(EPollEventType::EPOLLIN.bits() as u64);
193
194 Ok(())
195 }
196
flush_chars(&self, _tty: &TtyCoreData)197 fn flush_chars(&self, _tty: &TtyCoreData) {
198 // 不做处理
199 }
200
lookup( &self, index: usize, priv_data: TtyDriverPrivateData, ) -> Result<Arc<TtyCore>, SystemError>201 fn lookup(
202 &self,
203 index: usize,
204 priv_data: TtyDriverPrivateData,
205 ) -> Result<Arc<TtyCore>, SystemError> {
206 if let TtyDriverPrivateData::Pty(false) = priv_data {
207 return pts_driver()
208 .ttys()
209 .get(&index)
210 .cloned()
211 .ok_or(SystemError::ENODEV);
212 }
213
214 return Err(SystemError::ENOSYS);
215 }
216
close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError>217 fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError> {
218 let driver = tty.core().driver();
219
220 if tty.core().driver().tty_driver_sub_type() == TtyDriverSubType::PtySlave {
221 driver.ttys().remove(&tty.core().index());
222 let pts_root_inode =
223 ROOT_INODE().lookup_follow_symlink("/dev/pts", VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
224 let _ = pts_root_inode.unlink(&tty.core().index().to_string());
225 }
226
227 Ok(())
228 }
229
resize( &self, tty: Arc<TtyCore>, winsize: crate::driver::tty::termios::WindowSize, ) -> Result<(), SystemError>230 fn resize(
231 &self,
232 tty: Arc<TtyCore>,
233 winsize: crate::driver::tty::termios::WindowSize,
234 ) -> Result<(), SystemError> {
235 let core = tty.core();
236 if *core.window_size() == winsize {
237 return Ok(());
238 }
239
240 // TODO:向进程发送SIGWINCH信号
241
242 *core.window_size_write() = winsize;
243 *core.link().unwrap().core().window_size_write() = winsize;
244
245 Ok(())
246 }
247 }
248
ptmx_open( mut data: SpinLockGuard<FilePrivateData>, mode: &FileMode, ) -> Result<(), SystemError>249 pub fn ptmx_open(
250 mut data: SpinLockGuard<FilePrivateData>,
251 mode: &FileMode,
252 ) -> Result<(), SystemError> {
253 let pts_root_inode =
254 ROOT_INODE().lookup_follow_symlink("/dev/pts", VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
255
256 let fs = pts_root_inode
257 .fs()
258 .as_any_ref()
259 .downcast_ref::<MountFS>()
260 .unwrap()
261 .inner_filesystem();
262 let fsinfo = fs.as_any_ref().downcast_ref::<DevPtsFs>().unwrap();
263
264 let index = fsinfo.alloc_index()?;
265
266 let tty = ptm_driver().init_tty_device(Some(index))?;
267
268 // 设置privdata
269 *data = FilePrivateData::Tty(TtyFilePrivateData {
270 tty: tty.clone(),
271 mode: *mode,
272 });
273
274 let core = tty.core();
275 core.flags_write().insert(TtyFlag::PTY_LOCK);
276
277 let _ = pts_root_inode.create(
278 &index.to_string(),
279 FileType::CharDevice,
280 ModeType::from_bits_truncate(0x666),
281 )?;
282
283 ptm_driver().driver_funcs().open(core)?;
284
285 Ok(())
286 }
287