完成与Linux兼容的Ntty (#517)

* 已经完成的功能:
- 写:printf能够正常在tty输出
- 读:与键盘驱动接上
- 信号: 能够正常通过ctrl向前台进程发送信号

* 支持目前的shell,改动printk使其与新版tty兼容。

* 删除原有tty文件夹,并更改新tty文件名

* 添加clear清屏程序

* 实现tty部分ioctl,更改部分问题
This commit is contained in:
GnoCiYeH
2024-02-26 15:27:19 +08:00
committed by GitHub
parent 9993c0fc61
commit 52da9a5937
62 changed files with 8843 additions and 928 deletions

View File

@ -1,61 +1,446 @@
use core::fmt::Debug;
use core::{fmt::Debug, sync::atomic::Ordering};
use alloc::sync::Arc;
use alloc::{string::String, sync::Arc, vec::Vec};
use hashbrown::HashMap;
use system_error::SystemError;
use crate::driver::base::device::driver::Driver;
use crate::{
driver::{
base::{
char::CharDevOps,
device::{
device_number::{DeviceNumber, Major},
driver::Driver,
},
kobject::KObject,
},
tty::tty_port::TtyPortState,
},
libs::spinlock::SpinLock,
};
use super::tty_device::TtyDevice;
use super::{
termios::Termios,
tty_core::{TtyCore, TtyCoreData},
tty_ldisc::TtyLdiscManager,
tty_port::TTY_PORTS,
virtual_terminal::virtual_console::CURRENT_VCNUM,
};
/// TTY 驱动
///
///
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/tty_driver.h#434
pub trait TtyDriver: Debug + Send + Sync + Driver {
fn driver_name(&self) -> &str;
fn dev_name(&self) -> &str;
lazy_static! {
static ref TTY_DRIVERS: SpinLock<Vec<Arc<TtyDriver>>> = SpinLock::new(Vec::new());
}
fn metadata(&self) -> &TtyDriverMetadata;
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() {
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()));
}
fn other(&self) -> Option<&Arc<dyn TtyDriver>>;
fn ttys(&self) -> &[Arc<TtyDevice>];
fn tty_ops(&self) -> Option<&'static dyn TtyDriverOperations> {
None
}
}
#[derive(Debug, Clone, Copy)]
#[allow(dead_code)]
pub struct TtyDriverMetadata {
/// name of the driver used in /proc/tty
driver_name: &'static str,
/// used for constructing /dev node name
dev_name: &'static str,
/// used as a number base for constructing /dev node name
name_base: i32,
/// major /dev device number (zero for autoassignment)
major: i32,
/// the first minor /dev device number
minor_start: i32,
drv_type: TtyDriverType,
subtype: TtyDriverSubtype,
}
/// ## 注册驱动
pub fn tty_register_driver(mut driver: TtyDriver) -> Result<(), SystemError> {
// 查看是否注册设备号
if driver.major == Major::UNNAMED_MAJOR {
let dev_num = CharDevOps::alloc_chardev_region(
driver.minor_start,
driver.device_count,
driver.name,
)?;
driver.major = dev_num.major();
driver.minor_start = dev_num.minor();
} else {
let dev_num = DeviceNumber::new(driver.major, driver.minor_start);
CharDevOps::register_chardev_region(dev_num, driver.device_count, driver.name)?;
}
/// https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/tty_driver.h#411
#[derive(Debug, Clone, Copy)]
pub enum TtyDriverType {}
driver.flags |= TtyDriverFlag::TTY_DRIVER_INSTALLED;
/// https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/tty_driver.h#412
#[derive(Debug, Clone, Copy)]
pub enum TtyDriverSubtype {}
// 加入全局TtyDriver表
TTY_DRIVERS.lock().push(Arc::new(driver));
bitflags! {
/// https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/tty_driver.h?fi=SERIAL_TYPE_NORMAL#492
pub struct TtyDriverFlags: u64 {
// TODO: 加入procfs?
Ok(())
}
}
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/tty_driver.h#350
pub trait TtyDriverOperations {}
#[allow(dead_code)]
#[derive(Debug)]
#[cast_to([sync] Driver)]
pub struct TtyDriver {
/// /proc/tty中使用的驱动程序名称
driver_name: String,
/// 用于构造/dev节点名称例如name设置为tty,则按照name_base分配节点tty0,tty1等
name: &'static str,
/// 命名基数
name_base: usize,
/// 主设备号
major: Major,
/// 起始次设备号
minor_start: u32,
/// 最多支持的tty数量
device_count: u32,
/// tty驱动程序类型
tty_driver_type: TtyDriverType,
/// 驱动程序子类型
tty_driver_sub_type: TtyDriverSubType,
/// 每个tty的默认termios
init_termios: Termios,
/// 懒加载termios,在tty设备关闭时会将termios按照设备的index保存进这个集合以便下次打开使用
saved_termios: Vec<Termios>,
/// 驱动程序标志
flags: TtyDriverFlag,
/// pty链接此driver的入口
pty: Option<Arc<TtyDriver>>,
/// 具体类型的tty驱动方法
driver_funcs: Arc<dyn TtyOperation>,
/// 管理的tty设备列表
ttys: SpinLock<HashMap<usize, Arc<TtyCore>>>,
// procfs入口?
}
impl TtyDriver {
pub fn new(
count: u32,
node_name: &'static str,
node_name_base: usize,
major: Major,
minor_start: u32,
tty_driver_type: TtyDriverType,
default_termios: Termios,
driver_funcs: Arc<dyn TtyOperation>,
) -> Self {
TtyDriver {
driver_name: Default::default(),
name: node_name,
name_base: node_name_base,
major,
minor_start,
device_count: count,
tty_driver_type,
tty_driver_sub_type: Default::default(),
init_termios: default_termios,
flags: TtyDriverFlag::empty(),
pty: Default::default(),
driver_funcs,
ttys: SpinLock::new(HashMap::new()),
saved_termios: Vec::with_capacity(count as usize),
}
}
pub fn tty_line_name(&self, index: usize) -> String {
if self
.flags
.contains(TtyDriverFlag::TTY_DRIVER_UNNUMBERED_NODE)
{
return format!("{}", self.name);
} else {
return format!("{}{}", self.name, index + self.name_base);
}
}
pub fn add_tty(&self, tty_core: Arc<TtyCore>) {
self.ttys.lock().insert(tty_core.core().index(), tty_core);
}
#[inline]
pub fn driver_funcs(&self) -> Arc<dyn TtyOperation> {
self.driver_funcs.clone()
}
#[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 match device_guard.get(&index) {
Some(tty) => Some(tty.clone()),
None => None,
};
}
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.clone();
termios.line = self.init_termios.line;
tty.set_termios(termios);
}
}
// TODO:设置termios波特率
tty.add_count();
self.ttys.lock().insert(tty_index, tty_core);
Ok(())
}
fn driver_install_tty(driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> {
let res = tty.install(driver.clone(), tty.clone());
if res.is_err() {
let err = res.unwrap_err();
if err == SystemError::ENOSYS {
return driver.standard_install(tty);
} else {
return Err(err);
}
}
driver.add_tty(tty);
Ok(())
}
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())?;
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());
}
TtyLdiscManager::ldisc_setup(tty.clone(), None)?;
Ok(tty)
}
/// ## 通过设备号找到对应驱动并且初始化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) {
Some(tty) => {
// TODO: 暂时这么写因为还没写TtyPort
if tty.core().port().is_none() {
kwarn!("{} port is None", tty.core().name());
} else {
if tty.core().port().unwrap().state() == TtyPortState::KOPENED {
return Err(SystemError::EBUSY);
}
}
tty.reopen()?;
tty
}
None => Self::init_tty_device(driver, index)?,
};
CURRENT_VCNUM.store(index as isize, Ordering::SeqCst);
return Ok(tty);
}
pub fn tty_driver_type(&self) -> TtyDriverType {
self.tty_driver_type
}
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 {
fn as_any_ref(&self) -> &dyn core::any::Any {
todo!()
}
fn set_inode(&self, _inode: Option<alloc::sync::Arc<crate::filesystem::kernfs::KernFSInode>>) {
todo!()
}
fn inode(&self) -> Option<alloc::sync::Arc<crate::filesystem::kernfs::KernFSInode>> {
todo!()
}
fn parent(&self) -> Option<alloc::sync::Weak<dyn KObject>> {
todo!()
}
fn set_parent(&self, _parent: Option<alloc::sync::Weak<dyn KObject>>) {
todo!()
}
fn kset(&self) -> Option<alloc::sync::Arc<crate::driver::base::kset::KSet>> {
todo!()
}
fn set_kset(&self, _kset: Option<alloc::sync::Arc<crate::driver::base::kset::KSet>>) {
todo!()
}
fn kobj_type(&self) -> Option<&'static dyn crate::driver::base::kobject::KObjType> {
todo!()
}
fn set_kobj_type(&self, _ktype: Option<&'static dyn crate::driver::base::kobject::KObjType>) {
todo!()
}
fn name(&self) -> alloc::string::String {
todo!()
}
fn set_name(&self, _name: alloc::string::String) {
todo!()
}
fn kobj_state(
&self,
) -> crate::libs::rwlock::RwLockReadGuard<crate::driver::base::kobject::KObjectState> {
todo!()
}
fn kobj_state_mut(
&self,
) -> crate::libs::rwlock::RwLockWriteGuard<crate::driver::base::kobject::KObjectState> {
todo!()
}
fn set_kobj_state(&self, _state: crate::driver::base::kobject::KObjectState) {
todo!()
}
}
impl Driver for TtyDriver {
fn id_table(&self) -> Option<crate::driver::base::device::IdTable> {
todo!()
}
fn devices(
&self,
) -> alloc::vec::Vec<alloc::sync::Arc<dyn crate::driver::base::device::Device>> {
todo!()
}
fn add_device(&self, _device: alloc::sync::Arc<dyn crate::driver::base::device::Device>) {
todo!()
}
fn delete_device(&self, _device: &alloc::sync::Arc<dyn crate::driver::base::device::Device>) {
todo!()
}
fn set_bus(&self, _bus: Option<alloc::sync::Weak<dyn crate::driver::base::device::bus::Bus>>) {
todo!()
}
}
pub trait TtyOperation: Sync + Send + Debug {
fn install(&self, _driver: Arc<TtyDriver>, _tty: Arc<TtyCore>) -> Result<(), SystemError> {
return Err(SystemError::ENOSYS);
}
fn open(&self, tty: &TtyCoreData) -> Result<(), SystemError>;
/// ## 获取可写字符数
fn write_room(&self, _tty: &TtyCoreData) -> usize {
// 默认
2048
}
fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError>;
fn flush_chars(&self, tty: &TtyCoreData);
fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError>;
fn start(&self, _tty: &TtyCoreData) -> Result<(), SystemError> {
Err(SystemError::ENOSYS)
}
fn stop(&self, _tty: &TtyCoreData) -> Result<(), SystemError> {
Err(SystemError::ENOSYS)
}
fn flush_buffer(&self, _tty: &TtyCoreData) -> Result<(), SystemError> {
Err(SystemError::ENOSYS)
}
fn ioctl(&self, tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<(), SystemError>;
fn chars_in_buffer(&self) -> usize {
0
}
fn set_termios(&self, _tty: Arc<TtyCore>, _old_termios: Termios) -> Result<(), SystemError> {
Err(SystemError::ENOSYS)
}
}
#[allow(dead_code)]
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum TtyDriverType {
System,
Console,
Serial,
Pty,
Scc,
Syscons,
}
#[allow(dead_code)]
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum TtyDriverSubType {
Undefined,
Tty,
Console,
Syscons,
Sysptmx,
PtyMaster,
PtySlave,
SerialNormal,
}
impl Default for TtyDriverSubType {
fn default() -> Self {
Self::Undefined
}
}
bitflags! {
pub struct TtyDriverFlag: u32 {
/// 表示 tty 驱动程序已安装
const TTY_DRIVER_INSTALLED = 0x0001;
/// 请求 tty 层在最后一个进程关闭设备时重置 termios 设置
const TTY_DRIVER_RESET_TERMIOS = 0x0002;
/// 表示驱动程序将保证在设置了该标志的 tty 上不设置任何特殊字符处理标志(原模式)
const TTY_DRIVER_REAL_RAW = 0x0004;
/// 以下四个标志位为内存分配相关,目前设计无需使用
const TTY_DRIVER_DYNAMIC_DEV = 0x0008;
const TTY_DRIVER_DEVPTS_MEM = 0x0010;
const TTY_DRIVER_HARDWARE_BREAK = 0x0020;
const TTY_DRIVER_DYNAMIC_ALLOC = 0x0040;
/// 表示不创建带有编号的 /dev 节点。
/// 例如,创建 /dev/ttyprintk 而不是 /dev/ttyprintk0。仅在为单个 tty 设备分配驱动程序时适用。
const TTY_DRIVER_UNNUMBERED_NODE = 0x0080;
}
}