feat(tty): 将tty设备适配epoll,修改串口部分问题 (#968)

- tty文件适配epoll,使epoll能够监听tty
- 修改串口handle_irq,原有每次只读取一个字节会导致:输入left(esc+[+A)被错误解析为(esc)+([)+(A)三个字符
- 为串口加上vcdata用于控制输入输出的格式问题(未解决,这个pr捎带)
This commit is contained in:
GnoCiYeH 2024-10-13 01:10:36 +08:00 committed by GitHub
parent 40db1e61da
commit c709f79fda
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 148 additions and 106 deletions

View File

@ -19,12 +19,14 @@ use crate::{
}, },
serial::{AtomicBaudRate, BaudRate, DivisorFraction, UartPort}, serial::{AtomicBaudRate, BaudRate, DivisorFraction, UartPort},
tty::{ tty::{
console::ConsoleSwitch,
kthread::send_to_tty_refresh_thread, kthread::send_to_tty_refresh_thread,
termios::WindowSize, termios::WindowSize,
tty_core::{TtyCore, TtyCoreData}, tty_core::{TtyCore, TtyCoreData},
tty_driver::{TtyDriver, TtyDriverManager, TtyOperation}, tty_driver::{TtyDriver, TtyDriverManager, TtyOperation},
virtual_terminal::{vc_manager, VirtConsole}, virtual_terminal::{vc_manager, virtual_console::VirtualConsoleData, VirtConsole},
}, },
video::console::dummycon::dummy_console,
}, },
exception::{ exception::{
irqdata::IrqHandlerData, irqdata::IrqHandlerData,
@ -32,7 +34,7 @@ use crate::{
manage::irq_manager, manage::irq_manager,
IrqNumber, IrqNumber,
}, },
libs::rwlock::RwLock, libs::{rwlock::RwLock, spinlock::SpinLock},
}; };
use system_error::SystemError; use system_error::SystemError;
@ -265,9 +267,20 @@ impl UartPort for Serial8250PIOPort {
} }
fn handle_irq(&self) -> Result<(), SystemError> { fn handle_irq(&self) -> Result<(), SystemError> {
if let Some(c) = self.read_one_byte() { let mut buf = [0; 8];
send_to_tty_refresh_thread(&[c]); let mut index = 0;
// Read up to the size of the buffer
while index < buf.len() {
if let Some(c) = self.read_one_byte() {
buf[index] = c;
index += 1;
} else {
break; // No more bytes to read
}
} }
send_to_tty_refresh_thread(&buf[0..index]);
Ok(()) Ok(())
} }
@ -385,7 +398,18 @@ impl TtyOperation for Serial8250PIOTtyDriverInner {
if tty.core().index() >= unsafe { PIO_PORTS.len() } { if tty.core().index() >= unsafe { PIO_PORTS.len() } {
return Err(SystemError::ENODEV); return Err(SystemError::ENODEV);
} }
let vc = VirtConsole::new(None);
*tty.core().window_size_write() = WindowSize::DEFAULT;
let vc_data = Arc::new(SpinLock::new(VirtualConsoleData::new(usize::MAX)));
let mut vc_data_guard = vc_data.lock_irqsave();
vc_data_guard.set_driver_funcs(Arc::downgrade(&dummy_console()) as Weak<dyn ConsoleSwitch>);
vc_data_guard.init(
Some(tty.core().window_size().row.into()),
Some(tty.core().window_size().col.into()),
true,
);
drop(vc_data_guard);
let vc = VirtConsole::new(Some(vc_data));
let vc_index = vc_manager().alloc(vc.clone()).ok_or(SystemError::EBUSY)?; let vc_index = vc_manager().alloc(vc.clone()).ok_or(SystemError::EBUSY)?;
self.do_install(driver, tty, vc.clone()).inspect_err(|_| { self.do_install(driver, tty, vc.clone()).inspect_err(|_| {
vc_manager().free(vc_index); vc_manager().free(vc_index);

View File

@ -2,7 +2,7 @@ use super::tty_ldisc::LineDisciplineType;
/// ## 窗口大小 /// ## 窗口大小
#[repr(C)] #[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct WindowSize { pub struct WindowSize {
/// 行 /// 行
pub row: u16, pub row: u16,
@ -26,12 +26,6 @@ impl WindowSize {
} }
} }
impl Default for WindowSize {
fn default() -> Self {
Self::DEFAULT
}
}
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct Termios { pub struct Termios {
pub input_mode: InputMode, pub input_mode: InputMode,

View File

@ -31,7 +31,7 @@ use super::{
TtyLineDiscipline, TtyLineDiscipline,
}, },
tty_port::TtyPort, tty_port::TtyPort,
virtual_terminal::{vc_manager, virtual_console::VirtualConsoleData}, virtual_terminal::{vc_manager, virtual_console::VirtualConsoleData, DrawRegion},
}; };
#[derive(Debug)] #[derive(Debug)]
@ -489,6 +489,61 @@ impl TtyCoreData {
pub fn add_epitem(&self, epitem: Arc<EPollItem>) { pub fn add_epitem(&self, epitem: Arc<EPollItem>) {
self.epitems.lock().push_back(epitem) self.epitems.lock().push_back(epitem)
} }
pub fn eptiems(&self) -> &SpinLock<LinkedList<Arc<EPollItem>>> {
&self.epitems
}
pub fn do_write(&self, buf: &[u8], mut nr: usize) -> Result<usize, SystemError> {
// 关闭中断
if let Some(vc_data) = self.vc_data() {
let mut vc_data_guard = vc_data.lock_irqsave();
let mut offset = 0;
// 这个参数是用来扫描unicode字符的但是这部分目前未完成先写着
let mut rescan = false;
let mut ch: u32 = 0;
let mut draw = DrawRegion::default();
// 首先隐藏光标再写
vc_data_guard.hide_cursor();
while nr != 0 {
if !rescan {
ch = buf[offset] as u32;
offset += 1;
nr -= 1;
}
let (tc, rescan_last) = vc_data_guard.translate(&mut ch);
if tc.is_none() {
// 表示未转换完成
continue;
}
let tc = tc.unwrap();
rescan = rescan_last;
if vc_data_guard.is_control(tc, ch) {
vc_data_guard.flush(&mut draw);
vc_data_guard.do_control(ch);
continue;
}
if !vc_data_guard.console_write_normal(tc, ch, &mut draw) {
continue;
}
}
vc_data_guard.flush(&mut draw);
// TODO: notify update
return Ok(offset);
} else {
return Ok(0);
}
}
} }
impl TtyOperation for TtyCore { impl TtyOperation for TtyCore {

View File

@ -4,7 +4,10 @@ use alloc::sync::{Arc, Weak};
use kdepends::thingbuf::mpsc; use kdepends::thingbuf::mpsc;
use system_error::SystemError; use system_error::SystemError;
use crate::libs::spinlock::{SpinLock, SpinLockGuard}; use crate::{
libs::spinlock::{SpinLock, SpinLockGuard},
net::event_poll::EventPoll,
};
use super::tty_core::TtyCore; use super::tty_core::TtyCore;
@ -85,6 +88,8 @@ pub trait TtyPort: Sync + Send + Debug {
return ld.receive_buf(tty, buf, None, count); return ld.receive_buf(tty, buf, None, count);
} }
EventPoll::wakeup_epoll(tty.core().eptiems(), None)?;
ret ret
} }
} }

View File

@ -300,55 +300,6 @@ impl TtyConsoleDriverInner {
Ok(Self { console }) Ok(Self { console })
} }
fn do_write(&self, tty: &TtyCoreData, buf: &[u8], mut nr: usize) -> Result<usize, SystemError> {
// 关闭中断
let vc_data = tty.vc_data().unwrap();
let mut vc_data_guard = vc_data.lock_irqsave();
let mut offset = 0;
// 这个参数是用来扫描unicode字符的但是这部分目前未完成先写着
let mut rescan = false;
let mut ch: u32 = 0;
let mut draw = DrawRegion::default();
// 首先隐藏光标再写
vc_data_guard.hide_cursor();
while nr != 0 {
if !rescan {
ch = buf[offset] as u32;
offset += 1;
nr -= 1;
}
let (tc, rescan_last) = vc_data_guard.translate(&mut ch);
if tc.is_none() {
// 表示未转换完成
continue;
}
let tc = tc.unwrap();
rescan = rescan_last;
if vc_data_guard.is_control(tc, ch) {
vc_data_guard.flush(&mut draw);
vc_data_guard.do_control(ch);
continue;
}
if !vc_data_guard.console_write_normal(tc, ch, &mut draw) {
continue;
}
}
vc_data_guard.flush(&mut draw);
// TODO: notify update
return Ok(offset);
}
fn do_install(&self, tty: Arc<TtyCore>, vc: &Arc<VirtConsole>) -> Result<(), SystemError> { fn do_install(&self, tty: Arc<TtyCore>, vc: &Arc<VirtConsole>) -> Result<(), SystemError> {
let tty_core = tty.core(); let tty_core = tty.core();
@ -426,7 +377,7 @@ impl TtyOperation for TtyConsoleDriverInner {
// loop {} // loop {}
// } // }
send_to_default_serial8250_port(buf); send_to_default_serial8250_port(buf);
let ret = self.do_write(tty, buf, nr); let ret = tty.do_write(buf, nr);
self.flush_chars(tty); self.flush_chars(tty);
ret ret
} }

View File

@ -206,7 +206,7 @@ impl VirtualConsoleData {
} }
} }
pub(super) fn init(&mut self, rows: Option<usize>, cols: Option<usize>, clear: bool) { pub fn init(&mut self, rows: Option<usize>, cols: Option<usize>, clear: bool) {
if let Some(rows) = rows { if let Some(rows) = rows {
self.rows = rows; self.rows = rows;
} }
@ -242,7 +242,7 @@ impl VirtualConsoleData {
self.driver_funcs.as_ref().unwrap().upgrade().unwrap() self.driver_funcs.as_ref().unwrap().upgrade().unwrap()
} }
pub(super) fn set_driver_funcs(&mut self, func: Weak<dyn ConsoleSwitch>) { pub fn set_driver_funcs(&mut self, func: Weak<dyn ConsoleSwitch>) {
self.driver_funcs = Some(func); self.driver_funcs = Some(func);
} }
@ -312,7 +312,7 @@ impl VirtualConsoleData {
/// ///
/// ### 返回值 /// ### 返回值
/// ### (转换后的字符:i32是否需要更多的数据才能进行转换:bool /// ### (转换后的字符:i32是否需要更多的数据才能进行转换:bool
pub(super) fn translate(&mut self, c: &mut u32) -> (Option<u32>, bool) { pub fn translate(&mut self, c: &mut u32) -> (Option<u32>, bool) {
if self.vc_state != VirtualConsoleState::ESnormal { if self.vc_state != VirtualConsoleState::ESnormal {
// 在控制字符状态下不需要翻译 // 在控制字符状态下不需要翻译
return (Some(*c), false); return (Some(*c), false);
@ -440,7 +440,7 @@ impl VirtualConsoleData {
const CTRL_ALWAYS: u32 = 0x0800f501; const CTRL_ALWAYS: u32 = 0x0800f501;
/// ## 用于判断tc(终端字符)在当前VC下是不是需要显示的控制字符 /// ## 用于判断tc(终端字符)在当前VC下是不是需要显示的控制字符
pub(super) fn is_control(&self, tc: u32, c: u32) -> bool { pub fn is_control(&self, tc: u32, c: u32) -> bool {
// 当前vc状态机不在正常状态即在接收特殊字符的状态则是控制字符 // 当前vc状态机不在正常状态即在接收特殊字符的状态则是控制字符
if self.vc_state != VirtualConsoleState::ESnormal { if self.vc_state != VirtualConsoleState::ESnormal {
return true; return true;
@ -1257,7 +1257,7 @@ impl VirtualConsoleData {
/// ## 处理终端控制字符 /// ## 处理终端控制字符
#[inline(never)] #[inline(never)]
pub(super) fn do_control(&mut self, ch: u32) { pub fn do_control(&mut self, ch: u32) {
// 首先检查是否处于 ANSI 控制字符串状态 // 首先检查是否处于 ANSI 控制字符串状态
if self.vc_state.is_ansi_control_string() && (8..=13).contains(&ch) { if self.vc_state.is_ansi_control_string() && (8..=13).contains(&ch) {
return; return;
@ -1534,12 +1534,7 @@ impl VirtualConsoleData {
} }
#[inline(never)] #[inline(never)]
pub(super) fn console_write_normal( pub fn console_write_normal(&mut self, mut tc: u32, c: u32, draw: &mut DrawRegion) -> bool {
&mut self,
mut tc: u32,
c: u32,
draw: &mut DrawRegion,
) -> bool {
let mut attr = self.attr; let mut attr = self.attr;
let himask = self.hi_font_mask; let himask = self.hi_font_mask;
let charmask = if himask == 0 { 0xff } else { 0x1ff }; let charmask = if himask == 0 { 0xff } else { 0x1ff };
@ -1753,7 +1748,7 @@ impl VirtualConsoleData {
return (self.attr & 0x88) | ((self.attr & 0x70) >> 4) | ((self.attr & 0x07) << 4); return (self.attr & 0x88) | ((self.attr & 0x70) >> 4) | ((self.attr & 0x07) << 4);
} }
pub(super) fn flush(&self, draw: &mut DrawRegion) { pub fn flush(&self, draw: &mut DrawRegion) {
if draw.x.is_none() { if draw.x.is_none() {
return; return;
} }

View File

@ -137,7 +137,7 @@ impl IndexNode for EventFdInode {
let pollflag = EPollEventType::from_bits_truncate(self.poll(&data)? as u32); let pollflag = EPollEventType::from_bits_truncate(self.poll(&data)? as u32);
// 唤醒epoll中等待的进程 // 唤醒epoll中等待的进程
EventPoll::wakeup_epoll(&self.epitems, pollflag)?; EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?;
return Ok(8); return Ok(8);
} }
@ -184,7 +184,7 @@ impl IndexNode for EventFdInode {
let pollflag = EPollEventType::from_bits_truncate(self.poll(&data)? as u32); let pollflag = EPollEventType::from_bits_truncate(self.poll(&data)? as u32);
// 唤醒epoll中等待的进程 // 唤醒epoll中等待的进程
EventPoll::wakeup_epoll(&self.epitems, pollflag)?; EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?;
return Ok(8); return Ok(8);
} }

View File

@ -399,6 +399,15 @@ impl IndexNode for MountFSInode {
return self.inner_inode.ioctl(cmd, data, private_data); return self.inner_inode.ioctl(cmd, data, private_data);
} }
#[inline]
fn kernel_ioctl(
&self,
arg: Arc<dyn crate::net::event_poll::KernelIoctlData>,
data: &FilePrivateData,
) -> Result<usize, SystemError> {
return self.inner_inode.kernel_ioctl(arg, data);
}
#[inline] #[inline]
fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> { fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> {
return self.inner_inode.list(); return self.inner_inode.list();

View File

@ -267,7 +267,7 @@ impl IndexNode for LockedPipeInode {
let pollflag = EPollEventType::from_bits_truncate(inode.poll(&data)? as u32); let pollflag = EPollEventType::from_bits_truncate(inode.poll(&data)? as u32);
// 唤醒epoll中等待的进程 // 唤醒epoll中等待的进程
EventPoll::wakeup_epoll(&inode.epitems, pollflag)?; EventPoll::wakeup_epoll(&inode.epitems, Some(pollflag))?;
//返回读取的字节数 //返回读取的字节数
return Ok(num); return Ok(num);
@ -413,7 +413,7 @@ impl IndexNode for LockedPipeInode {
let pollflag = EPollEventType::from_bits_truncate(inode.poll(&data)? as u32); let pollflag = EPollEventType::from_bits_truncate(inode.poll(&data)? as u32);
// 唤醒epoll中等待的进程 // 唤醒epoll中等待的进程
EventPoll::wakeup_epoll(&inode.epitems, pollflag)?; EventPoll::wakeup_epoll(&inode.epitems, Some(pollflag))?;
// 返回写入的字节数 // 返回写入的字节数
return Ok(len); return Ok(len);

View File

@ -716,41 +716,50 @@ impl EventPoll {
/// ### epoll的回调支持epoll的文件有事件到来时直接调用该方法即可 /// ### epoll的回调支持epoll的文件有事件到来时直接调用该方法即可
pub fn wakeup_epoll( pub fn wakeup_epoll(
epitems: &SpinLock<LinkedList<Arc<EPollItem>>>, epitems: &SpinLock<LinkedList<Arc<EPollItem>>>,
pollflags: EPollEventType, pollflags: Option<EPollEventType>,
) -> Result<(), SystemError> { ) -> Result<(), SystemError> {
let mut epitems_guard = epitems.try_lock_irqsave()?; let mut epitems_guard = epitems.try_lock_irqsave()?;
// 一次只取一个,因为一次也只有一个进程能拿到对应文件的🔓 // 一次只取一个,因为一次也只有一个进程能拿到对应文件的🔓
if let Some(epitem) = epitems_guard.pop_front() { if let Some(epitem) = epitems_guard.pop_front() {
let epoll = epitem.epoll().upgrade().unwrap(); let pollflags = pollflags.unwrap_or({
let mut epoll_guard = epoll.try_lock()?; if let Some(file) = epitem.file.upgrade() {
let binding = epitem.clone(); EPollEventType::from_bits_truncate(file.poll()? as u32)
let event_guard = binding.event().read(); } else {
let ep_events = EPollEventType::from_bits_truncate(event_guard.events()); EPollEventType::empty()
}
});
// 检查事件合理性以及是否有感兴趣的事件 if let Some(epoll) = epitem.epoll().upgrade() {
if !(ep_events let mut epoll_guard = epoll.try_lock()?;
.difference(EPollEventType::EP_PRIVATE_BITS) let binding = epitem.clone();
.is_empty() let event_guard = binding.event().read();
|| pollflags.difference(ep_events).is_empty()) let ep_events = EPollEventType::from_bits_truncate(event_guard.events());
{
// TODO: 未处理pm相关
// 首先将就绪的epitem加入等待队列 // 检查事件合理性以及是否有感兴趣的事件
epoll_guard.ep_add_ready(epitem.clone()); if !(ep_events
.difference(EPollEventType::EP_PRIVATE_BITS)
.is_empty()
|| pollflags.difference(ep_events).is_empty())
{
// TODO: 未处理pm相关
if epoll_guard.ep_has_waiter() { // 首先将就绪的epitem加入等待队列
if ep_events.contains(EPollEventType::EPOLLEXCLUSIVE) epoll_guard.ep_add_ready(epitem.clone());
&& !pollflags.contains(EPollEventType::POLLFREE)
{ if epoll_guard.ep_has_waiter() {
// 避免惊群 if ep_events.contains(EPollEventType::EPOLLEXCLUSIVE)
epoll_guard.ep_wake_one(); && !pollflags.contains(EPollEventType::POLLFREE)
} else { {
epoll_guard.ep_wake_all(); // 避免惊群
epoll_guard.ep_wake_one();
} else {
epoll_guard.ep_wake_all();
}
} }
} }
}
epitems_guard.push_back(epitem); epitems_guard.push_back(epitem);
}
} }
Ok(()) Ok(())
} }

View File

@ -233,7 +233,7 @@ fn send_event(sockets: &smoltcp::iface::SocketSet) -> Result<(), SystemError> {
} }
EventPoll::wakeup_epoll( EventPoll::wakeup_epoll(
&posix_item.epitems, &posix_item.epitems,
EPollEventType::from_bits_truncate(events as u32), Some(EPollEventType::from_bits_truncate(events as u32)),
)?; )?;
drop(handle_guard); drop(handle_guard);
// crate::debug!( // crate::debug!(