diff --git a/kernel/src/driver/base/init.rs b/kernel/src/driver/base/init.rs index 6629f903..9bf3f064 100644 --- a/kernel/src/driver/base/init.rs +++ b/kernel/src/driver/base/init.rs @@ -1,3 +1,4 @@ +use crate::driver::input::serio::serio_bus_init; use system_error::SystemError; use super::{ @@ -16,6 +17,7 @@ pub(super) fn driver_init() -> Result<(), SystemError> { firmware_init()?; hypervisor_init()?; platform_bus_init()?; + serio_bus_init()?; cpu_device_manager().init()?; // 至此,已完成设备驱动模型的初始化 diff --git a/kernel/src/driver/input/mod.rs b/kernel/src/driver/input/mod.rs new file mode 100644 index 00000000..d3a1a545 --- /dev/null +++ b/kernel/src/driver/input/mod.rs @@ -0,0 +1,2 @@ +pub mod ps2_dev; +pub mod serio; diff --git a/kernel/src/driver/input/ps2_dev/mod.rs b/kernel/src/driver/input/ps2_dev/mod.rs new file mode 100644 index 00000000..feedb874 --- /dev/null +++ b/kernel/src/driver/input/ps2_dev/mod.rs @@ -0,0 +1 @@ +pub mod ps2_device; diff --git a/kernel/src/driver/input/ps2_dev/ps2_device.rs b/kernel/src/driver/input/ps2_dev/ps2_device.rs new file mode 100644 index 00000000..26050c7d --- /dev/null +++ b/kernel/src/driver/input/ps2_dev/ps2_device.rs @@ -0,0 +1,4 @@ +use crate::driver::{base::device::Device, input::serio::serio_device::SerioDevice}; + +// todo: https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/libps2.h#33 +pub trait Ps2Device: Device + SerioDevice {} diff --git a/kernel/src/driver/input/serio/mod.rs b/kernel/src/driver/input/serio/mod.rs new file mode 100644 index 00000000..2c6186b7 --- /dev/null +++ b/kernel/src/driver/input/serio/mod.rs @@ -0,0 +1,31 @@ +use alloc::sync::Arc; +use system_error::SystemError; + +use crate::driver::base::device::bus::{bus_register, Bus}; + +use self::subsys::SerioBus; + +pub mod serio_device; +pub mod serio_driver; +pub mod subsys; + +static mut SERIO_BUS: Option> = None; + +#[allow(dead_code)] +#[inline(always)] +pub fn serio_bus() -> Arc { + unsafe { SERIO_BUS.clone().unwrap() } +} + +/// # 函数的功能 +/// +/// 初始化serio bus +/// +/// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/serio.c#1024 +pub fn serio_bus_init() -> Result<(), SystemError> { + let serio_bus = SerioBus::new(); + let r = bus_register(serio_bus.clone() as Arc); + unsafe { SERIO_BUS = Some(serio_bus) }; + + return r; +} diff --git a/kernel/src/driver/input/serio/serio_device.rs b/kernel/src/driver/input/serio/serio_device.rs new file mode 100644 index 00000000..89f2f771 --- /dev/null +++ b/kernel/src/driver/input/serio/serio_device.rs @@ -0,0 +1,70 @@ +use alloc::sync::Arc; +use system_error::SystemError; + +use crate::driver::base::device::{bus::Bus, Device}; + +use super::serio_bus; + +/// 串行设备,实现该trait的设备实例挂载在serio总线上,同时应该实现Device trait +/// +/// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/serio.h#20 +pub trait SerioDevice: Device { + /// # 函数功能 + /// + /// Serio设备写入数据 + /// + /// ## 参数 + /// + /// - data 写入的数据 + /// + /// ## 返回值 + /// + /// 无 + fn write(&self, device: &Arc, data: u8) -> Result<(), SystemError>; + /// Serio设备连接驱动时调用 + fn open(&self, device: &Arc) -> Result<(), SystemError>; + /// Serio设备断开驱动时调用 + fn close(&self, device: &Arc) -> Result<(), SystemError>; + /// Serio设备初始化时调用 + fn start(&self, device: &Arc) -> Result<(), SystemError>; + /// Serio设备销毁时调用 + fn stop(&self, device: &Arc) -> Result<(), SystemError>; +} + +#[allow(dead_code)] +#[inline(always)] +pub fn serio_device_manager() -> &'static SerioDeviceManager { + &SerioDeviceManager +} + +pub struct SerioDeviceManager; + +#[allow(dead_code)] +impl SerioDeviceManager { + /// # 函数功能 + /// 注册Serio设备 + /// + /// ## 参数 + /// - device 待注册的设备 + /// + /// ## 返回值 + /// 无 + pub fn register_port(&self, device: Arc) -> Result<(), SystemError> { + self.init_port(device) + } + + /// # 函数功能 + /// 初始化Serio设备 + /// + /// ## 参数 + /// - device 待初始化的Serio设备 + /// + /// ## 返回值 + /// 无 + /// + /// todo:https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/serio.c#494 + pub fn init_port(&self, device: Arc) -> Result<(), SystemError> { + device.set_bus(Some(Arc::downgrade(&(serio_bus() as Arc)))); + Ok(()) + } +} diff --git a/kernel/src/driver/input/serio/serio_driver.rs b/kernel/src/driver/input/serio/serio_driver.rs new file mode 100644 index 00000000..8c0f9b18 --- /dev/null +++ b/kernel/src/driver/input/serio/serio_driver.rs @@ -0,0 +1,75 @@ +use alloc::sync::Arc; +use system_error::SystemError; + +use crate::driver::base::device::{ + bus::Bus, + driver::{driver_manager, Driver}, +}; + +use super::{serio_bus, serio_device::SerioDevice}; + +/// 实现该trait的设备驱动实例应挂载在serio总线上,同时应该实现Driver trait +/// +/// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/serio.h#67 +pub trait SerioDriver: Driver { + // 写入时唤醒设备 + fn write_wakeup(&self, device: &Arc) -> Result<(), SystemError>; + /// # 函数功能 + /// 中断函数 + /// + /// ## 参数 + /// - device: Serio设备 + /// - data: 端口数据 + /// - flag: 状态掩码 + /// + /// ## 返回值 + /// 无 + fn interrupt( + &self, + device: &Arc, + data: u8, + flag: u8, + ) -> Result<(), SystemError>; + /// Serio驱动连接设备 + fn connect(&self, device: &Arc) -> Result<(), SystemError>; + /// 重新连接设备 + fn reconnect(&self, device: &Arc) -> Result<(), SystemError>; + /// 快速重连设备 + fn fast_reconnect(&self, device: &Arc) -> Result<(), SystemError>; + /// 驱动断开设备 + fn disconnect(&self, device: &Arc) -> Result<(), SystemError>; + /// 清除设备状态 + fn cleanup(&self, device: &Arc) -> Result<(), SystemError>; +} + +///todo: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/serio.c#810 +pub struct SerioDriverManager; + +#[allow(dead_code)] +impl SerioDriverManager { + /// # 函数功能 + /// 注册Serio驱动 + /// + /// ## 参数 + /// - driver 待注册的Serio驱动 + /// + /// ## 返回值 + /// 无 + pub fn register(&self, driver: Arc) -> Result<(), SystemError> { + driver.set_bus(Some(Arc::downgrade(&(serio_bus() as Arc)))); + return driver_manager().register(driver as Arc); + } + + /// # 函数功能 + /// 卸载Serio驱动 + /// + /// ## 参数 + /// - driver 待卸载的Serio驱动 + /// + /// ## 返回值 + /// 无 + #[allow(dead_code)] + pub fn unregister(&self, driver: &Arc) { + driver_manager().unregister(&(driver.clone() as Arc)); + } +} diff --git a/kernel/src/driver/input/serio/subsys.rs b/kernel/src/driver/input/serio/subsys.rs new file mode 100644 index 00000000..d3291a85 --- /dev/null +++ b/kernel/src/driver/input/serio/subsys.rs @@ -0,0 +1,140 @@ +use alloc::{ + string::{String, ToString}, + sync::{Arc, Weak}, +}; +use intertrait::cast::CastArc; +use system_error::SystemError; + +use crate::{ + driver::{ + acpi::acpi_manager, + base::{ + device::{bus::Bus, driver::Driver, Device}, + kobject::KObject, + subsys::SubSysPrivate, + }, + }, + filesystem::{ + sysfs::{Attribute, AttributeGroup}, + vfs::syscall::ModeType, + }, +}; + +use super::{serio_device::SerioDevice, serio_driver::SerioDriver}; + +#[derive(Debug)] +pub struct SerioBus { + private: SubSysPrivate, +} + +impl SerioBus { + pub fn new() -> Arc { + let w: Weak = Weak::new(); + let private = SubSysPrivate::new("serio".to_string(), Some(w), None, &[]); + let bus = Arc::new(Self { private }); + bus.subsystem() + .set_bus(Some(Arc::downgrade(&(bus.clone() as Arc)))); + + return bus; + } +} + +impl Bus for SerioBus { + fn name(&self) -> String { + return "serio".to_string(); + } + + fn dev_name(&self) -> String { + return self.name(); + } + + fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] { + return &[&SerioDeviceAttrGroup]; + } + + fn subsystem(&self) -> &SubSysPrivate { + return &self.private; + } + + fn probe(&self, device: &Arc) -> Result<(), SystemError> { + let drv = device.driver().ok_or(SystemError::EINVAL)?; + let pdrv = drv.cast::().map_err(|_| { + kerror!( + "SerioBus::probe() failed: device.driver() is not a SerioDriver. Device: '{:?}'", + device.name() + ); + SystemError::EINVAL + })?; + + let pdev = device.clone().cast::().map_err(|_| { + kerror!( + "SerioBus::probe() failed: device is not a SerioDevice. Device: '{:?}'", + device.name() + ); + SystemError::EINVAL + })?; + + return pdrv.connect(&pdev); + } + + fn remove(&self, _device: &Arc) -> Result<(), SystemError> { + todo!() + } + + fn sync_state(&self, _device: &Arc) { + todo!() + } + + fn shutdown(&self, _device: &Arc) { + todo!() + } + + fn resume(&self, _device: &Arc) -> Result<(), SystemError> { + todo!() + } + + fn match_device( + &self, + device: &Arc, + driver: &Arc, + ) -> Result { + // 尝试从 ACPI 中匹配 + if let Ok(x) = acpi_manager().driver_match_device(driver, device) { + if x { + return Ok(true); + } + } + + // 尝试从 ID table 中匹配 + if let Some(drv_id_table) = driver.id_table() { + let pdev = device + .clone() + .cast::() + .map_err(|_| SystemError::EINVAL)?; + if drv_id_table.name().eq(&pdev.name()) { + return Ok(true); + } + } + + // 尝试根据设备名称匹配 + return Ok(device.name().eq(&driver.name())); + } +} + +#[derive(Debug)] +pub struct SerioDeviceAttrGroup; + +impl AttributeGroup for SerioDeviceAttrGroup { + fn name(&self) -> Option<&str> { + None + } + + /// todo: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/serio.c#473 + fn attrs(&self) -> &[&'static dyn Attribute] { + return &[]; + } + + fn is_visible(&self, _kobj: Arc, _attr: &dyn Attribute) -> Option { + None + } +} diff --git a/kernel/src/driver/mod.rs b/kernel/src/driver/mod.rs index e506ca0e..0c8c9aac 100644 --- a/kernel/src/driver/mod.rs +++ b/kernel/src/driver/mod.rs @@ -1,6 +1,7 @@ pub mod acpi; pub mod base; pub mod disk; +pub mod input; pub mod keyboard; pub mod net; pub mod open_firmware;