use core::intrinsics::unlikely; use alloc::{ string::{String, ToString}, sync::{Arc, Weak}, vec::Vec, }; use system_error::SystemError; use unified_init::macros::unified_init; use crate::{ driver::base::{ class::{class_manager, Class}, device::{ bus::Bus, device_manager, device_number::{DeviceNumber, Major}, driver::Driver, sys_dev_char_kset, Device, DeviceType, IdTable, }, kobject::{KObjType, KObject, KObjectState, LockedKObjectState}, kset::KSet, subsys::SubSysPrivate, }, filesystem::{ devfs::{devfs_register, DevFS, DeviceINode}, kernfs::KernFSInode, sysfs::AttributeGroup, vfs::{ file::FileMode, syscall::ModeType, FilePrivateData, FileSystem, FileType, IndexNode, Metadata, }, }, init::initcall::INITCALL_SUBSYS, libs::{ rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}, spinlock::{SpinLock, SpinLockGuard}, }, }; use super::{fbcon::fb_console_init, fbsysfs::FbDeviceAttrGroup, FbId, FrameBuffer}; /// `/sys/class/graphics` 的 class 实例 static mut CLASS_GRAPHICS_INSTANCE: Option> = None; lazy_static! { /// 帧缓冲区管理器 static ref FRAME_BUFFER_MANAGER: FrameBufferManager = FrameBufferManager::new(); } /// 获取 `/sys/class/graphics` 的 class 实例 #[inline(always)] #[allow(dead_code)] pub fn sys_class_graphics_instance() -> Option<&'static Arc> { unsafe { CLASS_GRAPHICS_INSTANCE.as_ref() } } #[inline(always)] pub fn frame_buffer_manager() -> &'static FrameBufferManager { &FRAME_BUFFER_MANAGER } /// 初始化帧缓冲区子系统 #[unified_init(INITCALL_SUBSYS)] pub fn fbmem_init() -> Result<(), SystemError> { let graphics_class = GraphicsClass::new(); class_manager().class_register(&(graphics_class.clone() as Arc))?; unsafe { CLASS_GRAPHICS_INSTANCE = Some(graphics_class); } fb_console_init()?; return Ok(()); } /// `/sys/class/graphics` 类 #[derive(Debug)] pub struct GraphicsClass { subsystem: SubSysPrivate, } impl GraphicsClass { const NAME: &'static str = "graphics"; pub fn new() -> Arc { let r = Self { subsystem: SubSysPrivate::new(Self::NAME.to_string(), None, None, &[]), }; let r = Arc::new(r); r.subsystem() .set_class(Some(Arc::downgrade(&r) as Weak)); return r; } } impl Class for GraphicsClass { fn name(&self) -> &'static str { return Self::NAME; } fn dev_kobj(&self) -> Option> { Some(sys_dev_char_kset() as Arc) } fn set_dev_kobj(&self, _kobj: Arc) { unimplemented!("GraphicsClass::set_dev_kobj"); } fn subsystem(&self) -> &SubSysPrivate { return &self.subsystem; } } /// 帧缓冲区管理器 #[derive(Debug)] pub struct FrameBufferManager { inner: RwLock, } #[derive(Debug)] struct InnerFrameBufferManager { /// 已经注册的帧缓冲区 registered_fbs: [Option>; FrameBufferManager::FB_MAX], } impl FrameBufferManager { pub const FB_MAX: usize = 32; pub fn new() -> Self { Self { inner: RwLock::new(InnerFrameBufferManager { registered_fbs: Default::default(), }), } } /// 注册一个帧缓冲区 /// /// # 参数 /// /// - fb: 帧缓冲区 pub fn register_fb(&self, fb: Arc) -> Result { let id = self.generate_fb_id().expect("no more fb id"); fb.set_fb_id(id); let fb_device = FbDevice::new(Arc::downgrade(&fb) as Weak, id); device_manager().device_default_initialize(&(fb_device.clone() as Arc)); fb_device.set_parent(Some(Arc::downgrade(&(fb.clone() as Arc)))); fb.set_fb_device(Some(fb_device.clone())); device_manager().add_device(fb_device.clone() as Arc)?; // 添加到devfs devfs_register(&fb_device.name(), fb_device.clone()).map_err(|e| { kerror!( "register fb device '{}' to devfs failed: {:?}", fb_device.name(), e ); device_manager().remove(&(fb_device.clone() as Arc)); e })?; // todo: 从Modedb中获取信息 // 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbmem.c#1584 let mut inner = self.inner.write(); inner.registered_fbs[id.data() as usize] = Some(fb.clone() as Arc); // todo: 把fb跟fbcon关联起来 return Ok(id); } /// 注销一个帧缓冲区 /// /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbmem.c#1726 #[allow(dead_code)] pub fn unregister_fb(&self, _fb: Arc) -> Result<(), SystemError> { todo!("unregister_fb") } /// 根据id查找帧缓冲区 pub fn find_fb_by_id(&self, id: FbId) -> Result>, SystemError> { if unlikely(!id.is_valid()) { return Err(SystemError::EINVAL); } let inner = self.inner.read(); return Ok(inner.registered_fbs[id.data() as usize].clone()); } fn generate_fb_id(&self) -> Option { for i in 0..Self::FB_MAX { if self.inner.read().registered_fbs[i].is_none() { return Some(FbId::new(i as u32)); } } return None; } } /// 抽象的帧缓冲区设备 /// /// 对应于`/sys/class/graphics/fb(x)`目录下的设备, 其中`(x)`为帧缓冲区的id /// /// 该设备的父设备为真实的帧缓冲区设备 #[derive(Debug)] #[cast_to([sync] Device)] pub struct FbDevice { inner: SpinLock, kobj_state: LockedKObjectState, } impl FbDevice { pub const BASENAME: &'static str = "fb"; fn new(fb: Weak, id: FbId) -> Arc { let r = Arc::new(Self { inner: SpinLock::new(InnerFbDevice { fb, kern_inode: None, parent: None, kset: None, ktype: None, fb_id: id, device_inode_fs: None, devfs_metadata: Metadata::new( FileType::FramebufferDevice, ModeType::from_bits_truncate(0o666), ), }), kobj_state: LockedKObjectState::new(None), }); let mut inner_guard = r.inner.lock(); inner_guard.devfs_metadata.raw_dev = r.do_device_number(&inner_guard); drop(inner_guard); return r; } pub fn framebuffer(&self) -> Option> { self.inner.lock().fb.upgrade() } /// 获取设备号 pub fn device_number(&self) -> DeviceNumber { let inner_guard = self.inner.lock(); self.do_device_number(&inner_guard) } fn do_device_number(&self, inner_guard: &SpinLockGuard<'_, InnerFbDevice>) -> DeviceNumber { DeviceNumber::new(Major::FB_MAJOR, inner_guard.fb_id.data()) } } #[derive(Debug)] struct InnerFbDevice { fb: Weak, kern_inode: Option>, parent: Option>, kset: Option>, ktype: Option<&'static dyn KObjType>, /// 帧缓冲区id fb_id: FbId, /// device inode要求的字段 device_inode_fs: Option>, devfs_metadata: Metadata, } impl KObject for FbDevice { fn as_any_ref(&self) -> &dyn core::any::Any { self } fn set_inode(&self, inode: Option>) { self.inner.lock().kern_inode = inode; } fn inode(&self) -> Option> { self.inner.lock().kern_inode.clone() } fn parent(&self) -> Option> { self.inner.lock().parent.clone() } fn set_parent(&self, parent: Option>) { self.inner.lock().parent = parent; } fn kset(&self) -> Option> { self.inner.lock().kset.clone() } fn set_kset(&self, kset: Option>) { self.inner.lock().kset = kset; } fn kobj_type(&self) -> Option<&'static dyn KObjType> { self.inner.lock().ktype } fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) { self.inner.lock().ktype = ktype; } fn name(&self) -> String { format!("{}{}", Self::BASENAME, self.inner.lock().fb_id.data()) } fn set_name(&self, _name: String) { // do nothing } fn kobj_state(&self) -> RwLockReadGuard { self.kobj_state.read() } fn kobj_state_mut(&self) -> RwLockWriteGuard { self.kobj_state.write() } fn set_kobj_state(&self, state: KObjectState) { *self.kobj_state.write() = state; } } impl Device for FbDevice { fn dev_type(&self) -> DeviceType { DeviceType::Char } fn id_table(&self) -> IdTable { IdTable::new(Self::BASENAME.to_string(), Some(self.device_number())) } fn set_bus(&self, _bus: Option>) { todo!() } fn class(&self) -> Option> { sys_class_graphics_instance().map(|ins| ins.clone() as Arc) } fn set_class(&self, _class: Option>) { // do nothing } fn driver(&self) -> Option> { None } fn set_driver(&self, _driver: Option>) { // do nothing } fn is_dead(&self) -> bool { false } fn can_match(&self) -> bool { false } fn set_can_match(&self, _can_match: bool) { // do nothing } fn state_synced(&self) -> bool { true } fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { Some(&[&FbDeviceAttrGroup]) } } impl DeviceINode for FbDevice { fn set_fs(&self, fs: Weak) { self.inner.lock().device_inode_fs = Some(fs); } } impl IndexNode for FbDevice { fn open( &self, _data: SpinLockGuard, _mode: &FileMode, ) -> Result<(), SystemError> { Ok(()) } fn close(&self, _data: SpinLockGuard) -> Result<(), SystemError> { Ok(()) } fn read_at( &self, offset: usize, len: usize, buf: &mut [u8], _data: SpinLockGuard, ) -> Result { let fb = self.inner.lock().fb.upgrade().unwrap(); return fb.fb_read(&mut buf[0..len], offset); } fn write_at( &self, offset: usize, len: usize, buf: &[u8], _data: SpinLockGuard, ) -> Result { let fb = self.inner.lock().fb.upgrade().unwrap(); return fb.fb_write(&buf[0..len], offset); } fn fs(&self) -> Arc { self.inner .lock() .device_inode_fs .as_ref() .unwrap() .upgrade() .unwrap() } fn as_any_ref(&self) -> &dyn core::any::Any { self } fn list(&self) -> Result, SystemError> { todo!() } fn metadata(&self) -> Result { Ok(self.inner.lock().devfs_metadata.clone()) } fn resize(&self, _len: usize) -> Result<(), SystemError> { return Ok(()); } }