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 40 pub fn fb_console_manager() -> &'static FbConsoleManager { 41 unsafe { FB_CONSOLE_MANAGER.as_ref().unwrap() } 42 } 43 44 /// 初始化framebuffer console 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 { 71 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)] 80 pub fn device(&self) -> &Arc<FbConsoleDevice> { 81 &self.device 82 } 83 84 /// 初始化设备 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 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 120 fn inner(&self) -> SpinLockGuard<InnerFbConsoleDevice> { 121 self.inner.lock() 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().kobject_common.kern_inode = inode; 132 } 133 134 fn inode(&self) -> Option<Arc<KernFSInode>> { 135 self.inner().kobject_common.kern_inode.clone() 136 } 137 138 fn parent(&self) -> Option<Weak<dyn KObject>> { 139 self.inner().kobject_common.parent.clone() 140 } 141 142 fn set_parent(&self, parent: Option<Weak<dyn KObject>>) { 143 self.inner().kobject_common.parent = parent; 144 } 145 146 fn kset(&self) -> Option<Arc<KSet>> { 147 self.inner().kobject_common.kset.clone() 148 } 149 150 fn set_kset(&self, kset: Option<Arc<KSet>>) { 151 self.inner().kobject_common.kset = kset; 152 } 153 154 fn kobj_type(&self) -> Option<&'static dyn KObjType> { 155 self.inner().kobject_common.kobj_type 156 } 157 158 fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) { 159 self.inner().kobject_common.kobj_type = ktype; 160 } 161 162 fn name(&self) -> String { 163 Self::NAME.to_string() 164 } 165 166 fn set_name(&self, _name: String) { 167 // 不允许修改 168 warn!("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().device_common.bus = bus; 194 } 195 196 fn bus(&self) -> Option<Weak<dyn Bus>> { 197 self.inner().device_common.bus.clone() 198 } 199 200 fn set_class(&self, _class: Option<Weak<dyn Class>>) { 201 // 不允许修改 202 warn!("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 .device_common 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().device_common.driver = driver; 219 } 220 221 fn is_dead(&self) -> bool { 222 self.inner().device_common.dead 223 } 224 225 fn can_match(&self) -> bool { 226 self.inner().device_common.can_match 227 } 228 229 fn set_can_match(&self, can_match: bool) { 230 self.inner().device_common.can_match = can_match; 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 fn dev_parent(&self) -> Option<Weak<dyn Device>> { 242 self.inner().device_common.get_parent_weak_or_clear() 243 } 244 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 { 255 fn name(&self) -> Option<&str> { 256 None 257 } 258 259 fn attrs(&self) -> &[&'static dyn Attribute] { 260 return &[&AttrRotate, &AttrRotateAll, &AttrCursorBlink]; 261 } 262 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 { 276 fn name(&self) -> &str { 277 "rotate" 278 } 279 280 fn mode(&self) -> ModeType { 281 ModeType::S_IRUGO | ModeType::S_IWUSR 282 } 283 284 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 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 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 { 305 fn name(&self) -> &str { 306 "rotate_all" 307 } 308 309 fn mode(&self) -> ModeType { 310 ModeType::S_IWUSR 311 } 312 313 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 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 { 328 fn name(&self) -> &str { 329 "cursor_blink" 330 } 331 332 fn mode(&self) -> ModeType { 333 ModeType::S_IRUGO | ModeType::S_IWUSR 334 } 335 336 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 341 fn show(&self, _kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> { 342 todo!() 343 } 344 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 { 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)] 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: 位图宽度 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)] 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 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 { 441 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 { 461 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 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 502 pub fn underline(c: u16) -> bool { 503 c & 0x400 != 0 504 } 505 506 pub fn blod(c: u16) -> bool { 507 c & 0x200 != 0 508 } 509 510 pub fn reverse(c: u16) -> bool { 511 c & 0x800 != 0 512 } 513 } 514