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