1 use alloc::{string::ToString, sync::Arc};
2 
3 use core::fmt::Debug;
4 
5 use super::{
6     device::{sys_dev_char_kset, Device, DeviceMatchName, DeviceMatcher},
7     kobject::{KObjType, KObject},
8     kset::KSet,
9     subsys::SubSysPrivate,
10 };
11 use crate::filesystem::sysfs::{sysfs_instance, Attribute, AttributeGroup, SysFSOps};
12 use system_error::SystemError;
13 
14 /// `/sys/class`的kset
15 static mut CLASS_KSET_INSTANCE: Option<Arc<KSet>> = None;
16 
17 #[inline(always)]
18 #[allow(dead_code)]
sys_class_kset() -> Arc<KSet>19 pub fn sys_class_kset() -> Arc<KSet> {
20     unsafe { CLASS_KSET_INSTANCE.clone().unwrap() }
21 }
22 
23 /// 初始化`/sys/class`的kset
classes_init() -> Result<(), SystemError>24 pub(super) fn classes_init() -> Result<(), SystemError> {
25     let class_kset = KSet::new("class".to_string());
26     class_kset
27         .register(None)
28         .expect("register class kset failed");
29     unsafe {
30         CLASS_KSET_INSTANCE = Some(class_kset);
31     }
32 
33     return Ok(());
34 }
35 
36 /// 设备分类
37 ///
38 /// 类是对设备的高级视图,它抽象了低级实现细节。
39 ///
40 /// 比如,驱动程序可能看到一个SCSI硬盘或一个ATA硬盘,但在类的这个级别,它们都只是硬盘。
41 /// 类允许用户空间根据设备的功能而不是它们如何连接或工作来操作设备。
42 ///
43 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/device/class.h#54
44 pub trait Class: Debug + Send + Sync {
45     /// 获取类的名称
name(&self) -> &'static str46     fn name(&self) -> &'static str;
47 
48     /// 属于该类的设备的基本属性。
dev_groups(&self) -> &'static [&'static dyn AttributeGroup]49     fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
50         return &[];
51     }
52 
53     /// 当前类的基本属性。
class_groups(&self) -> &'static [&'static dyn AttributeGroup]54     fn class_groups(&self) -> &'static [&'static dyn AttributeGroup] {
55         return &[];
56     }
57 
58     /// 表示此类的kobject,并将它链接到层次结构中。
59     ///
60     /// 当前class的所有设备,将会挂载到的`/sys/dev/`内的某个目录下。
dev_kobj(&self) -> Option<Arc<dyn KObject>>61     fn dev_kobj(&self) -> Option<Arc<dyn KObject>>;
62 
set_dev_kobj(&self, kobj: Arc<dyn KObject>)63     fn set_dev_kobj(&self, kobj: Arc<dyn KObject>);
64 
65     /// subsystem应当拥有的数据
subsystem(&self) -> &SubSysPrivate66     fn subsystem(&self) -> &SubSysPrivate;
67 
68     /// Called to release this class
class_release(&self)69     fn class_release(&self) {}
70 }
71 
72 impl dyn Class {
73     /// 在class内,根据条件寻找一个特定的设备
74     ///
75     /// ## 参数
76     ///
77     /// - `matcher` - 匹配器
78     /// - `data` - 传给匹配器的数据
79     #[allow(dead_code)]
find_device<T: Copy>( &self, matcher: &dyn DeviceMatcher<T>, data: T, ) -> Option<Arc<dyn Device>>80     pub fn find_device<T: Copy>(
81         &self,
82         matcher: &dyn DeviceMatcher<T>,
83         data: T,
84     ) -> Option<Arc<dyn Device>> {
85         let subsys = self.subsystem();
86         let guard = subsys.devices();
87         for dev in guard.iter() {
88             if matcher.match_device(&dev, data) {
89                 return Some(dev.clone());
90             }
91         }
92         return None;
93     }
94 
95     /// 根据名称匹配设备
96     ///
97     /// ## 参数
98     ///
99     /// - name 设备名称
100     #[allow(dead_code)]
find_device_by_name(&self, name: &str) -> Option<Arc<dyn Device>>101     pub fn find_device_by_name(&self, name: &str) -> Option<Arc<dyn Device>> {
102         return self.find_device(&DeviceMatchName, name);
103     }
104 }
105 
106 #[inline(always)]
class_manager() -> &'static ClassManager107 pub fn class_manager() -> &'static ClassManager {
108     return &ClassManager;
109 }
110 pub struct ClassManager;
111 
112 impl ClassManager {
113     /// 注册一个设备类
114     ///
115     /// 该方法会将设备类注册到`/sys/class`目录下,
116     /// 并创建它的默认属性组对应的文件。
117     ///
118     /// ## 参数
119     ///
120     /// - `class` - 设备类
class_register(&self, class: &Arc<dyn Class>) -> Result<(), SystemError>121     pub fn class_register(&self, class: &Arc<dyn Class>) -> Result<(), SystemError> {
122         let subsystem = class.subsystem();
123         let subsys = subsystem.subsys();
124         subsys.set_name(class.name().to_string());
125 
126         if class.dev_kobj().is_none() {
127             class.set_dev_kobj(sys_dev_char_kset() as Arc<dyn KObject>);
128         }
129 
130         subsys.set_kobj_type(Some(&ClassKObjbectType));
131         subsystem.set_class(Some(Arc::downgrade(class)));
132 
133         subsys.register(Some(sys_class_kset()))?;
134 
135         sysfs_instance().create_groups(&(subsys as Arc<dyn KObject>), class.class_groups())?;
136 
137         return Ok(());
138     }
139 
140     /// 注销一个设备类
141     #[allow(dead_code)]
class_unregister(&self, class: &Arc<dyn Class>)142     pub fn class_unregister(&self, class: &Arc<dyn Class>) {
143         let subsystem = class.subsystem();
144         let subsys = subsystem.subsys();
145         sysfs_instance().remove_groups(&(subsys.clone() as Arc<dyn KObject>), class.class_groups());
146         subsys.unregister();
147     }
148 }
149 
150 #[derive(Debug)]
151 pub struct ClassKObjbectType;
152 
153 impl KObjType for ClassKObjbectType {
sysfs_ops(&self) -> Option<&dyn SysFSOps>154     fn sysfs_ops(&self) -> Option<&dyn SysFSOps> {
155         Some(&ClassSysFSOps)
156     }
157 
attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]>158     fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
159         None
160     }
161 }
162 
163 #[derive(Debug)]
164 struct ClassSysFSOps;
165 
166 impl SysFSOps for ClassSysFSOps {
show( &self, _kobj: Arc<dyn KObject>, _attr: &dyn Attribute, _buf: &mut [u8], ) -> Result<usize, SystemError>167     fn show(
168         &self,
169         _kobj: Arc<dyn KObject>,
170         _attr: &dyn Attribute,
171         _buf: &mut [u8],
172     ) -> Result<usize, SystemError> {
173         todo!()
174     }
175 
store( &self, _kobj: Arc<dyn KObject>, _attr: &dyn Attribute, _buf: &[u8], ) -> Result<usize, SystemError>176     fn store(
177         &self,
178         _kobj: Arc<dyn KObject>,
179         _attr: &dyn Attribute,
180         _buf: &[u8],
181     ) -> Result<usize, SystemError> {
182         todo!()
183     }
184 }
185