From 9993c0fc61e9603f631bd6748ff0b4fecb7bd483 Mon Sep 17 00:00:00 2001 From: R0ronoa <84278015+2447742618@users.noreply.github.com> Date: Mon, 26 Feb 2024 15:03:13 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0i8042=E9=A9=B1=E5=8A=A8=20?= =?UTF-8?q?=E6=94=B9=E6=AD=A3serio=E8=AE=BE=E5=A4=87=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E7=BB=93=E6=9E=84=20(#538)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 添加i8042驱动 改正serio设备文件结构 --- .../driver/input/ps2_mouse/ps_mouse_device.rs | 17 +- .../driver/input/serio/i8042/i8042_device.rs | 190 ++++++++++++++++++ .../driver/input/serio/i8042/i8042_driver.rs | 190 ++++++++++++++++++ .../driver/input/serio/i8042/i8042_ports.rs | 185 +++++++++++++++++ kernel/src/driver/input/serio/i8042/mod.rs | 75 +++++++ kernel/src/driver/input/serio/mod.rs | 1 + 6 files changed, 651 insertions(+), 7 deletions(-) create mode 100644 kernel/src/driver/input/serio/i8042/i8042_device.rs create mode 100644 kernel/src/driver/input/serio/i8042/i8042_driver.rs create mode 100644 kernel/src/driver/input/serio/i8042/i8042_ports.rs create mode 100644 kernel/src/driver/input/serio/i8042/mod.rs diff --git a/kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs b/kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs index 3693583f..f0538b12 100644 --- a/kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs +++ b/kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs @@ -6,7 +6,6 @@ use alloc::{ }; use kdepends::ringbuffer::{AllocRingBuffer, RingBuffer}; use system_error::SystemError; -use unified_init::macros::unified_init; use crate::{ arch::{io::PortIOArch, CurrentIrqArch, CurrentPortIOArch}, @@ -20,7 +19,10 @@ use crate::{ kobject::{KObjType, KObject, KObjectState, LockedKObjectState}, kset::KSet, }, - input::serio::serio_device::{serio_device_manager, SerioDevice}, + input::{ + ps2_dev::ps2_device::Ps2Device, + serio::serio_device::{serio_device_manager, SerioDevice}, + }, }, exception::InterruptArch, filesystem::{ @@ -31,7 +33,6 @@ use crate::{ IndexNode, Metadata, }, }, - init::initcall::INITCALL_DEVICE, libs::{ rwlock::{RwLockReadGuard, RwLockWriteGuard}, spinlock::SpinLock, @@ -316,7 +317,7 @@ impl Ps2MouseDevice { // guard.current_state.flags.bits, // guard.current_state.x, // guard.current_state.y - // ) + // ); } _ => unreachable!(), } @@ -649,13 +650,15 @@ impl IndexNode for Ps2MouseDevice { } } -#[unified_init(INITCALL_DEVICE)] -fn rs_ps2_mouse_device_int() -> Result<(), SystemError> { +impl Ps2Device for Ps2MouseDevice {} + +pub fn rs_ps2_mouse_device_init(parent: Arc) -> Result<(), SystemError> { kdebug!("ps2_mouse_device initializing..."); let psmouse = Arc::new(Ps2MouseDevice::new()); device_manager().device_default_initialize(&(psmouse.clone() as Arc)); - serio_device_manager().register_port(psmouse.clone())?; + psmouse.set_parent(Some(Arc::downgrade(&parent))); + serio_device_manager().register_port(psmouse.clone() as Arc)?; devfs_register(&psmouse.name(), psmouse.clone()).map_err(|e| { kerror!( diff --git a/kernel/src/driver/input/serio/i8042/i8042_device.rs b/kernel/src/driver/input/serio/i8042/i8042_device.rs new file mode 100644 index 00000000..1523f446 --- /dev/null +++ b/kernel/src/driver/input/serio/i8042/i8042_device.rs @@ -0,0 +1,190 @@ +use alloc::{ + string::{String, ToString}, + sync::{Arc, Weak}, +}; + +use crate::{ + driver::base::{ + class::Class, + device::{bus::Bus, driver::Driver, Device, DeviceState, DeviceType, IdTable}, + kobject::{KObjType, KObject, KObjectState, LockedKObjectState}, + kset::KSet, + platform::{platform_device::PlatformDevice, CompatibleTable}, + }, + filesystem::kernfs::KernFSInode, + libs::{ + rwlock::{RwLockReadGuard, RwLockWriteGuard}, + spinlock::SpinLock, + }, +}; + +#[derive(Debug)] +#[cast_to([sync] Device)] +#[cast_to([sync] PlatformDevice)] +pub struct I8042PlatformDevice { + inner: SpinLock, + kobj_state: LockedKObjectState, +} + +impl I8042PlatformDevice { + pub const NAME: &'static str = "i8042"; + pub fn new() -> Self { + return Self { + inner: SpinLock::new(InnerI8042PlatformDevice { + bus: None, + class: None, + driver: None, + kern_inode: None, + parent: None, + kset: None, + kobj_type: None, + device_state: DeviceState::NotInitialized, + pdev_id: 0, + pdev_id_auto: false, + }), + kobj_state: LockedKObjectState::new(None), + }; + } +} + +#[derive(Debug)] +pub struct InnerI8042PlatformDevice { + bus: Option>, + class: Option>, + driver: Option>, + kern_inode: Option>, + parent: Option>, + kset: Option>, + kobj_type: Option<&'static dyn KObjType>, + device_state: DeviceState, + pdev_id: i32, + pdev_id_auto: bool, +} + +impl Device for I8042PlatformDevice { + fn dev_type(&self) -> DeviceType { + DeviceType::Char + } + + fn id_table(&self) -> IdTable { + IdTable::new(self.name(), None) + } + + fn bus(&self) -> Option> { + self.inner.lock().bus.clone() + } + + fn set_bus(&self, bus: Option>) { + self.inner.lock().bus = bus; + } + + fn set_class(&self, class: Option>) { + self.inner.lock().class = class; + } + + fn driver(&self) -> Option> { + self.inner.lock().driver.clone()?.upgrade() + } + + fn set_driver(&self, driver: Option>) { + self.inner.lock().driver = driver; + } + + fn is_dead(&self) -> bool { + false + } + + fn can_match(&self) -> bool { + true + } + + fn set_can_match(&self, _can_match: bool) {} + + fn state_synced(&self) -> bool { + true + } +} + +impl KObject for I8042PlatformDevice { + fn as_any_ref(&self) -> &dyn core::any::Any { + self + } + + fn set_inode(&self, inode: Option>) { + self.inner.lock().kern_inode = inode; + } + + fn inode(&self) -> Option> { + self.inner.lock().kern_inode.clone() + } + + fn parent(&self) -> Option> { + self.inner.lock().parent.clone() + } + + fn set_parent(&self, parent: Option>) { + self.inner.lock().parent = parent; + } + + fn kset(&self) -> Option> { + self.inner.lock().kset.clone() + } + + fn set_kset(&self, kset: Option>) { + self.inner.lock().kset = kset; + } + + fn kobj_type(&self) -> Option<&'static dyn KObjType> { + self.inner.lock().kobj_type + } + + fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) { + self.inner.lock().kobj_type = ktype; + } + + fn name(&self) -> String { + Self::NAME.to_string() + } + + fn set_name(&self, _name: String) { + // do nothing + } + + fn kobj_state(&self) -> RwLockReadGuard { + self.kobj_state.read() + } + + fn kobj_state_mut(&self) -> RwLockWriteGuard { + self.kobj_state.write() + } + + fn set_kobj_state(&self, state: KObjectState) { + *self.kobj_state.write() = state; + } +} + +impl PlatformDevice for I8042PlatformDevice { + fn pdev_name(&self) -> &str { + Self::NAME + } + + fn set_pdev_id(&self, id: i32) { + self.inner.lock().pdev_id = id; + } + + fn set_pdev_id_auto(&self, id_auto: bool) { + self.inner.lock().pdev_id_auto = id_auto; + } + + fn compatible_table(&self) -> CompatibleTable { + todo!() + } + + fn is_initialized(&self) -> bool { + self.inner.lock().device_state == DeviceState::Initialized + } + + fn set_state(&self, set_state: DeviceState) { + self.inner.lock().device_state = set_state; + } +} diff --git a/kernel/src/driver/input/serio/i8042/i8042_driver.rs b/kernel/src/driver/input/serio/i8042/i8042_driver.rs new file mode 100644 index 00000000..8186e1cc --- /dev/null +++ b/kernel/src/driver/input/serio/i8042/i8042_driver.rs @@ -0,0 +1,190 @@ +use alloc::{ + string::{String, ToString}, + sync::{Arc, Weak}, + vec::Vec, +}; +use system_error::SystemError; + +use crate::{ + driver::base::{ + device::{bus::Bus, driver::Driver, Device, IdTable}, + kobject::{KObjType, KObject, KObjectState, LockedKObjectState}, + kset::KSet, + platform::{platform_device::PlatformDevice, platform_driver::PlatformDriver}, + }, + filesystem::kernfs::KernFSInode, + libs::{ + rwlock::{RwLockReadGuard, RwLockWriteGuard}, + spinlock::SpinLock, + }, +}; + +use super::{i8042_device::I8042PlatformDevice, i8042_setup_aux}; + +#[derive(Debug)] +#[cast_to([sync] PlatformDriver)] +pub struct I8042Driver { + inner: SpinLock, + kobj_state: LockedKObjectState, +} + +impl I8042Driver { + pub const NAME: &'static str = "i8042"; + pub fn new() -> Arc { + let r = Arc::new(Self { + inner: SpinLock::new(InnerI8042Driver { + ktype: None, + kset: None, + parent: None, + kernfs_inode: None, + devices: Vec::new(), + bus: None, + self_ref: Weak::new(), + }), + kobj_state: LockedKObjectState::new(None), + }); + + r.inner.lock().self_ref = Arc::downgrade(&r); + + return r; + } +} + +#[derive(Debug)] +pub struct InnerI8042Driver { + ktype: Option<&'static dyn KObjType>, + kset: Option>, + parent: Option>, + kernfs_inode: Option>, + devices: Vec>, + bus: Option>, + + self_ref: Weak, +} + +impl PlatformDriver for I8042Driver { + // TODO: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/i8042.c#1542 + fn probe(&self, device: &Arc) -> Result<(), SystemError> { + let device = device + .clone() + .arc_any() + .downcast::() + .map_err(|_| SystemError::EINVAL)?; + + device.set_driver(Some(self.inner.lock().self_ref.clone())); + + i8042_setup_aux()?; + return Ok(()); + } + + // TODO: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/i8042.c#1587 + fn remove(&self, _device: &Arc) -> Result<(), SystemError> { + todo!() + } + + // TODO: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/i8042.c#1322 + fn shutdown(&self, _device: &Arc) -> Result<(), SystemError> { + todo!() + } + + fn suspend(&self, _device: &Arc) -> Result<(), SystemError> { + // do nothing + return Ok(()); + } + + fn resume(&self, _device: &Arc) -> Result<(), SystemError> { + // do nothing + return Ok(()); + } +} + +impl Driver for I8042Driver { + fn id_table(&self) -> Option { + Some(IdTable::new(I8042PlatformDevice::NAME.to_string(), None)) + } + + fn devices(&self) -> Vec> { + self.inner.lock().devices.clone() + } + + fn add_device(&self, device: Arc) { + let mut guard = self.inner.lock(); + // check if the device is already in the list + if guard.devices.iter().any(|dev| Arc::ptr_eq(dev, &device)) { + return; + } + + guard.devices.push(device); + } + + fn delete_device(&self, device: &Arc) { + let mut guard = self.inner.lock(); + guard.devices.retain(|dev| !Arc::ptr_eq(dev, device)); + } + + fn set_bus(&self, bus: Option>) { + self.inner.lock().bus = bus; + } + + fn bus(&self) -> Option> { + self.inner.lock().bus.clone() + } +} + +impl KObject for I8042Driver { + fn as_any_ref(&self) -> &dyn core::any::Any { + self + } + + fn set_inode(&self, inode: Option>) { + self.inner.lock().kernfs_inode = inode; + } + + fn inode(&self) -> Option> { + self.inner.lock().kernfs_inode.clone() + } + + fn parent(&self) -> Option> { + self.inner.lock().parent.clone() + } + + fn set_parent(&self, parent: Option>) { + self.inner.lock().parent = parent; + } + + fn kset(&self) -> Option> { + self.inner.lock().kset.clone() + } + + fn set_kset(&self, kset: Option>) { + self.inner.lock().kset = kset; + } + + fn kobj_type(&self) -> Option<&'static dyn KObjType> { + self.inner.lock().ktype + } + + fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) { + self.inner.lock().ktype = ktype; + } + + fn name(&self) -> String { + Self::NAME.to_string() + } + + fn set_name(&self, _name: String) { + // do nothing + } + + fn kobj_state(&self) -> RwLockReadGuard { + self.kobj_state.read() + } + + fn kobj_state_mut(&self) -> RwLockWriteGuard { + self.kobj_state.write() + } + + fn set_kobj_state(&self, state: KObjectState) { + *self.kobj_state.write() = state; + } +} diff --git a/kernel/src/driver/input/serio/i8042/i8042_ports.rs b/kernel/src/driver/input/serio/i8042/i8042_ports.rs new file mode 100644 index 00000000..5823f336 --- /dev/null +++ b/kernel/src/driver/input/serio/i8042/i8042_ports.rs @@ -0,0 +1,185 @@ +use alloc::{ + string::{String, ToString}, + sync::{Arc, Weak}, +}; +use system_error::SystemError; + +use crate::{ + driver::{ + base::{ + class::Class, + device::{bus::Bus, driver::Driver, Device, DeviceType, IdTable}, + kobject::{KObjType, KObject, KObjectState, LockedKObjectState}, + kset::KSet, + }, + input::serio::serio_device::SerioDevice, + }, + filesystem::kernfs::KernFSInode, + libs::{ + rwlock::{RwLockReadGuard, RwLockWriteGuard}, + spinlock::SpinLock, + }, +}; + +use super::{i8042_start, i8042_stop}; + +#[derive(Debug)] +#[cast_to([sync] Device)] +pub struct I8042AuxPort { + inner: SpinLock, + kobj_state: LockedKObjectState, +} + +#[derive(Debug)] +pub struct InnerI8042AuxPort { + bus: Option>, + class: Option>, + driver: Option>, + kern_inode: Option>, + parent: Option>, + kset: Option>, + kobj_type: Option<&'static dyn KObjType>, +} + +impl I8042AuxPort { + pub const NAME: &'static str = "serio1"; + pub fn new() -> Self { + return Self { + inner: SpinLock::new(InnerI8042AuxPort { + bus: None, + class: None, + driver: None, + kern_inode: None, + parent: None, + kset: None, + kobj_type: None, + }), + kobj_state: LockedKObjectState::new(None), + }; + } +} + +impl Device for I8042AuxPort { + fn dev_type(&self) -> DeviceType { + DeviceType::Char + } + + fn id_table(&self) -> IdTable { + IdTable::new(self.name(), None) + } + + fn bus(&self) -> Option> { + self.inner.lock().bus.clone() + } + + fn set_bus(&self, bus: Option>) { + self.inner.lock().bus = bus; + } + + fn set_class(&self, class: Option>) { + self.inner.lock().class = class; + } + + fn driver(&self) -> Option> { + self.inner.lock().driver.clone()?.upgrade() + } + + fn set_driver(&self, driver: Option>) { + self.inner.lock().driver = driver; + } + + fn is_dead(&self) -> bool { + false + } + + fn can_match(&self) -> bool { + true + } + + fn set_can_match(&self, _can_match: bool) {} + + fn state_synced(&self) -> bool { + true + } +} + +impl KObject for I8042AuxPort { + fn as_any_ref(&self) -> &dyn core::any::Any { + self + } + + fn set_inode(&self, inode: Option>) { + self.inner.lock().kern_inode = inode; + } + + fn inode(&self) -> Option> { + self.inner.lock().kern_inode.clone() + } + + fn parent(&self) -> Option> { + self.inner.lock().parent.clone() + } + + fn set_parent(&self, parent: Option>) { + self.inner.lock().parent = parent; + } + + fn kset(&self) -> Option> { + self.inner.lock().kset.clone() + } + + fn set_kset(&self, kset: Option>) { + self.inner.lock().kset = kset; + } + + fn kobj_type(&self) -> Option<&'static dyn KObjType> { + self.inner.lock().kobj_type + } + + fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) { + self.inner.lock().kobj_type = ktype; + } + + fn name(&self) -> String { + Self::NAME.to_string() + } + + fn set_name(&self, _name: String) { + // do nothing + } + + fn kobj_state(&self) -> RwLockReadGuard { + self.kobj_state.read() + } + + fn kobj_state_mut(&self) -> RwLockWriteGuard { + self.kobj_state.write() + } + + fn set_kobj_state(&self, state: KObjectState) { + *self.kobj_state.write() = state; + } +} + +impl SerioDevice for I8042AuxPort { + // TODO: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/i8042.c#387 + fn write(&self, _device: &Arc, _data: u8) -> Result<(), SystemError> { + todo!() + } + + fn open(&self, _device: &Arc) -> Result<(), SystemError> { + Ok(()) + } + + fn close(&self, _device: &Arc) -> Result<(), SystemError> { + Ok(()) + } + + fn start(&self, device: &Arc) -> Result<(), SystemError> { + i8042_start(device) + } + + fn stop(&self, device: &Arc) -> Result<(), SystemError> { + i8042_stop(device) + } +} diff --git a/kernel/src/driver/input/serio/i8042/mod.rs b/kernel/src/driver/input/serio/i8042/mod.rs new file mode 100644 index 00000000..82efffef --- /dev/null +++ b/kernel/src/driver/input/serio/i8042/mod.rs @@ -0,0 +1,75 @@ +use alloc::sync::Arc; +use system_error::SystemError; +use unified_init::macros::unified_init; + +use crate::{ + driver::{ + base::{ + device::{device_manager, Device}, + kobject::KObject, + platform::{ + platform_device::{platform_device_manager, PlatformDevice}, + platform_driver::{platform_driver_manager, PlatformDriver}, + }, + }, + input::ps2_mouse::ps_mouse_device::rs_ps2_mouse_device_init, + }, + init::initcall::INITCALL_DEVICE, +}; + +use self::{ + i8042_device::I8042PlatformDevice, i8042_driver::I8042Driver, i8042_ports::I8042AuxPort, +}; + +use super::serio_device::{serio_device_manager, SerioDevice}; + +pub mod i8042_device; +pub mod i8042_driver; +pub mod i8042_ports; + +static mut I8042_PLATFORM_DEVICE: Option> = None; + +pub fn i8042_platform_device() -> Arc { + unsafe { I8042_PLATFORM_DEVICE.clone().unwrap() } +} + +// TODO: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/i8042.c#1612 +#[unified_init(INITCALL_DEVICE)] +pub fn i8042_init() -> Result<(), SystemError> { + kdebug!("i8042 initializing..."); + let i8042_device = Arc::new(I8042PlatformDevice::new()); + device_manager().device_default_initialize(&(i8042_device.clone() as Arc)); + platform_device_manager().device_add(i8042_device.clone() as Arc)?; + unsafe { + I8042_PLATFORM_DEVICE = Some(i8042_device); + } + + let i8042_driver = I8042Driver::new(); + platform_driver_manager().register(i8042_driver.clone() as Arc)?; + Ok(()) +} + +// TODO: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/i8042.c#441 +pub fn i8042_start(_serio: &Arc) -> Result<(), SystemError> { + todo!() +} + +// TODO: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/i8042.c#471 +pub fn i8042_stop(_serio: &Arc) -> Result<(), SystemError> { + todo!() +} + +/// # 函数的功能 +/// 创建i8042 Aux设备 +/// +/// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/i8042.c#i8042_setup_aux +pub fn i8042_setup_aux() -> Result<(), SystemError> { + let aux_port = Arc::new(I8042AuxPort::new()); + aux_port.set_parent(Some(Arc::downgrade( + &(i8042_platform_device() as Arc), + ))); + serio_device_manager().register_port(aux_port.clone() as Arc)?; + + rs_ps2_mouse_device_init(aux_port.clone() as Arc)?; + Ok(()) +} diff --git a/kernel/src/driver/input/serio/mod.rs b/kernel/src/driver/input/serio/mod.rs index fcea9a7c..c8bdc158 100644 --- a/kernel/src/driver/input/serio/mod.rs +++ b/kernel/src/driver/input/serio/mod.rs @@ -5,6 +5,7 @@ use crate::driver::base::device::bus::{bus_register, Bus}; use self::subsys::SerioBus; +pub mod i8042; pub mod serio_device; pub mod serio_driver; pub mod subsys;