feat: 支持 sysfs下 block, char, Net, rtc, tty 等类型设备的 uevent 文件读操作 (#973)

* 新增CommonAttrGroup,基本支持sysfs下各种类型设备的uevent属性文件的读测试

* 修改net设备的uevent内容,使之与Linux语义一致

* 删除无用注释
This commit is contained in:
Val213 2024-10-14 13:07:37 +08:00 committed by GitHub
parent 4e4ce68e03
commit 38d161ccfe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 126 additions and 58 deletions

View File

@ -133,7 +133,7 @@ pub extern "sysv64" fn syscall_handler(frame: &mut TrapFrame) {
show &= false; show &= false;
} }
} }
show = false;
if show { if show {
debug!("[SYS] [Pid: {:?}] [Call: {:?}]", pid, to_print); debug!("[SYS] [Pid: {:?}] [Call: {:?}]", pid, to_print);
} }

View File

@ -1,9 +1,8 @@
/// 引入Module /// 引入Module
use crate::driver::{ use crate::{driver::{
base::{ base::{
device::{ device::{
device_number::{DeviceNumber, Major}, device_number::{DeviceNumber, Major}, Device, DeviceError, IdTable, BLOCKDEVS
Device, DeviceError, IdTable, BLOCKDEVS,
}, },
map::{ map::{
DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END, DEV_MAJOR_DYN_EXT_START, DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END, DEV_MAJOR_DYN_EXT_START,
@ -11,7 +10,7 @@ use crate::driver::{
}, },
}, },
block::cache::{cached_block_device::BlockCache, BlockCacheError, BLOCK_SIZE}, block::cache::{cached_block_device::BlockCache, BlockCacheError, BLOCK_SIZE},
}; }, filesystem::sysfs::AttributeGroup};
use alloc::{string::String, sync::Arc, vec::Vec}; use alloc::{string::String, sync::Arc, vec::Vec};
use core::{any::Any, fmt::Display, ops::Deref}; use core::{any::Any, fmt::Display, ops::Deref};

View File

@ -43,6 +43,7 @@ use super::{
}, },
kset::KSet, kset::KSet,
swnode::software_node_notify, swnode::software_node_notify,
uevent::UeventAttr,
}; };
pub mod bus; pub mod bus;
@ -1025,6 +1026,25 @@ impl Eq for DeviceId {}
impl IrqHandlerData for DeviceId {} impl IrqHandlerData for DeviceId {}
/// sysfs下设备的通用属性组
#[derive(Debug)]
pub struct CommonAttrGroup;
impl AttributeGroup for CommonAttrGroup {
fn name(&self) -> Option<&str> {
None
}
fn attrs(&self) -> &[&'static dyn Attribute] {
&[&UeventAttr]
}
fn is_visible(
&self,
_kobj: alloc::sync::Arc<dyn KObject>,
attr: &'static dyn Attribute,
) -> Option<crate::filesystem::vfs::syscall::ModeType> {
Some(attr.mode())
}
}
lazy_static! { lazy_static! {
/// class_dir列表通过parent kobject的name和class_dir的name来索引class_dir实例 /// class_dir列表通过parent kobject的name和class_dir的name来索引class_dir实例
static ref CLASS_DIR_KSET_INSTANCE: RwLock<BTreeMap<String, Arc<ClassDir>>> = RwLock::new(BTreeMap::new()); static ref CLASS_DIR_KSET_INSTANCE: RwLock<BTreeMap<String, Arc<ClassDir>>> = RwLock::new(BTreeMap::new());

View File

@ -22,7 +22,7 @@ use crate::{
use system_error::SystemError; use system_error::SystemError;
use super::{kset::KSet, uevent::kobject_uevent}; use super::{device::CommonAttrGroup, kset::KSet, uevent::kobject_uevent};
pub trait KObject: Any + Send + Sync + Debug + CastFromSync { pub trait KObject: Any + Send + Sync + Debug + CastFromSync {
fn as_any_ref(&self) -> &dyn core::any::Any; fn as_any_ref(&self) -> &dyn core::any::Any;

View File

@ -11,12 +11,12 @@ use crate::{
bus::{Bus, BusState}, bus::{Bus, BusState},
device_manager, device_manager,
driver::Driver, driver::Driver,
Device, DeviceCommonData, DevicePrivateData, DeviceType, IdTable, CommonAttrGroup, Device, DeviceCommonData, DevicePrivateData, DeviceType, IdTable,
}, },
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
kset::KSet, kset::KSet,
}, },
filesystem::kernfs::KernFSInode, filesystem::{kernfs::KernFSInode, sysfs::AttributeGroup},
libs::{ libs::{
rwlock::{RwLockReadGuard, RwLockWriteGuard}, rwlock::{RwLockReadGuard, RwLockWriteGuard},
spinlock::{SpinLock, SpinLockGuard}, spinlock::{SpinLock, SpinLockGuard},
@ -329,4 +329,8 @@ impl Device for PlatformBusDevice {
fn set_dev_parent(&self, dev_parent: Option<Weak<dyn Device>>) { fn set_dev_parent(&self, dev_parent: Option<Weak<dyn Device>>) {
self.inner().device_common.parent = dev_parent; self.inner().device_common.parent = dev_parent;
} }
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
Some(&[&CommonAttrGroup])
}
} }

View File

@ -19,6 +19,7 @@ use alloc::string::{String, ToString};
use alloc::sync::Arc; use alloc::sync::Arc;
use alloc::vec::Vec; use alloc::vec::Vec;
use intertrait::cast::CastArc; use intertrait::cast::CastArc;
use log::warn;
use system_error::SystemError; use system_error::SystemError;
use super::block::block_device::{BlockDevice, BlockDeviceOps}; use super::block::block_device::{BlockDevice, BlockDeviceOps};
@ -128,46 +129,60 @@ impl Attribute for UeventAttr {
/// 用户空间读取 uevent 文件,返回 uevent 信息 /// 用户空间读取 uevent 文件,返回 uevent 信息
fn show(&self, _kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> { fn show(&self, _kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
let device: Arc<dyn KObject> = _kobj let device = _kobj.cast::<dyn Device>().map_err(|e: Arc<dyn KObject>| {
.parent() warn!("device:{:?} is not a device!", e);
.and_then(|x| x.upgrade()) SystemError::EINVAL
.ok_or(SystemError::ENODEV)?; })?;
let device = kobj2device(device).ok_or(SystemError::EINVAL)?; log::info!("show uevent");
let device_type = device.dev_type(); let device_type = device.dev_type();
let mut uevent_content = String::new(); let mut uevent_content = String::new();
log::info!("device_type: {:?}", device_type);
match device_type { match device_type {
DeviceType::Block => { DeviceType::Block => {
let block_device = device let major = device.id_table().device_number().major().data();
.cast::<dyn BlockDevice>() let minor = device.id_table().device_number().minor();
.ok() let device_name = device.id_table().name();
.ok_or(SystemError::EINVAL)?;
let major = block_device.id_table().device_number().major().data();
let minor = block_device.id_table().device_number().minor();
let device_name = block_device.id_table().name();
writeln!(&mut uevent_content, "MAJOR={:?}", major).unwrap(); writeln!(&mut uevent_content, "MAJOR={:?}", major).unwrap();
writeln!(&mut uevent_content, "MINOR={:?}", minor).unwrap(); writeln!(&mut uevent_content, "MINOR={:?}", minor).unwrap();
writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap(); writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
writeln!(&mut uevent_content, "DEVTYPE=disk").unwrap(); writeln!(&mut uevent_content, "DEVTYPE=disk").unwrap();
} }
DeviceType::Char => { DeviceType::Char => {
let char_device = device let major = device.id_table().device_number().major().data();
.cast::<dyn CharDevice>() let minor = device.id_table().device_number().minor();
.ok() let device_name = device.id_table().name();
.ok_or(SystemError::EINVAL)?;
let major = char_device.id_table().device_number().major().data();
let minor = char_device.id_table().device_number().minor();
let device_name = char_device.id_table().name();
writeln!(&mut uevent_content, "MAJOR={}", major).unwrap(); writeln!(&mut uevent_content, "MAJOR={}", major).unwrap();
writeln!(&mut uevent_content, "MINOR={}", minor).unwrap(); writeln!(&mut uevent_content, "MINOR={}", minor).unwrap();
writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap(); writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
writeln!(&mut uevent_content, "DEVTYPE=char").unwrap(); writeln!(&mut uevent_content, "DEVTYPE=char").unwrap();
} }
DeviceType::Net => { DeviceType::Net => {
let net_device = device.cast::<dyn Iface>().ok().ok_or(SystemError::EINVAL)?; let net_device = device.clone().cast::<dyn Iface>().map_err(|e: Arc<dyn Device>| {
// let ifindex = net_device.ifindex().expect("Find ifindex error.\n"); warn!("device:{:?} is not a net device!", e);
let device_name = net_device.iface_name(); SystemError::EINVAL
})?;
let iface_id = net_device.nic_id();
let device_name = device.name();
writeln!(&mut uevent_content, "INTERFACE={}", device_name).unwrap(); writeln!(&mut uevent_content, "INTERFACE={}", device_name).unwrap();
// writeln!(&mut uevent_content, "IFINDEX={}", ifindex).unwrap(); writeln!(&mut uevent_content, "IFINDEX={}", iface_id).unwrap();
}
DeviceType::Bus => {
// 处理总线设备类型
let device_name = device.name();
writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
writeln!(&mut uevent_content, "DEVTYPE=bus").unwrap();
}
DeviceType::Rtc => {
// 处理RTC设备类型
let device_name = device.name();
writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
writeln!(&mut uevent_content, "DEVTYPE=rtc").unwrap();
}
DeviceType::Pci => {
// 处理PCI设备类型
let device_name = device.name();
writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
writeln!(&mut uevent_content, "DEVTYPE=pci").unwrap();
} }
_ => { _ => {
// 处理其他设备类型 // 处理其他设备类型
@ -180,17 +195,15 @@ impl Attribute for UeventAttr {
} }
/// 捕获来自用户空间对 uevent 文件的写操作触发uevent事件 /// 捕获来自用户空间对 uevent 文件的写操作触发uevent事件
fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> { fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
log::info!("store uevent");
return kobject_synth_uevent(_buf, _kobj); return kobject_synth_uevent(_buf, _kobj);
} }
} }
/// 将 kobject 转换为 device
fn kobj2device(kobj: Arc<dyn KObject>) -> Option<Arc<dyn Device>> {
kobj.cast::<dyn Device>().ok()
}
/// 将设备的基本信息写入 uevent 文件 /// 将设备的基本信息写入 uevent 文件
fn sysfs_emit_str(buf: &mut [u8], content: &str) -> Result<usize, SystemError> { fn sysfs_emit_str(buf: &mut [u8], content: &str) -> Result<usize, SystemError> {
log::info!("sysfs_emit_str");
let bytes = content.as_bytes(); let bytes = content.as_bytes();
if buf.len() < bytes.len() { if buf.len() < bytes.len() {
return Err(SystemError::ENOMEM); return Err(SystemError::ENOMEM);
@ -211,7 +224,10 @@ fn kobject_synth_uevent(buf: &[u8], kobj: Arc<dyn KObject>) -> Result<usize, Sys
}; };
if let Err(e) = result { if let Err(e) = result {
let device = kobj2device(kobj).ok_or(SystemError::EINVAL)?; let device = kobj.cast::<dyn Device>().map_err(|e: Arc<dyn KObject>| {
warn!("device:{:?} is not a device!", e);
SystemError::EINVAL
})?;
let devname = device.name(); let devname = device.name();
log::error!("synth uevent: {}: {:?}", devname, e); log::error!("synth uevent: {}: {:?}", devname, e);
return Err(SystemError::EINVAL); return Err(SystemError::EINVAL);

View File

@ -24,7 +24,7 @@ use crate::{
device::{ device::{
bus::Bus, bus::Bus,
driver::{Driver, DriverCommonData}, driver::{Driver, DriverCommonData},
Device, DeviceCommonData, DeviceId, DeviceType, IdTable, CommonAttrGroup, Device, DeviceCommonData, DeviceId, DeviceType, IdTable,
}, },
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
kset::KSet, kset::KSet,
@ -38,7 +38,7 @@ use crate::{
}, },
}, },
exception::{irqdesc::IrqReturn, IrqNumber}, exception::{irqdesc::IrqReturn, IrqNumber},
filesystem::{kernfs::KernFSInode, mbr::MbrDiskPartionTable}, filesystem::{kernfs::KernFSInode, mbr::MbrDiskPartionTable, sysfs::AttributeGroup},
init::initcall::INITCALL_POSTCORE, init::initcall::INITCALL_POSTCORE,
libs::{ libs::{
rwlock::{RwLockReadGuard, RwLockWriteGuard}, rwlock::{RwLockReadGuard, RwLockWriteGuard},
@ -342,7 +342,7 @@ impl VirtIODevice for VirtIOBlkDevice {
impl Device for VirtIOBlkDevice { impl Device for VirtIOBlkDevice {
fn dev_type(&self) -> DeviceType { fn dev_type(&self) -> DeviceType {
DeviceType::Net DeviceType::Block
} }
fn id_table(&self) -> IdTable { fn id_table(&self) -> IdTable {
@ -407,6 +407,10 @@ impl Device for VirtIOBlkDevice {
fn set_dev_parent(&self, parent: Option<Weak<dyn Device>>) { fn set_dev_parent(&self, parent: Option<Weak<dyn Device>>) {
self.inner().device_common.parent = parent; self.inner().device_common.parent = parent;
} }
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
Some(&[&CommonAttrGroup])
}
} }
impl KObject for VirtIOBlkDevice { impl KObject for VirtIOBlkDevice {
@ -472,7 +476,7 @@ fn virtio_blk_driver_init() -> Result<(), SystemError> {
let driver = VirtIOBlkDriver::new(); let driver = VirtIOBlkDriver::new();
virtio_driver_manager() virtio_driver_manager()
.register(driver.clone() as Arc<dyn VirtIODriver>) .register(driver.clone() as Arc<dyn VirtIODriver>)
.expect("Add virtio net driver failed"); .expect("Add virtio block driver failed");
unsafe { unsafe {
VIRTIO_BLK_DRIVER = Some(driver); VIRTIO_BLK_DRIVER = Some(driver);
} }

View File

@ -1,7 +1,7 @@
use crate::{ use crate::{
driver::base::{ driver::base::{
class::{class_manager, Class}, class::{class_manager, Class},
device::sys_dev_char_kset, device::{sys_dev_char_kset, CommonAttrGroup},
kobject::KObject, kobject::KObject,
subsys::SubSysPrivate, subsys::SubSysPrivate,
}, },
@ -78,6 +78,6 @@ impl Class for NetClass {
} }
fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] { fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
return &[&NetAttrGroup]; return &[&NetAttrGroup, &CommonAttrGroup];
} }
} }

View File

@ -25,7 +25,7 @@ use crate::{
device::{ device::{
bus::Bus, bus::Bus,
driver::{Driver, DriverCommonData}, driver::{Driver, DriverCommonData},
Device, DeviceCommonData, DeviceId, DeviceType, IdTable, CommonAttrGroup, Device, DeviceCommonData, DeviceId, DeviceType, IdTable,
}, },
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
kset::KSet, kset::KSet,
@ -41,7 +41,7 @@ use crate::{
}, },
}, },
exception::{irqdesc::IrqReturn, IrqNumber}, exception::{irqdesc::IrqReturn, IrqNumber},
filesystem::kernfs::KernFSInode, filesystem::{kernfs::KernFSInode, sysfs::AttributeGroup},
init::initcall::INITCALL_POSTCORE, init::initcall::INITCALL_POSTCORE,
libs::{ libs::{
rwlock::{RwLockReadGuard, RwLockWriteGuard}, rwlock::{RwLockReadGuard, RwLockWriteGuard},
@ -249,6 +249,10 @@ impl Device for VirtIONetDevice {
fn set_dev_parent(&self, parent: Option<Weak<dyn Device>>) { fn set_dev_parent(&self, parent: Option<Weak<dyn Device>>) {
self.inner().device_common.parent = parent; self.inner().device_common.parent = parent;
} }
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
Some(&[&CommonAttrGroup])
}
} }
impl VirtIODevice for VirtIONetDevice { impl VirtIODevice for VirtIONetDevice {

View File

@ -8,7 +8,10 @@ use alloc::{
use crate::{ use crate::{
driver::base::{ driver::base::{
class::Class, class::Class,
device::{bus::Bus, driver::Driver, Device, DeviceCommonData, DeviceType, IdTable}, device::{
bus::Bus, driver::Driver, CommonAttrGroup, Device, DeviceCommonData, DeviceType,
IdTable,
},
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
kset::KSet, kset::KSet,
}, },
@ -84,7 +87,7 @@ impl PciDevice for PciGeneralDevice {
impl Device for PciGeneralDevice { impl Device for PciGeneralDevice {
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
Some(&[&BasicPciReadOnlyAttrs]) Some(&[&BasicPciReadOnlyAttrs, &CommonAttrGroup])
} }
fn bus(&self) -> Option<Weak<dyn Bus>> { fn bus(&self) -> Option<Weak<dyn Bus>> {

View File

@ -10,7 +10,10 @@ use crate::{
driver::{ driver::{
base::{ base::{
class::Class, class::Class,
device::{bus::Bus, driver::Driver, Device, DeviceCommonData, DeviceType, IdTable}, device::{
bus::Bus, driver::Driver, CommonAttrGroup, Device, DeviceCommonData, DeviceType,
IdTable,
},
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
kset::KSet, kset::KSet,
}, },
@ -74,7 +77,7 @@ impl PciDevice for TestDevice {
impl Device for TestDevice { impl Device for TestDevice {
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
Some(&[&HelloAttr]) Some(&[&HelloAttr, &CommonAttrGroup])
} }
fn bus(&self) -> Option<Weak<dyn Bus>> { fn bus(&self) -> Option<Weak<dyn Bus>> {

View File

@ -9,10 +9,11 @@ use unified_init::macros::unified_init;
use crate::{ use crate::{
driver::base::{ driver::base::{
class::{class_manager, Class}, class::{class_manager, Class},
device::{device_manager, sys_dev_char_kset}, device::{device_manager, sys_dev_char_kset, CommonAttrGroup},
kobject::KObject, kobject::KObject,
subsys::SubSysPrivate, subsys::SubSysPrivate,
}, },
filesystem::sysfs::AttributeGroup,
init::initcall::INITCALL_SUBSYS, init::initcall::INITCALL_SUBSYS,
time::{timekeeping::do_settimeofday64, PosixTimeSpec}, time::{timekeeping::do_settimeofday64, PosixTimeSpec},
}; };
@ -78,6 +79,9 @@ impl Class for RtcClass {
fn subsystem(&self) -> &SubSysPrivate { fn subsystem(&self) -> &SubSysPrivate {
return &self.subsystem; return &self.subsystem;
} }
fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
return &[&CommonAttrGroup];
}
} }
/// 注册rtc通用设备 /// 注册rtc通用设备

View File

@ -9,7 +9,8 @@ use crate::{
driver::base::{ driver::base::{
class::Class, class::Class,
device::{ device::{
bus::Bus, device_manager, driver::Driver, Device, DeviceCommonData, DeviceType, IdTable, bus::Bus, device_manager, driver::Driver, CommonAttrGroup, Device, DeviceCommonData,
DeviceType, IdTable,
}, },
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
kset::KSet, kset::KSet,
@ -172,7 +173,7 @@ impl Device for RtcGeneralDevice {
true true
} }
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
Some(&[&RtcAttrGroup]) Some(&[&RtcAttrGroup, &CommonAttrGroup])
} }
fn dev_parent(&self) -> Option<Weak<dyn Device>> { fn dev_parent(&self) -> Option<Weak<dyn Device>> {

View File

@ -8,10 +8,11 @@ use unified_init::macros::unified_init;
use crate::{ use crate::{
driver::base::{ driver::base::{
class::{class_manager, Class}, class::{class_manager, Class},
device::sys_dev_char_kset, device::{sys_dev_char_kset, CommonAttrGroup},
kobject::KObject, kobject::KObject,
subsys::SubSysPrivate, subsys::SubSysPrivate,
}, },
filesystem::sysfs::AttributeGroup,
init::initcall::INITCALL_SUBSYS, init::initcall::INITCALL_SUBSYS,
}; };
@ -61,6 +62,10 @@ impl Class for TtyClass {
fn subsystem(&self) -> &SubSysPrivate { fn subsystem(&self) -> &SubSysPrivate {
return &self.subsystem; return &self.subsystem;
} }
fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
return &[&CommonAttrGroup];
}
} }
/// 初始化帧缓冲区子系统 /// 初始化帧缓冲区子系统

View File

@ -11,8 +11,8 @@ use crate::{
base::{ base::{
class::Class, class::Class,
device::{ device::{
bus::Bus, device_manager, driver::Driver, Device, DeviceCommonData, DeviceType, bus::Bus, device_manager, driver::Driver, CommonAttrGroup, Device,
IdTable, DeviceCommonData, DeviceType, IdTable,
}, },
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
kset::KSet, kset::KSet,
@ -235,7 +235,7 @@ impl Device for FbConsoleDevice {
} }
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
return Some(&[&AnonymousAttributeGroup]); return Some(&[&AnonymousAttributeGroup, &CommonAttrGroup]);
} }
fn dev_parent(&self) -> Option<Weak<dyn Device>> { fn dev_parent(&self) -> Option<Weak<dyn Device>> {

View File

@ -18,7 +18,7 @@ use crate::{
device_manager, device_manager,
device_number::{DeviceNumber, Major}, device_number::{DeviceNumber, Major},
driver::Driver, driver::Driver,
sys_dev_char_kset, Device, DeviceCommonData, DeviceType, IdTable, sys_dev_char_kset, CommonAttrGroup, Device, DeviceCommonData, DeviceType, IdTable,
}, },
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
kset::KSet, kset::KSet,
@ -112,6 +112,10 @@ impl Class for GraphicsClass {
fn subsystem(&self) -> &SubSysPrivate { fn subsystem(&self) -> &SubSysPrivate {
return &self.subsystem; return &self.subsystem;
} }
fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
return &[&CommonAttrGroup];
}
} }
/// 帧缓冲区管理器 /// 帧缓冲区管理器
@ -373,7 +377,7 @@ impl Device for FbDevice {
} }
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
Some(&[&FbDeviceAttrGroup]) Some(&[&FbDeviceAttrGroup, &CommonAttrGroup])
} }
fn dev_parent(&self) -> Option<Weak<dyn Device>> { fn dev_parent(&self) -> Option<Weak<dyn Device>> {

View File

@ -5,6 +5,7 @@ use unified_init::macros::unified_init;
use crate::{ use crate::{
driver::base::{ driver::base::{
device::CommonAttrGroup,
kobject::{KObjType, KObject, KObjectManager, KObjectSysFSOps}, kobject::{KObjType, KObject, KObjectManager, KObjectSysFSOps},
kset::KSet, kset::KSet,
}, },
@ -45,7 +46,7 @@ impl KObjType for IrqKObjType {
} }
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
Some(&[&IrqAttrGroup]) Some(&[&IrqAttrGroup, &CommonAttrGroup])
} }
fn release(&self, _kobj: Arc<dyn KObject>) { fn release(&self, _kobj: Arc<dyn KObject>) {