use alloc::{ string::{String, ToString}, sync::{Arc, Weak}, }; use intertrait::cast::CastArc; use crate::{ driver::{ acpi::glue::acpi_device_notify, base::map::{LockedDevsMap, LockedKObjMap}, }, filesystem::{ sysfs::{ file::sysfs_emit_str, sysfs_instance, Attribute, AttributeGroup, SysFSOps, SysFSOpsSupport, }, vfs::syscall::ModeType, }, }; use core::fmt::Debug; use core::intrinsics::unlikely; use system_error::SystemError; use self::{ bus::{bus_add_device, bus_probe_device, Bus}, device_number::{DeviceNumber, Major}, driver::Driver, }; use super::{ class::Class, kobject::{KObjType, KObject, KObjectManager, KObjectState}, kset::KSet, swnode::software_node_notify, }; pub mod bus; pub mod dd; pub mod device_number; pub mod driver; pub mod init; static mut DEVICE_MANAGER: Option = None; #[inline(always)] pub fn device_manager() -> &'static DeviceManager { unsafe { DEVICE_MANAGER.as_ref().unwrap() } } lazy_static! { // 全局字符设备号管理实例 pub static ref CHARDEVS: Arc = Arc::new(LockedDevsMap::default()); // 全局块设备管理实例 pub static ref BLOCKDEVS: Arc = Arc::new(LockedDevsMap::default()); // 全局设备管理实例 pub static ref DEVMAP: Arc = Arc::new(LockedKObjMap::default()); } /// `/sys/devices` 的 kset 实例 static mut DEVICES_KSET_INSTANCE: Option> = None; /// `/sys/dev` 的 kset 实例 static mut DEV_KSET_INSTANCE: Option> = None; /// `/sys/dev/block` 的 kset 实例 static mut DEV_BLOCK_KSET_INSTANCE: Option> = None; /// `/sys/dev/char` 的 kset 实例 static mut DEV_CHAR_KSET_INSTANCE: Option> = None; /// `/sys/devices/virtual` 的 kset 实例 static mut DEVICES_VIRTUAL_KSET_INSTANCE: Option> = None; /// 获取`/sys/devices`的kset实例 #[inline(always)] pub(super) fn sys_devices_kset() -> Arc { unsafe { DEVICES_KSET_INSTANCE.as_ref().unwrap().clone() } } /// 获取`/sys/dev`的kset实例 #[inline(always)] pub(super) fn sys_dev_kset() -> Arc { unsafe { DEV_KSET_INSTANCE.as_ref().unwrap().clone() } } /// 获取`/sys/dev/block`的kset实例 #[inline(always)] #[allow(dead_code)] pub fn sys_dev_block_kset() -> Arc { unsafe { DEV_BLOCK_KSET_INSTANCE.as_ref().unwrap().clone() } } /// 获取`/sys/dev/char`的kset实例 #[inline(always)] pub fn sys_dev_char_kset() -> Arc { unsafe { DEV_CHAR_KSET_INSTANCE.as_ref().unwrap().clone() } } pub(self) unsafe fn set_sys_dev_block_kset(kset: Arc) { DEV_BLOCK_KSET_INSTANCE = Some(kset); } pub(self) unsafe fn set_sys_dev_char_kset(kset: Arc) { DEV_CHAR_KSET_INSTANCE = Some(kset); } /// 获取`/sys/devices/virtual`的kset实例 pub fn sys_devices_virtual_kset() -> Arc { unsafe { DEVICES_VIRTUAL_KSET_INSTANCE.as_ref().unwrap().clone() } } pub(self) unsafe fn set_sys_devices_virtual_kset(kset: Arc) { DEVICES_VIRTUAL_KSET_INSTANCE = Some(kset); } /// 设备应该实现的操作 /// /// ## 注意 /// /// 由于设备驱动模型需要从Arc转换为Arc, /// 因此,所有的实现了Device trait的结构体,都应该在结构体上方标注`#[cast_to([sync] Device)]`, /// /// 否则在释放设备资源的时候,会由于无法转换为Arc而导致资源泄露,并且release回调函数也不会被调用。 pub trait Device: KObject { // TODO: 待实现 open, close /// @brief: 获取设备类型 /// @parameter: None /// @return: 实现该trait的设备所属类型 fn dev_type(&self) -> DeviceType; /// @brief: 获取设备标识 /// @parameter: None /// @return: 该设备唯一标识 fn id_table(&self) -> IdTable; /// 设备释放时的回调函数 fn release(&self) { let name = self.name(); kwarn!( "device {} does not have a release() function, it is broken and must be fixed.", name ); } /// 获取当前设备所属的总线 fn bus(&self) -> Option> { return None; } /// 设置当前设备所属的总线 /// /// (一定要传入Arc,因为bus的subsysprivate里面存储的是Device的Arc指针) /// /// 注意,如果实现了当前方法,那么必须实现`bus()`方法 fn set_bus(&self, bus: Option>); /// 获取当前设备所属的类 fn class(&self) -> Option> { return None; } /// 设置当前设备所属的类 /// /// 注意,如果实现了当前方法,那么必须实现`class()`方法 fn set_class(&self, class: Option>); /// 返回已经与当前设备匹配好的驱动程序 fn driver(&self) -> Option>; fn set_driver(&self, driver: Option>); /// 当前设备是否已经挂掉了 fn is_dead(&self) -> bool; /// 当前设备是否处于可以被匹配的状态 /// /// The device has matched with a driver at least once or it is in /// a bus (like AMBA) which can't check for matching drivers until /// other devices probe successfully. fn can_match(&self) -> bool; fn set_can_match(&self, can_match: bool); /// The hardware state of this device has been synced to match /// the software state of this device by calling the driver/bus /// sync_state() callback. fn state_synced(&self) -> bool; fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { None } } impl dyn Device { #[inline(always)] pub fn is_registered(&self) -> bool { self.kobj_state().contains(KObjectState::IN_SYSFS) } } // 暂定是不可修改的,在初始化的时候就要确定。以后可能会包括例如硬件中断包含的信息 #[allow(dead_code)] #[derive(Debug, Clone)] pub struct DevicePrivateData { id_table: IdTable, state: DeviceState, } #[allow(dead_code)] impl DevicePrivateData { pub fn new(id_table: IdTable, state: DeviceState) -> Self { Self { id_table, state } } pub fn id_table(&self) -> &IdTable { &self.id_table } pub fn state(&self) -> DeviceState { self.state } pub fn set_state(&mut self, state: DeviceState) { self.state = state; } } /// @brief: 设备类型 #[allow(dead_code)] #[derive(Debug, Eq, PartialEq)] pub enum DeviceType { Bus, Net, Gpu, Input, Block, Rtc, Serial, Intc, PlatformDev, Char, } /// @brief: 设备标识符类型 #[derive(Debug, Clone, Hash, PartialOrd, PartialEq, Ord, Eq)] pub struct IdTable { basename: String, id: Option, } /// @brief: 设备标识符操作方法集 impl IdTable { /// @brief: 创建一个新的设备标识符 /// @parameter name: 设备名 /// @parameter id: 设备id /// @return: 设备标识符 pub fn new(basename: String, id: Option) -> IdTable { return IdTable { basename, id }; } /// @brief: 将设备标识符转换成name /// @parameter None /// @return: 设备名 pub fn name(&self) -> String { if self.id.is_none() { return self.basename.clone(); } else { let id = self.id.unwrap(); return format!("{}:{}", id.major().data(), id.minor()); } } pub fn device_number(&self) -> DeviceNumber { return self.id.unwrap_or(DeviceNumber::default()); } } impl Default for IdTable { fn default() -> Self { IdTable::new("unknown".to_string(), None) } } // 以现在的模型,设备在加载到系统中就是已经初始化的状态了,因此可以考虑把这个删掉 /// @brief: 设备当前状态 #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum DeviceState { NotInitialized = 0, Initialized = 1, UnDefined = 2, } /// @brief: 设备错误类型 #[allow(dead_code)] #[derive(Debug, Copy, Clone)] pub enum DeviceError { DriverExists, // 设备已存在 DeviceExists, // 驱动已存在 InitializeFailed, // 初始化错误 NotInitialized, // 未初始化的设备 NoDeviceForDriver, // 没有合适的设备匹配驱动 NoDriverForDevice, // 没有合适的驱动匹配设备 RegisterError, // 注册失败 UnsupportedOperation, // 不支持的操作 } impl Into for DeviceError { fn into(self) -> SystemError { match self { DeviceError::DriverExists => SystemError::EEXIST, DeviceError::DeviceExists => SystemError::EEXIST, DeviceError::InitializeFailed => SystemError::EIO, DeviceError::NotInitialized => SystemError::ENODEV, DeviceError::NoDeviceForDriver => SystemError::ENODEV, DeviceError::NoDriverForDevice => SystemError::ENODEV, DeviceError::RegisterError => SystemError::EIO, DeviceError::UnsupportedOperation => SystemError::EIO, } } } /// @brief: 将u32类型转换为设备状态类型 impl From for DeviceState { fn from(state: u32) -> Self { match state { 0 => DeviceState::NotInitialized, 1 => DeviceState::Initialized, _ => todo!(), } } } /// @brief: 将设备状态转换为u32类型 impl From for u32 { fn from(state: DeviceState) -> Self { match state { DeviceState::NotInitialized => 0, DeviceState::Initialized => 1, DeviceState::UnDefined => 2, } } } #[derive(Debug)] pub struct DeviceKObjType; impl KObjType for DeviceKObjType { // https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/core.c#2307 fn release(&self, kobj: Arc) { let dev = kobj.cast::().unwrap(); /* * Some platform devices are driven without driver attached * and managed resources may have been acquired. Make sure * all resources are released. * * Drivers still can add resources into device after device * is deleted but alive, so release devres here to avoid * possible memory leak. */ // todo: 在引入devres之后再实现 // devres_release_all(kobj); dev.release(); } fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { None } fn sysfs_ops(&self) -> Option<&dyn SysFSOps> { Some(&DeviceSysFSOps) } } #[derive(Debug)] pub(super) struct DeviceSysFSOps; impl SysFSOps for DeviceSysFSOps { fn store( &self, kobj: Arc, attr: &dyn Attribute, buf: &[u8], ) -> Result { return attr.store(kobj, buf); } fn show( &self, kobj: Arc, attr: &dyn Attribute, buf: &mut [u8], ) -> Result { return attr.show(kobj, buf); } } /// @brief Device管理器 #[derive(Debug)] pub struct DeviceManager; impl DeviceManager { /// @brief: 创建一个新的设备管理器 /// @parameter: None /// @return: DeviceManager实体 #[inline] const fn new() -> DeviceManager { return Self; } pub fn register(&self, device: Arc) -> Result<(), SystemError> { self.device_default_initialize(&device); return self.add_device(device); } /// @brief: 添加设备 /// @parameter id_table: 总线标识符,用于唯一标识该总线 /// @parameter dev: 设备实例 /// @return: None /// /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/core.c#3398 /// /// todo: 完善错误处理逻辑:如果添加失败,需要将之前添加的内容全部回滚 #[inline(never)] #[allow(dead_code)] pub fn add_device(&self, device: Arc) -> Result<(), SystemError> { // 在这里处理与parent相关的逻辑 let current_parent = device .parent() .map(|x| x.upgrade()) .flatten() .map(|x| x.arc_any().cast::().ok()) .flatten(); let actual_parent = self.get_device_parent(&device, current_parent)?; if let Some(actual_parent) = actual_parent { // kdebug!( // "device '{}' parent is '{}', strong_count: {}", // device.name().to_string(), // actual_parent.name(), // Arc::strong_count(&actual_parent) // ); device.set_parent(Some(Arc::downgrade(&actual_parent))); } KObjectManager::add_kobj(device.clone() as Arc, None).map_err(|e| { kerror!("add device '{:?}' failed: {:?}", device.name(), e); e })?; self.device_platform_notify(&device); self.add_class_symlinks(&device)?; self.add_attrs(&device)?; bus_add_device(&device)?; if device.id_table().device_number().major() != Major::UNNAMED_MAJOR { self.create_file(&device, &DeviceAttrDev)?; self.create_sys_dev_entry(&device)?; } // 通知客户端有关设备添加的信息。此调用必须在 dpm_sysfs_add() 之后且在 kobject_uevent() 之前执行。 if let Some(bus) = device.bus().map(|bus| bus.upgrade()).flatten() { bus.subsystem().bus_notifier().call_chain( bus::BusNotifyEvent::AddDevice, Some(&device), None, ); } // todo: 发送uevent: KOBJ_ADD // probe drivers for a new device bus_probe_device(&device); if let Some(class) = device.class() { class.subsystem().add_device_to_vec(&device)?; for class_interface in class.subsystem().interfaces() { class_interface.add_device(&device).ok(); } } return Ok(()); } /// 获取设备真实的parent kobject /// /// ## 参数 /// /// - `device`: 设备 /// - `current_parent`: 当前的parent kobject /// /// ## 返回值 /// /// - `Ok(Some(kobj))`: 如果找到了真实的parent kobject,那么返回它 /// - `Ok(None)`: 如果没有找到真实的parent kobject,那么返回None /// - `Err(e)`: 如果发生错误,那么返回错误 fn get_device_parent( &self, device: &Arc, current_parent: Option>, ) -> Result>, SystemError> { // kdebug!("get_device_parent() device:{:?}", device.name()); if let Some(_) = device.class() { let parent_kobj: Arc; // kdebug!("current_parent:{:?}", current_parent); if current_parent.is_none() { parent_kobj = sys_devices_virtual_kset() as Arc; } else { let cp = current_parent.unwrap(); if cp.class().is_some() { return Ok(Some(cp.clone() as Arc)); } else { parent_kobj = cp.clone() as Arc; } } // 是否需要glue dir? return Ok(Some(parent_kobj)); } // subsystems can specify a default root directory for their devices if current_parent.is_none() { if let Some(bus) = device.bus().map(|bus| bus.upgrade()).flatten() { if let Some(root) = bus.root_device().map(|x| x.upgrade()).flatten() { return Ok(Some(root as Arc)); } } } if current_parent.is_some() { return Ok(Some(current_parent.unwrap().clone() as Arc)); } return Ok(None); } /// @brief: 卸载设备 /// @parameter id_table: 总线标识符,用于唯一标识该设备 /// @return: None /// /// ## 注意 /// 该函数已废弃,不再使用 #[inline] #[allow(dead_code)] pub fn remove_device(&self, _id_table: &IdTable) { todo!() } /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#542 pub fn remove(&self, _dev: &Arc) { todo!("DeviceManager::remove") } /// @brief: 获取设备 /// @parameter id_table: 设备标识符,用于唯一标识该设备 /// @return: 设备实例 #[inline] #[allow(dead_code)] pub fn find_device_by_idtable(&self, _id_table: &IdTable) -> Option> { todo!("find_device_by_idtable") } fn device_platform_notify(&self, dev: &Arc) { acpi_device_notify(dev); software_node_notify(dev); } // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/core.c#3224 fn add_class_symlinks(&self, dev: &Arc) -> Result<(), SystemError> { let class = dev.class(); if class.is_none() { return Ok(()); } // 定义错误处理函数,用于在添加符号链接失败时,移除已经添加的符号链接 let err_remove_device = |dev_kobj: &Arc| { sysfs_instance().remove_link(dev_kobj, "device".to_string()); }; let err_remove_subsystem = |dev_kobj: &Arc| { sysfs_instance().remove_link(dev_kobj, "subsystem".to_string()); }; let class = class.unwrap(); let dev_kobj = dev.clone() as Arc; let subsys_kobj = class.subsystem().subsys() as Arc; sysfs_instance().create_link(Some(&dev_kobj), &subsys_kobj, "subsystem".to_string())?; // todo: 这里需要处理class的parent逻辑, 添加device链接 if let Some(parent) = dev.parent().map(|x| x.upgrade()).flatten() { let parent_kobj = parent.clone() as Arc; sysfs_instance() .create_link(Some(&dev_kobj), &&parent_kobj, "device".to_string()) .map_err(|e| { err_remove_subsystem(&dev_kobj); e })?; } sysfs_instance() .create_link(Some(&subsys_kobj), &dev_kobj, dev.name()) .map_err(|e| { err_remove_device(&dev_kobj); err_remove_subsystem(&dev_kobj); e })?; return Ok(()); } /// 在sysfs中,为指定的设备创建属性文件 /// /// ## 参数 /// /// - `dev`: 设备 fn add_attrs(&self, dev: &Arc) -> Result<(), SystemError> { // 定义错误处理函数,用于在添加属性文件失败时,移除已经添加的属性组 let err_remove_class_groups = |dev: &Arc| { if let Some(class) = dev.class() { let attr_groups = class.dev_groups(); self.remove_groups(dev, attr_groups); } }; let err_remove_kobj_type_groups = |dev: &Arc| { if let Some(kobj_type) = dev.kobj_type() { let attr_groups = kobj_type.attribute_groups().unwrap_or(&[]); self.remove_groups(dev, attr_groups); } }; // 真正开始添加属性文件 // 添加设备类的属性文件 if let Some(class) = dev.class() { let attr_groups = class.dev_groups(); self.add_groups(dev, attr_groups)?; } // 添加kobj_type的属性文件 if let Some(kobj_type) = dev.kobj_type() { self.add_groups(dev, kobj_type.attribute_groups().unwrap_or(&[])) .map_err(|e| { err_remove_class_groups(dev); e })?; } // 添加设备本身的属性文件 self.add_groups(dev, dev.attribute_groups().unwrap_or(&[])) .map_err(|e| { err_remove_kobj_type_groups(dev); err_remove_class_groups(dev); e })?; return Ok(()); } /// 在sysfs中,为指定的设备创建属性组,以及属性组中的属性文件 /// /// ## 参数 /// /// - `dev`: 设备 /// - `attr_groups`: 属性组 pub fn add_groups( &self, dev: &Arc, attr_groups: &'static [&dyn AttributeGroup], ) -> Result<(), SystemError> { let kobj = dev.clone() as Arc; return sysfs_instance().create_groups(&kobj, attr_groups); } /// 在sysfs中,为指定的设备移除属性组,以及属性组中的属性文件 /// /// ## 参数 /// /// - `dev`: 设备 /// - `attr_groups`: 要移除的属性组 pub fn remove_groups( &self, dev: &Arc, attr_groups: &'static [&dyn AttributeGroup], ) { let kobj = dev.clone() as Arc; sysfs_instance().remove_groups(&kobj, attr_groups); } /// 为设备在sysfs中创建属性文件 /// /// ## 参数 /// /// - `dev`: 设备 /// - `attr`: 属性 pub fn create_file( &self, dev: &Arc, attr: &'static dyn Attribute, ) -> Result<(), SystemError> { if unlikely( attr.mode().contains(ModeType::S_IRUGO) && (!attr.support().contains(SysFSOpsSupport::SHOW)), ) { kwarn!( "Attribute '{}': read permission without 'show'", attr.name() ); } if unlikely( attr.mode().contains(ModeType::S_IWUGO) && (!attr.support().contains(SysFSOpsSupport::STORE)), ) { kwarn!( "Attribute '{}': write permission without 'store'", attr.name() ); } let kobj = dev.clone() as Arc; return sysfs_instance().create_file(&kobj, attr); } /// 在/sys/dev下,或者设备所属的class下,为指定的设备创建链接 fn create_sys_dev_entry(&self, dev: &Arc) -> Result<(), SystemError> { let target_kobj = self.device_to_dev_kobj(dev); let name = dev.id_table().name(); let current_kobj = dev.clone() as Arc; return sysfs_instance().create_link(Some(&target_kobj), ¤t_kobj, name); } /// Delete symlink for device in `/sys/dev` or `/sys/class/` #[allow(dead_code)] fn remove_sys_dev_entry(&self, dev: &Arc) { let kobj = self.device_to_dev_kobj(dev); let name = dev.id_table().name(); sysfs_instance().remove_link(&kobj, name); } /// device_to_dev_kobj - select a /sys/dev/ directory for the device /// /// By default we select char/ for new entries. /// /// ## 参数 /// /// - `dev`: 设备 fn device_to_dev_kobj(&self, _dev: &Arc) -> Arc { // todo: 处理class的逻辑 let kobj = sys_dev_char_kset().as_kobject(); return kobj; } /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/core.c?fi=device_links_force_bind#1226 pub fn device_links_force_bind(&self, _dev: &Arc) { todo!("device_links_force_bind") } /// 把device对象的一些结构进行默认初始化 /// /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/core.c?fi=device_initialize#2976 pub fn device_default_initialize(&self, dev: &Arc) { dev.set_kset(Some(sys_devices_kset())); dev.set_kobj_type(Some(&DeviceKObjType)); return; } /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c?r=&mo=29885&fi=1100#1100 pub fn device_driver_attach( &self, _driver: &Arc, _dev: &Arc, ) -> Result<(), SystemError> { todo!("device_driver_attach") } /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c?r=&mo=35401&fi=1313#1313 pub fn device_driver_detach(&self, _dev: &Arc) { todo!("device_driver_detach") } } /// @brief: 设备注册 /// @parameter: name: 设备名 /// @return: 操作成功,返回(),操作失败,返回错误码 pub fn device_register(device: Arc) -> Result<(), SystemError> { return device_manager().register(device); } /// @brief: 设备卸载 /// @parameter: name: 设备名 /// @return: 操作成功,返回(),操作失败,返回错误码 pub fn device_unregister(_device: Arc) { // DEVICE_MANAGER.add_device(device.id_table(), device.clone()); // match sys_device_unregister(&device.id_table().name()) { // Ok(_) => { // device.set_inode(None); // return Ok(()); // } // Err(_) => Err(DeviceError::RegisterError), // } todo!("device_unregister") } /// 设备文件夹下的`dev`文件的属性 #[derive(Debug, Clone, Copy)] pub struct DeviceAttrDev; impl Attribute for DeviceAttrDev { fn mode(&self) -> ModeType { // 0o444 return ModeType::S_IRUGO; } fn name(&self) -> &str { "dev" } fn show(&self, kobj: Arc, buf: &mut [u8]) -> Result { let dev = kobj.cast::().map_err(|kobj| { kerror!( "Intertrait casting not implemented for kobj: {}", kobj.name() ); SystemError::EOPNOTSUPP_OR_ENOTSUP })?; let device_number = dev.id_table().device_number(); let s = format!( "{}:{}\n", device_number.major().data(), device_number.minor() ); return sysfs_emit_str(buf, &s); } fn support(&self) -> SysFSOpsSupport { SysFSOpsSupport::SHOW } } /// 设备匹配器 /// /// 用于匹配设备是否符合某个条件 /// /// ## 参数 /// /// - `T` - 匹配器的数据类型 /// - `data` - 匹配器的数据 pub trait DeviceMatcher: Debug { fn match_device(&self, device: &Arc, data: T) -> bool; } /// 用于根据名称匹配设备的匹配器 #[derive(Debug)] pub struct DeviceMatchName; impl DeviceMatcher<&str> for DeviceMatchName { #[inline] fn match_device(&self, device: &Arc, data: &str) -> bool { return device.name() == data; } }