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