use core::{any::Any, fmt::Debug, hash::Hash, ops::Deref}; use alloc::{ string::String, sync::{Arc, Weak}, }; use driver_base_macros::get_weak_or_clear; use intertrait::CastFromSync; use crate::{ filesystem::{ kernfs::KernFSInode, sysfs::{sysfs_instance, Attribute, AttributeGroup, SysFSOps, SysFSOpsSupport}, }, kerror, libs::{ casting::DowncastArc, rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}, }, }; use system_error::SystemError; use super::kset::KSet; pub trait KObject: Any + Send + Sync + Debug + CastFromSync { fn as_any_ref(&self) -> &dyn core::any::Any; /// 设置当前kobject对应的sysfs inode(类型为KernFSInode) fn set_inode(&self, inode: Option>); /// 获取当前kobject对应的sysfs inode(类型为KernFSInode) fn inode(&self) -> Option>; fn parent(&self) -> Option>; /// 设置当前kobject的parent kobject(不一定与kset相同) fn set_parent(&self, parent: Option>); /// 当前kobject属于哪个kset fn kset(&self) -> Option>; /// 设置当前kobject所属的kset fn set_kset(&self, kset: Option>); fn kobj_type(&self) -> Option<&'static dyn KObjType>; fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>); fn name(&self) -> String; fn set_name(&self, name: String); fn kobj_state(&self) -> RwLockReadGuard; fn kobj_state_mut(&self) -> RwLockWriteGuard; fn set_kobj_state(&self, state: KObjectState); } impl dyn KObject { /// 更新kobject的状态 pub fn update_kobj_state(&self, insert: Option, remove: Option) { let insert = insert.unwrap_or(KObjectState::empty()); let remove = remove.unwrap_or(KObjectState::empty()); let mut state = self.kobj_state_mut(); *state = (*state | insert) & !remove; } } impl DowncastArc for dyn KObject { fn as_any_arc(self: Arc) -> Arc { self } } /// kobject的公共数据 #[derive(Debug, Default)] pub struct KObjectCommonData { pub kern_inode: Option>, pub parent: Option>, pub kset: Option>, pub kobj_type: Option<&'static dyn KObjType>, } impl KObjectCommonData { pub fn get_parent_or_clear_weak(&mut self) -> Option> { get_weak_or_clear!(self.parent) } } pub trait KObjType: Debug + Send + Sync { /// 当指定的kobject被释放时,设备驱动模型会调用此方法 fn release(&self, _kobj: Arc) {} fn sysfs_ops(&self) -> Option<&dyn SysFSOps>; fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]>; } bitflags! { pub struct KObjectState: u32 { const IN_SYSFS = 1 << 0; const ADD_UEVENT_SENT = 1 << 1; const REMOVE_UEVENT_SENT = 1 << 2; const INITIALIZED = 1 << 3; } } #[derive(Debug)] pub struct LockedKObjectState(RwLock); impl LockedKObjectState { pub fn new(state: Option) -> LockedKObjectState { let state = state.unwrap_or(KObjectState::empty()); LockedKObjectState(RwLock::new(state)) } } impl Deref for LockedKObjectState { type Target = RwLock; fn deref(&self) -> &Self::Target { &self.0 } } impl Default for LockedKObjectState { fn default() -> Self { LockedKObjectState::new(None) } } #[derive(Debug)] pub struct KObjectSysFSOps; impl SysFSOps for KObjectSysFSOps { fn support(&self, attr: &dyn Attribute) -> SysFSOpsSupport { return attr.support(); } fn show( &self, kobj: Arc, attr: &dyn Attribute, buf: &mut [u8], ) -> Result { let r = attr.show(kobj, buf).map_err(|e| { if e == SystemError::EOPNOTSUPP_OR_ENOTSUP { SystemError::EIO } else { e } }); return r; } fn store( &self, kobj: Arc, attr: &dyn Attribute, buf: &[u8], ) -> Result { let r = attr.store(kobj, buf).map_err(|e| { if e == SystemError::EOPNOTSUPP_OR_ENOTSUP { SystemError::EIO } else { e } }); return r; } } #[derive(Debug)] pub struct KObjectManager; impl KObjectManager { #[allow(dead_code)] pub fn init_and_add_kobj( kobj: Arc, join_kset: Option>, ) -> Result<(), SystemError> { Self::kobj_init(&kobj); Self::add_kobj(kobj, join_kset) } #[allow(dead_code)] pub fn kobj_init(kobj: &Arc) { kobj.set_kobj_type(Some(&DynamicKObjKType)); } pub fn add_kobj( kobj: Arc, join_kset: Option>, ) -> Result<(), SystemError> { if let Some(kset) = join_kset { kset.join(&kobj); // 如果kobject没有parent,那么就将这个kset作为parent if kobj.parent().is_none() { kobj.set_parent(Some(Arc::downgrade(&(kset as Arc)))); } } let r = Self::create_dir(kobj.clone()); if let Err(e) = r { // https://code.dragonos.org.cn/xref/linux-6.1.9/lib/kobject.c?r=&mo=10426&fi=394#224 if let Some(kset) = kobj.kset() { kset.leave(&kobj); } kobj.set_parent(None); if e == SystemError::EEXIST { kerror!("KObjectManager::add_kobj() failed with error: {e:?}, kobj:{kobj:?}"); } return Err(e); } kobj.update_kobj_state(Some(KObjectState::IN_SYSFS), None); return Ok(()); } fn create_dir(kobj: Arc) -> Result<(), SystemError> { // create dir in sysfs sysfs_instance().create_dir(kobj.clone())?; // create default attributes in sysfs if let Some(ktype) = kobj.kobj_type() { let groups = ktype.attribute_groups(); if let Some(groups) = groups { let r = sysfs_instance().create_groups(&kobj, groups); if let Err(e) = r { sysfs_instance().remove_dir(&kobj); return Err(e); } } } return Ok(()); } /// 从sysfs中移除kobject pub fn remove_kobj(kobj: Arc) { let ktype = kobj.kobj_type(); if let Some(ktype) = ktype { if let Some(groups) = ktype.attribute_groups() { sysfs_instance().remove_groups(&kobj, groups); } } // todo: 发送uevent: KOBJ_REMOVE sysfs_instance().remove_dir(&kobj); kobj.update_kobj_state(None, Some(KObjectState::IN_SYSFS)); let kset = kobj.kset(); if let Some(kset) = kset { kset.leave(&kobj); } kobj.set_parent(None); } } /// 动态创建的kobject对象的ktype #[derive(Debug)] pub struct DynamicKObjKType; impl KObjType for DynamicKObjKType { fn release(&self, kobj: Arc) { kdebug!("DynamicKObjKType::release() kobj:{:?}", kobj.name()); } fn sysfs_ops(&self) -> Option<&dyn SysFSOps> { Some(&KObjectSysFSOps) } fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { None } }