xref: /DragonOS/kernel/src/driver/tty/pty/unix98pty.rs (revision d031d46fd9e9a62e8e975dba76e3bdef027f63b6)
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