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