完成与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

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,2 @@
pub mod vga8x16;
pub mod vga8x8;

View File

@ -0,0 +1,10 @@
use crate::libs::font::FontDesc;
pub const FONT_VGA_8X16: FontDesc = FontDesc {
index: 1,
name: "VGA8x16",
width: 8,
height: 16,
char_count: 256,
data: include_bytes!("../bin/VGA_8X16.bytes"),
};

View File

@ -0,0 +1,11 @@
use crate::libs::font::FontDesc;
#[allow(dead_code)]
pub const FONT_VGA_8X8: FontDesc = FontDesc {
index: 0,
name: "VGA8x8",
width: 8,
height: 8,
char_count: 256,
data: include_bytes!("../bin/VGA_8X8.bytes"),
};

View File

@ -0,0 +1,49 @@
use self::font_type::vga8x16::FONT_VGA_8X16;
pub mod font_type;
pub struct FontDesc {
pub index: usize,
pub name: &'static str,
pub width: u32,
pub height: u32,
pub char_count: u32,
pub data: &'static [u8],
}
impl FontDesc {
pub fn get_default_font(_xres: u32, _yres: u32, _font_w: u32, _font_h: u32) -> &'static Self {
// todo: 目前先直接返回一个字体
&FONT_VGA_8X16
}
pub const DOUBLE_WIDTH_RANGE: &'static [(u32, u32)] = &[
(0x1100, 0x115F),
(0x2329, 0x232A),
(0x2E80, 0x303E),
(0x3040, 0xA4CF),
(0xAC00, 0xD7A3),
(0xF900, 0xFAFF),
(0xFE10, 0xFE19),
(0xFE30, 0xFE6F),
(0xFF00, 0xFF60),
(0xFFE0, 0xFFE6),
(0x20000, 0x2FFFD),
(0x30000, 0x3FFFD),
];
pub fn is_double_width(ch: u32) -> bool {
if ch < Self::DOUBLE_WIDTH_RANGE.first().unwrap().0
|| ch > Self::DOUBLE_WIDTH_RANGE.last().unwrap().1
{
return false;
}
for (first, last) in Self::DOUBLE_WIDTH_RANGE {
if ch > *first && ch < *last {
return true;
}
}
false
}
}

View File

@ -1,6 +1,11 @@
use core::sync::atomic::Ordering;
use alloc::sync::Arc;
use crate::driver::tty::tty_device::TtyDevice;
use crate::driver::tty::{
tty_port::{TtyPort, TTY_PORTS},
virtual_terminal::virtual_console::CURRENT_VCNUM,
};
#[allow(dead_code)]
pub const NUM_SCAN_CODES: u8 = 0x80;
@ -28,25 +33,21 @@ pub enum KeyFlag {
pub struct TypeOneFSM {
status: ScanCodeStatus,
current_state: TypeOneFSMState,
tty: Arc<TtyDevice>,
}
impl TypeOneFSM {
#[allow(dead_code)]
pub fn new(tty: Arc<TtyDevice>) -> Self {
pub fn new() -> Self {
Self {
status: ScanCodeStatus::new(),
current_state: TypeOneFSMState::Start,
tty,
}
}
/// @brief 解析扫描码
#[allow(dead_code)]
pub fn parse(&mut self, scancode: u8) -> TypeOneFSMState {
self.current_state = self
.current_state
.parse(scancode, &mut self.status, &self.tty);
self.current_state = self.current_state.parse(scancode, &mut self.status);
self.current_state
}
}
@ -69,42 +70,30 @@ pub enum TypeOneFSMState {
impl TypeOneFSMState {
/// @brief 状态机总控程序
fn parse(
&self,
scancode: u8,
scancode_status: &mut ScanCodeStatus,
tty: &Arc<TtyDevice>,
) -> TypeOneFSMState {
fn parse(&self, scancode: u8, scancode_status: &mut ScanCodeStatus) -> TypeOneFSMState {
// kdebug!("the code is {:#x}\n", scancode);
match self {
TypeOneFSMState::Start => {
return self.handle_start(scancode, scancode_status, tty);
return self.handle_start(scancode, scancode_status);
}
TypeOneFSMState::PauseBreak(n) => {
return self.handle_pause_break(*n, scancode_status, tty);
return self.handle_pause_break(*n, scancode_status);
}
TypeOneFSMState::Func0 => {
return self.handle_func0(scancode, scancode_status, tty);
return self.handle_func0(scancode, scancode_status);
}
TypeOneFSMState::Type3 => {
return self.handle_type3(scancode, scancode_status, tty);
}
TypeOneFSMState::PrtscPress(n) => {
return self.handle_prtsc_press(*n, scancode_status, tty)
return self.handle_type3(scancode, scancode_status);
}
TypeOneFSMState::PrtscPress(n) => return self.handle_prtsc_press(*n, scancode_status),
TypeOneFSMState::PrtscRelease(n) => {
return self.handle_prtsc_release(*n, scancode_status, tty)
return self.handle_prtsc_release(*n, scancode_status)
}
}
}
/// @brief 处理起始状态
fn handle_start(
&self,
scancode: u8,
scancode_status: &mut ScanCodeStatus,
tty: &Arc<TtyDevice>,
) -> TypeOneFSMState {
fn handle_start(&self, scancode: u8, scancode_status: &mut ScanCodeStatus) -> TypeOneFSMState {
//kdebug!("in handle_start the code is {:#x}\n",scancode);
match scancode {
0xe1 => {
@ -115,7 +104,7 @@ impl TypeOneFSMState {
}
_ => {
//kdebug!("in _d the code is {:#x}\n",scancode);
return TypeOneFSMState::Type3.handle_type3(scancode, scancode_status, tty);
return TypeOneFSMState::Type3.handle_type3(scancode, scancode_status);
}
}
}
@ -125,17 +114,16 @@ impl TypeOneFSMState {
&self,
scancode: u8,
scancode_status: &mut ScanCodeStatus,
tty: &Arc<TtyDevice>,
) -> TypeOneFSMState {
static PAUSE_BREAK_SCAN_CODE: [u8; 6] = [0xe1, 0x1d, 0x45, 0xe1, 0x9d, 0xc5];
let i = match self {
TypeOneFSMState::PauseBreak(i) => *i,
_ => {
return self.handle_type3(scancode, scancode_status, tty);
return self.handle_type3(scancode, scancode_status);
}
};
if scancode != PAUSE_BREAK_SCAN_CODE[i as usize] {
return self.handle_type3(scancode, scancode_status, tty);
return self.handle_type3(scancode, scancode_status);
} else {
if i == 5 {
// 所有Pause Break扫描码都被清除
@ -146,12 +134,7 @@ impl TypeOneFSMState {
}
}
fn handle_func0(
&self,
scancode: u8,
scancode_status: &mut ScanCodeStatus,
tty: &Arc<TtyDevice>,
) -> TypeOneFSMState {
fn handle_func0(&self, scancode: u8, scancode_status: &mut ScanCodeStatus) -> TypeOneFSMState {
//0xE0
match scancode {
0x2a => {
@ -214,7 +197,7 @@ impl TypeOneFSMState {
}
0x53 => {
scancode_status.del = true;
Self::emit(tty, 127);
Self::emit(127);
}
0xd3 => {
scancode_status.del = false;
@ -233,32 +216,32 @@ impl TypeOneFSMState {
}
0x48 => {
scancode_status.arrow_u = true;
Self::emit(tty, 224);
Self::emit(tty, 72);
Self::emit(224);
Self::emit(72);
}
0xc8 => {
scancode_status.arrow_u = false;
}
0x4b => {
scancode_status.arrow_l = true;
Self::emit(tty, 224);
Self::emit(tty, 75);
Self::emit(224);
Self::emit(75);
}
0xcb => {
scancode_status.arrow_l = false;
}
0x50 => {
scancode_status.arrow_d = true;
Self::emit(tty, 224);
Self::emit(tty, 80);
Self::emit(224);
Self::emit(80);
}
0xd0 => {
scancode_status.arrow_d = false;
}
0x4d => {
scancode_status.arrow_r = true;
Self::emit(tty, 224);
Self::emit(tty, 77);
Self::emit(224);
Self::emit(77);
}
0xcd => {
scancode_status.arrow_r = false;
@ -269,14 +252,14 @@ impl TypeOneFSMState {
scancode_status.kp_forward_slash = true;
let ch = '/' as u8;
Self::emit(tty, ch);
Self::emit(ch);
}
0xb5 => {
scancode_status.kp_forward_slash = false;
}
0x1c => {
scancode_status.kp_enter = true;
Self::emit(tty, '\n' as u8);
Self::emit('\n' as u8);
}
0x9c => {
scancode_status.kp_enter = false;
@ -288,12 +271,7 @@ impl TypeOneFSMState {
return TypeOneFSMState::Start;
}
fn handle_type3(
&self,
scancode: u8,
scancode_status: &mut ScanCodeStatus,
tty: &Arc<TtyDevice>,
) -> TypeOneFSMState {
fn handle_type3(&self, scancode: u8, scancode_status: &mut ScanCodeStatus) -> TypeOneFSMState {
// 判断按键是被按下还是抬起
let flag_make = if (scancode & (TYPE1_KEYCODE_FLAG_BREAK as u8)) > 0 {
false //up
@ -358,18 +336,36 @@ impl TypeOneFSMState {
}
}
let ch = TYPE1_KEY_CODE_MAPTABLE[col as usize + 2 * index as usize];
let mut ch = TYPE1_KEY_CODE_MAPTABLE[col as usize + 2 * index as usize];
if key != KeyFlag::NoneFlag {
// kdebug!("EMIT: ch is '{}', keyflag is {:?}\n", ch as char, key);
Self::emit(tty, ch);
if scancode_status.ctrl_l || scancode_status.ctrl_r {
ch = Self::to_ctrl(ch);
}
Self::emit(ch);
}
return TypeOneFSMState::Start;
}
#[inline]
fn to_ctrl(ch: u8) -> u8 {
return match ch as char {
'a'..='z' => ch - 0x40,
'A'..='Z' => ch - 0x40,
'@'..='_' => ch - 0x40,
_ => ch,
};
}
#[inline(always)]
fn emit(tty: &Arc<TtyDevice>, ch: u8) {
fn emit(ch: u8) {
// 发送到tty
tty.input(&[ch]).ok();
let _ = Self::current_port().receive_buf(&[ch], &[], 1);
}
#[inline]
fn current_port() -> Arc<dyn TtyPort> {
TTY_PORTS[CURRENT_VCNUM.load(Ordering::SeqCst) as usize].clone()
}
/// @brief 处理Prtsc按下事件
@ -377,7 +373,6 @@ impl TypeOneFSMState {
&self,
scancode: u8,
scancode_status: &mut ScanCodeStatus,
tty: &Arc<TtyDevice>,
) -> TypeOneFSMState {
static PRTSC_SCAN_CODE: [u8; 4] = [0xe0, 0x2a, 0xe0, 0x37];
let i = match self {
@ -389,7 +384,7 @@ impl TypeOneFSMState {
return TypeOneFSMState::Start;
}
if scancode != PRTSC_SCAN_CODE[i as usize] {
return self.handle_type3(scancode, scancode_status, tty);
return self.handle_type3(scancode, scancode_status);
} else {
if i == 3 {
// 成功解析出PrtscPress
@ -405,7 +400,6 @@ impl TypeOneFSMState {
&self,
scancode: u8,
scancode_status: &mut ScanCodeStatus,
tty: &Arc<TtyDevice>,
) -> TypeOneFSMState {
static PRTSC_SCAN_CODE: [u8; 4] = [0xe0, 0xb7, 0xe0, 0xaa];
let i = match self {
@ -417,7 +411,7 @@ impl TypeOneFSMState {
return TypeOneFSMState::Start;
}
if scancode != PRTSC_SCAN_CODE[i as usize] {
return self.handle_type3(scancode, scancode_status, tty);
return self.handle_type3(scancode, scancode_status);
} else {
if i == 3 {
// 成功解析出PrtscRelease

View File

@ -8,9 +8,7 @@ use alloc::{boxed::Box, collections::LinkedList, string::String, sync::Arc};
use system_error::SystemError;
use crate::{
driver::{
tty::serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager,
},
driver::{serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager},
libs::{lib_ui::textui::textui_is_enable_put_to_window, rwlock::RwLock, spinlock::SpinLock},
mm::VirtAddr,
};

View File

@ -1,6 +1,11 @@
use crate::{
driver::{
tty::serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager,
serial::serial8250::send_to_default_serial8250_port,
tty::{
tty_driver::TtyOperation, tty_port::TTY_PORTS,
virtual_terminal::virtual_console::CURRENT_VCNUM,
},
video::video_refresh_manager,
},
kdebug, kinfo,
libs::{
@ -984,6 +989,29 @@ where
#[no_mangle]
pub extern "C" fn rs_textui_putchar(character: u8, fr_color: u32, bk_color: u32) -> i32 {
let current_vcnum = CURRENT_VCNUM.load(Ordering::SeqCst);
if current_vcnum != -1 {
// tty已经初始化了之后才输出到屏幕
let fr = (fr_color & 0x00ff0000) >> 16;
let fg = (fr_color & 0x0000ff00) >> 8;
let fb = fr_color & 0x000000ff;
let br = (bk_color & 0x00ff0000) >> 16;
let bg = (bk_color & 0x0000ff00) >> 8;
let bb = bk_color & 0x000000ff;
let buf = format!(
"\x1B[38;2;{fr};{fg};{fb};48;2;{br};{bg};{bb}m{}\x1B[0m",
character as char
);
let port = TTY_PORTS[current_vcnum as usize].clone();
let tty = port.port_data().tty();
if tty.is_some() {
let tty = tty.unwrap();
return tty
.write(tty.core(), buf.as_bytes(), buf.len())
.map(|_| 0)
.unwrap_or_else(|e| e.to_posix_errno());
}
}
return textui_putchar(
character as char,
FontColor::from(fr_color),

View File

@ -6,7 +6,7 @@ use core::{
use system_error::SystemError;
use crate::driver::{
tty::serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager,
serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager,
};
use super::textui::{

View File

@ -25,3 +25,5 @@ pub mod volatile;
pub mod futex;
pub mod rand;
pub mod wait_queue;
pub mod font;

View File

@ -1,10 +1,20 @@
use core::fmt::{self, Write};
use core::{
fmt::{self, Write},
sync::atomic::Ordering,
};
use alloc::string::ToString;
use super::lib_ui::textui::{textui_putstr, FontColor};
use crate::{
driver::{
serial::serial8250::send_to_default_serial8250_port,
tty::{
tty_driver::TtyOperation, tty_port::TTY_PORTS,
virtual_terminal::virtual_console::CURRENT_VCNUM,
},
},
filesystem::procfs::{
kmsg::KMSG,
log::{LogLevel, LogMessage},
@ -57,7 +67,7 @@ macro_rules! kinfo {
macro_rules! kwarn {
($($arg:tt)*) => {
$crate::libs::printk::Logger.log(4,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
$crate::libs::printk::PrintkWriter.__write_string_color($crate::libs::lib_ui::textui::FontColor::YELLOW, $crate::libs::lib_ui::textui::FontColor::BLACK, "[ WARN ] ");
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("\x1B[1;33m[ WARN ] \x1B[0m"));
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
}
}
@ -66,7 +76,7 @@ macro_rules! kwarn {
macro_rules! kerror {
($($arg:tt)*) => {
$crate::libs::printk::Logger.log(3,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
$crate::libs::printk::PrintkWriter.__write_string_color($crate::libs::lib_ui::textui::FontColor::RED, $crate::libs::lib_ui::textui::FontColor::BLACK, "[ ERROR ] ");
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("\x1B[41m[ ERROR ] \x1B[0m"));
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
}
}
@ -75,7 +85,7 @@ macro_rules! kerror {
macro_rules! kBUG {
($($arg:tt)*) => {
$crate::libs::printk::Logger.log(1,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
$crate::libs::printk::PrintkWriter.__write_string_color($crate::libs::lib_ui::textui::FontColor::RED, $crate::libs::lib_ui::textui::FontColor::BLACK, "[ BUG ] ");
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("\x1B[41m[ BUG ] \x1B[0m"));
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
}
}
@ -91,11 +101,21 @@ impl PrintkWriter {
/// 并输出白底黑字
/// @param str: 要写入的字符
pub fn __write_string(&mut self, s: &str) {
textui_putstr(s, FontColor::WHITE, FontColor::BLACK).ok();
}
pub fn __write_string_color(&self, fr_color: FontColor, bk_color: FontColor, s: &str) {
textui_putstr(s, fr_color, bk_color).ok();
let current_vcnum = CURRENT_VCNUM.load(Ordering::SeqCst);
if current_vcnum != -1 {
// tty已经初始化了之后才输出到屏幕
let port = TTY_PORTS[current_vcnum as usize].clone();
let tty = port.port_data().tty();
if tty.is_some() {
let tty = tty.unwrap();
let _ = tty.write(tty.core(), s.as_bytes(), s.len());
send_to_default_serial8250_port(s.as_bytes());
} else {
let _ = textui_putstr(s, FontColor::WHITE, FontColor::BLACK);
}
} else {
let _ = textui_putstr(s, FontColor::WHITE, FontColor::BLACK);
}
}
}