use core::intrinsics::likely; use core::ops::BitXor; use bitmap::{traits::BitMapOps, StaticBitmap}; use alloc::sync::{Arc, Weak}; use system_error::SystemError; use crate::{ arch::ipc::signal::Signal, driver::tty::{ termios::{ControlCharIndex, InputMode, LocalMode, OutputMode, Termios}, tty_core::{EchoOperation, TtyCore, TtyCoreData, TtyFlag, TtyIoctlCmd, TtyPacketStatus}, tty_driver::{TtyDriverFlag, TtyOperation}, tty_job_control::TtyJobCtrlManager, }, filesystem::vfs::file::FileMode, libs::{ rwlock::RwLockReadGuard, spinlock::{SpinLock, SpinLockGuard}, }, mm::VirtAddr, net::event_poll::EPollEventType, process::ProcessManager, syscall::{user_access::UserBufferWriter, Syscall}, }; use super::TtyLineDiscipline; pub const NTTY_BUFSIZE: usize = 4096; pub const ECHO_COMMIT_WATERMARK: usize = 256; pub const ECHO_BLOCK: usize = 256; pub const ECHO_DISCARD_WATERMARK: usize = NTTY_BUFSIZE - (ECHO_BLOCK + 32); fn ntty_buf_mask(idx: usize) -> usize { return idx & (NTTY_BUFSIZE - 1); } #[derive(Debug)] pub struct NTtyLinediscipline { pub data: SpinLock, } impl NTtyLinediscipline { #[inline] pub fn disc_data(&self) -> SpinLockGuard { self.data.lock_irqsave() } #[inline] pub fn disc_data_try_lock(&self) -> Result, SystemError> { self.data.try_lock_irqsave() } fn ioctl_helper(&self, tty: Arc, cmd: u32, arg: usize) -> Result { match cmd { TtyIoctlCmd::TCXONC => { todo!() } TtyIoctlCmd::TCFLSH => { todo!() } _ => { return TtyCore::tty_mode_ioctl(tty.clone(), cmd, arg); } } } } #[derive(Debug)] pub struct NTtyData { /// 写者管理,tty只有一个写者,即ttydevice,所以不需要加锁 /// 读取缓冲区的头指针,表示下一个将要接受进buf的字符的位置 read_head: usize, /// 提交缓冲区的头指针,用于行规程处理 commit_head: usize, /// 规范缓冲区的头指针,用于规范模式的处理 canon_head: usize, /// 回显缓冲区的头指针,用于存储需要回显的字符 echo_head: usize, /// 回显过程中用于提交的头指针 echo_commit: usize, /// 标记回显字符的起始位置 echo_mark: usize, /// 读者管理 /// 读取字符的尾指针,即当前读取位置 read_tail: usize, /// 行的起始位置 line_start: usize, /// 预读字符数,用于处理控制字符 lookahead_count: usize, // 更改以下六个标记时必须持有termios的锁 /// Line-next 标志,表示下一个输入字符应当按字面处理 lnext: bool, /// 擦除状态的标志 erasing: bool, /// Raw 模式的标志 raw: bool, /// Real raw 模式的标志 real_raw: bool, /// 规范模式的标志 icanon: bool, /// 是否开启echo echo: bool, /// 标志是否正在进行推送 pushing: bool, /// 是否没有空间可写 no_room: bool, /// 光标所在列 cursor_column: u32, /// 规范模式下光标所在列 canon_cursor_column: u32, /// 回显缓冲区的尾指针 echo_tail: usize, /// 写者与读者共享 read_buf: [u8; NTTY_BUFSIZE], echo_buf: [u8; NTTY_BUFSIZE], read_flags: StaticBitmap, char_map: StaticBitmap<256>, tty: Option>, } impl NTtyData { pub fn new() -> Self { Self { read_head: 0, commit_head: 0, canon_head: 0, echo_head: 0, echo_commit: 0, echo_mark: 0, read_tail: 0, line_start: 0, lookahead_count: 0, lnext: false, erasing: false, raw: false, real_raw: false, icanon: false, pushing: false, echo: false, cursor_column: 0, canon_cursor_column: 0, echo_tail: 0, read_buf: [0; NTTY_BUFSIZE], echo_buf: [0; NTTY_BUFSIZE], read_flags: StaticBitmap::new(), char_map: StaticBitmap::new(), tty: None, no_room: false, } } #[inline] pub fn read_cnt(&self) -> usize { self.read_head - self.read_tail } #[inline] pub fn read_at(&self, i: usize) -> u8 { let i = i & (NTTY_BUFSIZE - 1); self.read_buf[i] } /// ### 接收数据到NTTY pub fn receive_buf_common( &mut self, tty: Arc, buf: &[u8], flags: Option<&[u8]>, mut count: usize, flow: bool, ) -> Result { // 获取termios读锁 let termios = tty.core().termios(); let mut overflow; let mut n; let mut offset = 0; let mut recved = 0; loop { let tail = self.read_tail; let mut room = NTTY_BUFSIZE - (self.read_head - tail); if termios.input_mode.contains(InputMode::PARMRK) { room = (room + 2) / 3; } room -= 1; if room == 0 || room > NTTY_BUFSIZE { // 可能溢出 overflow = self.icanon && self.canon_head == tail; if room > NTTY_BUFSIZE && overflow { self.read_head -= 1; } self.no_room = flow && !overflow; room = if overflow { !0 } else { 0 } } else { overflow = false; } n = count.min(room); if n == 0 { break; } if !overflow { if let Some(flags) = flags { self.receive_buf(tty.clone(), &buf[offset..], Some(&flags[offset..]), n); } else { self.receive_buf(tty.clone(), &buf[offset..], flags, n); } } offset += n; count -= n; recved += n; if tty.core().flags().contains(TtyFlag::LDISC_CHANGING) { break; } } // TODO: throttle Ok(recved) } pub fn receive_buf( &mut self, tty: Arc, buf: &[u8], flags: Option<&[u8]>, count: usize, ) { let termios = tty.core().termios(); let preops = termios.input_mode.contains(InputMode::ISTRIP) || termios.input_mode.contains(InputMode::IUCLC) || termios.local_mode.contains(LocalMode::IEXTEN); let look_ahead = self.lookahead_count.min(count); if self.real_raw { self.receive_buf_real_raw(buf, count); } else if self.raw || (termios.local_mode.contains(LocalMode::EXTPROC) && !preops) { self.receive_buf_raw(buf, flags, count); } else if tty.core().is_closing() && !termios.local_mode.contains(LocalMode::EXTPROC) { todo!() } else { if look_ahead > 0 { self.receive_buf_standard(tty.clone(), buf, flags, look_ahead, true); } if count > look_ahead { self.receive_buf_standard(tty.clone(), buf, flags, count - look_ahead, false); } // 刷新echo self.flush_echoes(tty.clone()); tty.flush_chars(tty.core()); } self.lookahead_count -= look_ahead; if self.icanon && !termios.local_mode.contains(LocalMode::EXTPROC) { return; } self.commit_head = self.read_head; if self.read_cnt() > 0 { tty.core() .read_wq() .wakeup_any((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDBAND).bits() as u64); } } fn receive_buf_real_raw(&mut self, buf: &[u8], mut count: usize) { let mut head = ntty_buf_mask(self.read_head); let mut n = count.min(NTTY_BUFSIZE - head); // 假如有一部分在队列头部,则这部分是拷贝尾部部分 self.read_buf[head..(head + n)].copy_from_slice(&buf[0..n]); self.read_head += n; count -= n; let offset = n; // 假如有一部分在队列头部,则这部分是拷贝头部部分 head = ntty_buf_mask(self.read_head); n = count.min(NTTY_BUFSIZE - head); self.read_buf[head..(head + n)].copy_from_slice(&buf[offset..(offset + n)]); self.read_head += n; } fn receive_buf_raw(&mut self, buf: &[u8], flags: Option<&[u8]>, mut count: usize) { // TTY_NORMAL 目前这部分未做,所以先占位置而不做抽象 let mut flag = 1; let mut f_offset = 0; let mut c_offset = 0; while count != 0 { if flags.is_some() { flag = flags.as_ref().unwrap()[f_offset]; f_offset += 1; } if likely(flag == 1) { self.read_buf[self.read_head] = buf[c_offset]; c_offset += 1; self.read_head += 1; } else { todo!() } count -= 1; } } pub fn flush_echoes(&mut self, tty: Arc) { let termios = tty.core().termios(); if !termios.local_mode.contains(LocalMode::ECHO) && !termios.local_mode.contains(LocalMode::ECHONL) || self.echo_commit == self.echo_head { return; } self.echo_commit = self.echo_head; drop(termios); let _ = self.echoes(tty); } pub fn receive_buf_standard( &mut self, tty: Arc, buf: &[u8], flags: Option<&[u8]>, mut count: usize, lookahead_done: bool, ) { let termios = tty.core().termios(); if flags.is_some() { todo!("ntty recv buf flags todo"); } let mut offset = 0; while count > 0 { if offset >= buf.len() { break; } let mut c = buf[offset]; offset += 1; if self.lnext { // 将下一个字符当做字面值处理 self.lnext = false; if termios.input_mode.contains(InputMode::ISTRIP) { c &= 0x7f; } if termios.input_mode.contains(InputMode::IUCLC) && termios.local_mode.contains(LocalMode::IEXTEN) { c = (c as char).to_ascii_lowercase() as u8; self.receive_char(c, tty.clone()) } continue; } if termios.input_mode.contains(InputMode::ISTRIP) { c &= 0x7f; } if termios.input_mode.contains(InputMode::IUCLC) && termios.local_mode.contains(LocalMode::IEXTEN) { c = (c as char).to_ascii_lowercase() as u8; } if termios.local_mode.contains(LocalMode::EXTPROC) { self.add_read_byte(c); continue; } if self.char_map.get(c as usize).unwrap() { // 特殊字符 self.receive_special_char(c, tty.clone(), lookahead_done) } else { self.receive_char(c, tty.clone()); } count -= 1; } } #[inline(never)] pub fn receive_special_char(&mut self, mut c: u8, tty: Arc, lookahead_done: bool) { let is_flow_ctrl = self.is_flow_ctrl_char(tty.clone(), c, lookahead_done); let termios = tty.core().termios(); // 启用软件流控,并且该字符已经当做软件流控字符处理 if termios.input_mode.contains(InputMode::IXON) && is_flow_ctrl { return; } if termios.local_mode.contains(LocalMode::ISIG) { if c == termios.control_characters[ControlCharIndex::VINTR] { self.recv_sig_char(tty.clone(), &termios, Signal::SIGINT, c); return; } if c == termios.control_characters[ControlCharIndex::VQUIT] { self.recv_sig_char(tty.clone(), &termios, Signal::SIGQUIT, c); return; } if c == termios.control_characters[ControlCharIndex::VSUSP] { self.recv_sig_char(tty.clone(), &termios, Signal::SIGTSTP, c); return; } } let flow = tty.core().flow_irqsave(); if flow.stopped && !flow.tco_stopped && termios.input_mode.contains(InputMode::IXON) && termios.input_mode.contains(InputMode::IXANY) { tty.tty_start(); self.process_echoes(tty.clone()); } drop(flow); if c == b'\r' { if termios.input_mode.contains(InputMode::IGNCR) { // 忽略 return; } if termios.input_mode.contains(InputMode::ICRNL) { // 映射为换行 c = b'\n'; } } else if c == b'\n' && termios.input_mode.contains(InputMode::INLCR) { // 映射为回车 c = b'\r'; } if self.icanon { if c == termios.control_characters[ControlCharIndex::VERASE] || c == termios.control_characters[ControlCharIndex::VKILL] || (c == termios.control_characters[ControlCharIndex::VWERASE] && termios.local_mode.contains(LocalMode::IEXTEN)) { self.eraser(c, &termios); self.commit_echoes(tty.clone()); return; } if c == termios.control_characters[ControlCharIndex::VLNEXT] && termios.local_mode.contains(LocalMode::IEXTEN) { self.lnext = true; if termios.local_mode.contains(LocalMode::ECHO) { self.finish_erasing(); if termios.local_mode.contains(LocalMode::ECHOCTL) { self.echo_char_raw(b'^'); self.echo_char_raw(8); self.commit_echoes(tty.clone()); } } return; } if c == termios.control_characters[ControlCharIndex::VREPRINT] && termios.local_mode.contains(LocalMode::ECHO) && termios.local_mode.contains(LocalMode::IEXTEN) { let mut tail = self.canon_head; self.finish_erasing(); self.echo_char(c, &termios); self.echo_char_raw(b'\n'); while ntty_buf_mask(tail) != ntty_buf_mask(self.read_head) { self.echo_char(self.read_buf[ntty_buf_mask(tail)], &termios); tail += 1; } self.commit_echoes(tty.clone()); return; } if c == b'\n' { if termios.local_mode.contains(LocalMode::ECHO) || termios.local_mode.contains(LocalMode::ECHONL) { self.echo_char_raw(b'\n'); self.commit_echoes(tty.clone()); } self.read_flags.set(ntty_buf_mask(self.read_head), true); self.read_buf[ntty_buf_mask(self.read_head)] = c; self.read_head += 1; self.canon_head = self.read_head; tty.core().read_wq().wakeup_any( (EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64, ); return; } if c == termios.control_characters[ControlCharIndex::VEOF] { c = ControlCharIndex::DISABLE_CHAR; self.read_flags.set(ntty_buf_mask(self.read_head), true); self.read_buf[ntty_buf_mask(self.read_head)] = c; self.read_head += 1; self.canon_head = self.read_head; tty.core().read_wq().wakeup_any( (EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64, ); return; } if c == termios.control_characters[ControlCharIndex::VEOL] || (c == termios.control_characters[ControlCharIndex::VEOL2] && termios.local_mode.contains(LocalMode::IEXTEN)) { if termios.local_mode.contains(LocalMode::ECHO) { if self.canon_head == self.read_head { self.add_echo_byte(EchoOperation::Start.to_u8()); self.add_echo_byte(EchoOperation::SetCanonCol.to_u8()); } self.echo_char(c, &termios); self.commit_echoes(tty.clone()); } if c == 0o377 && termios.input_mode.contains(InputMode::PARMRK) { self.read_buf[ntty_buf_mask(self.read_head)] = c; self.read_head += 1; } self.read_flags.set(ntty_buf_mask(self.read_head), true); self.read_buf[ntty_buf_mask(self.read_head)] = c; self.read_head += 1; self.canon_head = self.read_head; tty.core().read_wq().wakeup_any( (EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64, ); return; } } if termios.local_mode.contains(LocalMode::ECHO) { self.finish_erasing(); if c == b'\n' { self.echo_char_raw(b'\n'); } else { if self.canon_head == self.read_head { self.add_echo_byte(EchoOperation::Start.to_u8()); self.add_echo_byte(EchoOperation::SetCanonCol.to_u8()); } self.echo_char(c, &termios); } self.commit_echoes(tty.clone()); } if c == 0o377 && termios.input_mode.contains(InputMode::PARMRK) { self.read_buf[ntty_buf_mask(self.read_head)] = c; self.read_head += 1; } self.read_buf[ntty_buf_mask(self.read_head)] = c; self.read_head += 1; } /// ## ntty默认eraser function #[inline(never)] fn eraser(&mut self, mut c: u8, termios: &RwLockReadGuard) { if self.read_head == self.canon_head { return; } let erase = c == termios.control_characters[ControlCharIndex::VERASE]; let werase = c == termios.control_characters[ControlCharIndex::VWERASE]; let kill = !erase && !werase; if kill { if !termios.local_mode.contains(LocalMode::ECHO) { self.read_head = self.canon_head; return; } if !termios.local_mode.contains(LocalMode::ECHOK) || !termios.local_mode.contains(LocalMode::ECHOKE) || !termios.local_mode.contains(LocalMode::ECHOE) { self.read_head = self.canon_head; if self.erasing { self.echo_char_raw(c); self.erasing = false; } self.echo_char(c, termios); if termios.local_mode.contains(LocalMode::ECHOK) { // 添加新行 self.echo_char_raw(b'\n'); } return; } } let mut head; let mut cnt; while ntty_buf_mask(self.read_head) != ntty_buf_mask(self.canon_head) { head = self.read_head; loop { // 消除多字节字符 head -= 1; c = self.read_buf[ntty_buf_mask(head)]; if !(Self::is_continuation(c, termios) && ntty_buf_mask(head) != ntty_buf_mask(self.canon_head)) { break; } } if Self::is_continuation(c, termios) { break; } if werase { todo!() } cnt = self.read_head - head; self.read_head = head; if termios.local_mode.contains(LocalMode::ECHO) { if termios.local_mode.contains(LocalMode::ECHOPRT) { if !self.erasing { self.echo_char_raw(b'\\'); self.erasing = true; } self.echo_char(c, termios); cnt -= 1; while cnt > 0 { cnt -= 1; head += 1; self.echo_char_raw(self.read_buf[ntty_buf_mask(head)]); self.add_echo_byte(EchoOperation::Start.to_u8()); self.add_echo_byte(EchoOperation::MoveBackCol.to_u8()); } } else if erase && !termios.local_mode.contains(LocalMode::ECHOE) { self.echo_char( termios.control_characters[ControlCharIndex::VERASE], termios, ); } else if c == b'\t' { let mut num_chars = 0; let mut after_tab = false; let mut tail = self.read_head; while ntty_buf_mask(tail) != ntty_buf_mask(self.canon_head) { tail -= 1; c = self.read_buf[ntty_buf_mask(tail)]; if c == b'\t' { after_tab = true; break; } else if (c as char).is_control() { if termios.local_mode.contains(LocalMode::ECHOCTL) { num_chars += 2; } } else if !Self::is_continuation(c, termios) { num_chars += 1; } } self.echo_erase_tab(num_chars, after_tab); } else { if (c as char).is_control() && termios.local_mode.contains(LocalMode::ECHOCTL) { // 8 => '\b' self.echo_char_raw(8); self.echo_char_raw(b' '); self.echo_char_raw(8); } if !(c as char).is_control() || termios.local_mode.contains(LocalMode::ECHOCTL) { // 8 => '\b' self.echo_char_raw(8); self.echo_char_raw(b' '); self.echo_char_raw(8); } } } if erase { break; } } if self.read_head == self.canon_head && termios.local_mode.contains(LocalMode::ECHO) { self.finish_erasing(); } } fn finish_erasing(&mut self) { if self.erasing { self.echo_char_raw(b'/'); self.erasing = false; } } fn echo_erase_tab(&mut self, mut num: u8, after_tab: bool) { self.add_echo_byte(EchoOperation::Start.to_u8()); self.add_echo_byte(EchoOperation::EraseTab.to_u8()); num &= 7; if after_tab { num |= 0x80; } self.add_echo_byte(num); } /// ## 多字节字符检测 /// 检测是否为多字节字符的后续字节 fn is_continuation(c: u8, termios: &RwLockReadGuard) -> bool { return termios.input_mode.contains(InputMode::IUTF8) && (c & 0xc0) == 0x80; } /// ## 该字符是否已经当做流控字符处理 pub fn is_flow_ctrl_char(&mut self, tty: Arc, c: u8, lookahead_done: bool) -> bool { let termios = tty.core().termios(); if !(termios.control_characters[ControlCharIndex::VSTART] == c || termios.control_characters[ControlCharIndex::VSTOP] == c) { return false; } if lookahead_done { return true; } if termios.control_characters[ControlCharIndex::VSTART] == c { tty.tty_start(); self.process_echoes(tty.clone()); return true; } else { tty.tty_stop(); return true; } } /// ## 接收到信号字符时的处理 fn recv_sig_char( &mut self, tty: Arc, termios: &RwLockReadGuard, signal: Signal, c: u8, ) { self.input_signal(tty.clone(), termios, signal); if termios.input_mode.contains(InputMode::IXON) { tty.tty_start(); } if termios.local_mode.contains(LocalMode::ECHO) { self.echo_char(c, termios); self.commit_echoes(tty); } else { self.process_echoes(tty); } } /// ## 处理输入信号 pub fn input_signal( &mut self, tty: Arc, termios: &RwLockReadGuard, signal: Signal, ) { // 先处理信号 let mut ctrl_info = tty.core().contorl_info_irqsave(); let pg = ctrl_info.pgid; if let Some(pg) = pg { let _ = Syscall::kill(pg, signal as i32); } ctrl_info.pgid = None; ctrl_info.session = None; if !termios.local_mode.contains(LocalMode::NOFLSH) { // 重置 self.echo_head = 0; self.echo_tail = 0; self.echo_mark = 0; self.echo_commit = 0; let _ = tty.flush_buffer(tty.core()); self.read_head = 0; self.canon_head = 0; self.read_tail = 0; self.line_start = 0; self.erasing = false; self.read_flags.set_all(false); self.pushing = false; self.lookahead_count = 0; if tty.core().link().is_some() { self.packet_mode_flush(tty.core()); } } } pub fn receive_char(&mut self, c: u8, tty: Arc) { let termios = tty.core().termios(); if termios.local_mode.contains(LocalMode::ECHO) { if self.erasing { self.add_echo_byte(b'/'); self.erasing = false; } if self.canon_head == self.read_head { self.add_echo_byte(EchoOperation::Start.to_u8()); self.add_echo_byte(EchoOperation::SetCanonCol.to_u8()); } self.echo_char(c, &termios); self.commit_echoes(tty.clone()); } if c == 0o377 && tty.core().termios().input_mode.contains(InputMode::PARMRK) { self.add_read_byte(c); } self.add_read_byte(c); } pub fn echo_char(&mut self, c: u8, termios: &RwLockReadGuard) { if c == EchoOperation::Start.to_u8() { self.add_echo_byte(EchoOperation::Start.to_u8()); self.add_echo_byte(EchoOperation::Start.to_u8()); } else { if termios.local_mode.contains(LocalMode::ECHOCTL) && (c as char).is_control() && c != b'\t' { self.add_echo_byte(EchoOperation::Start.to_u8()); } self.add_echo_byte(c); } } pub fn echo_char_raw(&mut self, c: u8) { if c == EchoOperation::Start.to_u8() { self.add_echo_byte(EchoOperation::Start.to_u8()); self.add_echo_byte(EchoOperation::Start.to_u8()); } else { self.add_echo_byte(c); } } /// ## 提交echobuf里的数据显示 pub fn commit_echoes(&mut self, tty: Arc) { let head = self.echo_head; self.echo_mark = head; let old = self.echo_commit - self.echo_tail; // 需要echo的字符个数 let nr = head - self.echo_tail; if nr < ECHO_COMMIT_WATERMARK || nr % ECHO_BLOCK > old % ECHO_BLOCK { return; } self.echo_commit = head; let echoed = self.echoes(tty.clone()); if echoed.is_ok() && echoed.unwrap() > 0 { tty.flush_chars(tty.core()); } } pub fn add_echo_byte(&mut self, c: u8) { self.echo_buf[ntty_buf_mask(self.echo_head)] = c; self.echo_head += 1; } pub fn add_read_byte(&mut self, c: u8) { self.read_buf[ntty_buf_mask(self.read_head)] = c; self.read_head += 1; } /// ### 将read_buffer的部分值置0 /// /// 只会在规范模式和禁用echo下执行 #[inline] pub fn zero_buffer(&mut self, offset: usize, size: usize) { let offset = offset & (NTTY_BUFSIZE - 1); if self.icanon && !self.echo { let n = offset + size; if n > NTTY_BUFSIZE { for c in &mut self.read_buf[offset..NTTY_BUFSIZE] { *c = 0 } for c in &mut self.read_buf[0..(n - NTTY_BUFSIZE)] { *c = 0 } } else { for c in &mut self.read_buf[offset..n] { *c = 0 } }; } } /// ## 从ntty中拷贝数据 /// /// ### 参数 /// /// ### to: 存储数据 /// ### tail: 读取尾 pub fn ntty_copy( &mut self, to: &mut [u8], tail: usize, n: &mut usize, ) -> Result<(), SystemError> { if to.len() < *n { *n = to.len(); // return Err(SystemError::EINVAL); } if tail > NTTY_BUFSIZE { return Err(SystemError::EINVAL); } let size = NTTY_BUFSIZE - tail; if size < *n { // 有一部分数据在头部,则先拷贝后面部分,再拷贝头部 // TODO: tty审计? to[0..size].copy_from_slice(&self.read_buf[tail..(tail + size)]); to[size..(*n)].copy_from_slice(&self.read_buf[0..(*n - size)]); } else { to[..*n].copy_from_slice(&self.read_buf[tail..(tail + *n)]) } self.zero_buffer(tail, *n); Ok(()) } /// ## 规范模式下跳过EOF pub fn canon_skip_eof(&mut self) { // 没有数据 if self.read_tail == self.canon_head { return; } let tail = self.read_tail & (NTTY_BUFSIZE - 1); // 查看read_flags是否读取位置为特殊字符 if !self.read_flags.get(tail).unwrap() { return; } // 确保读取位置是'\0'字符 if self.read_buf[tail] != ControlCharIndex::DISABLE_CHAR { return; } // 处理该字符,将read_flagsw该位清除 self.read_flags.set(tail, false); // 读取位置+1,即跳过该字符不做处理 self.read_tail += 1; } /// ## 在规范模式(canonical mode)下从读缓冲中复制一行 /// /// 一次只拷贝一行 /// /// ## 参数 /// ### dst: 存放数据 /// ### nr: 需要拷贝的数据大小 /// /// ## 返回值 /// ### true: 表示一行未结束并且还有数据可读 /// ### false: 一行已结束或者没有数据可读 pub fn canon_copy_from_read_buf( &mut self, dst: &mut [u8], nr: &mut usize, offset: &mut usize, ) -> Result { if *nr == 0 { return Ok(false); } let canon_head = self.canon_head; // 取得能够读到的字符数,即canon_head - self.read_tail和nr最小值 let mut n = (*nr).min(canon_head - self.read_tail); // 获得读尾index let tail = self.read_tail & (NTTY_BUFSIZE - 1); // 避免越界,这个size才是实际读取大小 let size = if tail + n > NTTY_BUFSIZE { NTTY_BUFSIZE } else { tail + n }; // 找到eol的坐标 let tmp = self.read_flags.next_index(tail); // 找到的话即为坐标,未找到的话即为NTTY_BUFSIZE let mut eol = if let Some(tmp) = tmp { tmp } else { size }; if eol > size { eol = size } // 是否需要绕回缓冲区头部 let more = n - (size - tail); // 是否找到eol let found = if eol == NTTY_BUFSIZE && more > 0 { // 需要返回头部 let ret = self.read_flags.first_index(); if let Some(tmp) = ret { // 在头部范围内找到eol if tmp < more { eol = tmp; } } else { eol = more; } eol != more } else { // 不需要返回头部 eol != size }; n = eol - tail; if n > NTTY_BUFSIZE { // 减法溢出则加上BUFSIZE即可限制在0-NTTY_BUFSIZE内 n += NTTY_BUFSIZE; } // 规范模式下实际扫描过的字符数,需要将eol计算在内 let count = if found { n + 1 } else { n }; // 表示这一行未结束 if !found || self.read_at(eol) != ControlCharIndex::DISABLE_CHAR { n = count; } self.ntty_copy(&mut dst[*offset..], tail, &mut n)?; *nr -= n; *offset += n; if found { self.read_flags.set(eol, false); } self.read_tail += count; if found { if !self.pushing { self.line_start = self.read_tail; } else { self.pushing = false; } // todo: 审计? return Ok(false); } // 这里是表示没有找到eol,根据是否还有数据可读返回 Ok(self.read_tail != canon_head) } /// ## 根据终端的模式和输入缓冲区中的数据量,判断是否可读字符 pub fn input_available(&self, termios: RwLockReadGuard, poll: bool) -> bool { // 计算最小字符数 let amt = if poll && termios.control_characters[ControlCharIndex::VTIME] as u32 == 0 && termios.control_characters[ControlCharIndex::VMIN] as u32 != 0 { termios.control_characters[ControlCharIndex::VMIN] as usize } else { 1 }; // 规范模式且非拓展 if self.icanon && !termios.local_mode.contains(LocalMode::EXTPROC) { return self.canon_head != self.read_tail; } else { return (self.commit_head - self.read_tail) >= amt; } } /// ## 非规范模式下从read_buf读取数据 /// /// ## 参数 /// ### termios: tty对应的termioss读锁守卫 /// ### dst: 存储读取数据 /// ### nr: 读取长度 /// /// ## 返回值 /// ### true: 还有更多数据可读 /// ### false: 无更多数据可读 pub fn copy_from_read_buf( &mut self, termios: RwLockReadGuard, dst: &mut [u8], nr: &mut usize, offset: &mut usize, ) -> Result { let head = self.commit_head; let tail = self.read_tail & (NTTY_BUFSIZE - 1); // 计算出可读的字符数 let mut n = (NTTY_BUFSIZE - tail).min(head - self.read_tail); n = n.min(*nr); if n > 0 { // 拷贝数据 self.ntty_copy(&mut dst[*offset..], tail, &mut n)?; // todo:审计? self.read_tail += n; // 是否只读取了eof let eof = n == 1 && self.read_buf[tail] == termios.control_characters[ControlCharIndex::VEOF]; if termios.local_mode.contains(LocalMode::EXTPROC) && self.icanon && eof && head == self.read_tail { return Ok(false); } *nr -= n; *offset += n; return Ok(head != self.read_tail); } Ok(false) } /// ## 用于处理带有 OPOST(Output Post-processing)标志的输出块的函数 /// OPOST 是 POSIX 终端驱动器标志之一,用于指定在写入终端设备之前对输出数据进行一些后期处理。 pub fn process_output_block( &mut self, core: &TtyCoreData, termios: RwLockReadGuard, buf: &[u8], nr: usize, ) -> Result { let mut nr = nr; let tty = self.tty.clone().unwrap().upgrade().unwrap(); let space = tty.write_room(tty.core()); // 如果读取数量大于了可用空间,则取最小的为真正的写入数量 if nr > space { nr = space } let mut cnt = 0; for (i, c) in buf.iter().enumerate().take(nr) { cnt = i; let c = *c; if c as usize == 8 { // 表示退格 if self.cursor_column > 0 { self.cursor_column -= 1; } continue; } match c as char { '\n' => { if termios.output_mode.contains(OutputMode::ONLRET) { // 将回车映射为\n,即将\n换为回车 self.cursor_column = 0; } if termios.output_mode.contains(OutputMode::ONLCR) { // 输出时将\n换为\r\n break; } self.canon_cursor_column = self.cursor_column; } '\r' => { if termios.output_mode.contains(OutputMode::ONOCR) && self.cursor_column == 0 { // 光标已经在第0列,则不输出回车符 break; } if termios.output_mode.contains(OutputMode::OCRNL) { break; } self.canon_cursor_column = self.cursor_column; } '\t' => { break; } _ => { // 判断是否为控制字符 if !(c as char).is_control() { if termios.output_mode.contains(OutputMode::OLCUC) { break; } // 判断是否为utf8模式下的连续字符 if !(termios.input_mode.contains(InputMode::IUTF8) && (c as usize) & 0xc0 == 0x80) { self.cursor_column += 1; } } } } } drop(termios); return tty.write(core, buf, cnt); } /// ## 处理回显 pub fn process_echoes(&mut self, tty: Arc) { if self.echo_mark == self.echo_tail { return; } self.echo_commit = self.echo_mark; let echoed = self.echoes(tty.clone()); if echoed.is_ok() && echoed.unwrap() > 0 { tty.flush_chars(tty.core()); } } #[inline(never)] pub fn echoes(&mut self, tty: Arc) -> Result { let mut space = tty.write_room(tty.core()); let ospace = space; let termios = tty.core().termios(); let core = tty.core(); let mut tail = self.echo_tail; while ntty_buf_mask(self.echo_commit) != ntty_buf_mask(tail) { let c = self.echo_buf[ntty_buf_mask(tail)]; if EchoOperation::from_u8(c) == EchoOperation::Start { if ntty_buf_mask(self.echo_commit) == ntty_buf_mask(tail + 1) { self.echo_tail = tail; return Ok(ospace - space); } // 获取到start,之后取第一个作为op let op = EchoOperation::from_u8(self.echo_buf[ntty_buf_mask(tail + 1)]); match op { EchoOperation::Start => { if space == 0 { break; } if tty .put_char(tty.core(), EchoOperation::Start.to_u8()) .is_err() { tty.write(core, &[EchoOperation::Start.to_u8()], 1)?; } self.cursor_column += 1; space -= 1; tail += 2; } EchoOperation::MoveBackCol => { if self.cursor_column > 0 { self.cursor_column -= 1; } tail += 2; } EchoOperation::SetCanonCol => { self.canon_cursor_column = self.cursor_column; tail += 2; } EchoOperation::EraseTab => { if ntty_buf_mask(self.echo_commit) == ntty_buf_mask(tail + 2) { self.echo_tail = tail; return Ok(ospace - space); } // 要擦除的制表符所占用的列数 let mut char_num = self.echo_buf[ntty_buf_mask(tail + 2)] as usize; /* 如果 num_chars 的最高位(0x80)未设置, 表示这是从输入的起始位置而不是从先前的制表符开始计算的列数。 在这种情况下,将 num_chars 与 ldata->canon_column 相加,否则,列数就是正常的制表符列数。 */ if char_num & 0x80 == 0 { char_num += self.canon_cursor_column as usize; } // 计算要回退的列数,即制表符宽度减去实际占用的列数 let mut num_bs = 8 - (char_num & 7); if num_bs > space { // 表示左边没有足够空间回退 break; } space -= num_bs; while num_bs != 0 { num_bs -= 1; // 8 => '\b' if tty.put_char(tty.core(), 8).is_err() { tty.write(core, &[8], 1)?; } if self.cursor_column > 0 { self.cursor_column -= 1; } } // 已经读取了 tail tail+1 tail+2,所以这里偏移加3 tail += 3; } EchoOperation::Undefined(ch) => { match ch { 8 => { if tty.put_char(tty.core(), 8).is_err() { tty.write(core, &[8], 1)?; } if tty.put_char(tty.core(), b' ').is_err() { tty.write(core, &[b' '], 1)?; } self.cursor_column -= 1; space -= 1; tail += 1; } _ => { // 不是特殊字节码,则表示控制字符 例如 ^C if space < 2 { break; } if tty.put_char(tty.core(), b'^').is_err() { tty.write(core, &[b'^'], 1)?; } if tty.put_char(tty.core(), ch ^ 0o100).is_err() { tty.write(core, &[ch ^ 0o100], 1)?; } self.cursor_column += 2; space -= 2; tail += 2; } } } } } else { if termios.output_mode.contains(OutputMode::OPOST) { let ret = self.do_output_char(tty.clone(), c, space); if ret.is_err() { break; } space -= ret.unwrap(); } else { if space == 0 { break; } if tty.put_char(tty.core(), c).is_err() { tty.write(core, &[c], 1)?; } space -= 1; } tail += 1; } } // 如果回显缓冲区接近满(在下一次提交之前可能会发生回显溢出的情况),则丢弃足够的尾部数据以防止随后的溢出。 while self.echo_commit > tail && self.echo_commit - tail >= ECHO_DISCARD_WATERMARK { if self.echo_buf[ntty_buf_mask(tail)] == EchoOperation::Start.to_u8() { if self.echo_buf[ntty_buf_mask(tail + 1)] == EchoOperation::EraseTab.to_u8() { tail += 3; } else { tail += 2; } } else { tail += 1; } } self.echo_tail = tail; return Ok(ospace - space); } /// ## 处理输出字符(带有 OPOST 处理) pub fn process_output(&mut self, tty: Arc, c: u8) -> bool { let space = tty.write_room(tty.core()); if self.do_output_char(tty, c, space).is_err() { return false; } true } // ## 设置带有 OPOST 处理的tty输出一个字符 pub fn do_output_char( &mut self, tty: Arc, c: u8, space: usize, ) -> Result { if space == 0 { return Err(SystemError::ENOBUFS); } let termios = tty.core().termios(); let core = tty.core(); let mut c = c; if c as usize == 8 { // 表示退格 if self.cursor_column > 0 { self.cursor_column -= 1; } if tty.put_char(tty.core(), c).is_err() { tty.write(core, &[c], 1)?; } return Ok(1); } match c as char { '\n' => { if termios.output_mode.contains(OutputMode::ONLRET) { // 回车符 self.cursor_column = 0; } if termios.output_mode.contains(OutputMode::ONLCR) { // 映射为“\r\n” if space < 2 { return Err(SystemError::ENOBUFS); } self.cursor_column = 0; self.canon_cursor_column = 0; // 通过驱动写入 tty.write(core, "\r\n".as_bytes(), 2)?; return Ok(2); } self.canon_cursor_column = self.cursor_column; } '\r' => { if termios.output_mode.contains(OutputMode::ONOCR) && self.cursor_column == 0 { // 光标已经在第0列,则不输出回车符 return Ok(0); } if termios.output_mode.contains(OutputMode::OCRNL) { // 输出的\r映射为\n c = b'\n'; if termios.output_mode.contains(OutputMode::ONLRET) { // \r映射为\n,但是保留\r特性 self.cursor_column = 0; self.canon_cursor_column = 0; } } else { self.cursor_column = 0; self.canon_cursor_column = 0; } } '\t' => { // 计算输出一个\t需要的空间 let spaces = 8 - (self.cursor_column & 7) as usize; if termios.output_mode.contains(OutputMode::TABDLY) && OutputMode::TABDLY.bits() == OutputMode::XTABS.bits() { // 配置的tab选项是真正输出空格到驱动 if space < spaces { // 空间不够 return Err(SystemError::ENOBUFS); } self.cursor_column += spaces as u32; // 写入sapces个空格 tty.write(core, " ".as_bytes(), spaces)?; return Ok(spaces); } self.cursor_column += spaces as u32; } _ => { // 判断是否为控制字符 if !(c as char).is_control() { if termios.output_mode.contains(OutputMode::OLCUC) { c = c.to_ascii_uppercase(); } // 判断是否为utf8模式下的连续字符 if !(termios.input_mode.contains(InputMode::IUTF8) && (c as usize) & 0xc0 == 0x80) { self.cursor_column += 1; } } } } if tty.put_char(tty.core(), c).is_err() { tty.write(core, &[c], 1)?; } Ok(1) } fn packet_mode_flush(&self, tty: &TtyCoreData) { let link = tty.link().unwrap(); if link.core().contorl_info_irqsave().packet { tty.contorl_info_irqsave() .pktstatus .insert(TtyPacketStatus::TIOCPKT_FLUSHREAD); link.core().read_wq().wakeup_all(); } } } impl TtyLineDiscipline for NTtyLinediscipline { fn open(&self, tty: Arc) -> Result<(), system_error::SystemError> { // 反向绑定tty到disc self.disc_data().tty = Some(Arc::downgrade(&tty)); // 特定的tty设备在这里可能需要取消端口节流 return self.set_termios(tty, None); } fn close(&self, _tty: Arc) -> Result<(), system_error::SystemError> { todo!() } /// ## 重置缓冲区的基本信息 fn flush_buffer(&self, tty: Arc) -> Result<(), system_error::SystemError> { let core = tty.core(); let _ = core.termios(); let mut ldata = self.disc_data(); ldata.read_head = 0; ldata.canon_head = 0; ldata.read_tail = 0; ldata.commit_head = 0; ldata.line_start = 0; ldata.erasing = false; ldata.read_flags.set_all(false); ldata.pushing = false; ldata.lookahead_count = 0; // todo: kick worker? // packet mode? if core.link().is_some() { ldata.packet_mode_flush(core); } Ok(()) } #[inline(never)] fn read( &self, tty: Arc, buf: &mut [u8], len: usize, cookie: &mut bool, _offset: usize, mode: FileMode, ) -> Result { let mut ldata; if mode.contains(FileMode::O_NONBLOCK) { let ret = self.disc_data_try_lock(); if ret.is_err() { return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); } ldata = ret.unwrap(); } else { ldata = self.disc_data(); } let core = tty.core(); let termios = core.termios(); let mut nr = len; let mut offset = 0; // 表示接着读 if *cookie { // 规范且非拓展模式 if ldata.icanon && !termios.local_mode.contains(LocalMode::EXTPROC) { // 跳过EOF字符 if len == 0 { ldata.canon_skip_eof(); } else if ldata.canon_copy_from_read_buf(buf, &mut nr, &mut offset)? { return Ok(len - nr); } } else if ldata.copy_from_read_buf(termios, buf, &mut nr, &mut offset)? { return Ok(len - nr); } // 没有数据可读 // todo: kick worker? or 关闭节流? *cookie = false; return Ok(len - nr); } drop(termios); TtyJobCtrlManager::tty_check_change(tty.clone(), Signal::SIGTTIN)?; let mut minimum: usize = 0; if !ldata.icanon { let core = tty.core(); let termios = core.termios(); minimum = termios.control_characters[ControlCharIndex::VMIN] as usize; if minimum == 0 { minimum = 1; } } let packet = core.contorl_info_irqsave().packet; let mut ret: Result = Ok(0); // 记录读取前 的tail let tail = ldata.read_tail; drop(ldata); while nr != 0 { // todo: 处理packet模式 if packet { let link = core.link().unwrap(); let link = link.core(); let mut ctrl = link.contorl_info_irqsave(); if !ctrl.pktstatus.is_empty() { if offset != 0 { break; } let cs = ctrl.pktstatus; ctrl.pktstatus = TtyPacketStatus::empty(); buf[offset] = cs.bits(); offset += 1; // nr -= 1; break; } } let mut ldata = self.disc_data(); let core = tty.core(); if !ldata.input_available(core.termios(), false) { if core.flags().contains(TtyFlag::OTHER_CLOSED) { ret = Err(SystemError::EIO); break; } if core.flags().contains(TtyFlag::HUPPED) || core.flags().contains(TtyFlag::HUPPING) { break; } if mode.contains(FileMode::O_NONBLOCK) || core.flags().contains(TtyFlag::LDISC_CHANGING) { ret = Err(SystemError::EAGAIN_OR_EWOULDBLOCK); break; } if ProcessManager::current_pcb() .sig_info_irqsave() .sig_pending() .has_pending() { ret = Err(SystemError::ERESTARTSYS); break; } // 休眠一段时间 // 获取到termios读锁,避免termios被更改导致行为异常 // let termios = core.termios_preempt_enable(); // let helper = WakeUpHelper::new(ProcessManager::current_pcb()); // let wakeup_helper = Timer::new(helper, timeout); // wakeup_helper.activate(); // drop(termios); drop(ldata); core.read_wq() .sleep((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64); continue; } if ldata.icanon && !core.termios().local_mode.contains(LocalMode::EXTPROC) { if ldata.canon_copy_from_read_buf(buf, &mut nr, &mut offset)? { *cookie = true; offset += len - nr; return Ok(offset); } } else { // 非标准模式 // todo: 处理packet模式 if packet && offset == 0 { buf[offset] = TtyPacketStatus::TIOCPKT_DATA.bits(); offset += 1; nr -= 1; } // 拷贝数据 if ldata.copy_from_read_buf(core.termios(), buf, &mut nr, &mut offset)? && offset >= minimum { *cookie = true; return Ok(offset); } } if offset >= minimum { break; } } let ldata = self.disc_data(); if tail != ldata.read_tail { // todo: kick worker? } if offset > 0 { return Ok(offset); } ret } #[inline(never)] fn write( &self, tty: Arc, buf: &[u8], len: usize, mode: FileMode, ) -> Result { let mut nr = len; let mut ldata = self.disc_data(); let pcb = ProcessManager::current_pcb(); let binding = tty.clone(); let core = binding.core(); let termios = *core.termios(); if termios.local_mode.contains(LocalMode::TOSTOP) { TtyJobCtrlManager::tty_check_change(tty.clone(), Signal::SIGTTOU)?; } ldata.process_echoes(tty.clone()); // drop(ldata); let mut offset = 0; loop { if pcb.sig_info_irqsave().sig_pending().has_pending() { return Err(SystemError::ERESTARTSYS); } if core.flags().contains(TtyFlag::HUPPED) { return Err(SystemError::EIO); } if termios.output_mode.contains(OutputMode::OPOST) { while nr > 0 { // let mut ldata = self.disc_data(); // 获得一次处理后的数量 let ret = ldata.process_output_block(core, core.termios(), &buf[offset..], nr); let num = match ret { Ok(num) => num, Err(e) => { if e == SystemError::EAGAIN_OR_EWOULDBLOCK { break; } else { return Err(e); } } }; offset += num; nr -= num; if nr == 0 { break; } let c = buf[offset]; if !ldata.process_output(tty.clone(), c) { break; } offset += 1; nr -= 1; } tty.flush_chars(core); } else { while nr > 0 { let write = tty.write(core, &buf[offset..], nr)?; if write == 0 { break; } offset += write; nr -= write; } } if nr == 0 { break; } if mode.contains(FileMode::O_NONBLOCK) || core.flags().contains(TtyFlag::LDISC_CHANGING) { return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); } // 到这里表明没位置可写了 // 休眠一段时间 // 获取到termios读锁,避免termios被更改导致行为异常 core.write_wq() .sleep(EPollEventType::EPOLLOUT.bits() as u64); } Ok(offset) } fn ioctl( &self, tty: Arc, cmd: u32, arg: usize, ) -> Result { match cmd { TtyIoctlCmd::TIOCOUTQ => { let mut user_writer = UserBufferWriter::new( VirtAddr::new(arg).as_ptr::(), core::mem::size_of::(), true, )?; let count = tty.chars_in_buffer(); user_writer.copy_one_to_user::(&(count as i32), 0)?; return Ok(0); } TtyIoctlCmd::FIONREAD => { let ldata = self.disc_data(); let termios = tty.core().termios(); let retval; if termios.local_mode.contains(LocalMode::ICANON) && !termios.local_mode.contains(LocalMode::EXTPROC) { if ldata.canon_head == ldata.read_tail { retval = 0; } else { let head = ldata.canon_head; let mut tail = ldata.read_tail; let mut nr = head - tail; while ntty_buf_mask(head) != ntty_buf_mask(tail) { if ldata.read_flags.get(ntty_buf_mask(tail)).unwrap() && ldata.read_buf[ntty_buf_mask(tail)] == ControlCharIndex::DISABLE_CHAR { nr -= 1; } tail += 1; } retval = nr; } } else { retval = ldata.read_cnt(); } let mut user_writer = UserBufferWriter::new( VirtAddr::new(arg).as_ptr::(), core::mem::size_of::(), true, )?; user_writer.copy_one_to_user::(&(retval as i32), 0)?; return Ok(0); } _ => { return self.ioctl_helper(tty, cmd, arg); } } } #[inline(never)] fn set_termios( &self, tty: Arc, old: Option, ) -> Result<(), system_error::SystemError> { let core = tty.core(); let termios = core.termios(); let mut ldata = self.disc_data(); let contorl_chars = termios.control_characters; // 第一次设置或者规范模式 (ICANON) 或者扩展处理 (EXTPROC) 标志发生变化 let mut spec_mode_changed = false; if let Some(old) = old { let local_mode = old.local_mode.bitxor(termios.local_mode); spec_mode_changed = local_mode.contains(LocalMode::ICANON) || local_mode.contains(LocalMode::EXTPROC); } if old.is_none() || spec_mode_changed { // 重置read_flags ldata.read_flags.set_all(false); ldata.line_start = ldata.read_tail; // 不是规范模式或者有可读数据 if !termios.local_mode.contains(LocalMode::ICANON) || ldata.read_cnt() != 0 { ldata.canon_head = ldata.read_tail; ldata.pushing = false; } else { let read_head = ldata.read_head; ldata .read_flags .set((read_head - 1) & (NTTY_BUFSIZE - 1), true); ldata.canon_head = ldata.read_head; ldata.pushing = true; } ldata.commit_head = ldata.read_head; ldata.erasing = false; ldata.lnext = false; } // 设置模式 ldata.icanon = termios.local_mode.contains(LocalMode::ICANON); // 设置回显 if termios.local_mode.contains(LocalMode::ECHO) { ldata.echo = true; } if termios.input_mode.contains(InputMode::ISTRIP) || termios.input_mode.contains(InputMode::IUCLC) || termios.input_mode.contains(InputMode::IGNCR) || termios.input_mode.contains(InputMode::IXON) || termios.local_mode.contains(LocalMode::ISIG) || termios.local_mode.contains(LocalMode::ECHO) || termios.input_mode.contains(InputMode::PARMRK) { // 非原模式 ldata.char_map.set_all(false); // 忽略回车符或者将回车映射为换行符 if termios.input_mode.contains(InputMode::IGNCR) || termios.input_mode.contains(InputMode::ICRNL) { ldata.char_map.set('\r' as usize, true); } // 将换行映射为回车 if termios.input_mode.contains(InputMode::INLCR) { ldata.char_map.set('\n' as usize, true); } // 规范模式 if termios.local_mode.contains(LocalMode::ICANON) { ldata .char_map .set(contorl_chars[ControlCharIndex::VERASE] as usize, true); ldata .char_map .set(contorl_chars[ControlCharIndex::VKILL] as usize, true); ldata .char_map .set(contorl_chars[ControlCharIndex::VEOF] as usize, true); ldata.char_map.set('\n' as usize, true); ldata .char_map .set(contorl_chars[ControlCharIndex::VEOL] as usize, true); if termios.local_mode.contains(LocalMode::IEXTEN) { ldata .char_map .set(contorl_chars[ControlCharIndex::VWERASE] as usize, true); ldata .char_map .set(contorl_chars[ControlCharIndex::VLNEXT] as usize, true); ldata .char_map .set(contorl_chars[ControlCharIndex::VEOL2] as usize, true); if termios.local_mode.contains(LocalMode::ECHO) { ldata .char_map .set(contorl_chars[ControlCharIndex::VREPRINT] as usize, true); } } } // 软件流控制 if termios.input_mode.contains(InputMode::IXON) { ldata .char_map .set(contorl_chars[ControlCharIndex::VSTART] as usize, true); ldata .char_map .set(contorl_chars[ControlCharIndex::VSTOP] as usize, true); } if termios.local_mode.contains(LocalMode::ISIG) { ldata .char_map .set(contorl_chars[ControlCharIndex::VINTR] as usize, true); ldata .char_map .set(contorl_chars[ControlCharIndex::VQUIT] as usize, true); ldata .char_map .set(contorl_chars[ControlCharIndex::VSUSP] as usize, true); } ldata .char_map .set(ControlCharIndex::DISABLE_CHAR as usize, true); ldata.raw = false; ldata.real_raw = false; } else { // 原模式或real_raw ldata.raw = true; ldata.real_raw = termios.input_mode.contains(InputMode::IGNBRK) || (!termios.input_mode.contains(InputMode::BRKINT) && !termios.input_mode.contains(InputMode::PARMRK)) && (termios.input_mode.contains(InputMode::IGNPAR) || !termios.input_mode.contains(InputMode::INPCK)) && (core .driver() .flags() .contains(TtyDriverFlag::TTY_DRIVER_REAL_RAW)); } // if !termios.input_mode.contains(InputMode::IXON) // && old.is_some() // && old.unwrap().input_mode.contains(InputMode::IXON) && ! // {} core.read_wq().wakeup_all(); core.write_wq().wakeup_all(); Ok(()) } fn poll(&self, tty: Arc) -> Result { let core = tty.core(); let ldata = self.disc_data(); let mut event = EPollEventType::empty(); if ldata.input_available(core.termios(), true) { event.insert(EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM) } if core.contorl_info_irqsave().packet { let link = core.link(); if link.is_some() && !link .unwrap() .core() .contorl_info_irqsave() .pktstatus .is_empty() { event.insert( EPollEventType::EPOLLPRI | EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM, ); } } if core.flags().contains(TtyFlag::OTHER_CLOSED) { event.insert(EPollEventType::EPOLLHUP); } if core.driver().driver_funcs().chars_in_buffer() < 256 && core.driver().driver_funcs().write_room(core) > 0 { event.insert(EPollEventType::EPOLLOUT | EPollEventType::EPOLLWRNORM); } Ok(event.bits() as usize) } fn hangup(&self, _tty: Arc) -> Result<(), system_error::SystemError> { todo!() } fn receive_buf( &self, tty: Arc, buf: &[u8], flags: Option<&[u8]>, count: usize, ) -> Result { let mut ldata = self.disc_data(); ldata.receive_buf_common(tty, buf, flags, count, false) } fn receive_buf2( &self, tty: Arc, buf: &[u8], flags: Option<&[u8]>, count: usize, ) -> Result { let mut ldata = self.disc_data(); ldata.receive_buf_common(tty, buf, flags, count, true) } }