152da9a59SGnoCiYeH use core::sync::atomic::Ordering; 252da9a59SGnoCiYeH 3*dfe53cf0SGnoCiYeH use alloc::{ 4*dfe53cf0SGnoCiYeH string::{String, ToString}, 5*dfe53cf0SGnoCiYeH sync::Arc, 6*dfe53cf0SGnoCiYeH vec::Vec, 7*dfe53cf0SGnoCiYeH }; 852da9a59SGnoCiYeH use system_error::SystemError; 952da9a59SGnoCiYeH 1052da9a59SGnoCiYeH use crate::{ 1152da9a59SGnoCiYeH driver::{ 1252da9a59SGnoCiYeH base::device::{ 1352da9a59SGnoCiYeH device_number::{DeviceNumber, Major}, 1452da9a59SGnoCiYeH device_register, IdTable, 1552da9a59SGnoCiYeH }, 1652da9a59SGnoCiYeH video::fbdev::base::fbcon::framebuffer_console::BlittingFbConsole, 1752da9a59SGnoCiYeH }, 1852da9a59SGnoCiYeH filesystem::devfs::devfs_register, 1952da9a59SGnoCiYeH libs::spinlock::SpinLock, 2052da9a59SGnoCiYeH }; 2152da9a59SGnoCiYeH 2252da9a59SGnoCiYeH use self::virtual_console::{VirtualConsoleData, CURRENT_VCNUM}; 2352da9a59SGnoCiYeH 2452da9a59SGnoCiYeH use super::{ 2552da9a59SGnoCiYeH console::ConsoleSwitch, 2652da9a59SGnoCiYeH termios::{InputMode, TTY_STD_TERMIOS}, 2752da9a59SGnoCiYeH tty_core::{TtyCore, TtyCoreData}, 28*dfe53cf0SGnoCiYeH tty_device::{TtyDevice, TtyType}, 2952da9a59SGnoCiYeH tty_driver::{TtyDriver, TtyDriverManager, TtyDriverType, TtyOperation}, 3052da9a59SGnoCiYeH }; 3152da9a59SGnoCiYeH 3252da9a59SGnoCiYeH pub mod console_map; 3352da9a59SGnoCiYeH pub mod virtual_console; 3452da9a59SGnoCiYeH 3552da9a59SGnoCiYeH pub const MAX_NR_CONSOLES: u32 = 63; 3652da9a59SGnoCiYeH pub const VC_MAXCOL: usize = 32767; 3752da9a59SGnoCiYeH pub const VC_MAXROW: usize = 32767; 3852da9a59SGnoCiYeH 3952da9a59SGnoCiYeH pub const DEFAULT_RED: [u16; 16] = [ 4052da9a59SGnoCiYeH 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x55, 0xff, 0x55, 0xff, 0x55, 0xff, 0x55, 0xff, 4152da9a59SGnoCiYeH ]; 4252da9a59SGnoCiYeH 4352da9a59SGnoCiYeH pub const DEFAULT_GREEN: [u16; 16] = [ 4452da9a59SGnoCiYeH 0x00, 0x00, 0xaa, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff, 4552da9a59SGnoCiYeH ]; 4652da9a59SGnoCiYeH 4752da9a59SGnoCiYeH pub const DEFAULT_BLUE: [u16; 16] = [ 4852da9a59SGnoCiYeH 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xff, 0xff, 0xff, 0xff, 4952da9a59SGnoCiYeH ]; 5052da9a59SGnoCiYeH 51b5b571e0SLoGin pub const COLOR_TABLE: &[u8] = &[0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15]; 5252da9a59SGnoCiYeH 5352da9a59SGnoCiYeH lazy_static! { 5452da9a59SGnoCiYeH pub static ref VIRT_CONSOLES: Vec<Arc<SpinLock<VirtualConsoleData>>> = { 5552da9a59SGnoCiYeH let mut v = Vec::with_capacity(MAX_NR_CONSOLES as usize); 5652da9a59SGnoCiYeH for i in 0..MAX_NR_CONSOLES as usize { 5752da9a59SGnoCiYeH v.push(Arc::new(SpinLock::new(VirtualConsoleData::new(i)))); 5852da9a59SGnoCiYeH } 5952da9a59SGnoCiYeH 6052da9a59SGnoCiYeH v 6152da9a59SGnoCiYeH }; 6252da9a59SGnoCiYeH } 6352da9a59SGnoCiYeH 6452da9a59SGnoCiYeH #[derive(Debug, Clone, Copy, Default)] 6552da9a59SGnoCiYeH pub struct Color { 6652da9a59SGnoCiYeH pub red: u16, 6752da9a59SGnoCiYeH pub green: u16, 6852da9a59SGnoCiYeH pub blue: u16, 6952da9a59SGnoCiYeH pub transp: u16, 7052da9a59SGnoCiYeH } 7152da9a59SGnoCiYeH 7252da9a59SGnoCiYeH impl Color { 7352da9a59SGnoCiYeH pub fn from_256(col: u32) -> Self { 7452da9a59SGnoCiYeH let mut color = Self::default(); 7552da9a59SGnoCiYeH if col < 8 { 7652da9a59SGnoCiYeH color.red = if col & 1 != 0 { 0xaa } else { 0x00 }; 7752da9a59SGnoCiYeH color.green = if col & 2 != 0 { 0xaa } else { 0x00 }; 7852da9a59SGnoCiYeH color.blue = if col & 4 != 0 { 0xaa } else { 0x00 }; 7952da9a59SGnoCiYeH } else if col < 16 { 8052da9a59SGnoCiYeH color.red = if col & 1 != 0 { 0xff } else { 0x55 }; 8152da9a59SGnoCiYeH color.green = if col & 2 != 0 { 0xff } else { 0x55 }; 8252da9a59SGnoCiYeH color.blue = if col & 4 != 0 { 0xff } else { 0x55 }; 8352da9a59SGnoCiYeH } else if col < 232 { 8452da9a59SGnoCiYeH color.red = ((col - 16) / 36 * 85 / 2) as u16; 8552da9a59SGnoCiYeH color.green = ((col - 16) / 6 % 6 * 85 / 2) as u16; 8652da9a59SGnoCiYeH color.blue = ((col - 16) % 6 * 85 / 2) as u16; 8752da9a59SGnoCiYeH } else { 8852da9a59SGnoCiYeH let col = (col * 10 - 2312) as u16; 8952da9a59SGnoCiYeH color.red = col; 9052da9a59SGnoCiYeH color.green = col; 9152da9a59SGnoCiYeH color.blue = col; 9252da9a59SGnoCiYeH } 9352da9a59SGnoCiYeH 9452da9a59SGnoCiYeH color 9552da9a59SGnoCiYeH } 9652da9a59SGnoCiYeH } 9752da9a59SGnoCiYeH 9852da9a59SGnoCiYeH #[derive(Debug)] 9952da9a59SGnoCiYeH pub struct TtyConsoleDriverInner { 10052da9a59SGnoCiYeH console: Arc<BlittingFbConsole>, 10152da9a59SGnoCiYeH } 10252da9a59SGnoCiYeH 10352da9a59SGnoCiYeH impl TtyConsoleDriverInner { 10452da9a59SGnoCiYeH pub fn new() -> Result<Self, SystemError> { 10552da9a59SGnoCiYeH Ok(Self { 10652da9a59SGnoCiYeH console: Arc::new(BlittingFbConsole::new()?), 10752da9a59SGnoCiYeH }) 10852da9a59SGnoCiYeH } 10952da9a59SGnoCiYeH 11052bcb59eSGnoCiYeH fn do_write(&self, tty: &TtyCoreData, buf: &[u8], mut nr: usize) -> Result<usize, SystemError> { 11152da9a59SGnoCiYeH // 关闭中断 11252da9a59SGnoCiYeH let mut vc_data = tty.vc_data_irqsave(); 11352da9a59SGnoCiYeH 11452da9a59SGnoCiYeH let mut offset = 0; 11552da9a59SGnoCiYeH 11652da9a59SGnoCiYeH // 这个参数是用来扫描unicode字符的,但是这部分目前未完成,先写着 11752da9a59SGnoCiYeH let mut rescan = false; 11852da9a59SGnoCiYeH let mut ch: u32 = 0; 11952da9a59SGnoCiYeH 12052da9a59SGnoCiYeH let mut draw = DrawRegion::default(); 12152da9a59SGnoCiYeH 12252da9a59SGnoCiYeH // 首先隐藏光标再写 12352da9a59SGnoCiYeH vc_data.hide_cursor(); 12452da9a59SGnoCiYeH 12552da9a59SGnoCiYeH while nr != 0 { 12652da9a59SGnoCiYeH if !rescan { 12752da9a59SGnoCiYeH ch = buf[offset] as u32; 12852da9a59SGnoCiYeH offset += 1; 12952da9a59SGnoCiYeH nr -= 1; 13052da9a59SGnoCiYeH } 13152da9a59SGnoCiYeH 13252da9a59SGnoCiYeH let (tc, rescan_last) = vc_data.translate(&mut ch); 13352da9a59SGnoCiYeH if tc.is_none() { 13452da9a59SGnoCiYeH // 表示未转换完成 13552da9a59SGnoCiYeH continue; 13652da9a59SGnoCiYeH } 13752da9a59SGnoCiYeH 13852da9a59SGnoCiYeH let tc = tc.unwrap(); 13952da9a59SGnoCiYeH rescan = rescan_last; 14052da9a59SGnoCiYeH 14152da9a59SGnoCiYeH if vc_data.is_control(tc, ch) { 14252da9a59SGnoCiYeH vc_data.flush(&mut draw); 14352da9a59SGnoCiYeH vc_data.do_control(ch); 14452da9a59SGnoCiYeH continue; 14552da9a59SGnoCiYeH } 14652da9a59SGnoCiYeH 14752da9a59SGnoCiYeH if !vc_data.console_write_normal(tc, ch, &mut draw) { 14852da9a59SGnoCiYeH continue; 14952da9a59SGnoCiYeH } 15052da9a59SGnoCiYeH } 15152da9a59SGnoCiYeH 15252da9a59SGnoCiYeH vc_data.flush(&mut draw); 15352da9a59SGnoCiYeH 15452da9a59SGnoCiYeH // TODO: notify update 15552da9a59SGnoCiYeH return Ok(offset); 15652da9a59SGnoCiYeH } 15752bcb59eSGnoCiYeH } 15852da9a59SGnoCiYeH 15952bcb59eSGnoCiYeH impl TtyOperation for TtyConsoleDriverInner { 16052bcb59eSGnoCiYeH fn install(&self, _driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> { 16152bcb59eSGnoCiYeH let tty_core = tty.core(); 16252bcb59eSGnoCiYeH let mut vc_data = VIRT_CONSOLES[tty_core.index()].lock(); 16352bcb59eSGnoCiYeH 16452bcb59eSGnoCiYeH self.console.con_init(&mut vc_data, true)?; 16552bcb59eSGnoCiYeH if vc_data.complement_mask == 0 { 16652bcb59eSGnoCiYeH vc_data.complement_mask = if vc_data.color_mode { 0x7700 } else { 0x0800 }; 16752bcb59eSGnoCiYeH } 16852bcb59eSGnoCiYeH vc_data.s_complement_mask = vc_data.complement_mask; 16952bcb59eSGnoCiYeH // vc_data.bytes_per_row = vc_data.cols << 1; 17052bcb59eSGnoCiYeH vc_data.index = tty_core.index(); 17152bcb59eSGnoCiYeH vc_data.bottom = vc_data.rows; 17252bcb59eSGnoCiYeH vc_data.set_driver_funcs(Arc::downgrade( 17352bcb59eSGnoCiYeH &(self.console.clone() as Arc<dyn ConsoleSwitch>), 17452bcb59eSGnoCiYeH )); 17552bcb59eSGnoCiYeH 17652bcb59eSGnoCiYeH // todo: unicode字符集处理? 17752bcb59eSGnoCiYeH 17852bcb59eSGnoCiYeH if vc_data.cols > VC_MAXCOL || vc_data.rows > VC_MAXROW { 17952bcb59eSGnoCiYeH return Err(SystemError::EINVAL); 18052bcb59eSGnoCiYeH } 18152bcb59eSGnoCiYeH 18252bcb59eSGnoCiYeH vc_data.init(None, None, true); 18352bcb59eSGnoCiYeH vc_data.update_attr(); 18452bcb59eSGnoCiYeH 18552bcb59eSGnoCiYeH let window_size = tty_core.window_size_upgradeable(); 18652bcb59eSGnoCiYeH if window_size.col == 0 && window_size.row == 0 { 18752bcb59eSGnoCiYeH let mut window_size = window_size.upgrade(); 18852bcb59eSGnoCiYeH window_size.col = vc_data.cols as u16; 18952bcb59eSGnoCiYeH window_size.row = vc_data.rows as u16; 19052bcb59eSGnoCiYeH } 19152bcb59eSGnoCiYeH 19252bcb59eSGnoCiYeH if vc_data.utf { 19352bcb59eSGnoCiYeH tty_core.termios_write().input_mode.insert(InputMode::IUTF8); 19452bcb59eSGnoCiYeH } else { 19552bcb59eSGnoCiYeH tty_core.termios_write().input_mode.remove(InputMode::IUTF8); 19652bcb59eSGnoCiYeH } 19752bcb59eSGnoCiYeH 198*dfe53cf0SGnoCiYeH // 设置tty的端口为vc端口 199*dfe53cf0SGnoCiYeH vc_data.port().setup_internal_tty(Arc::downgrade(&tty)); 200*dfe53cf0SGnoCiYeH tty.set_port(vc_data.port()); 20152bcb59eSGnoCiYeH // 加入sysfs? 20252bcb59eSGnoCiYeH 203*dfe53cf0SGnoCiYeH CURRENT_VCNUM.store(tty_core.index() as isize, Ordering::SeqCst); 20452bcb59eSGnoCiYeH Ok(()) 20552bcb59eSGnoCiYeH } 20652bcb59eSGnoCiYeH 20752bcb59eSGnoCiYeH fn open(&self, _tty: &TtyCoreData) -> Result<(), SystemError> { 20852bcb59eSGnoCiYeH Ok(()) 20952bcb59eSGnoCiYeH } 21052bcb59eSGnoCiYeH 21152bcb59eSGnoCiYeH fn write_room(&self, _tty: &TtyCoreData) -> usize { 21252bcb59eSGnoCiYeH 32768 21352bcb59eSGnoCiYeH } 21452bcb59eSGnoCiYeH 21552bcb59eSGnoCiYeH /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/tty/vt/vt.c#2894 21652bcb59eSGnoCiYeH #[inline(never)] 21752bcb59eSGnoCiYeH fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError> { 218*dfe53cf0SGnoCiYeH // if String::from_utf8_lossy(buf) == "Hello world!\n" { 219*dfe53cf0SGnoCiYeH // loop {} 220*dfe53cf0SGnoCiYeH // } 22152bcb59eSGnoCiYeH let ret = self.do_write(tty, buf, nr); 22252bcb59eSGnoCiYeH self.flush_chars(tty); 22352bcb59eSGnoCiYeH ret 22452bcb59eSGnoCiYeH } 22552bcb59eSGnoCiYeH 22652bcb59eSGnoCiYeH #[inline(never)] 22752da9a59SGnoCiYeH fn flush_chars(&self, tty: &TtyCoreData) { 22852da9a59SGnoCiYeH let mut vc_data = tty.vc_data_irqsave(); 22952da9a59SGnoCiYeH vc_data.set_cursor(); 23052da9a59SGnoCiYeH } 23152da9a59SGnoCiYeH 23252da9a59SGnoCiYeH fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError> { 23352da9a59SGnoCiYeH self.write(tty, &[ch], 1)?; 23452da9a59SGnoCiYeH Ok(()) 23552da9a59SGnoCiYeH } 23652da9a59SGnoCiYeH 23752da9a59SGnoCiYeH fn ioctl(&self, _tty: Arc<TtyCore>, _cmd: u32, _arg: usize) -> Result<(), SystemError> { 23852da9a59SGnoCiYeH // TODO 23952da9a59SGnoCiYeH Err(SystemError::ENOIOCTLCMD) 24052da9a59SGnoCiYeH } 241*dfe53cf0SGnoCiYeH 242*dfe53cf0SGnoCiYeH fn close(&self, _tty: Arc<TtyCore>) -> Result<(), SystemError> { 243*dfe53cf0SGnoCiYeH Ok(()) 244*dfe53cf0SGnoCiYeH } 24552da9a59SGnoCiYeH } 24652da9a59SGnoCiYeH 24752da9a59SGnoCiYeH #[derive(Debug, Clone)] 24852da9a59SGnoCiYeH pub struct VtModeData { 24952da9a59SGnoCiYeH mode: VtMode, 25052da9a59SGnoCiYeH /// 释放请求时触发的信号 25152da9a59SGnoCiYeH relsig: u16, 25252da9a59SGnoCiYeH /// 获取请求时触发的信号 25352da9a59SGnoCiYeH acqsig: u16, 25452da9a59SGnoCiYeH } 25552da9a59SGnoCiYeH 25652da9a59SGnoCiYeH #[allow(dead_code)] 25752da9a59SGnoCiYeH #[derive(Debug, Clone)] 25852da9a59SGnoCiYeH pub enum VtMode { 25952da9a59SGnoCiYeH /// 自动切换模式,即在请求输入时自动切换到终端 26052da9a59SGnoCiYeH Auto, 26152da9a59SGnoCiYeH /// 手动切换模式,需要通过 ioctl 请求切换到终端 26252da9a59SGnoCiYeH Process, 26352da9a59SGnoCiYeH /// 等待终端确认,即在切换到终端时等待终端的确认信号 26452da9a59SGnoCiYeH Ackacq, 26552da9a59SGnoCiYeH } 26652da9a59SGnoCiYeH 26752da9a59SGnoCiYeH /// 用于给vc确定要写入的buf位置 26852da9a59SGnoCiYeH #[derive(Debug, Default)] 26952da9a59SGnoCiYeH pub struct DrawRegion { 27052da9a59SGnoCiYeH /// 偏移量 27152da9a59SGnoCiYeH pub offset: usize, 27252da9a59SGnoCiYeH /// 写入数量 27352da9a59SGnoCiYeH pub size: usize, 27452da9a59SGnoCiYeH pub x: Option<u32>, 27552da9a59SGnoCiYeH } 27652da9a59SGnoCiYeH 27752da9a59SGnoCiYeH // 初始化虚拟终端 27852da9a59SGnoCiYeH #[inline(never)] 27952da9a59SGnoCiYeH pub fn vty_init() -> Result<(), SystemError> { 28052da9a59SGnoCiYeH // 注册虚拟终端设备并将虚拟终端设备加入到文件系统 28152da9a59SGnoCiYeH let vc0 = TtyDevice::new( 282*dfe53cf0SGnoCiYeH "vc0".to_string(), 28352da9a59SGnoCiYeH IdTable::new( 28452da9a59SGnoCiYeH String::from("vc0"), 28552da9a59SGnoCiYeH Some(DeviceNumber::new(Major::TTY_MAJOR, 0)), 28652da9a59SGnoCiYeH ), 287*dfe53cf0SGnoCiYeH TtyType::Tty, 28852da9a59SGnoCiYeH ); 28952da9a59SGnoCiYeH // 注册tty设备 29052da9a59SGnoCiYeH // CharDevOps::cdev_add( 29152da9a59SGnoCiYeH // vc0.clone() as Arc<dyn CharDevice>, 29252da9a59SGnoCiYeH // IdTable::new( 29352da9a59SGnoCiYeH // String::from("vc0"), 29452da9a59SGnoCiYeH // Some(DeviceNumber::new(Major::TTY_MAJOR, 0)), 29552da9a59SGnoCiYeH // ), 29652da9a59SGnoCiYeH // 1, 29752da9a59SGnoCiYeH // )?; 29852da9a59SGnoCiYeH 29952da9a59SGnoCiYeH // CharDevOps::register_chardev_region(DeviceNumber::new(Major::TTY_MAJOR, 0), 1, "/dev/vc/0")?; 30052da9a59SGnoCiYeH device_register(vc0.clone())?; 30152da9a59SGnoCiYeH devfs_register("vc0", vc0)?; 30252da9a59SGnoCiYeH 30352da9a59SGnoCiYeH // vcs_init? 30452da9a59SGnoCiYeH 30552da9a59SGnoCiYeH let console_driver = TtyDriver::new( 30652da9a59SGnoCiYeH MAX_NR_CONSOLES, 30752da9a59SGnoCiYeH "tty", 30852da9a59SGnoCiYeH 1, 30952da9a59SGnoCiYeH Major::TTY_MAJOR, 31052da9a59SGnoCiYeH 0, 31152da9a59SGnoCiYeH TtyDriverType::Console, 312b5b571e0SLoGin *TTY_STD_TERMIOS, 31352da9a59SGnoCiYeH Arc::new(TtyConsoleDriverInner::new()?), 31452da9a59SGnoCiYeH ); 31552da9a59SGnoCiYeH 31652da9a59SGnoCiYeH TtyDriverManager::tty_register_driver(console_driver)?; 31752da9a59SGnoCiYeH 31852da9a59SGnoCiYeH CURRENT_VCNUM.store(0, Ordering::SeqCst); 31952da9a59SGnoCiYeH 32052da9a59SGnoCiYeH // 初始化键盘? 32152da9a59SGnoCiYeH 32252da9a59SGnoCiYeH // TODO: 为vc 32352da9a59SGnoCiYeH 32452da9a59SGnoCiYeH Ok(()) 32552da9a59SGnoCiYeH } 326