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