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