xref: /DragonOS/kernel/src/driver/video/fbdev/base/fbcon/mod.rs (revision 4b0170bd6bb374d0e9699a0076cc23b976ad6db7)
1 use alloc::{
2     string::{String, ToString},
3     sync::{Arc, Weak},
4     vec::Vec,
5 };
6 use system_error::SystemError;
7 
8 use crate::{
9     driver::{
10         base::{
11             class::Class,
12             device::{bus::Bus, device_manager, driver::Driver, Device, DeviceType, IdTable},
13             kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
14             kset::KSet,
15         },
16         tty::virtual_terminal::virtual_console::{CursorOperation, VcCursor, VirtualConsoleData},
17     },
18     filesystem::{
19         kernfs::KernFSInode,
20         sysfs::{file::sysfs_emit_str, Attribute, AttributeGroup, SysFSOpsSupport},
21         vfs::syscall::ModeType,
22     },
23     libs::{
24         rwlock::{RwLockReadGuard, RwLockWriteGuard},
25         spinlock::{SpinLock, SpinLockGuard},
26     },
27 };
28 
29 use super::{fbmem::sys_class_graphics_instance, FbCursor, ScrollMode};
30 
31 pub mod framebuffer_console;
32 
33 /// framebuffer console设备管理器实例
34 static mut FB_CONSOLE_MANAGER: Option<FbConsoleManager> = None;
35 
36 pub fn fb_console_manager() -> &'static FbConsoleManager {
37     unsafe { FB_CONSOLE_MANAGER.as_ref().unwrap() }
38 }
39 
40 /// 初始化framebuffer console
41 pub(super) fn fb_console_init() -> Result<(), SystemError> {
42     // todo: 对全局的console信号量加锁(linux中是console_lock)
43 
44     let fbcon_device: Arc<FbConsoleDevice> = FbConsoleDevice::new();
45 
46     {
47         let fbcon_manager = FbConsoleManager::new(fbcon_device.clone());
48         unsafe { FB_CONSOLE_MANAGER = Some(fbcon_manager) };
49     }
50 
51     device_manager().register(fbcon_device.clone() as Arc<dyn Device>)?;
52     fb_console_manager().init_device()?;
53 
54     return Ok(());
55 }
56 
57 /// framebuffer console设备管理器
58 #[derive(Debug)]
59 pub struct FbConsoleManager {
60     _inner: SpinLock<InnerFbConsoleManager>,
61     /// framebuffer console设备实例
62     /// (对应`/sys/class/graphics/fbcon`)
63     device: Arc<FbConsoleDevice>,
64 }
65 
66 impl FbConsoleManager {
67     pub fn new(device: Arc<FbConsoleDevice>) -> Self {
68         return Self {
69             _inner: SpinLock::new(InnerFbConsoleManager {}),
70             device,
71         };
72     }
73 
74     #[allow(dead_code)]
75     #[inline(always)]
76     pub fn device(&self) -> &Arc<FbConsoleDevice> {
77         &self.device
78     }
79 
80     /// 初始化设备
81     fn init_device(&self) -> Result<(), SystemError> {
82         return Ok(()); // todo
83     }
84 }
85 
86 #[derive(Debug)]
87 struct InnerFbConsoleManager {}
88 
89 #[derive(Debug)]
90 struct InnerFbConsoleDevice {
91     kernfs_inode: Option<Arc<KernFSInode>>,
92     parent: Option<Weak<dyn KObject>>,
93     kset: Option<Arc<KSet>>,
94     bus: Option<Weak<dyn Bus>>,
95     driver: Option<Weak<dyn Driver>>,
96     ktype: Option<&'static dyn KObjType>,
97 }
98 
99 /// `/sys/class/graphics/fbcon`代表的 framebuffer console 设备
100 #[derive(Debug)]
101 #[cast_to([sync] Device)]
102 pub struct FbConsoleDevice {
103     inner: SpinLock<InnerFbConsoleDevice>,
104     kobj_state: LockedKObjectState,
105 }
106 
107 impl FbConsoleDevice {
108     const NAME: &'static str = "fbcon";
109 
110     pub fn new() -> Arc<Self> {
111         return Arc::new(Self {
112             inner: SpinLock::new(InnerFbConsoleDevice {
113                 kernfs_inode: None,
114                 parent: None,
115                 kset: None,
116                 bus: None,
117                 ktype: None,
118                 driver: None,
119             }),
120             kobj_state: LockedKObjectState::new(None),
121         });
122     }
123 }
124 
125 impl KObject for FbConsoleDevice {
126     fn as_any_ref(&self) -> &dyn core::any::Any {
127         self
128     }
129 
130     fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
131         self.inner.lock().kernfs_inode = inode;
132     }
133 
134     fn inode(&self) -> Option<Arc<KernFSInode>> {
135         self.inner.lock().kernfs_inode.clone()
136     }
137 
138     fn parent(&self) -> Option<Weak<dyn KObject>> {
139         self.inner.lock().parent.clone()
140     }
141 
142     fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
143         self.inner.lock().parent = parent;
144     }
145 
146     fn kset(&self) -> Option<Arc<KSet>> {
147         self.inner.lock().kset.clone()
148     }
149 
150     fn set_kset(&self, kset: Option<Arc<KSet>>) {
151         self.inner.lock().kset = kset;
152     }
153 
154     fn kobj_type(&self) -> Option<&'static dyn KObjType> {
155         self.inner.lock().ktype
156     }
157 
158     fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
159         self.inner.lock().ktype = ktype;
160     }
161 
162     fn name(&self) -> String {
163         Self::NAME.to_string()
164     }
165 
166     fn set_name(&self, _name: String) {
167         // 不允许修改
168         kwarn!("fbcon name can not be changed");
169     }
170 
171     fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
172         self.kobj_state.read()
173     }
174 
175     fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
176         self.kobj_state.write()
177     }
178 
179     fn set_kobj_state(&self, state: KObjectState) {
180         *self.kobj_state.write() = state;
181     }
182 }
183 impl Device for FbConsoleDevice {
184     fn dev_type(&self) -> DeviceType {
185         DeviceType::Char
186     }
187 
188     fn id_table(&self) -> IdTable {
189         IdTable::new(Self::NAME.to_string(), None)
190     }
191 
192     fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
193         self.inner.lock().bus = bus;
194     }
195 
196     fn bus(&self) -> Option<Weak<dyn Bus>> {
197         self.inner.lock().bus.clone()
198     }
199 
200     fn set_class(&self, _class: Option<Weak<dyn Class>>) {
201         // 不允许修改
202         kwarn!("fbcon's class can not be changed");
203     }
204 
205     fn class(&self) -> Option<Arc<dyn Class>> {
206         sys_class_graphics_instance().map(|ins| ins.clone() as Arc<dyn Class>)
207     }
208 
209     fn driver(&self) -> Option<Arc<dyn Driver>> {
210         self.inner
211             .lock()
212             .driver
213             .clone()
214             .and_then(|driver| driver.upgrade())
215     }
216 
217     fn set_driver(&self, driver: Option<Weak<dyn Driver>>) {
218         self.inner.lock().driver = driver;
219     }
220 
221     fn is_dead(&self) -> bool {
222         todo!()
223     }
224 
225     fn can_match(&self) -> bool {
226         todo!()
227     }
228 
229     fn set_can_match(&self, _can_match: bool) {
230         todo!()
231     }
232 
233     fn state_synced(&self) -> bool {
234         todo!()
235     }
236 
237     fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
238         return Some(&[&AnonymousAttributeGroup]);
239     }
240 }
241 
242 /// framebuffer console设备的匿名属性组
243 #[derive(Debug)]
244 struct AnonymousAttributeGroup;
245 
246 impl AttributeGroup for AnonymousAttributeGroup {
247     fn name(&self) -> Option<&str> {
248         None
249     }
250 
251     fn attrs(&self) -> &[&'static dyn Attribute] {
252         return &[&AttrRotate, &AttrRotateAll, &AttrCursorBlink];
253     }
254 
255     fn is_visible(
256         &self,
257         _kobj: Arc<dyn KObject>,
258         attr: &'static dyn Attribute,
259     ) -> Option<ModeType> {
260         return Some(attr.mode());
261     }
262 }
263 
264 #[derive(Debug)]
265 struct AttrRotate;
266 
267 impl Attribute for AttrRotate {
268     fn name(&self) -> &str {
269         "rotate"
270     }
271 
272     fn mode(&self) -> ModeType {
273         ModeType::S_IRUGO | ModeType::S_IWUSR
274     }
275 
276     fn support(&self) -> SysFSOpsSupport {
277         SysFSOpsSupport::ATTR_SHOW | SysFSOpsSupport::ATTR_STORE
278     }
279 
280     /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbcon.c#3226
281     fn show(&self, _kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
282         kwarn!("fbcon rotate show not implemented");
283         return sysfs_emit_str(buf, "0\n");
284     }
285 
286     /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbcon.c#3182
287     fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
288         kwarn!("fbcon rotate store not implemented");
289         return Err(SystemError::ENOSYS);
290     }
291 }
292 
293 #[derive(Debug)]
294 struct AttrRotateAll;
295 
296 impl Attribute for AttrRotateAll {
297     fn name(&self) -> &str {
298         "rotate_all"
299     }
300 
301     fn mode(&self) -> ModeType {
302         ModeType::S_IWUSR
303     }
304 
305     fn support(&self) -> SysFSOpsSupport {
306         SysFSOpsSupport::ATTR_STORE
307     }
308 
309     /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbcon.c#3204
310     fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
311         kwarn!("fbcon rotate_all store not implemented");
312         return Err(SystemError::ENOSYS);
313     }
314 }
315 
316 #[derive(Debug)]
317 struct AttrCursorBlink;
318 
319 impl Attribute for AttrCursorBlink {
320     fn name(&self) -> &str {
321         "cursor_blink"
322     }
323 
324     fn mode(&self) -> ModeType {
325         ModeType::S_IRUGO | ModeType::S_IWUSR
326     }
327 
328     fn support(&self) -> SysFSOpsSupport {
329         SysFSOpsSupport::ATTR_SHOW | SysFSOpsSupport::ATTR_STORE
330     }
331 
332     /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbcon.c#3245
333     fn show(&self, _kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
334         todo!()
335     }
336 
337     fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
338         todo!()
339     }
340 }
341 
342 #[derive(Debug, Default)]
343 pub struct FrameBufferConsoleData {
344     /// 光标闪烁间隔
345     pub cursor_blink_jiffies: i64,
346     /// 是否刷新光标
347     pub cursor_flash: bool,
348     ///
349     pub display: FbConsoleDisplay,
350     /// 光标状态
351     pub cursor_state: FbCursor,
352     /// 重设光标?
353     pub cursor_reset: bool,
354     /// cursor 位图数据
355     pub cursor_data: Vec<u8>,
356 }
357 
358 pub trait FrameBufferConsole {
359     fn fbcon_data(&self) -> SpinLockGuard<FrameBufferConsoleData>;
360 
361     /// ## 将位块移动到目标位置
362     /// 坐标均以字体为单位而不是pixel
363     /// ### 参数
364     /// ### sy: 起始位置的y坐标
365     /// ### sx: 起始位置的x坐标、
366     /// ### dy: 目标位置的y坐标
367     /// ### dx: 目标位置的x坐标
368     /// ### height: 位图高度
369     /// ### width: 位图宽度
370     #[allow(clippy::too_many_arguments)]
371     fn bmove(
372         &self,
373         vc_data: &VirtualConsoleData,
374         sy: i32,
375         sx: i32,
376         dy: i32,
377         dx: i32,
378         height: u32,
379         width: u32,
380     ) -> Result<(), SystemError>;
381 
382     /// ## 清除位图
383     ///
384     /// ### 参数
385     /// ### sy: 原位置的y坐标
386     /// ### sx: 原位置的x坐标、
387     /// ### height: 位图高度
388     /// ### width: 位图宽度
389     fn clear(
390         &self,
391         vc_data: &VirtualConsoleData,
392         sy: u32,
393         sx: u32,
394         height: u32,
395         width: u32,
396     ) -> Result<(), SystemError>;
397 
398     /// ## 显示字符串
399     ///
400     /// ### 参数
401     /// ### y: 起始位置y坐标
402     /// ### x: 起始位置的x坐标、
403     /// ### fg: 前景色
404     /// ### bg: 背景色
405     #[allow(clippy::too_many_arguments)]
406     fn put_string(
407         &self,
408         vc_data: &VirtualConsoleData,
409         data: &[u16],
410         count: u32,
411         y: u32,
412         x: u32,
413         fg: u32,
414         bg: u32,
415     ) -> Result<(), SystemError>;
416 
417     fn cursor(&self, vc_data: &VirtualConsoleData, op: CursorOperation, fg: u32, bg: u32);
418 }
419 
420 /// 表示 framebuffer 控制台与低级帧缓冲设备之间接口的数据结构
421 #[derive(Debug, Default)]
422 pub struct FbConsoleDisplay {
423     /// 硬件滚动的行数
424     pub yscroll: u32,
425     /// 光标
426     pub cursor_shape: VcCursor,
427     /// 滚动模式
428     pub scroll_mode: ScrollMode,
429     virt_rows: u32,
430 }
431 
432 impl FbConsoleDisplay {
433     pub fn real_y(&self, mut ypos: u32) -> u32 {
434         let rows = self.virt_rows;
435         ypos += self.yscroll;
436         if ypos < rows {
437             return ypos;
438         } else {
439             return ypos - rows;
440         }
441     }
442 }
443 
444 bitflags! {
445     pub struct FbConAttr:u8 {
446         const UNDERLINE = 1;
447         const REVERSE   = 2;
448         const BOLD      = 4;
449     }
450 }
451 
452 impl FbConAttr {
453     pub fn get_attr(c: u16, color_depth: u32) -> Self {
454         let mut attr = Self::empty();
455         if color_depth == 1 {
456             if Self::underline(c) {
457                 attr.insert(Self::UNDERLINE);
458             }
459             if Self::reverse(c) {
460                 attr.intersects(Self::REVERSE);
461             }
462             if Self::blod(c) {
463                 attr.insert(Self::BOLD);
464             }
465         }
466         attr
467     }
468 
469     pub fn update_attr(&self, dst: &mut [u8], src: &[u8], vc_data: &VirtualConsoleData) {
470         let mut offset = if vc_data.font.height < 10 { 1 } else { 2 } as usize;
471 
472         let width = (vc_data.font.width + 7) / 8;
473         let cellsize = (vc_data.font.height * width) as usize;
474 
475         // 大于offset的部分就是下划线
476         offset = cellsize - (offset * width as usize);
477         for i in 0..cellsize {
478             let mut c = src[i];
479             if self.contains(Self::UNDERLINE) && i >= offset {
480                 // 下划线
481                 c = 0xff;
482             }
483             if self.contains(Self::BOLD) {
484                 c |= c >> 1;
485             }
486             if self.contains(Self::REVERSE) {
487                 c = !c;
488             }
489 
490             dst[i] = c;
491         }
492     }
493 
494     pub fn underline(c: u16) -> bool {
495         c & 0x400 != 0
496     }
497 
498     pub fn blod(c: u16) -> bool {
499         c & 0x200 != 0
500     }
501 
502     pub fn reverse(c: u16) -> bool {
503         c & 0x800 != 0
504     }
505 }
506