1 use core::{fmt::Formatter, sync::atomic::Ordering}; 2 3 use alloc::{ 4 string::{String, ToString}, 5 sync::Arc, 6 vec::Vec, 7 }; 8 use system_error::SystemError; 9 10 use crate::{ 11 driver::base::device::{ 12 device_number::{DeviceNumber, Major}, 13 device_register, IdTable, 14 }, 15 filesystem::devfs::devfs_register, 16 libs::spinlock::SpinLock, 17 }; 18 19 use self::virtual_console::{VirtualConsoleData, CURRENT_VCNUM}; 20 21 use super::{ 22 console::ConsoleSwitch, 23 termios::{InputMode, TTY_STD_TERMIOS}, 24 tty_core::{TtyCore, TtyCoreData}, 25 tty_device::{TtyDevice, TtyType}, 26 tty_driver::{TtyDriver, TtyDriverManager, TtyDriverType, TtyOperation}, 27 }; 28 29 pub mod console_map; 30 pub mod virtual_console; 31 32 pub const MAX_NR_CONSOLES: u32 = 63; 33 pub const VC_MAXCOL: usize = 32767; 34 pub const VC_MAXROW: usize = 32767; 35 36 pub const DEFAULT_RED: [u16; 16] = [ 37 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x55, 0xff, 0x55, 0xff, 0x55, 0xff, 0x55, 0xff, 38 ]; 39 40 pub const DEFAULT_GREEN: [u16; 16] = [ 41 0x00, 0x00, 0xaa, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff, 42 ]; 43 44 pub const DEFAULT_BLUE: [u16; 16] = [ 45 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xff, 0xff, 0xff, 0xff, 46 ]; 47 48 pub const COLOR_TABLE: &[u8] = &[0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15]; 49 50 lazy_static! { 51 pub static ref VIRT_CONSOLES: Vec<Arc<SpinLock<VirtualConsoleData>>> = { 52 let mut v = Vec::with_capacity(MAX_NR_CONSOLES as usize); 53 for i in 0..MAX_NR_CONSOLES as usize { 54 v.push(Arc::new(SpinLock::new(VirtualConsoleData::new(i)))); 55 } 56 57 v 58 }; 59 } 60 61 #[derive(Debug, Clone, Copy, Default)] 62 pub struct Color { 63 pub red: u16, 64 pub green: u16, 65 pub blue: u16, 66 pub transp: u16, 67 } 68 69 impl Color { 70 pub fn from_256(col: u32) -> Self { 71 let mut color = Self::default(); 72 if col < 8 { 73 color.red = if col & 1 != 0 { 0xaa } else { 0x00 }; 74 color.green = if col & 2 != 0 { 0xaa } else { 0x00 }; 75 color.blue = if col & 4 != 0 { 0xaa } else { 0x00 }; 76 } else if col < 16 { 77 color.red = if col & 1 != 0 { 0xff } else { 0x55 }; 78 color.green = if col & 2 != 0 { 0xff } else { 0x55 }; 79 color.blue = if col & 4 != 0 { 0xff } else { 0x55 }; 80 } else if col < 232 { 81 color.red = ((col - 16) / 36 * 85 / 2) as u16; 82 color.green = ((col - 16) / 6 % 6 * 85 / 2) as u16; 83 color.blue = ((col - 16) % 6 * 85 / 2) as u16; 84 } else { 85 let col = (col * 10 - 2312) as u16; 86 color.red = col; 87 color.green = col; 88 color.blue = col; 89 } 90 91 color 92 } 93 } 94 95 pub struct TtyConsoleDriverInner { 96 console: Arc<dyn ConsoleSwitch>, 97 } 98 99 impl core::fmt::Debug for TtyConsoleDriverInner { 100 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { 101 write!(f, "TtyConsoleDriverInner") 102 } 103 } 104 105 impl TtyConsoleDriverInner { 106 pub fn new() -> Result<Self, SystemError> { 107 let console = { 108 #[cfg(not(target_arch = "riscv64"))] 109 { 110 Arc::new(crate::driver::video::fbdev::base::fbcon::framebuffer_console::BlittingFbConsole::new()?) 111 } 112 113 #[cfg(target_arch = "riscv64")] 114 crate::driver::video::console::dummycon::dummy_console() 115 }; 116 117 Ok(Self { console }) 118 } 119 120 fn do_write(&self, tty: &TtyCoreData, buf: &[u8], mut nr: usize) -> Result<usize, SystemError> { 121 // 关闭中断 122 let mut vc_data = tty.vc_data_irqsave(); 123 124 let mut offset = 0; 125 126 // 这个参数是用来扫描unicode字符的,但是这部分目前未完成,先写着 127 let mut rescan = false; 128 let mut ch: u32 = 0; 129 130 let mut draw = DrawRegion::default(); 131 132 // 首先隐藏光标再写 133 vc_data.hide_cursor(); 134 135 while nr != 0 { 136 if !rescan { 137 ch = buf[offset] as u32; 138 offset += 1; 139 nr -= 1; 140 } 141 142 let (tc, rescan_last) = vc_data.translate(&mut ch); 143 if tc.is_none() { 144 // 表示未转换完成 145 continue; 146 } 147 148 let tc = tc.unwrap(); 149 rescan = rescan_last; 150 151 if vc_data.is_control(tc, ch) { 152 vc_data.flush(&mut draw); 153 vc_data.do_control(ch); 154 continue; 155 } 156 157 if !vc_data.console_write_normal(tc, ch, &mut draw) { 158 continue; 159 } 160 } 161 162 vc_data.flush(&mut draw); 163 164 // TODO: notify update 165 return Ok(offset); 166 } 167 } 168 169 impl TtyOperation for TtyConsoleDriverInner { 170 fn install(&self, _driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> { 171 let tty_core = tty.core(); 172 let mut vc_data = VIRT_CONSOLES[tty_core.index()].lock(); 173 174 self.console.con_init(&mut vc_data, true)?; 175 if vc_data.complement_mask == 0 { 176 vc_data.complement_mask = if vc_data.color_mode { 0x7700 } else { 0x0800 }; 177 } 178 vc_data.s_complement_mask = vc_data.complement_mask; 179 // vc_data.bytes_per_row = vc_data.cols << 1; 180 vc_data.index = tty_core.index(); 181 vc_data.bottom = vc_data.rows; 182 vc_data.set_driver_funcs(Arc::downgrade( 183 &(self.console.clone() as Arc<dyn ConsoleSwitch>), 184 )); 185 186 // todo: unicode字符集处理? 187 188 if vc_data.cols > VC_MAXCOL || vc_data.rows > VC_MAXROW { 189 return Err(SystemError::EINVAL); 190 } 191 192 vc_data.init(None, None, true); 193 vc_data.update_attr(); 194 195 let window_size = tty_core.window_size_upgradeable(); 196 if window_size.col == 0 && window_size.row == 0 { 197 let mut window_size = window_size.upgrade(); 198 window_size.col = vc_data.cols as u16; 199 window_size.row = vc_data.rows as u16; 200 } 201 202 if vc_data.utf { 203 tty_core.termios_write().input_mode.insert(InputMode::IUTF8); 204 } else { 205 tty_core.termios_write().input_mode.remove(InputMode::IUTF8); 206 } 207 208 // 设置tty的端口为vc端口 209 vc_data.port().setup_internal_tty(Arc::downgrade(&tty)); 210 tty.set_port(vc_data.port()); 211 // 加入sysfs? 212 213 CURRENT_VCNUM.store(tty_core.index() as isize, Ordering::SeqCst); 214 Ok(()) 215 } 216 217 fn open(&self, _tty: &TtyCoreData) -> Result<(), SystemError> { 218 Ok(()) 219 } 220 221 fn write_room(&self, _tty: &TtyCoreData) -> usize { 222 32768 223 } 224 225 /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/tty/vt/vt.c#2894 226 #[inline(never)] 227 fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError> { 228 // if String::from_utf8_lossy(buf) == "Hello world!\n" { 229 // loop {} 230 // } 231 let ret = self.do_write(tty, buf, nr); 232 self.flush_chars(tty); 233 ret 234 } 235 236 #[inline(never)] 237 fn flush_chars(&self, tty: &TtyCoreData) { 238 let mut vc_data = tty.vc_data_irqsave(); 239 vc_data.set_cursor(); 240 } 241 242 fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError> { 243 self.write(tty, &[ch], 1)?; 244 Ok(()) 245 } 246 247 fn ioctl(&self, _tty: Arc<TtyCore>, _cmd: u32, _arg: usize) -> Result<(), SystemError> { 248 // TODO 249 Err(SystemError::ENOIOCTLCMD) 250 } 251 252 fn close(&self, _tty: Arc<TtyCore>) -> Result<(), SystemError> { 253 Ok(()) 254 } 255 256 fn resize( 257 &self, 258 _tty: Arc<TtyCore>, 259 _winsize: super::termios::WindowSize, 260 ) -> Result<(), SystemError> { 261 todo!() 262 } 263 } 264 265 #[derive(Debug, Clone)] 266 pub struct VtModeData { 267 mode: VtMode, 268 /// 释放请求时触发的信号 269 relsig: u16, 270 /// 获取请求时触发的信号 271 acqsig: u16, 272 } 273 274 #[allow(dead_code)] 275 #[derive(Debug, Clone)] 276 pub enum VtMode { 277 /// 自动切换模式,即在请求输入时自动切换到终端 278 Auto, 279 /// 手动切换模式,需要通过 ioctl 请求切换到终端 280 Process, 281 /// 等待终端确认,即在切换到终端时等待终端的确认信号 282 Ackacq, 283 } 284 285 /// 用于给vc确定要写入的buf位置 286 #[derive(Debug, Default)] 287 pub struct DrawRegion { 288 /// 偏移量 289 pub offset: usize, 290 /// 写入数量 291 pub size: usize, 292 pub x: Option<u32>, 293 } 294 295 // 初始化虚拟终端 296 #[inline(never)] 297 pub fn vty_init() -> Result<(), SystemError> { 298 // 注册虚拟终端设备并将虚拟终端设备加入到文件系统 299 let vc0 = TtyDevice::new( 300 "vc0".to_string(), 301 IdTable::new( 302 String::from("vc0"), 303 Some(DeviceNumber::new(Major::TTY_MAJOR, 0)), 304 ), 305 TtyType::Tty, 306 ); 307 // 注册tty设备 308 // CharDevOps::cdev_add( 309 // vc0.clone() as Arc<dyn CharDevice>, 310 // IdTable::new( 311 // String::from("vc0"), 312 // Some(DeviceNumber::new(Major::TTY_MAJOR, 0)), 313 // ), 314 // 1, 315 // )?; 316 317 // CharDevOps::register_chardev_region(DeviceNumber::new(Major::TTY_MAJOR, 0), 1, "/dev/vc/0")?; 318 device_register(vc0.clone())?; 319 devfs_register("vc0", vc0)?; 320 321 // vcs_init? 322 323 let console_driver = TtyDriver::new( 324 MAX_NR_CONSOLES, 325 "tty", 326 1, 327 Major::TTY_MAJOR, 328 0, 329 TtyDriverType::Console, 330 *TTY_STD_TERMIOS, 331 Arc::new(TtyConsoleDriverInner::new()?), 332 ); 333 334 TtyDriverManager::tty_register_driver(console_driver)?; 335 336 CURRENT_VCNUM.store(0, Ordering::SeqCst); 337 338 // 初始化键盘? 339 340 // TODO: 为vc 341 342 Ok(()) 343 } 344