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 { 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::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 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 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 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 197 fn flush_chars(&self, _tty: &TtyCoreData) { 198 // 不做处理 199 } 200 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 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 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 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