use alloc::{ string::ToString, sync::{Arc, Weak}, vec::Vec, }; use system_error::SystemError; use unified_init::macros::unified_init; use crate::{ arch::{io::PortIOArch, CurrentPortIOArch}, driver::{ base::{ device::{bus::Bus, driver::Driver, Device, DeviceId, IdTable}, kobject::{KObjType, KObject, KObjectState, LockedKObjectState}, kset::KSet, }, input::serio::{ serio_device::SerioDevice, serio_driver::{serio_driver_manager, SerioDriver}, }, }, exception::{ irqdata::IrqHandlerData, irqdesc::{IrqHandleFlags, IrqHandler, IrqReturn}, manage::irq_manager, IrqNumber, }, filesystem::kernfs::KernFSInode, init::initcall::INITCALL_DEVICE, libs::{ rwlock::{RwLockReadGuard, RwLockWriteGuard}, spinlock::SpinLock, }, }; use super::ps_mouse_device::{ps2_mouse_device, Ps2MouseDevice}; const PS2_MOUSE_IRQ_NUM: IrqNumber = IrqNumber::new(0x2c); #[no_mangle] unsafe extern "C" fn ps2_mouse_driver_interrupt() {} #[derive(Debug)] struct Ps2MouseIrqHandler; impl IrqHandler for Ps2MouseIrqHandler { fn handle( &self, _irq: IrqNumber, _static_data: Option<&dyn IrqHandlerData>, _dev_id: Option>, ) -> Result { if let Some(psmouse_device) = ps2_mouse_device() { return Ok(ps2_mouse_driver() .interrupt(&(psmouse_device as Arc), 0, 0) .map(|_| IrqReturn::Handled) .unwrap_or_else(|_| IrqReturn::NotHandled)); } else { unsafe { CurrentPortIOArch::in8(0x60) }; return Ok(IrqReturn::NotHandled); } } } static mut PS2_MOUSE_DRIVER: Option> = None; #[allow(dead_code)] pub fn ps2_mouse_driver() -> Arc { unsafe { PS2_MOUSE_DRIVER.clone().unwrap() } } #[derive(Debug)] #[cast_to([sync] Driver)] #[cast_to([sync] SerioDriver)] pub struct Ps2MouseDriver { inner: SpinLock, kobj_state: LockedKObjectState, } impl Ps2MouseDriver { pub const NAME: &'static str = "psmouse"; pub fn new() -> Arc { let r = Arc::new(Ps2MouseDriver { inner: SpinLock::new(InnerPs2MouseDriver { 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; } #[allow(dead_code)] pub fn process_packet(&self) { let guard = self.inner.lock(); if guard.devices.is_empty() { return; } let device: Option<&Ps2MouseDevice> = guard.devices[0] .as_any_ref() .downcast_ref::(); let _ = device.unwrap().process_packet(); } } #[derive(Debug)] pub struct InnerPs2MouseDriver { ktype: Option<&'static dyn KObjType>, kset: Option>, parent: Option>, kernfs_inode: Option>, devices: Vec>, bus: Option>, self_ref: Weak, } impl Driver for Ps2MouseDriver { fn id_table(&self) -> Option { Some(IdTable::new("psmouse".to_string(), None)) } fn devices(&self) -> alloc::vec::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 Ps2MouseDriver { 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) -> alloc::string::String { Self::NAME.to_string() } fn set_name(&self, _name: alloc::string::String) {} 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 SerioDriver for Ps2MouseDriver { fn write_wakeup( &self, _device: &Arc, ) -> Result<(), system_error::SystemError> { todo!() } fn interrupt( &self, device: &Arc, _char: u8, _int: u8, ) -> Result<(), system_error::SystemError> { let device = device .clone() .arc_any() .downcast::() .map_err(|_| SystemError::EINVAL)?; device.process_packet()?; Ok(()) } fn connect(&self, device: &Arc) -> Result<(), system_error::SystemError> { let device = device .clone() .arc_any() .downcast::() .map_err(|_| SystemError::EINVAL)?; device.set_driver(Some(self.inner.lock_irqsave().self_ref.clone())); device.init()?; irq_manager().request_irq( PS2_MOUSE_IRQ_NUM, "psmouse".to_string(), &Ps2MouseIrqHandler, IrqHandleFlags::IRQF_SHARED | IrqHandleFlags::IRQF_TRIGGER_RISING, Some(DeviceId::new(Some(Self::NAME), None).unwrap()), )?; return Ok(()); } fn reconnect(&self, _device: &Arc) -> Result<(), system_error::SystemError> { todo!() } fn fast_reconnect( &self, _device: &Arc, ) -> Result<(), system_error::SystemError> { todo!() } fn disconnect(&self, _device: &Arc) -> Result<(), system_error::SystemError> { todo!() } fn cleanup(&self, _device: &Arc) -> Result<(), system_error::SystemError> { todo!() } } #[unified_init(INITCALL_DEVICE)] fn ps2_mouse_driver_init() -> Result<(), SystemError> { kdebug!("Ps2_mouse_drive initializing..."); let driver = Ps2MouseDriver::new(); serio_driver_manager().register(driver.clone())?; unsafe { PS2_MOUSE_DRIVER = Some(driver) }; kdebug!("Ps2_mouse_drive initialized!"); return Ok(()); }