mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-18 20:36:31 +00:00
实现pty,附带测试程序 (#685)
* 实现pty,附带测试程序 * fmt ** clippy * 将file层的锁粒度缩小,从而不使用no_preempt。更改pipe在sleep部分的bug * 修复拼写错误
This commit is contained in:
@ -18,6 +18,12 @@ impl Major {
|
||||
/// /dev/fb* framebuffers
|
||||
pub const FB_MAJOR: Self = Self::new(29);
|
||||
|
||||
/// Pty
|
||||
pub const UNIX98_PTY_MASTER_MAJOR: Self = Self::new(128);
|
||||
pub const UNIX98_PTY_MAJOR_COUNT: Self = Self::new(8);
|
||||
pub const UNIX98_PTY_SLAVE_MAJOR: Self =
|
||||
Self::new(Self::UNIX98_PTY_MASTER_MAJOR.0 + Self::UNIX98_PTY_MAJOR_COUNT.0);
|
||||
|
||||
pub const fn new(x: u32) -> Self {
|
||||
Major(x)
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ use crate::filesystem::vfs::syscall::ModeType;
|
||||
use crate::filesystem::vfs::{
|
||||
core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata,
|
||||
};
|
||||
use crate::libs::spinlock::SpinLockGuard;
|
||||
use crate::{libs::spinlock::SpinLock, time::TimeSpec};
|
||||
use alloc::{
|
||||
string::String,
|
||||
@ -76,11 +77,15 @@ impl IndexNode for LockedAhciInode {
|
||||
self
|
||||
}
|
||||
|
||||
fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), SystemError> {
|
||||
fn open(
|
||||
&self,
|
||||
_data: SpinLockGuard<FilePrivateData>,
|
||||
_mode: &FileMode,
|
||||
) -> Result<(), SystemError> {
|
||||
Err(SystemError::EOPNOTSUPP_OR_ENOTSUP)
|
||||
}
|
||||
|
||||
fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
|
||||
fn close(&self, _data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> {
|
||||
Err(SystemError::EOPNOTSUPP_OR_ENOTSUP)
|
||||
}
|
||||
|
||||
@ -114,13 +119,13 @@ impl IndexNode for LockedAhciInode {
|
||||
offset: usize, // lba地址
|
||||
len: usize,
|
||||
buf: &mut [u8],
|
||||
data: &mut FilePrivateData,
|
||||
data: SpinLockGuard<FilePrivateData>,
|
||||
) -> Result<usize, SystemError> {
|
||||
if buf.len() < len {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
|
||||
if let FilePrivateData::Unused = data {
|
||||
if let FilePrivateData::Unused = *data {
|
||||
return self.0.lock().disk.read_at_bytes(offset, len, buf);
|
||||
}
|
||||
|
||||
@ -133,13 +138,13 @@ impl IndexNode for LockedAhciInode {
|
||||
offset: usize, // lba地址
|
||||
len: usize,
|
||||
buf: &[u8],
|
||||
data: &mut FilePrivateData,
|
||||
data: SpinLockGuard<FilePrivateData>,
|
||||
) -> Result<usize, SystemError> {
|
||||
if buf.len() < len {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
|
||||
if let FilePrivateData::Unused = data {
|
||||
if let FilePrivateData::Unused = *data {
|
||||
return self.0.lock().disk.write_at_bytes(offset, len, buf);
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ use crate::{
|
||||
},
|
||||
libs::{
|
||||
rwlock::{RwLockReadGuard, RwLockWriteGuard},
|
||||
spinlock::SpinLock,
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
},
|
||||
time::TimeSpec,
|
||||
};
|
||||
@ -587,7 +587,7 @@ impl DeviceINode for Ps2MouseDevice {
|
||||
impl IndexNode for Ps2MouseDevice {
|
||||
fn open(
|
||||
&self,
|
||||
_data: &mut FilePrivateData,
|
||||
_data: SpinLockGuard<FilePrivateData>,
|
||||
_mode: &crate::filesystem::vfs::file::FileMode,
|
||||
) -> Result<(), SystemError> {
|
||||
let mut guard = self.inner.lock_irqsave();
|
||||
@ -595,7 +595,7 @@ impl IndexNode for Ps2MouseDevice {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
|
||||
fn close(&self, _data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> {
|
||||
let mut guard = self.inner.lock_irqsave();
|
||||
guard.buf.clear();
|
||||
Ok(())
|
||||
@ -606,7 +606,7 @@ impl IndexNode for Ps2MouseDevice {
|
||||
_offset: usize,
|
||||
_len: usize,
|
||||
buf: &mut [u8],
|
||||
_data: &mut FilePrivateData,
|
||||
_data: SpinLockGuard<FilePrivateData>,
|
||||
) -> Result<usize, SystemError> {
|
||||
let mut guard = self.inner.lock_irqsave();
|
||||
|
||||
@ -625,7 +625,7 @@ impl IndexNode for Ps2MouseDevice {
|
||||
_offset: usize,
|
||||
_len: usize,
|
||||
_buf: &[u8],
|
||||
_data: &mut FilePrivateData,
|
||||
_data: SpinLockGuard<FilePrivateData>,
|
||||
) -> Result<usize, SystemError> {
|
||||
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||
}
|
||||
|
@ -27,7 +27,11 @@ use crate::{
|
||||
},
|
||||
},
|
||||
init::initcall::INITCALL_DEVICE,
|
||||
libs::{keyboard_parser::TypeOneFSM, rwlock::RwLock, spinlock::SpinLock},
|
||||
libs::{
|
||||
keyboard_parser::TypeOneFSM,
|
||||
rwlock::RwLock,
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
},
|
||||
time::TimeSpec,
|
||||
};
|
||||
use system_error::SystemError;
|
||||
@ -115,7 +119,7 @@ impl IndexNode for LockedPS2KeyBoardInode {
|
||||
_offset: usize,
|
||||
_len: usize,
|
||||
_buf: &mut [u8],
|
||||
_data: &mut FilePrivateData,
|
||||
_data: SpinLockGuard<FilePrivateData>,
|
||||
) -> Result<usize, SystemError> {
|
||||
return Err(SystemError::ENOSYS);
|
||||
}
|
||||
@ -125,16 +129,20 @@ impl IndexNode for LockedPS2KeyBoardInode {
|
||||
_offset: usize,
|
||||
_len: usize,
|
||||
_buf: &[u8],
|
||||
_data: &mut FilePrivateData,
|
||||
_data: SpinLockGuard<FilePrivateData>,
|
||||
) -> Result<usize, SystemError> {
|
||||
return Err(SystemError::ENOSYS);
|
||||
}
|
||||
|
||||
fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), SystemError> {
|
||||
fn open(
|
||||
&self,
|
||||
_data: SpinLockGuard<FilePrivateData>,
|
||||
_mode: &FileMode,
|
||||
) -> Result<(), SystemError> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
|
||||
fn close(&self, _data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ use kdepends::thingbuf::StaticThingBuf;
|
||||
|
||||
use crate::{
|
||||
arch::sched::sched,
|
||||
driver::tty::virtual_terminal::virtual_console::CURRENT_VCNUM,
|
||||
process::{
|
||||
kthread::{KernelThreadClosure, KernelThreadMechanism},
|
||||
ProcessControlBlock, ProcessFlags,
|
||||
@ -54,7 +55,12 @@ fn tty_refresh_thread() -> i32 {
|
||||
*item = KEYBUF.pop().unwrap();
|
||||
}
|
||||
|
||||
let _ = current_tty_port().receive_buf(&data[0..to_dequeue], &[], to_dequeue);
|
||||
if CURRENT_VCNUM.load(core::sync::atomic::Ordering::SeqCst) != -1 {
|
||||
let _ = current_tty_port().receive_buf(&data[0..to_dequeue], &[], to_dequeue);
|
||||
} else {
|
||||
// 这里由于stdio未初始化,所以无法找到port
|
||||
// TODO: 考虑改用双端队列,能够将丢失的输入插回
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ use alloc::vec::Vec;
|
||||
|
||||
pub mod console;
|
||||
pub mod kthread;
|
||||
pub mod pty;
|
||||
mod sysfs;
|
||||
pub mod termios;
|
||||
pub mod tty_core;
|
||||
|
288
kernel/src/driver/tty/pty/mod.rs
Normal file
288
kernel/src/driver/tty/pty/mod.rs
Normal file
@ -0,0 +1,288 @@
|
||||
use alloc::{
|
||||
string::{String, ToString},
|
||||
sync::Arc,
|
||||
};
|
||||
use system_error::SystemError;
|
||||
use unified_init::macros::unified_init;
|
||||
|
||||
use crate::{
|
||||
driver::base::device::{
|
||||
device_number::{DeviceNumber, Major},
|
||||
device_register, IdTable,
|
||||
},
|
||||
filesystem::devfs::devfs_register,
|
||||
init::initcall::INITCALL_DEVICE,
|
||||
libs::lazy_init::Lazy,
|
||||
mm::VirtAddr,
|
||||
syscall::user_access::{UserBufferReader, UserBufferWriter},
|
||||
};
|
||||
|
||||
use self::unix98pty::{Unix98PtyDriverInner, NR_UNIX98_PTY_MAX};
|
||||
|
||||
use super::{
|
||||
termios::{ControlMode, InputMode, LocalMode, OutputMode, TTY_STD_TERMIOS},
|
||||
tty_core::{TtyCore, TtyCoreData, TtyFlag, TtyPacketStatus},
|
||||
tty_device::{TtyDevice, TtyType},
|
||||
tty_driver::{TtyDriver, TtyDriverManager, TtyDriverSubType, TtyDriverType, TTY_DRIVERS},
|
||||
tty_port::{DefaultTtyPort, TtyPort},
|
||||
};
|
||||
|
||||
pub mod unix98pty;
|
||||
|
||||
static PTM_DRIVER: Lazy<Arc<TtyDriver>> = Lazy::new();
|
||||
static PTS_DRIVER: Lazy<Arc<TtyDriver>> = Lazy::new();
|
||||
|
||||
pub(super) fn ptm_driver() -> Arc<TtyDriver> {
|
||||
PTM_DRIVER.ensure();
|
||||
PTM_DRIVER.get().clone()
|
||||
}
|
||||
|
||||
pub(super) fn pts_driver() -> Arc<TtyDriver> {
|
||||
PTS_DRIVER.ensure();
|
||||
PTS_DRIVER.get().clone()
|
||||
}
|
||||
|
||||
// lazy_static! {
|
||||
// pub static ref PTM_DRIVER: Arc<TtyDriver> = {
|
||||
// let mut ptm_driver = TtyDriver::new(
|
||||
// NR_UNIX98_PTY_MAX,
|
||||
// "ptm",
|
||||
// 0,
|
||||
// Major::UNIX98_PTY_MASTER_MAJOR,
|
||||
// 0,
|
||||
// TtyDriverType::Pty,
|
||||
// *TTY_STD_TERMIOS,
|
||||
// Arc::new(Unix98PtyDriverInner::new()),
|
||||
// );
|
||||
|
||||
// ptm_driver.set_subtype(TtyDriverSubType::PtyMaster);
|
||||
// let term = ptm_driver.init_termios_mut();
|
||||
// term.input_mode = InputMode::empty();
|
||||
// term.output_mode = OutputMode::empty();
|
||||
// term.control_mode = ControlMode::B38400 | ControlMode::CS8 | ControlMode::CREAD;
|
||||
// term.local_mode = LocalMode::empty();
|
||||
// term.input_speed = 38400;
|
||||
// term.output_speed = 38400;
|
||||
// TtyDriverManager::tty_register_driver(ptm_driver).unwrap()
|
||||
// };
|
||||
// pub static ref PTS_DRIVER: Arc<TtyDriver> = {
|
||||
// let mut pts_driver = TtyDriver::new(
|
||||
// NR_UNIX98_PTY_MAX,
|
||||
// "pts",
|
||||
// 0,
|
||||
// Major::UNIX98_PTY_SLAVE_MAJOR,
|
||||
// 0,
|
||||
// TtyDriverType::Pty,
|
||||
// *TTY_STD_TERMIOS,
|
||||
// Arc::new(Unix98PtyDriverInner::new()),
|
||||
// );
|
||||
|
||||
// pts_driver.set_subtype(TtyDriverSubType::PtySlave);
|
||||
// let term = pts_driver.init_termios_mut();
|
||||
// term.input_mode = InputMode::empty();
|
||||
// term.output_mode = OutputMode::empty();
|
||||
// term.control_mode = ControlMode::B38400 | ControlMode::CS8 | ControlMode::CREAD;
|
||||
// term.local_mode = LocalMode::empty();
|
||||
// term.input_speed = 38400;
|
||||
// term.output_speed = 38400;
|
||||
// TtyDriverManager::tty_register_driver(pts_driver).unwrap()
|
||||
// };
|
||||
// }
|
||||
|
||||
pub struct PtyCommon;
|
||||
|
||||
impl PtyCommon {
|
||||
pub fn pty_common_install(
|
||||
driver: Arc<TtyDriver>,
|
||||
tty: Arc<TtyCore>,
|
||||
legacy: bool,
|
||||
) -> Result<(), SystemError> {
|
||||
let core = tty.core();
|
||||
let other_driver = driver.other_pty_driver().unwrap();
|
||||
let other_tty = TtyCore::new(other_driver.clone(), core.index());
|
||||
other_driver.add_tty(other_tty.clone());
|
||||
|
||||
let port0: Arc<dyn TtyPort> = Arc::new(DefaultTtyPort::new());
|
||||
let port1: Arc<dyn TtyPort> = Arc::new(DefaultTtyPort::new());
|
||||
|
||||
let o_core = other_tty.core();
|
||||
|
||||
if legacy {
|
||||
core.init_termios();
|
||||
o_core.init_termios();
|
||||
|
||||
driver
|
||||
.other_pty_driver()
|
||||
.unwrap()
|
||||
.ttys()
|
||||
.insert(core.index(), other_tty.clone());
|
||||
driver.ttys().insert(core.index(), tty.clone());
|
||||
} else {
|
||||
*core.termios_write() = driver.init_termios();
|
||||
*o_core.termios_write() = driver.other_pty_driver().unwrap().init_termios();
|
||||
}
|
||||
|
||||
core.set_link(Arc::downgrade(&other_tty));
|
||||
o_core.set_link(Arc::downgrade(&tty));
|
||||
|
||||
port0.setup_internal_tty(Arc::downgrade(&other_tty));
|
||||
port1.setup_internal_tty(Arc::downgrade(&tty));
|
||||
other_tty.set_port(port0);
|
||||
tty.set_port(port1);
|
||||
|
||||
core.add_count();
|
||||
o_core.add_count();
|
||||
|
||||
// 将pts加入pts Driver管理队列
|
||||
PTS_DRIVER.ttys().insert(core.index(), other_tty);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pty_common_open(core: &TtyCoreData) -> Result<(), SystemError> {
|
||||
if let Some(link) = core.link() {
|
||||
let link_core = link.core();
|
||||
|
||||
if core.flags().contains(TtyFlag::OTHER_CLOSED) {
|
||||
core.flags_write().insert(TtyFlag::IO_ERROR);
|
||||
return Err(SystemError::EIO);
|
||||
}
|
||||
|
||||
if link_core.flags().contains(TtyFlag::PTY_LOCK) {
|
||||
core.flags_write().insert(TtyFlag::IO_ERROR);
|
||||
return Err(SystemError::EIO);
|
||||
}
|
||||
|
||||
if core.driver().tty_driver_sub_type() == TtyDriverSubType::PtySlave
|
||||
&& link_core.count() != 1
|
||||
{
|
||||
// 只能有一个master,如果当前为slave,则link的count必须为1
|
||||
core.flags_write().insert(TtyFlag::IO_ERROR);
|
||||
return Err(SystemError::EIO);
|
||||
}
|
||||
|
||||
core.flags_write().remove(TtyFlag::IO_ERROR);
|
||||
link_core.flags_write().remove(TtyFlag::OTHER_CLOSED);
|
||||
core.flags_write().insert(TtyFlag::THROTTLED);
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
return Err(SystemError::ENODEV);
|
||||
}
|
||||
|
||||
pub fn pty_set_lock(tty: &TtyCoreData, arg: VirtAddr) -> Result<(), SystemError> {
|
||||
let user_reader =
|
||||
UserBufferReader::new(arg.as_ptr::<i32>(), core::mem::size_of::<i32>(), true)?;
|
||||
|
||||
if *user_reader.read_one_from_user::<i32>(0)? != 0 {
|
||||
tty.flags_write().insert(TtyFlag::PTY_LOCK);
|
||||
} else {
|
||||
tty.flags_write().remove(TtyFlag::PTY_LOCK);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pty_get_lock(tty: &TtyCoreData, arg: VirtAddr) -> Result<(), SystemError> {
|
||||
let mut user_writer =
|
||||
UserBufferWriter::new(arg.as_ptr::<i32>(), core::mem::size_of::<i32>(), true)?;
|
||||
user_writer.copy_one_to_user(&tty.flags().contains(TtyFlag::PTY_LOCK), 0)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pty_set_packet_mode(tty: &TtyCoreData, arg: VirtAddr) -> Result<(), SystemError> {
|
||||
let user_reader =
|
||||
UserBufferReader::new(arg.as_ptr::<i32>(), core::mem::size_of::<i32>(), true)?;
|
||||
|
||||
let mut ctrl = tty.contorl_info_irqsave();
|
||||
if *user_reader.read_one_from_user::<i32>(0)? != 0 {
|
||||
if !ctrl.packet {
|
||||
tty.link().unwrap().core().contorl_info_irqsave().pktstatus =
|
||||
TtyPacketStatus::empty();
|
||||
ctrl.packet = true;
|
||||
}
|
||||
} else {
|
||||
ctrl.packet = false;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pty_get_packet_mode(tty: &TtyCoreData, arg: VirtAddr) -> Result<(), SystemError> {
|
||||
let mut user_writer =
|
||||
UserBufferWriter::new(arg.as_ptr::<i32>(), core::mem::size_of::<i32>(), true)?;
|
||||
user_writer.copy_one_to_user(&tty.contorl_info_irqsave().packet, 0)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unix98pty_init() -> Result<(), SystemError> {
|
||||
let ptm_driver = ptm_driver();
|
||||
let pts_driver = pts_driver();
|
||||
ptm_driver.set_other_pty_driver(Arc::downgrade(&pts_driver));
|
||||
pts_driver.set_other_pty_driver(Arc::downgrade(&ptm_driver));
|
||||
|
||||
let idt = IdTable::new(
|
||||
String::from("ptmx"),
|
||||
Some(DeviceNumber::new(Major::TTYAUX_MAJOR, 2)),
|
||||
);
|
||||
let ptmx_dev = TtyDevice::new(
|
||||
"ptmx".to_string(),
|
||||
idt.clone(),
|
||||
TtyType::Pty(super::tty_device::PtyType::Ptm),
|
||||
);
|
||||
|
||||
ptmx_dev.inner_write().metadata_mut().raw_dev = idt.device_number();
|
||||
device_register(ptmx_dev.clone())?;
|
||||
devfs_register("ptmx", ptmx_dev)?;
|
||||
|
||||
TTY_DRIVERS.lock().push(ptm_driver);
|
||||
TTY_DRIVERS.lock().push(pts_driver);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[unified_init(INITCALL_DEVICE)]
|
||||
#[inline(never)]
|
||||
pub fn pty_init() -> Result<(), SystemError> {
|
||||
let mut ptm_driver = TtyDriver::new(
|
||||
NR_UNIX98_PTY_MAX,
|
||||
"ptm",
|
||||
0,
|
||||
Major::UNIX98_PTY_MASTER_MAJOR,
|
||||
0,
|
||||
TtyDriverType::Pty,
|
||||
*TTY_STD_TERMIOS,
|
||||
Arc::new(Unix98PtyDriverInner::new()),
|
||||
);
|
||||
ptm_driver.set_subtype(TtyDriverSubType::PtyMaster);
|
||||
let term = ptm_driver.init_termios_mut();
|
||||
term.input_mode = InputMode::empty();
|
||||
term.output_mode = OutputMode::empty();
|
||||
term.control_mode = ControlMode::B38400 | ControlMode::CS8 | ControlMode::CREAD;
|
||||
term.local_mode = LocalMode::empty();
|
||||
term.input_speed = 38400;
|
||||
term.output_speed = 38400;
|
||||
PTM_DRIVER.init(TtyDriverManager::tty_register_driver(ptm_driver).unwrap());
|
||||
|
||||
let mut pts_driver = TtyDriver::new(
|
||||
NR_UNIX98_PTY_MAX,
|
||||
"pts",
|
||||
0,
|
||||
Major::UNIX98_PTY_SLAVE_MAJOR,
|
||||
0,
|
||||
TtyDriverType::Pty,
|
||||
*TTY_STD_TERMIOS,
|
||||
Arc::new(Unix98PtyDriverInner::new()),
|
||||
);
|
||||
pts_driver.set_subtype(TtyDriverSubType::PtySlave);
|
||||
let term = pts_driver.init_termios_mut();
|
||||
term.input_mode = InputMode::empty();
|
||||
term.output_mode = OutputMode::empty();
|
||||
term.control_mode = ControlMode::B38400 | ControlMode::CS8 | ControlMode::CREAD;
|
||||
term.local_mode = LocalMode::empty();
|
||||
term.input_speed = 38400;
|
||||
term.output_speed = 38400;
|
||||
PTS_DRIVER.init(TtyDriverManager::tty_register_driver(pts_driver).unwrap());
|
||||
|
||||
return PtyCommon::unix98pty_init();
|
||||
}
|
222
kernel/src/driver/tty/pty/unix98pty.rs
Normal file
222
kernel/src/driver/tty/pty/unix98pty.rs
Normal file
@ -0,0 +1,222 @@
|
||||
use alloc::{string::ToString, sync::Arc};
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
driver::tty::{
|
||||
termios::Termios,
|
||||
tty_core::{TtyCore, TtyCoreData, TtyFlag, TtyIoctlCmd, TtyPacketStatus},
|
||||
tty_device::TtyFilePrivateData,
|
||||
tty_driver::{TtyDriver, TtyDriverPrivateData, TtyDriverSubType, TtyOperation},
|
||||
},
|
||||
filesystem::{
|
||||
devpts::DevPtsFs,
|
||||
vfs::{
|
||||
file::FileMode, syscall::ModeType, FilePrivateData, FileType, MountFS, ROOT_INODE,
|
||||
VFS_MAX_FOLLOW_SYMLINK_TIMES,
|
||||
},
|
||||
},
|
||||
libs::spinlock::SpinLockGuard,
|
||||
mm::VirtAddr,
|
||||
net::event_poll::EPollEventType,
|
||||
syscall::user_access::UserBufferWriter,
|
||||
};
|
||||
|
||||
use super::{ptm_driver, pts_driver, PtyCommon};
|
||||
|
||||
pub const NR_UNIX98_PTY_MAX: u32 = 128;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Unix98PtyDriverInner;
|
||||
|
||||
impl Unix98PtyDriverInner {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
impl TtyOperation for Unix98PtyDriverInner {
|
||||
fn install(&self, driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> {
|
||||
PtyCommon::pty_common_install(driver, tty, false)
|
||||
}
|
||||
|
||||
fn open(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
|
||||
PtyCommon::pty_common_open(tty)
|
||||
}
|
||||
|
||||
fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError> {
|
||||
let to = tty.checked_link()?;
|
||||
|
||||
if nr == 0 || tty.flow_irqsave().stopped {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
to.core().port().unwrap().receive_buf(buf, &[], nr)
|
||||
}
|
||||
|
||||
fn write_room(&self, tty: &TtyCoreData) -> usize {
|
||||
// TODO 暂时
|
||||
if tty.flow_irqsave().stopped {
|
||||
return 0;
|
||||
}
|
||||
|
||||
8192
|
||||
}
|
||||
|
||||
fn flush_buffer(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
|
||||
let to = tty.checked_link()?;
|
||||
|
||||
let mut ctrl = to.core().contorl_info_irqsave();
|
||||
ctrl.pktstatus.insert(TtyPacketStatus::TIOCPKT_FLUSHWRITE);
|
||||
|
||||
to.core().read_wq().wakeup_all();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ioctl(&self, tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<(), SystemError> {
|
||||
let core = tty.core();
|
||||
if core.driver().tty_driver_sub_type() != TtyDriverSubType::PtyMaster {
|
||||
return Err(SystemError::ENOSYS);
|
||||
}
|
||||
|
||||
match cmd {
|
||||
TtyIoctlCmd::TIOCSPTLCK => {
|
||||
return PtyCommon::pty_set_lock(core, VirtAddr::new(arg));
|
||||
}
|
||||
TtyIoctlCmd::TIOCGPTLCK => {
|
||||
return PtyCommon::pty_get_lock(core, VirtAddr::new(arg));
|
||||
}
|
||||
TtyIoctlCmd::TIOCPKT => {
|
||||
return PtyCommon::pty_set_packet_mode(core, VirtAddr::new(arg));
|
||||
}
|
||||
TtyIoctlCmd::TIOCGPKT => {
|
||||
return PtyCommon::pty_get_packet_mode(core, VirtAddr::new(arg));
|
||||
}
|
||||
TtyIoctlCmd::TIOCGPTN => {
|
||||
let mut user_writer =
|
||||
UserBufferWriter::new(arg as *mut u32, core::mem::size_of::<u32>(), true)?;
|
||||
|
||||
return user_writer.copy_one_to_user(&(core.index() as u32), 0);
|
||||
}
|
||||
_ => {
|
||||
return Err(SystemError::ENOIOCTLCMD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_termios(&self, tty: Arc<TtyCore>, _old_termios: Termios) -> Result<(), SystemError> {
|
||||
let core = tty.core();
|
||||
if core.driver().tty_driver_sub_type() != TtyDriverSubType::PtySlave {
|
||||
return Err(SystemError::ENOSYS);
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn start(&self, core: &TtyCoreData) -> Result<(), SystemError> {
|
||||
if core.driver().tty_driver_sub_type() != TtyDriverSubType::PtySlave {
|
||||
return Err(SystemError::ENOSYS);
|
||||
}
|
||||
|
||||
let link = core.checked_link()?;
|
||||
|
||||
let mut ctrl = core.contorl_info_irqsave();
|
||||
ctrl.pktstatus.remove(TtyPacketStatus::TIOCPKT_STOP);
|
||||
ctrl.pktstatus.insert(TtyPacketStatus::TIOCPKT_START);
|
||||
|
||||
link.core()
|
||||
.read_wq()
|
||||
.wakeup_any(EPollEventType::EPOLLIN.bits() as u64);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn stop(&self, core: &TtyCoreData) -> Result<(), SystemError> {
|
||||
if core.driver().tty_driver_sub_type() != TtyDriverSubType::PtySlave {
|
||||
return Err(SystemError::ENOSYS);
|
||||
}
|
||||
|
||||
let link = core.checked_link()?;
|
||||
|
||||
let mut ctrl = core.contorl_info_irqsave();
|
||||
ctrl.pktstatus.remove(TtyPacketStatus::TIOCPKT_START);
|
||||
ctrl.pktstatus.insert(TtyPacketStatus::TIOCPKT_STOP);
|
||||
|
||||
link.core()
|
||||
.read_wq()
|
||||
.wakeup_any(EPollEventType::EPOLLIN.bits() as u64);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn flush_chars(&self, _tty: &TtyCoreData) {
|
||||
// 不做处理
|
||||
}
|
||||
|
||||
fn lookup(
|
||||
&self,
|
||||
index: usize,
|
||||
priv_data: TtyDriverPrivateData,
|
||||
) -> Result<Arc<TtyCore>, SystemError> {
|
||||
if let TtyDriverPrivateData::Pty(false) = priv_data {
|
||||
return pts_driver()
|
||||
.ttys()
|
||||
.get(&index)
|
||||
.cloned()
|
||||
.ok_or(SystemError::ENODEV);
|
||||
}
|
||||
|
||||
return Err(SystemError::ENOSYS);
|
||||
}
|
||||
|
||||
fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError> {
|
||||
let driver = tty.core().driver();
|
||||
|
||||
driver.ttys().remove(&tty.core().index());
|
||||
if tty.core().driver().tty_driver_sub_type() == TtyDriverSubType::PtySlave {
|
||||
let pts_root_inode =
|
||||
ROOT_INODE().lookup_follow_symlink("/dev/pts", VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
|
||||
let _ = pts_root_inode.unlink(&tty.core().index().to_string());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ptmx_open(
|
||||
mut data: SpinLockGuard<FilePrivateData>,
|
||||
mode: &FileMode,
|
||||
) -> Result<(), SystemError> {
|
||||
let pts_root_inode =
|
||||
ROOT_INODE().lookup_follow_symlink("/dev/pts", VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
|
||||
|
||||
let fs = pts_root_inode
|
||||
.fs()
|
||||
.as_any_ref()
|
||||
.downcast_ref::<MountFS>()
|
||||
.unwrap()
|
||||
.inner_filesystem();
|
||||
let fsinfo = fs.as_any_ref().downcast_ref::<DevPtsFs>().unwrap();
|
||||
|
||||
let index = fsinfo.alloc_index()?;
|
||||
|
||||
let tty = TtyDriver::init_tty_device(ptm_driver(), index)?;
|
||||
|
||||
// 设置privdata
|
||||
*data = FilePrivateData::Tty(TtyFilePrivateData {
|
||||
tty: tty.clone(),
|
||||
mode: *mode,
|
||||
});
|
||||
|
||||
let core = tty.core();
|
||||
core.flags_write().insert(TtyFlag::PTY_LOCK);
|
||||
|
||||
let _ = pts_root_inode.create(
|
||||
&index.to_string(),
|
||||
FileType::CharDevice,
|
||||
ModeType::from_bits_truncate(0x666),
|
||||
)?;
|
||||
|
||||
ptm_driver().driver_funcs().open(core)?;
|
||||
|
||||
Ok(())
|
||||
}
|
@ -1,9 +1,14 @@
|
||||
use core::{
|
||||
fmt::Debug,
|
||||
sync::atomic::{AtomicBool, AtomicUsize},
|
||||
sync::atomic::{AtomicBool, AtomicUsize, Ordering},
|
||||
};
|
||||
|
||||
use alloc::{collections::LinkedList, string::String, sync::Arc, vec::Vec};
|
||||
use alloc::{
|
||||
collections::LinkedList,
|
||||
string::String,
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
};
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
@ -55,7 +60,7 @@ impl TtyCore {
|
||||
ctrl: SpinLock::new(TtyContorlInfo::default()),
|
||||
closing: AtomicBool::new(false),
|
||||
flow: SpinLock::new(TtyFlowState::default()),
|
||||
link: None,
|
||||
link: RwLock::default(),
|
||||
epitems: SpinLock::new(LinkedList::new()),
|
||||
};
|
||||
|
||||
@ -138,7 +143,7 @@ impl TtyCore {
|
||||
|
||||
self.core()
|
||||
.write_wq
|
||||
.wakeup(EPollEventType::EPOLLOUT.bits() as u64);
|
||||
.wakeup_any(EPollEventType::EPOLLOUT.bits() as u64);
|
||||
}
|
||||
|
||||
pub fn tty_mode_ioctl(tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<usize, SystemError> {
|
||||
@ -252,7 +257,7 @@ pub struct TtyContorlInfo {
|
||||
pub pgid: Option<Pid>,
|
||||
|
||||
/// packet模式下使用,目前未用到
|
||||
pub pktstatus: u8,
|
||||
pub pktstatus: TtyPacketStatus,
|
||||
pub packet: bool,
|
||||
}
|
||||
|
||||
@ -296,7 +301,7 @@ pub struct TtyCoreData {
|
||||
/// 流控状态
|
||||
flow: SpinLock<TtyFlowState>,
|
||||
/// 链接tty
|
||||
link: Option<Arc<TtyCore>>,
|
||||
link: RwLock<Weak<TtyCore>>,
|
||||
/// epitems
|
||||
epitems: SpinLock<LinkedList<Arc<EPollItem>>>,
|
||||
}
|
||||
@ -332,6 +337,11 @@ impl TtyCoreData {
|
||||
*self.flags.read_irqsave()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn flags_write(&self) -> RwLockWriteGuard<'_, TtyFlag> {
|
||||
self.flags.write_irqsave()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn termios(&self) -> RwLockReadGuard<'_, Termios> {
|
||||
self.termios.read_irqsave()
|
||||
@ -348,6 +358,11 @@ impl TtyCoreData {
|
||||
*termios_guard = termios;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn count(&self) -> usize {
|
||||
self.count.load(Ordering::SeqCst)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn add_count(&self) {
|
||||
self.count
|
||||
@ -391,7 +406,36 @@ impl TtyCoreData {
|
||||
|
||||
#[inline]
|
||||
pub fn link(&self) -> Option<Arc<TtyCore>> {
|
||||
self.link.clone()
|
||||
self.link.read().upgrade()
|
||||
}
|
||||
|
||||
pub fn checked_link(&self) -> Result<Arc<TtyCore>, SystemError> {
|
||||
if let Some(link) = self.link() {
|
||||
return Ok(link);
|
||||
}
|
||||
return Err(SystemError::ENODEV);
|
||||
}
|
||||
|
||||
pub fn set_link(&self, link: Weak<TtyCore>) {
|
||||
*self.link.write() = link;
|
||||
}
|
||||
|
||||
pub fn init_termios(&self) {
|
||||
let tty_index = self.index();
|
||||
let driver = self.driver();
|
||||
// 初始化termios
|
||||
if !driver
|
||||
.flags()
|
||||
.contains(super::tty_driver::TtyDriverFlag::TTY_DRIVER_RESET_TERMIOS)
|
||||
{
|
||||
// 先查看是否有已经保存的termios
|
||||
if let Some(t) = driver.saved_termios().get(tty_index) {
|
||||
let mut termios = *t;
|
||||
termios.line = driver.init_termios().line;
|
||||
self.set_termios(termios);
|
||||
}
|
||||
}
|
||||
// TODO:设置termios波特率?
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -463,6 +507,10 @@ impl TtyOperation for TtyCore {
|
||||
.driver_funcs()
|
||||
.set_termios(tty, old_termios);
|
||||
}
|
||||
|
||||
fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError> {
|
||||
self.core().tty_driver.driver_funcs().close(tty)
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
@ -492,6 +540,19 @@ bitflags! {
|
||||
/// 终端线路驱动程序已停止
|
||||
const LDISC_HALTED = 1 << 22;
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct TtyPacketStatus: u8 {
|
||||
/* Used for packet mode */
|
||||
const TIOCPKT_DATA = 0;
|
||||
const TIOCPKT_FLUSHREAD = 1;
|
||||
const TIOCPKT_FLUSHWRITE = 2;
|
||||
const TIOCPKT_STOP = 4;
|
||||
const TIOCPKT_START = 8;
|
||||
const TIOCPKT_NOSTOP = 16;
|
||||
const TIOCPKT_DOSTOP = 32;
|
||||
const TIOCPKT_IOCTL = 64;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@ -614,4 +675,12 @@ impl TtyIoctlCmd {
|
||||
pub const TIOCCBRK: u32 = 0x5428;
|
||||
/// Return the session ID of FD
|
||||
pub const TIOCGSID: u32 = 0x5429;
|
||||
/// 设置ptl锁标记
|
||||
pub const TIOCSPTLCK: u32 = 0x40045431;
|
||||
/// 获取ptl锁标记
|
||||
pub const TIOCGPTLCK: u32 = 0x80045439;
|
||||
/// 获取packet标记
|
||||
pub const TIOCGPKT: u32 = 0x80045438;
|
||||
/// 获取pts index
|
||||
pub const TIOCGPTN: u32 = 0x80045430;
|
||||
}
|
||||
|
@ -29,7 +29,10 @@ use crate::{
|
||||
vfs::{file::FileMode, syscall::ModeType, FilePrivateData, FileType, IndexNode, Metadata},
|
||||
},
|
||||
init::initcall::INITCALL_DEVICE,
|
||||
libs::rwlock::RwLock,
|
||||
libs::{
|
||||
rwlock::{RwLock, RwLockWriteGuard},
|
||||
spinlock::SpinLockGuard,
|
||||
},
|
||||
mm::VirtAddr,
|
||||
net::event_poll::{EPollItem, EventPoll},
|
||||
process::ProcessManager,
|
||||
@ -38,10 +41,11 @@ use crate::{
|
||||
|
||||
use super::{
|
||||
kthread::tty_flush_thread_init,
|
||||
pty::unix98pty::ptmx_open,
|
||||
sysfs::sys_class_tty_instance,
|
||||
termios::WindowSize,
|
||||
tty_core::{TtyCore, TtyFlag, TtyIoctlCmd},
|
||||
tty_driver::{TtyDriver, TtyDriverSubType, TtyDriverType, TtyOperation},
|
||||
tty_driver::{TtyDriver, TtyDriverManager, TtyDriverSubType, TtyDriverType, TtyOperation},
|
||||
tty_job_control::TtyJobCtrlManager,
|
||||
virtual_terminal::vty_init,
|
||||
};
|
||||
@ -72,13 +76,30 @@ impl InnerTtyDevice {
|
||||
metadata: Metadata::new(FileType::CharDevice, ModeType::from_bits_truncate(0o755)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn metadata_mut(&mut self) -> &mut Metadata {
|
||||
&mut self.metadata
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum TtyType {
|
||||
Tty,
|
||||
Pty(PtyType),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum PtyType {
|
||||
Ptm,
|
||||
Pts,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cast_to([sync] Device)]
|
||||
pub struct TtyDevice {
|
||||
name: &'static str,
|
||||
name: String,
|
||||
id_table: IdTable,
|
||||
tty_type: TtyType,
|
||||
inner: RwLock<InnerTtyDevice>,
|
||||
kobj_state: LockedKObjectState,
|
||||
/// TTY所属的文件系统
|
||||
@ -86,7 +107,7 @@ pub struct TtyDevice {
|
||||
}
|
||||
|
||||
impl TtyDevice {
|
||||
pub fn new(name: &'static str, id_table: IdTable) -> Arc<TtyDevice> {
|
||||
pub fn new(name: String, id_table: IdTable, tty_type: TtyType) -> Arc<TtyDevice> {
|
||||
let dev_num = id_table.device_number();
|
||||
let dev = TtyDevice {
|
||||
name,
|
||||
@ -94,23 +115,37 @@ impl TtyDevice {
|
||||
inner: RwLock::new(InnerTtyDevice::new()),
|
||||
kobj_state: LockedKObjectState::new(None),
|
||||
fs: RwLock::new(Weak::default()),
|
||||
tty_type,
|
||||
};
|
||||
|
||||
dev.inner.write().metadata.raw_dev = dev_num;
|
||||
|
||||
Arc::new(dev)
|
||||
}
|
||||
|
||||
pub fn inner_write(&self) -> RwLockWriteGuard<InnerTtyDevice> {
|
||||
self.inner.write()
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexNode for TtyDevice {
|
||||
fn open(
|
||||
&self,
|
||||
data: &mut crate::filesystem::vfs::FilePrivateData,
|
||||
mut data: SpinLockGuard<FilePrivateData>,
|
||||
mode: &crate::filesystem::vfs::file::FileMode,
|
||||
) -> Result<(), SystemError> {
|
||||
if self.tty_type == TtyType::Pty(PtyType::Ptm) {
|
||||
if let FilePrivateData::Tty(_) = &*data {
|
||||
return Ok(());
|
||||
}
|
||||
return ptmx_open(data, mode);
|
||||
}
|
||||
let dev_num = self.metadata()?.raw_dev;
|
||||
|
||||
let tty = TtyDriver::open_tty(dev_num)?;
|
||||
let (index, driver) =
|
||||
TtyDriverManager::lookup_tty_driver(dev_num).ok_or(SystemError::ENODEV)?;
|
||||
|
||||
let tty = TtyDriver::open_tty(index, driver)?;
|
||||
|
||||
// 设置privdata
|
||||
*data = FilePrivateData::Tty(TtyFilePrivateData {
|
||||
@ -148,14 +183,16 @@ impl IndexNode for TtyDevice {
|
||||
_offset: usize,
|
||||
len: usize,
|
||||
buf: &mut [u8],
|
||||
data: &mut crate::filesystem::vfs::FilePrivateData,
|
||||
data: SpinLockGuard<FilePrivateData>,
|
||||
) -> Result<usize, system_error::SystemError> {
|
||||
let (tty, mode) = if let FilePrivateData::Tty(tty_priv) = data {
|
||||
(tty_priv.tty.clone(), tty_priv.mode)
|
||||
let (tty, mode) = if let FilePrivateData::Tty(tty_priv) = &*data {
|
||||
(tty_priv.tty(), tty_priv.mode)
|
||||
} else {
|
||||
return Err(SystemError::EIO);
|
||||
};
|
||||
|
||||
drop(data);
|
||||
|
||||
let ld = tty.ldisc();
|
||||
let mut offset = 0;
|
||||
let mut cookie = false;
|
||||
@ -188,15 +225,15 @@ impl IndexNode for TtyDevice {
|
||||
_offset: usize,
|
||||
len: usize,
|
||||
buf: &[u8],
|
||||
data: &mut crate::filesystem::vfs::FilePrivateData,
|
||||
data: SpinLockGuard<FilePrivateData>,
|
||||
) -> Result<usize, system_error::SystemError> {
|
||||
let mut count = len;
|
||||
let (tty, mode) = if let FilePrivateData::Tty(tty_priv) = data {
|
||||
(tty_priv.tty.clone(), tty_priv.mode)
|
||||
let (tty, mode) = if let FilePrivateData::Tty(tty_priv) = &*data {
|
||||
(tty_priv.tty(), tty_priv.mode)
|
||||
} else {
|
||||
return Err(SystemError::EIO);
|
||||
};
|
||||
|
||||
drop(data);
|
||||
let ld = tty.ldisc();
|
||||
let core = tty.core();
|
||||
let mut chunk = 2048;
|
||||
@ -239,7 +276,7 @@ impl IndexNode for TtyDevice {
|
||||
}
|
||||
|
||||
fn as_any_ref(&self) -> &dyn core::any::Any {
|
||||
todo!()
|
||||
self
|
||||
}
|
||||
|
||||
fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, system_error::SystemError> {
|
||||
@ -250,17 +287,30 @@ impl IndexNode for TtyDevice {
|
||||
Ok(self.inner.read().metadata.clone())
|
||||
}
|
||||
|
||||
fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
|
||||
fn set_metadata(&self, metadata: &Metadata) -> Result<(), SystemError> {
|
||||
let mut guard = self.inner_write();
|
||||
guard.metadata = metadata.clone();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn close(&self, data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> {
|
||||
let (tty, _mode) = if let FilePrivateData::Tty(tty_priv) = &*data {
|
||||
(tty_priv.tty(), tty_priv.mode)
|
||||
} else {
|
||||
return Err(SystemError::EIO);
|
||||
};
|
||||
drop(data);
|
||||
tty.close(tty.clone())
|
||||
}
|
||||
|
||||
fn resize(&self, _len: usize) -> Result<(), SystemError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ioctl(&self, cmd: u32, arg: usize, data: &FilePrivateData) -> Result<usize, SystemError> {
|
||||
let (tty, _) = if let FilePrivateData::Tty(tty_priv) = data {
|
||||
(tty_priv.tty.clone(), tty_priv.mode)
|
||||
(tty_priv.tty(), tty_priv.mode)
|
||||
} else {
|
||||
return Err(SystemError::EIO);
|
||||
};
|
||||
@ -485,8 +535,14 @@ impl CharDevice for TtyDevice {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TtyFilePrivateData {
|
||||
tty: Arc<TtyCore>,
|
||||
mode: FileMode,
|
||||
pub tty: Arc<TtyCore>,
|
||||
pub mode: FileMode,
|
||||
}
|
||||
|
||||
impl TtyFilePrivateData {
|
||||
pub fn tty(&self) -> Arc<TtyCore> {
|
||||
self.tty.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// 初始化tty设备和console子设备
|
||||
@ -494,19 +550,21 @@ pub struct TtyFilePrivateData {
|
||||
#[inline(never)]
|
||||
pub fn tty_init() -> Result<(), SystemError> {
|
||||
let tty = TtyDevice::new(
|
||||
"tty0",
|
||||
"tty0".to_string(),
|
||||
IdTable::new(
|
||||
String::from("tty0"),
|
||||
Some(DeviceNumber::new(Major::TTY_MAJOR, 0)),
|
||||
),
|
||||
TtyType::Tty,
|
||||
);
|
||||
|
||||
let console = TtyDevice::new(
|
||||
"console",
|
||||
"console".to_string(),
|
||||
IdTable::new(
|
||||
String::from("console"),
|
||||
Some(DeviceNumber::new(Major::TTYAUX_MAJOR, 1)),
|
||||
),
|
||||
TtyType::Tty,
|
||||
);
|
||||
|
||||
// 注册tty设备
|
||||
@ -536,8 +594,8 @@ pub fn tty_init() -> Result<(), SystemError> {
|
||||
// 将这两个设备注册到devfs,TODO:这里console设备应该与tty在一个设备group里面
|
||||
device_register(tty.clone())?;
|
||||
device_register(console.clone())?;
|
||||
devfs_register(tty.name, tty)?;
|
||||
devfs_register(console.name, console)?;
|
||||
devfs_register(&tty.name.clone(), tty)?;
|
||||
devfs_register(&console.name.clone(), console)?;
|
||||
|
||||
serial_init()?;
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
use core::{fmt::Debug, sync::atomic::Ordering};
|
||||
use core::fmt::Debug;
|
||||
|
||||
use alloc::{
|
||||
string::{String, ToString},
|
||||
sync::Arc,
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
@ -20,38 +20,46 @@ use crate::{
|
||||
},
|
||||
tty::tty_port::TtyPortState,
|
||||
},
|
||||
libs::spinlock::SpinLock,
|
||||
libs::{
|
||||
rwlock::RwLock,
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
},
|
||||
};
|
||||
|
||||
use super::{
|
||||
termios::Termios,
|
||||
tty_core::{TtyCore, TtyCoreData},
|
||||
tty_ldisc::TtyLdiscManager,
|
||||
tty_port::TTY_PORTS,
|
||||
virtual_terminal::virtual_console::CURRENT_VCNUM,
|
||||
tty_port::{DefaultTtyPort, TtyPort},
|
||||
};
|
||||
|
||||
lazy_static! {
|
||||
static ref TTY_DRIVERS: SpinLock<Vec<Arc<TtyDriver>>> = SpinLock::new(Vec::new());
|
||||
pub static ref TTY_DRIVERS: SpinLock<Vec<Arc<TtyDriver>>> = SpinLock::new(Vec::new());
|
||||
}
|
||||
|
||||
pub enum TtyDriverPrivateData {
|
||||
Unused,
|
||||
/// true表示主设备 false表示从设备
|
||||
Pty(bool),
|
||||
}
|
||||
|
||||
pub struct TtyDriverManager;
|
||||
impl TtyDriverManager {
|
||||
pub fn lookup_tty_driver(dev_num: DeviceNumber) -> Option<(usize, Arc<TtyDriver>)> {
|
||||
let drivers_guard = TTY_DRIVERS.lock();
|
||||
for (index, driver) in drivers_guard.iter().enumerate() {
|
||||
for driver in drivers_guard.iter() {
|
||||
let base = DeviceNumber::new(driver.major, driver.minor_start);
|
||||
if dev_num < base || dev_num.data() > base.data() + driver.device_count {
|
||||
continue;
|
||||
}
|
||||
return Some((index, driver.clone()));
|
||||
return Some(((dev_num.data() - base.data()) as usize, driver.clone()));
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// ## 注册驱动
|
||||
pub fn tty_register_driver(mut driver: TtyDriver) -> Result<(), SystemError> {
|
||||
pub fn tty_register_driver(mut driver: TtyDriver) -> Result<Arc<TtyDriver>, SystemError> {
|
||||
// 查看是否注册设备号
|
||||
if driver.major == Major::UNNAMED_MAJOR {
|
||||
let dev_num = CharDevOps::alloc_chardev_region(
|
||||
@ -69,11 +77,12 @@ impl TtyDriverManager {
|
||||
driver.flags |= TtyDriverFlag::TTY_DRIVER_INSTALLED;
|
||||
|
||||
// 加入全局TtyDriver表
|
||||
TTY_DRIVERS.lock().push(Arc::new(driver));
|
||||
let driver = Arc::new(driver);
|
||||
TTY_DRIVERS.lock().push(driver.clone());
|
||||
|
||||
// TODO: 加入procfs?
|
||||
|
||||
Ok(())
|
||||
Ok(driver)
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,11 +113,13 @@ pub struct TtyDriver {
|
||||
/// 驱动程序标志
|
||||
flags: TtyDriverFlag,
|
||||
/// pty链接此driver的入口
|
||||
pty: Option<Arc<TtyDriver>>,
|
||||
other_pty_driver: RwLock<Weak<TtyDriver>>,
|
||||
/// 具体类型的tty驱动方法
|
||||
driver_funcs: Arc<dyn TtyOperation>,
|
||||
/// 管理的tty设备列表
|
||||
ttys: SpinLock<HashMap<usize, Arc<TtyCore>>>,
|
||||
/// 管理的端口列表
|
||||
ports: RwLock<Vec<Arc<dyn TtyPort>>>,
|
||||
// procfs入口?
|
||||
}
|
||||
|
||||
@ -124,6 +135,10 @@ impl TtyDriver {
|
||||
default_termios: Termios,
|
||||
driver_funcs: Arc<dyn TtyOperation>,
|
||||
) -> Self {
|
||||
let mut ports: Vec<Arc<dyn TtyPort>> = Vec::with_capacity(count as usize);
|
||||
for _ in 0..count {
|
||||
ports.push(Arc::new(DefaultTtyPort::new()))
|
||||
}
|
||||
TtyDriver {
|
||||
driver_name: Default::default(),
|
||||
name: node_name,
|
||||
@ -135,10 +150,11 @@ impl TtyDriver {
|
||||
tty_driver_sub_type: Default::default(),
|
||||
init_termios: default_termios,
|
||||
flags: TtyDriverFlag::empty(),
|
||||
pty: Default::default(),
|
||||
other_pty_driver: Default::default(),
|
||||
driver_funcs,
|
||||
ttys: SpinLock::new(HashMap::new()),
|
||||
saved_termios: Vec::with_capacity(count as usize),
|
||||
ports: RwLock::new(ports),
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,34 +178,65 @@ impl TtyDriver {
|
||||
self.driver_funcs.clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn init_termios(&self) -> Termios {
|
||||
self.init_termios
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn init_termios_mut(&mut self) -> &mut Termios {
|
||||
&mut self.init_termios
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn other_pty_driver(&self) -> Option<Arc<TtyDriver>> {
|
||||
self.other_pty_driver.read().upgrade()
|
||||
}
|
||||
|
||||
pub fn set_other_pty_driver(&self, driver: Weak<TtyDriver>) {
|
||||
*self.other_pty_driver.write() = driver
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_subtype(&mut self, tp: TtyDriverSubType) {
|
||||
self.tty_driver_sub_type = tp;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn ttys(&self) -> SpinLockGuard<HashMap<usize, Arc<TtyCore>>> {
|
||||
self.ttys.lock()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn saved_termios(&self) -> &Vec<Termios> {
|
||||
&self.saved_termios
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn flags(&self) -> TtyDriverFlag {
|
||||
self.flags
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lockup_tty(&self, index: usize) -> Option<Arc<TtyCore>> {
|
||||
let device_guard = self.ttys.lock();
|
||||
return device_guard.get(&index).cloned();
|
||||
fn lookup_tty(&self, index: usize) -> Option<Arc<TtyCore>> {
|
||||
let ret = self
|
||||
.driver_funcs()
|
||||
.lookup(index, TtyDriverPrivateData::Unused);
|
||||
if let Err(SystemError::ENOSYS) = ret {
|
||||
let device_guard = self.ttys.lock();
|
||||
return device_guard.get(&index).cloned();
|
||||
}
|
||||
ret.ok()
|
||||
}
|
||||
|
||||
fn standard_install(&self, tty_core: Arc<TtyCore>) -> Result<(), SystemError> {
|
||||
let tty = tty_core.core();
|
||||
let tty_index = tty.index();
|
||||
// 初始化termios
|
||||
if !self.flags.contains(TtyDriverFlag::TTY_DRIVER_RESET_TERMIOS) {
|
||||
// 先查看是否有已经保存的termios
|
||||
if let Some(t) = self.saved_termios.get(tty_index) {
|
||||
let mut termios = *t;
|
||||
termios.line = self.init_termios.line;
|
||||
tty.set_termios(termios);
|
||||
}
|
||||
}
|
||||
tty.init_termios();
|
||||
// TODO:设置termios波特率?
|
||||
|
||||
tty.add_count();
|
||||
|
||||
self.ttys.lock().insert(tty_index, tty_core);
|
||||
self.ttys.lock().insert(tty.index(), tty_core);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -210,7 +257,10 @@ impl TtyDriver {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn init_tty_device(driver: Arc<TtyDriver>, index: usize) -> Result<Arc<TtyCore>, SystemError> {
|
||||
pub fn init_tty_device(
|
||||
driver: Arc<TtyDriver>,
|
||||
index: usize,
|
||||
) -> Result<Arc<TtyCore>, SystemError> {
|
||||
let tty = TtyCore::new(driver.clone(), index);
|
||||
|
||||
Self::driver_install_tty(driver.clone(), tty.clone())?;
|
||||
@ -218,8 +268,9 @@ impl TtyDriver {
|
||||
let core = tty.core();
|
||||
|
||||
if core.port().is_none() {
|
||||
TTY_PORTS[core.index()].setup_tty(Arc::downgrade(&tty));
|
||||
tty.set_port(TTY_PORTS[core.index()].clone());
|
||||
let ports = driver.ports.read();
|
||||
ports[core.index()].setup_internal_tty(Arc::downgrade(&tty));
|
||||
tty.set_port(ports[core.index()].clone());
|
||||
}
|
||||
|
||||
TtyLdiscManager::ldisc_setup(tty.clone(), None)?;
|
||||
@ -228,11 +279,8 @@ impl TtyDriver {
|
||||
}
|
||||
|
||||
/// ## 通过设备号找到对应驱动并且初始化Tty
|
||||
pub fn open_tty(dev_num: DeviceNumber) -> Result<Arc<TtyCore>, SystemError> {
|
||||
let (index, driver) =
|
||||
TtyDriverManager::lookup_tty_driver(dev_num).ok_or(SystemError::ENODEV)?;
|
||||
|
||||
let tty = match driver.lockup_tty(index) {
|
||||
pub fn open_tty(index: usize, driver: Arc<TtyDriver>) -> Result<Arc<TtyCore>, SystemError> {
|
||||
let tty = match driver.lookup_tty(index) {
|
||||
Some(tty) => {
|
||||
// TODO: 暂时这么写,因为还没写TtyPort
|
||||
if tty.core().port().is_none() {
|
||||
@ -247,8 +295,6 @@ impl TtyDriver {
|
||||
None => Self::init_tty_device(driver, index)?,
|
||||
};
|
||||
|
||||
CURRENT_VCNUM.store(index as isize, Ordering::SeqCst);
|
||||
|
||||
return Ok(tty);
|
||||
}
|
||||
|
||||
@ -259,10 +305,6 @@ impl TtyDriver {
|
||||
pub fn tty_driver_sub_type(&self) -> TtyDriverSubType {
|
||||
self.tty_driver_sub_type
|
||||
}
|
||||
|
||||
pub fn init_termios(&self) -> Termios {
|
||||
self.init_termios
|
||||
}
|
||||
}
|
||||
|
||||
impl KObject for TtyDriver {
|
||||
@ -368,7 +410,9 @@ pub trait TtyOperation: Sync + Send + Debug {
|
||||
|
||||
fn flush_chars(&self, tty: &TtyCoreData);
|
||||
|
||||
fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError>;
|
||||
fn put_char(&self, _tty: &TtyCoreData, _ch: u8) -> Result<(), SystemError> {
|
||||
Err(SystemError::ENOSYS)
|
||||
}
|
||||
|
||||
fn start(&self, _tty: &TtyCoreData) -> Result<(), SystemError> {
|
||||
Err(SystemError::ENOSYS)
|
||||
@ -391,6 +435,16 @@ pub trait TtyOperation: Sync + Send + Debug {
|
||||
fn set_termios(&self, _tty: Arc<TtyCore>, _old_termios: Termios) -> Result<(), SystemError> {
|
||||
Err(SystemError::ENOSYS)
|
||||
}
|
||||
|
||||
fn lookup(
|
||||
&self,
|
||||
_index: usize,
|
||||
_priv_data: TtyDriverPrivateData,
|
||||
) -> Result<Arc<TtyCore>, SystemError> {
|
||||
Err(SystemError::ENOSYS)
|
||||
}
|
||||
|
||||
fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError>;
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
@ -7,7 +7,7 @@ use crate::filesystem::vfs::file::FileMode;
|
||||
|
||||
use super::{
|
||||
termios::Termios,
|
||||
tty_core::{TtyCore, TtyCoreData},
|
||||
tty_core::{TtyCore, TtyCoreData, TtyFlag},
|
||||
};
|
||||
|
||||
pub mod ntty;
|
||||
@ -99,7 +99,7 @@ impl TtyLdiscManager {
|
||||
/// ### 参数
|
||||
/// - tty:需要设置的tty
|
||||
/// - o_tty: other tty 用于pty pair
|
||||
pub fn ldisc_setup(tty: Arc<TtyCore>, _o_tty: Option<Arc<TtyCore>>) -> Result<(), SystemError> {
|
||||
pub fn ldisc_setup(tty: Arc<TtyCore>, o_tty: Option<Arc<TtyCore>>) -> Result<(), SystemError> {
|
||||
let ld = tty.ldisc();
|
||||
|
||||
let ret = ld.open(tty);
|
||||
@ -109,7 +109,16 @@ impl TtyLdiscManager {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: 处理PTY
|
||||
// 处理PTY
|
||||
if let Some(o_tty) = o_tty {
|
||||
let ld = o_tty.ldisc();
|
||||
|
||||
let ret: Result<(), SystemError> = ld.open(o_tty.clone());
|
||||
if ret.is_err() {
|
||||
o_tty.core().flags_write().remove(TtyFlag::LDISC_OPEN);
|
||||
let _ = ld.close(o_tty.clone());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ use crate::{
|
||||
arch::ipc::signal::Signal,
|
||||
driver::tty::{
|
||||
termios::{ControlCharIndex, InputMode, LocalMode, OutputMode, Termios},
|
||||
tty_core::{EchoOperation, TtyCore, TtyCoreData, TtyFlag, TtyIoctlCmd},
|
||||
tty_core::{EchoOperation, TtyCore, TtyCoreData, TtyFlag, TtyIoctlCmd, TtyPacketStatus},
|
||||
tty_driver::{TtyDriverFlag, TtyOperation},
|
||||
tty_job_control::TtyJobCtrlManager,
|
||||
},
|
||||
@ -812,6 +812,10 @@ impl NTtyData {
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1521,6 +1525,17 @@ impl NTtyData {
|
||||
}
|
||||
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 {
|
||||
@ -1551,7 +1566,10 @@ impl TtyLineDiscipline for NTtyLinediscipline {
|
||||
ldata.lookahead_count = 0;
|
||||
|
||||
// todo: kick worker?
|
||||
// todo: packet mode?
|
||||
// packet mode?
|
||||
if core.link().is_some() {
|
||||
ldata.packet_mode_flush(core);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -1618,12 +1636,31 @@ impl TtyLineDiscipline for NTtyLinediscipline {
|
||||
}
|
||||
}
|
||||
|
||||
let packet = core.contorl_info_irqsave().packet;
|
||||
let mut ret: Result<usize, SystemError> = 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();
|
||||
@ -1676,7 +1713,11 @@ impl TtyLineDiscipline for NTtyLinediscipline {
|
||||
} 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
|
||||
@ -2025,7 +2066,14 @@ impl TtyLineDiscipline for NTtyLinediscipline {
|
||||
|
||||
if core.contorl_info_irqsave().packet {
|
||||
let link = core.link();
|
||||
if link.is_some() && link.unwrap().core().contorl_info_irqsave().pktstatus != 0 {
|
||||
if link.is_some()
|
||||
&& !link
|
||||
.unwrap()
|
||||
.core()
|
||||
.contorl_info_irqsave()
|
||||
.pktstatus
|
||||
.is_empty()
|
||||
{
|
||||
event.insert(
|
||||
EPollEventType::EPOLLPRI
|
||||
| EPollEventType::EPOLLIN
|
||||
|
@ -1,36 +1,29 @@
|
||||
use core::{fmt::Debug, sync::atomic::Ordering};
|
||||
|
||||
use alloc::{
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
};
|
||||
use alloc::sync::{Arc, Weak};
|
||||
use kdepends::thingbuf::mpsc;
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
driver::tty::virtual_terminal::MAX_NR_CONSOLES,
|
||||
libs::spinlock::{SpinLock, SpinLockGuard},
|
||||
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
|
||||
|
||||
use super::{
|
||||
tty_core::TtyCore,
|
||||
virtual_terminal::{virtual_console::CURRENT_VCNUM, VIRT_CONSOLES},
|
||||
};
|
||||
|
||||
use super::{tty_core::TtyCore, virtual_terminal::virtual_console::CURRENT_VCNUM};
|
||||
|
||||
const TTY_PORT_BUFSIZE: usize = 4096;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref TTY_PORTS: Vec<Arc<dyn TtyPort>> = {
|
||||
let mut v: Vec<Arc<dyn TtyPort>> = Vec::with_capacity(MAX_NR_CONSOLES as usize);
|
||||
for _ in 0..MAX_NR_CONSOLES as usize {
|
||||
v.push(Arc::new(DefaultTtyPort::new()))
|
||||
}
|
||||
|
||||
v
|
||||
};
|
||||
}
|
||||
|
||||
/// 获取当前tty port
|
||||
#[inline]
|
||||
pub fn current_tty_port() -> Arc<dyn TtyPort> {
|
||||
TTY_PORTS[CURRENT_VCNUM.load(Ordering::SeqCst) as usize].clone()
|
||||
VIRT_CONSOLES[CURRENT_VCNUM.load(Ordering::SeqCst) as usize]
|
||||
.lock_irqsave()
|
||||
.port()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn tty_port(index: usize) -> Arc<dyn TtyPort> {
|
||||
VIRT_CONSOLES[index].lock_irqsave().port()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@ -41,6 +34,14 @@ pub struct TtyPortData {
|
||||
sender: mpsc::Sender<u8>,
|
||||
receiver: mpsc::Receiver<u8>,
|
||||
tty: Weak<TtyCore>,
|
||||
/// 内部tty,即与port直接相连的
|
||||
internal_tty: Weak<TtyCore>,
|
||||
}
|
||||
|
||||
impl Default for TtyPortData {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl TtyPortData {
|
||||
@ -52,11 +53,12 @@ impl TtyPortData {
|
||||
sender,
|
||||
receiver,
|
||||
tty: Weak::new(),
|
||||
internal_tty: Weak::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tty(&self) -> Option<Arc<TtyCore>> {
|
||||
self.tty.upgrade()
|
||||
pub fn internal_tty(&self) -> Option<Arc<TtyCore>> {
|
||||
self.internal_tty.upgrade()
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,13 +82,13 @@ pub trait TtyPort: Sync + Send + Debug {
|
||||
}
|
||||
|
||||
/// 为port设置tty
|
||||
fn setup_tty(&self, tty: Weak<TtyCore>) {
|
||||
self.port_data().tty = tty;
|
||||
fn setup_internal_tty(&self, tty: Weak<TtyCore>) {
|
||||
self.port_data().internal_tty = tty;
|
||||
}
|
||||
|
||||
/// 作为客户端的tty ports接收数据
|
||||
fn receive_buf(&self, buf: &[u8], _flags: &[u8], count: usize) -> Result<usize, SystemError> {
|
||||
let tty = self.port_data().tty.upgrade().unwrap();
|
||||
let tty = self.port_data().internal_tty().unwrap();
|
||||
|
||||
let ld = tty.ldisc();
|
||||
|
||||
|
@ -1,6 +1,10 @@
|
||||
use core::sync::atomic::Ordering;
|
||||
|
||||
use alloc::{string::String, sync::Arc, vec::Vec};
|
||||
use alloc::{
|
||||
string::{String, ToString},
|
||||
sync::Arc,
|
||||
vec::Vec,
|
||||
};
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
@ -21,7 +25,7 @@ use super::{
|
||||
console::ConsoleSwitch,
|
||||
termios::{InputMode, TTY_STD_TERMIOS},
|
||||
tty_core::{TtyCore, TtyCoreData},
|
||||
tty_device::TtyDevice,
|
||||
tty_device::{TtyDevice, TtyType},
|
||||
tty_driver::{TtyDriver, TtyDriverManager, TtyDriverType, TtyOperation},
|
||||
};
|
||||
|
||||
@ -191,8 +195,12 @@ impl TtyOperation for TtyConsoleDriverInner {
|
||||
tty_core.termios_write().input_mode.remove(InputMode::IUTF8);
|
||||
}
|
||||
|
||||
// 设置tty的端口为vc端口
|
||||
vc_data.port().setup_internal_tty(Arc::downgrade(&tty));
|
||||
tty.set_port(vc_data.port());
|
||||
// 加入sysfs?
|
||||
|
||||
CURRENT_VCNUM.store(tty_core.index() as isize, Ordering::SeqCst);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -207,6 +215,9 @@ impl TtyOperation for TtyConsoleDriverInner {
|
||||
/// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/tty/vt/vt.c#2894
|
||||
#[inline(never)]
|
||||
fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError> {
|
||||
// if String::from_utf8_lossy(buf) == "Hello world!\n" {
|
||||
// loop {}
|
||||
// }
|
||||
let ret = self.do_write(tty, buf, nr);
|
||||
self.flush_chars(tty);
|
||||
ret
|
||||
@ -227,6 +238,10 @@ impl TtyOperation for TtyConsoleDriverInner {
|
||||
// TODO
|
||||
Err(SystemError::ENOIOCTLCMD)
|
||||
}
|
||||
|
||||
fn close(&self, _tty: Arc<TtyCore>) -> Result<(), SystemError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -264,11 +279,12 @@ pub struct DrawRegion {
|
||||
pub fn vty_init() -> Result<(), SystemError> {
|
||||
// 注册虚拟终端设备并将虚拟终端设备加入到文件系统
|
||||
let vc0 = TtyDevice::new(
|
||||
"vc0",
|
||||
"vc0".to_string(),
|
||||
IdTable::new(
|
||||
String::from("vc0"),
|
||||
Some(DeviceNumber::new(Major::TTY_MAJOR, 0)),
|
||||
),
|
||||
TtyType::Tty,
|
||||
);
|
||||
// 注册tty设备
|
||||
// CharDevOps::cdev_add(
|
||||
|
@ -9,7 +9,11 @@ use bitmap::{traits::BitMapOps, StaticBitmap};
|
||||
use crate::{
|
||||
driver::{
|
||||
serial::serial8250::send_to_default_serial8250_port,
|
||||
tty::{console::ConsoleSwitch, ConsoleFont, KDMode},
|
||||
tty::{
|
||||
console::ConsoleSwitch,
|
||||
tty_port::{DefaultTtyPort, TtyPort},
|
||||
ConsoleFont, KDMode,
|
||||
},
|
||||
},
|
||||
libs::{font::FontDesc, rwlock::RwLock},
|
||||
process::Pid,
|
||||
@ -142,6 +146,9 @@ pub struct VirtualConsoleData {
|
||||
|
||||
/// 对应的Console Driver funcs
|
||||
driver_funcs: Option<Weak<dyn ConsoleSwitch>>,
|
||||
|
||||
/// 对应端口
|
||||
port: Arc<dyn TtyPort>,
|
||||
}
|
||||
|
||||
impl VirtualConsoleData {
|
||||
@ -204,9 +211,15 @@ impl VirtualConsoleData {
|
||||
driver_funcs: None,
|
||||
cursor_type: VcCursor::empty(),
|
||||
num,
|
||||
port: Arc::new(DefaultTtyPort::new()),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn port(&self) -> Arc<dyn TtyPort> {
|
||||
self.port.clone()
|
||||
}
|
||||
|
||||
pub(super) fn init(&mut self, rows: Option<usize>, cols: Option<usize>, clear: bool) {
|
||||
if let Some(rows) = rows {
|
||||
self.rows = rows;
|
||||
|
@ -383,11 +383,15 @@ impl DeviceINode for FbDevice {
|
||||
}
|
||||
|
||||
impl IndexNode for FbDevice {
|
||||
fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), SystemError> {
|
||||
fn open(
|
||||
&self,
|
||||
_data: SpinLockGuard<FilePrivateData>,
|
||||
_mode: &FileMode,
|
||||
) -> Result<(), SystemError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
|
||||
fn close(&self, _data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> {
|
||||
Ok(())
|
||||
}
|
||||
fn read_at(
|
||||
@ -395,7 +399,7 @@ impl IndexNode for FbDevice {
|
||||
offset: usize,
|
||||
len: usize,
|
||||
buf: &mut [u8],
|
||||
_data: &mut FilePrivateData,
|
||||
_data: SpinLockGuard<FilePrivateData>,
|
||||
) -> Result<usize, SystemError> {
|
||||
let fb = self.inner.lock().fb.upgrade().unwrap();
|
||||
return fb.fb_read(&mut buf[0..len], offset);
|
||||
@ -406,7 +410,7 @@ impl IndexNode for FbDevice {
|
||||
offset: usize,
|
||||
len: usize,
|
||||
buf: &[u8],
|
||||
_data: &mut FilePrivateData,
|
||||
_data: SpinLockGuard<FilePrivateData>,
|
||||
) -> Result<usize, SystemError> {
|
||||
let fb = self.inner.lock().fb.upgrade().unwrap();
|
||||
return fb.fb_write(&buf[0..len], offset);
|
||||
|
Reference in New Issue
Block a user