diff --git a/kernel/src/driver/input/mod.rs b/kernel/src/driver/input/mod.rs index d3a1a545..bb48b065 100644 --- a/kernel/src/driver/input/mod.rs +++ b/kernel/src/driver/input/mod.rs @@ -1,2 +1,3 @@ pub mod ps2_dev; +pub mod ps2_mouse; pub mod serio; diff --git a/kernel/src/driver/input/ps2_mouse/mod.rs b/kernel/src/driver/input/ps2_mouse/mod.rs new file mode 100644 index 00000000..9c8d0160 --- /dev/null +++ b/kernel/src/driver/input/ps2_mouse/mod.rs @@ -0,0 +1,2 @@ +pub mod ps_mouse_device; +pub mod ps_mouse_driver; diff --git a/kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs b/kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs new file mode 100644 index 00000000..3693583f --- /dev/null +++ b/kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs @@ -0,0 +1,672 @@ +use core::hint::spin_loop; + +use alloc::{ + string::ToString, + sync::{Arc, Weak}, +}; +use kdepends::ringbuffer::{AllocRingBuffer, RingBuffer}; +use system_error::SystemError; +use unified_init::macros::unified_init; + +use crate::{ + arch::{io::PortIOArch, CurrentIrqArch, CurrentPortIOArch}, + driver::{ + base::{ + class::Class, + device::{ + bus::Bus, device_manager, device_number::DeviceNumber, driver::Driver, Device, + DeviceType, IdTable, + }, + kobject::{KObjType, KObject, KObjectState, LockedKObjectState}, + kset::KSet, + }, + input::serio::serio_device::{serio_device_manager, SerioDevice}, + }, + exception::InterruptArch, + filesystem::{ + devfs::{devfs_register, DevFS, DeviceINode}, + kernfs::KernFSInode, + vfs::{ + core::generate_inode_id, syscall::ModeType, FilePrivateData, FileSystem, FileType, + IndexNode, Metadata, + }, + }, + init::initcall::INITCALL_DEVICE, + libs::{ + rwlock::{RwLockReadGuard, RwLockWriteGuard}, + spinlock::SpinLock, + }, + time::TimeSpec, +}; + +static mut PS2_MOUSE_DEVICE: Option> = None; + +pub fn ps2_mouse_device() -> Option> { + unsafe { PS2_MOUSE_DEVICE.clone() } +} + +const ADDRESS_PORT_ADDRESS: u16 = 0x64; +const DATA_PORT_ADDRESS: u16 = 0x60; + +const KEYBOARD_COMMAND_ENABLE_PS2_MOUSE_PORT: u8 = 0xa8; +const KEYBOARD_COMMAND_SEND_TO_PS2_MOUSE: u8 = 0xd4; + +const MOUSE_BUFFER_CAPACITY: usize = 15; + +bitflags! { + /// Represents the flags currently set for the mouse. + #[derive(Default)] + pub struct MouseFlags: u8 { + /// Whether or not the left mouse button is pressed. + const LEFT_BUTTON = 0b0000_0001; + + /// Whether or not the right mouse button is pressed. + const RIGHT_BUTTON = 0b0000_0010; + + /// Whether or not the middle mouse button is pressed. + const MIDDLE_BUTTON = 0b0000_0100; + + /// Whether or not the packet is valid or not. + const ALWAYS_ONE = 0b0000_1000; + + /// Whether or not the x delta is negative. + const X_SIGN = 0b0001_0000; + + /// Whether or not the y delta is negative. + const Y_SIGN = 0b0010_0000; + + /// Whether or not the x delta overflowed. + const X_OVERFLOW = 0b0100_0000; + + /// Whether or not the y delta overflowed. + const Y_OVERFLOW = 0b1000_0000; + } +} + +#[derive(Debug)] +enum PsMouseCommand { + SampleRate(u8), + EnablePacketStreaming, + // SetDefaults = 0xF6, + InitKeyboard, + GetMouseId, + SetSampleRate, +} + +impl Into for PsMouseCommand { + fn into(self) -> u8 { + match self { + Self::SampleRate(x) => x, + Self::EnablePacketStreaming => 0xf4, + Self::InitKeyboard => 0x47, + Self::GetMouseId => 0xf2, + Self::SetSampleRate => 0xf3, + } + } +} + +#[derive(Debug)] +pub struct MouseState { + flags: MouseFlags, + x: i16, + y: i16, +} + +#[allow(dead_code)] +impl MouseState { + /// Returns a new `MouseState`. + pub const fn new() -> MouseState { + MouseState { + flags: MouseFlags::empty(), + x: 0, + y: 0, + } + } + + /// Returns true if the left mouse button is currently down. + pub fn left_button_down(&self) -> bool { + self.flags.contains(MouseFlags::LEFT_BUTTON) + } + + /// Returns true if the left mouse button is currently up. + pub fn left_button_up(&self) -> bool { + !self.flags.contains(MouseFlags::LEFT_BUTTON) + } + + /// Returns true if the right mouse button is currently down. + pub fn right_button_down(&self) -> bool { + self.flags.contains(MouseFlags::RIGHT_BUTTON) + } + + /// Returns true if the right mouse button is currently up. + pub fn right_button_up(&self) -> bool { + !self.flags.contains(MouseFlags::RIGHT_BUTTON) + } + + /// Returns true if the x axis has moved. + pub fn x_moved(&self) -> bool { + self.x != 0 + } + + /// Returns true if the y axis has moved. + pub fn y_moved(&self) -> bool { + self.y != 0 + } + + /// Returns true if the x or y axis has moved. + pub fn moved(&self) -> bool { + self.x_moved() || self.y_moved() + } + + /// Returns the x delta of the mouse state. + pub fn get_x(&self) -> i16 { + self.x + } + + /// Returns the y delta of the mouse state. + pub fn get_y(&self) -> i16 { + self.y + } +} + +#[derive(Debug)] +#[cast_to([sync] Device, SerioDevice)] +pub struct Ps2MouseDevice { + inner: SpinLock, + kobj_state: LockedKObjectState, +} + +impl Ps2MouseDevice { + pub const NAME: &'static str = "psmouse"; + pub fn new() -> Self { + let r = Self { + inner: SpinLock::new(InnerPs2MouseDevice { + bus: None, + class: None, + driver: None, + kern_inode: None, + parent: None, + kset: None, + kobj_type: None, + current_packet: 0, + current_state: MouseState::new(), + buf: AllocRingBuffer::new(MOUSE_BUFFER_CAPACITY), + devfs_metadata: Metadata { + dev_id: 1, + inode_id: generate_inode_id(), + size: 4096, + blk_size: 0, + blocks: 0, + atime: TimeSpec::default(), + mtime: TimeSpec::default(), + ctime: TimeSpec::default(), + file_type: FileType::CharDevice, // 文件夹,block设备,char设备 + mode: ModeType::from_bits_truncate(0o644), + nlinks: 1, + uid: 0, + gid: 0, + raw_dev: DeviceNumber::default(), // 这里用来作为device number + }, + device_inode_fs: None, + }), + kobj_state: LockedKObjectState::new(None), + }; + return r; + } + + pub fn init(&self) -> Result<(), SystemError> { + let _irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; + + self.write_control_port(KEYBOARD_COMMAND_ENABLE_PS2_MOUSE_PORT)?; + for _i in 0..1000 { + for _j in 0..1000 { + spin_loop(); + } + } + self.read_data_port().ok(); + + self.send_command_to_ps2mouse(PsMouseCommand::EnablePacketStreaming) + .map_err(|e| { + kerror!("ps2 mouse init error: {:?}", e); + e + })?; + self.read_data_port().ok(); + for _i in 0..1000 { + for _j in 0..1000 { + spin_loop(); + } + } + + // self.send_command_to_ps2mouse(PsMouseCommand::InitKeyboard)?; + self.do_send_command(DATA_PORT_ADDRESS as u8, PsMouseCommand::InitKeyboard.into())?; + self.read_data_port().ok(); + for _i in 0..1000 { + for _j in 0..1000 { + spin_loop(); + } + } + + self.set_sample_rate(20)?; + // self.get_mouse_id()?; + Ok(()) + } + + #[allow(dead_code)] + pub fn get_mouse_id(&self) -> Result<(), SystemError> { + self.send_command_to_ps2mouse(PsMouseCommand::GetMouseId)?; + let _mouse_id = self.read_data_port()?; + Ok(()) + } + + /// 设置鼠标采样率 + /// + /// `hz` 合法值为 10,20,40,60,80,100,200 + pub fn set_sample_rate(&self, hz: u8) -> Result<(), SystemError> { + const SAMPLE_RATE: [u8; 7] = [10, 20, 40, 60, 80, 100, 200]; + if !SAMPLE_RATE.contains(&hz) { + return Err(SystemError::EINVAL); + } + + self.send_command_to_ps2mouse(PsMouseCommand::SetSampleRate)?; + self.read_data_port().ok(); + for _i in 0..1000 { + for _j in 0..1000 { + spin_loop(); + } + } + + self.send_command_to_ps2mouse(PsMouseCommand::SampleRate(hz))?; + for _i in 0..1000 { + for _j in 0..1000 { + spin_loop(); + } + } + self.read_data_port().ok(); + Ok(()) + } + + /// # 函数的功能 + /// 鼠标设备处理数据包 + pub fn process_packet(&self) -> Result<(), SystemError> { + let packet = self.read_data_port()?; + let mut guard = self.inner.lock(); + guard.buf.push(packet); // 更新缓冲区 + match guard.current_packet { + 0 => { + let flags: MouseFlags = MouseFlags::from_bits_truncate(packet); + if !flags.contains(MouseFlags::ALWAYS_ONE) { + return Ok(()); + } + guard.current_state.flags = flags; + } + 1 => { + let flags = guard.current_state.flags.clone(); + if !flags.contains(MouseFlags::X_OVERFLOW) { + guard.current_state.x = self.get_x_movement(packet, flags); + } + } + 2 => { + let flags = guard.current_state.flags.clone(); + if !flags.contains(MouseFlags::Y_OVERFLOW) { + guard.current_state.y = self.get_y_movement(packet, flags); + } + + // kdebug!( + // "Ps2MouseDevice packet : flags:{}, x:{}, y:{}\n", + // guard.current_state.flags.bits, + // guard.current_state.x, + // guard.current_state.y + // ) + } + _ => unreachable!(), + } + guard.current_packet = (guard.current_packet + 1) % 3; + Ok(()) + } + + fn get_x_movement(&self, packet: u8, flags: MouseFlags) -> i16 { + if flags.contains(MouseFlags::X_SIGN) { + return self.sign_extend(packet); + } else { + return packet as i16; + } + } + + fn get_y_movement(&self, packet: u8, flags: MouseFlags) -> i16 { + if flags.contains(MouseFlags::Y_SIGN) { + return self.sign_extend(packet); + } else { + return packet as i16; + } + } + + fn sign_extend(&self, packet: u8) -> i16 { + ((packet as u16) | 0xFF00) as i16 + } + + fn read_data_port(&self) -> Result { + self.wait_for_write()?; + let cmd = unsafe { CurrentPortIOArch::in8(ADDRESS_PORT_ADDRESS) }; + if (cmd & 0x21) == 0x21 { + let data = unsafe { CurrentPortIOArch::in8(DATA_PORT_ADDRESS) }; + return Ok(data); + } else { + return Err(SystemError::ENODATA); + } + } + + #[inline(never)] + fn send_command_to_ps2mouse(&self, command: PsMouseCommand) -> Result<(), SystemError> { + self.do_send_command(KEYBOARD_COMMAND_SEND_TO_PS2_MOUSE, command.into())?; + Ok(()) + } + + #[inline(never)] + fn do_send_command(&self, ctrl: u8, command: u8) -> Result<(), SystemError> { + self.write_control_port(ctrl)?; + self.write_data_port(command)?; + return Ok(()); + } + + fn write_data_port(&self, data: u8) -> Result<(), SystemError> { + self.wait_for_write()?; + unsafe { + CurrentPortIOArch::out8(DATA_PORT_ADDRESS, data); + } + Ok(()) + } + + fn write_control_port(&self, command: u8) -> Result<(), SystemError> { + self.wait_for_write()?; + unsafe { + CurrentPortIOArch::out8(ADDRESS_PORT_ADDRESS, command); + } + Ok(()) + } + + fn wait_for_read(&self) -> Result<(), SystemError> { + let timeout = 100_000; + for _ in 0..timeout { + let value = unsafe { CurrentPortIOArch::in8(ADDRESS_PORT_ADDRESS) }; + if (value & 0x1) == 0x1 { + return Ok(()); + } + } + Err(SystemError::ETIMEDOUT) + } + + fn wait_for_write(&self) -> Result<(), SystemError> { + let timeout = 100_000; + for _ in 0..timeout { + let value = unsafe { CurrentPortIOArch::in8(ADDRESS_PORT_ADDRESS) }; + if (value & 0x2) == 0 { + return Ok(()); + } + } + Err(SystemError::ETIMEDOUT) + } +} + +#[derive(Debug)] +struct InnerPs2MouseDevice { + bus: Option>, + class: Option>, + driver: Option>, + kern_inode: Option>, + parent: Option>, + kset: Option>, + kobj_type: Option<&'static dyn KObjType>, + + /// 鼠标数据 + current_state: MouseState, + current_packet: u8, + /// 鼠标数据环形缓冲区 + buf: AllocRingBuffer, + + /// device inode要求的字段 + device_inode_fs: Option>, + devfs_metadata: Metadata, +} + +impl Device for Ps2MouseDevice { + fn is_dead(&self) -> bool { + false + } + + fn dev_type(&self) -> DeviceType { + DeviceType::Char + } + + fn id_table(&self) -> IdTable { + IdTable::new(self.name().to_string(), None) + } + + fn set_bus(&self, bus: Option>) { + self.inner.lock_irqsave().bus = bus; + } + + fn set_class(&self, class: Option>) { + self.inner.lock_irqsave().class = class; + } + + fn driver(&self) -> Option> { + self.inner.lock_irqsave().driver.clone()?.upgrade() + } + + fn set_driver(&self, driver: Option>) { + self.inner.lock_irqsave().driver = driver; + } + + fn can_match(&self) -> bool { + true + } + + fn set_can_match(&self, _can_match: bool) {} + + fn state_synced(&self) -> bool { + true + } + + fn bus(&self) -> Option> { + self.inner.lock_irqsave().bus.clone() + } + + fn class(&self) -> Option> { + self.inner.lock_irqsave().class.clone() + } +} + +impl SerioDevice for Ps2MouseDevice { + fn write( + &self, + _device: &alloc::sync::Arc, + _data: u8, + ) -> Result<(), system_error::SystemError> { + todo!() + } + + fn open( + &self, + _device: &alloc::sync::Arc, + ) -> Result<(), system_error::SystemError> { + todo!() + } + + fn close( + &self, + _device: &alloc::sync::Arc, + ) -> Result<(), system_error::SystemError> { + todo!() + } + + fn start( + &self, + _device: &alloc::sync::Arc, + ) -> Result<(), system_error::SystemError> { + todo!() + } + + fn stop( + &self, + _device: &alloc::sync::Arc, + ) -> Result<(), system_error::SystemError> { + todo!() + } +} + +impl KObject for Ps2MouseDevice { + fn as_any_ref(&self) -> &dyn core::any::Any { + self + } + + fn set_inode(&self, inode: Option>) { + self.inner.lock_irqsave().kern_inode = inode; + } + + fn inode(&self) -> Option> { + self.inner.lock_irqsave().kern_inode.clone() + } + + fn parent(&self) -> Option> { + self.inner.lock_irqsave().parent.clone() + } + + fn set_parent(&self, parent: Option>) { + self.inner.lock_irqsave().parent = parent + } + + fn kset(&self) -> Option> { + self.inner.lock_irqsave().kset.clone() + } + + fn set_kset(&self, kset: Option>) { + self.inner.lock_irqsave().kset = kset; + } + + fn kobj_type(&self) -> Option<&'static dyn KObjType> { + self.inner.lock_irqsave().kobj_type.clone() + } + + fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) { + self.inner.lock_irqsave().kobj_type = 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 DeviceINode for Ps2MouseDevice { + fn set_fs(&self, fs: Weak) { + self.inner.lock_irqsave().device_inode_fs = Some(fs); + } +} + +impl IndexNode for Ps2MouseDevice { + fn open( + &self, + _data: &mut FilePrivateData, + _mode: &crate::filesystem::vfs::file::FileMode, + ) -> Result<(), SystemError> { + let mut guard = self.inner.lock_irqsave(); + guard.buf.clear(); + Ok(()) + } + + fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> { + let mut guard = self.inner.lock_irqsave(); + guard.buf.clear(); + Ok(()) + } + + fn read_at( + &self, + _offset: usize, + _len: usize, + buf: &mut [u8], + _data: &mut FilePrivateData, + ) -> Result { + let mut guard = self.inner.lock_irqsave(); + + if guard.buf.len() >= 3 { + for i in 0..3 { + buf[i] = guard.buf.dequeue().unwrap(); + } + return Ok(3); + } else { + return Ok(0); + } + } + + fn write_at( + &self, + _offset: usize, + _len: usize, + _buf: &[u8], + _data: &mut FilePrivateData, + ) -> Result { + return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + } + + fn fs(&self) -> Arc { + self.inner + .lock_irqsave() + .device_inode_fs + .as_ref() + .unwrap() + .upgrade() + .unwrap() + } + + fn as_any_ref(&self) -> &dyn core::any::Any { + self + } + + fn list(&self) -> Result, SystemError> { + todo!() + } + + fn metadata(&self) -> Result { + Ok(self.inner.lock_irqsave().devfs_metadata.clone()) + } + + fn resize(&self, _len: usize) -> Result<(), SystemError> { + Ok(()) + } +} + +#[unified_init(INITCALL_DEVICE)] +fn rs_ps2_mouse_device_int() -> 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())?; + + devfs_register(&psmouse.name(), psmouse.clone()).map_err(|e| { + kerror!( + "register psmouse device '{}' to devfs failed: {:?}", + psmouse.name(), + e + ); + device_manager().remove(&(psmouse.clone() as Arc)); + e + })?; + + unsafe { PS2_MOUSE_DEVICE = Some(psmouse) }; + return Ok(()); +} diff --git a/kernel/src/driver/input/ps2_mouse/ps_mouse_driver.rs b/kernel/src/driver/input/ps2_mouse/ps_mouse_driver.rs new file mode 100644 index 00000000..5138c62c --- /dev/null +++ b/kernel/src/driver/input/ps2_mouse/ps_mouse_driver.rs @@ -0,0 +1,260 @@ +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, IdTable}, + kobject::{KObjType, KObject, KObjectState, LockedKObjectState}, + kset::KSet, + }, + input::serio::{ + serio_device::SerioDevice, + serio_driver::{serio_driver_manager, SerioDriver}, + }, + }, + filesystem::kernfs::KernFSInode, + init::initcall::INITCALL_DEVICE, + libs::{ + rwlock::{RwLockReadGuard, RwLockWriteGuard}, + spinlock::SpinLock, + }, +}; + +use super::ps_mouse_device::{ps2_mouse_device, Ps2MouseDevice}; + +extern "C" { + fn c_ps2_mouse_init(); +} + +#[no_mangle] +unsafe extern "C" fn ps2_mouse_driver_interrupt() { + if let Some(psmouse_device) = ps2_mouse_device() { + ps2_mouse_driver() + .interrupt(&(psmouse_device as Arc), 0, 0) + .ok(); + } else { + unsafe { CurrentPortIOArch::in8(0x60) }; + } +} + +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()?; + unsafe { c_ps2_mouse_init() }; + 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 initing..."); + let driver = Ps2MouseDriver::new(); + serio_driver_manager().register(driver.clone())?; + unsafe { PS2_MOUSE_DRIVER = Some(driver) }; + return Ok(()); +} diff --git a/kernel/src/driver/input/serio/mod.rs b/kernel/src/driver/input/serio/mod.rs index 2c6186b7..fcea9a7c 100644 --- a/kernel/src/driver/input/serio/mod.rs +++ b/kernel/src/driver/input/serio/mod.rs @@ -18,8 +18,7 @@ pub fn serio_bus() -> Arc { } /// # 函数的功能 -/// -/// 初始化serio bus +/// 初始化Serio总线 /// /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/serio.c#1024 pub fn serio_bus_init() -> Result<(), SystemError> { diff --git a/kernel/src/driver/input/serio/serio_device.rs b/kernel/src/driver/input/serio/serio_device.rs index 89f2f771..cb610ab2 100644 --- a/kernel/src/driver/input/serio/serio_device.rs +++ b/kernel/src/driver/input/serio/serio_device.rs @@ -1,7 +1,7 @@ use alloc::sync::Arc; use system_error::SystemError; -use crate::driver::base::device::{bus::Bus, Device}; +use crate::driver::base::device::{bus::Bus, device_manager, Device}; use super::serio_bus; @@ -31,7 +31,6 @@ pub trait SerioDevice: Device { fn stop(&self, device: &Arc) -> Result<(), SystemError>; } -#[allow(dead_code)] #[inline(always)] pub fn serio_device_manager() -> &'static SerioDeviceManager { &SerioDeviceManager @@ -39,7 +38,6 @@ pub fn serio_device_manager() -> &'static SerioDeviceManager { pub struct SerioDeviceManager; -#[allow(dead_code)] impl SerioDeviceManager { /// # 函数功能 /// 注册Serio设备 @@ -65,6 +63,7 @@ impl SerioDeviceManager { /// 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)))); + device_manager().add_device(device.clone() as Arc)?; Ok(()) } } diff --git a/kernel/src/driver/input/serio/serio_driver.rs b/kernel/src/driver/input/serio/serio_driver.rs index 8c0f9b18..48deaea0 100644 --- a/kernel/src/driver/input/serio/serio_driver.rs +++ b/kernel/src/driver/input/serio/serio_driver.rs @@ -24,6 +24,8 @@ pub trait SerioDriver: Driver { /// /// ## 返回值 /// 无 + /// + /// todo:https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/serio.c?fi=__serio_register_driver#989 fn interrupt( &self, device: &Arc, @@ -43,6 +45,12 @@ pub trait SerioDriver: Driver { } ///todo: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/serio.c#810 + +#[inline(always)] +pub fn serio_driver_manager() -> &'static SerioDriverManager { + &SerioDriverManager +} + pub struct SerioDriverManager; #[allow(dead_code)] diff --git a/kernel/src/driver/mouse/ps2_mouse.c b/kernel/src/driver/mouse/ps2_mouse.c index a0167646..aac1c110 100644 --- a/kernel/src/driver/mouse/ps2_mouse.c +++ b/kernel/src/driver/mouse/ps2_mouse.c @@ -5,46 +5,7 @@ #include #include -static struct ps2_mouse_input_buffer *ps2_mouse_buf_ptr = NULL; -static int c = 0; -struct apic_IO_APIC_RTE_entry ps2_mouse_entry; -static unsigned char ps2_mouse_id = 0; -struct ps2_mouse_packet_3bytes pak; -static int ps2_mouse_count = 0; -/** - * @brief 清空缓冲区 - * - */ -static void ps2_mouse_clear_buf() -{ - ps2_mouse_buf_ptr->ptr_head = ps2_mouse_buf_ptr->buffer; - ps2_mouse_buf_ptr->ptr_tail = ps2_mouse_buf_ptr->buffer; - ps2_mouse_buf_ptr->count = 0; - memset(ps2_mouse_buf_ptr->buffer, 0, ps2_mouse_buffer_size); -} - -/** - * @brief 从缓冲队列中获取鼠标数据字节 - * @return 鼠标数据包的字节 - * 若缓冲队列为空则返回-1024 - */ -static int ps2_mouse_get_scancode() -{ - // 缓冲队列为空 - if (ps2_mouse_buf_ptr->count == 0) - while (!ps2_mouse_buf_ptr->count) - nop(); - - if (ps2_mouse_buf_ptr->ptr_tail == ps2_mouse_buf_ptr->buffer + ps2_mouse_buffer_size) - ps2_mouse_buf_ptr->ptr_tail = ps2_mouse_buf_ptr->buffer; - - int ret = (int)((char)(*(ps2_mouse_buf_ptr->ptr_tail))); - --(ps2_mouse_buf_ptr->count); - ++(ps2_mouse_buf_ptr->ptr_tail); - // printk("count=%d", ps2_mouse_buf_ptr->count); - - return ret; -} +extern void ps2_mouse_driver_interrupt(); /** * @brief 鼠标中断处理函数(中断上半部) @@ -55,25 +16,11 @@ static int ps2_mouse_get_scancode() */ void ps2_mouse_handler(ul irq_num, ul param, struct pt_regs *regs) { - // 读取鼠标输入的信息 - unsigned char x = io_in8(PORT_KEYBOARD_DATA); - - // 当头指针越过界时,恢复指向数组头部 - if (ps2_mouse_buf_ptr->ptr_head == ps2_mouse_buf_ptr->buffer + ps2_mouse_buffer_size) - ps2_mouse_buf_ptr->ptr_head = ps2_mouse_buf_ptr->buffer; - - if (ps2_mouse_buf_ptr->count >= ps2_mouse_buffer_size) - { - kwarn("ps2_mouse input buffer is full."); - return; - } - - *ps2_mouse_buf_ptr->ptr_head = x; - ++(ps2_mouse_buf_ptr->count); - ++(ps2_mouse_buf_ptr->ptr_head); - printk("c=%d\tval = %d\n", ++c, x); + ps2_mouse_driver_interrupt(); } +struct apic_IO_APIC_RTE_entry ps2_mouse_entry; + hardware_intr_controller ps2_mouse_intr_controller = { .enable = apic_ioapic_enable, @@ -84,301 +31,28 @@ hardware_intr_controller ps2_mouse_intr_controller = }; -/** - * @brief 从键盘控制器读取ps2_mouse id - * - * @return unsigned char 鼠标id - */ -static unsigned char ps2_mouse_get_mouse_ID() -{ - // 读取鼠标的ID - io_out8(PORT_KEYBOARD_CONTROL, KEYBOARD_COMMAND_SEND_TO_PS2_MOUSE); - wait_keyboard_write(); - io_out8(PORT_KEYBOARD_DATA, PS2_MOUSE_GET_ID); - wait_keyboard_write(); - ps2_mouse_id = io_in8(PORT_KEYBOARD_DATA); - wait_keyboard_write(); - io_in8(PORT_KEYBOARD_DATA); - for (int i = 0; i < 1000; i++) - for (int j = 0; j < 1000; j++) - nop(); - return ps2_mouse_id; -} - -/** - * @brief 设置鼠标采样率 - * - * @param hz 采样率 - */ -int ps2_mouse_set_sample_rate(unsigned int hz) -{ - switch (hz) - { - case 10: - case 20: - case 40: - case 60: - case 80: - case 100: - case 200: - wait_keyboard_write(); - io_out8(PORT_KEYBOARD_CONTROL, KEYBOARD_COMMAND_SEND_TO_PS2_MOUSE); - wait_keyboard_write(); - io_out8(PORT_KEYBOARD_DATA, PS2_MOUSE_SET_SAMPLING_RATE); - wait_keyboard_write(); - io_in8(PORT_KEYBOARD_DATA); - - for (int i = 0; i < 1000; i++) - for (int j = 0; j < 1000; j++) - nop(); - - io_out8(PORT_KEYBOARD_CONTROL, KEYBOARD_COMMAND_SEND_TO_PS2_MOUSE); - wait_keyboard_write(); - io_out8(PORT_KEYBOARD_DATA, hz); - for (int i = 0; i < 1000; i++) - for (int j = 0; j < 1000; j++) - nop(); - wait_keyboard_write(); - io_in8(PORT_KEYBOARD_DATA); - - break; - - default: - return EINVALID_ARGUMENT; - break; - } - return SUCCESS; -} -/** - * @brief 使鼠标支持滚轮 - * 该模式下,鼠标ID=3 - */ -static int ps2_mouse_enable_scroll_wheel() -{ - if (ps2_mouse_id == 3) - return SUCCESS; - - ps2_mouse_set_sample_rate(200); - ps2_mouse_set_sample_rate(100); - ps2_mouse_set_sample_rate(80); - if (ps2_mouse_get_mouse_ID() != 3) - { - kerror("Cannot set mouse ID to 3"); - return EFAIL; - } - // 清空缓冲区,防止解析时产生错误 - ps2_mouse_clear_buf(); - return SUCCESS; -} -/** - * @brief 使鼠标支持5键 - * 该模式下ID=4 - */ -static int ps2_mouse_enable_5keys() -{ - if (ps2_mouse_id == 4) - return SUCCESS; - // 根据规范,应当先启用ID=3 - ps2_mouse_enable_scroll_wheel(); - - ps2_mouse_set_sample_rate(200); - ps2_mouse_set_sample_rate(200); - ps2_mouse_set_sample_rate(80); - if (ps2_mouse_get_mouse_ID() != 4) - { - kerror("Cannot set ps2_mouse ID to 4"); - return EFAIL; - } - // 清空缓冲区,防止解析时产生错误 - ps2_mouse_clear_buf(); - - return SUCCESS; -} /** * @brief 初始化鼠标驱动程序 * */ -void ps2_mouse_init() +void c_ps2_mouse_init() { - // 初始化鼠标读入队列缓冲区 - ps2_mouse_buf_ptr = (struct ps2_mouse_input_buffer *)kzalloc(sizeof(struct ps2_mouse_input_buffer), 0); - ps2_mouse_buf_ptr->ptr_head = ps2_mouse_buf_ptr->buffer; - ps2_mouse_buf_ptr->ptr_tail = ps2_mouse_buf_ptr->buffer; - ps2_mouse_buf_ptr->count = 0; - memset(ps2_mouse_buf_ptr->buffer, 0, ps2_mouse_buffer_size); - // ======== 初始化中断RTE entry ========== - // ps2_mouse_entry.vector = PS2_MOUSE_INTR_VECTOR; // 设置中断向量号 - // ps2_mouse_entry.deliver_mode = IO_APIC_FIXED; // 投递模式:混合 - // ps2_mouse_entry.dest_mode = DEST_PHYSICAL; // 物理模式投递中断 - // ps2_mouse_entry.deliver_status = IDLE; - // ps2_mouse_entry.trigger_mode = EDGE_TRIGGER; // 设置边沿触发 - // ps2_mouse_entry.polarity = POLARITY_HIGH; // 高电平触发 - // ps2_mouse_entry.remote_IRR = IRR_RESET; - // ps2_mouse_entry.mask = MASKED; - // ps2_mouse_entry.reserved = 0; + ps2_mouse_entry.vector = PS2_MOUSE_INTR_VECTOR; // 设置中断向量号 + ps2_mouse_entry.deliver_mode = IO_APIC_FIXED; // 投递模式:混合 + ps2_mouse_entry.dest_mode = DEST_PHYSICAL; // 物理模式投递中断 + ps2_mouse_entry.deliver_status = IDLE; + ps2_mouse_entry.trigger_mode = EDGE_TRIGGER; // 设置边沿触发 + ps2_mouse_entry.polarity = POLARITY_HIGH; // 高电平触发 + ps2_mouse_entry.remote_IRR = IRR_RESET; + ps2_mouse_entry.mask = MASKED; + ps2_mouse_entry.reserved = 0; - // ps2_mouse_entry.destination.physical.reserved1 = 0; - // ps2_mouse_entry.destination.physical.reserved2 = 0; - // ps2_mouse_entry.destination.physical.phy_dest = 0; // 设置投递到BSP处理器 + ps2_mouse_entry.destination.physical.reserved1 = 0; + ps2_mouse_entry.destination.physical.reserved2 = 0; + ps2_mouse_entry.destination.physical.phy_dest = 0; // 设置投递到BSP处理器 // 注册中断处理程序 - irq_register(PS2_MOUSE_INTR_VECTOR, &ps2_mouse_entry, &ps2_mouse_handler, (ul)ps2_mouse_buf_ptr, &ps2_mouse_intr_controller, "ps/2 mouse"); - - wait_keyboard_write(); - io_out8(PORT_KEYBOARD_CONTROL, KEYBOARD_COMMAND_ENABLE_PS2_MOUSE_PORT); // 开启鼠标端口 - for (int i = 0; i < 1000; i++) - for (int j = 0; j < 1000; j++) - nop(); - wait_keyboard_write(); - io_in8(PORT_KEYBOARD_DATA); - - io_out8(PORT_KEYBOARD_CONTROL, KEYBOARD_COMMAND_SEND_TO_PS2_MOUSE); - wait_keyboard_write(); - io_out8(PORT_KEYBOARD_DATA, PS2_MOUSE_ENABLE); // 允许鼠标设备发送数据包 - wait_keyboard_write(); - io_in8(PORT_KEYBOARD_DATA); - - for (int i = 0; i < 1000; i++) - for (int j = 0; j < 1000; j++) - nop(); - wait_keyboard_write(); - io_out8(PORT_KEYBOARD_CONTROL, KEYBOARD_COMMAND_WRITE); - wait_keyboard_write(); - io_out8(PORT_KEYBOARD_DATA, KEYBOARD_PARAM_INIT); // 设置键盘控制器 - wait_keyboard_write(); - io_in8(PORT_KEYBOARD_DATA); - for (int i = 0; i < 1000; i++) - for (int j = 0; j < 1000; j++) - nop(); - wait_keyboard_write(); - //ps2_mouse_enable_5keys(); - ps2_mouse_get_mouse_ID(); - ps2_mouse_set_sample_rate(30); - ps2_mouse_clear_buf(); - kdebug("ps2_mouse ID:%d", ps2_mouse_id); - c = 0; - //ps2_mouse_count = 1; -} - -/** - * @brief 卸载鼠标驱动程序 - * - */ -void ps2_mouse_exit() -{ - irq_unregister(PS2_MOUSE_INTR_VECTOR); - kfree((ul *)ps2_mouse_buf_ptr); -} - -/** - * @brief 获取鼠标数据包 - * - * @param packet 数据包的返回值 - * @return int 错误码 - */ -int ps2_mouse_get_packet(void *packet) -{ - // if (ps2_mouse_buf_ptr->count != 0) - // kdebug("at get packet: count=%d", ps2_mouse_buf_ptr->count); - int code = 0; - switch (ps2_mouse_id) - { - case 0: // 3bytes 数据包 - if (ps2_mouse_buf_ptr->count < 4) - return EFAIL; - do - { - code = ps2_mouse_get_scancode(); - ((struct ps2_mouse_packet_3bytes *)packet)->byte0 = (unsigned char)code; - } while (code == -1024); - - do - { - code = ps2_mouse_get_scancode(); - ((struct ps2_mouse_packet_3bytes *)packet)->movement_x = (char)code; - } while (code == -1024); - - do - { - code = ps2_mouse_get_scancode(); - ((struct ps2_mouse_packet_3bytes *)packet)->movement_y = (char)code; - } while (code == -1024); - - return SUCCESS; - break; - - case 3: // 4bytes数据包 - case 4: - if (ps2_mouse_buf_ptr->count < 5) - return EFAIL; - do - { - code = ps2_mouse_get_scancode(); - ((struct ps2_mouse_packet_4bytes *)packet)->byte0 = (unsigned char)code; - } while (code == -1024); - - do - { - code = ps2_mouse_get_scancode(); - ((struct ps2_mouse_packet_4bytes *)packet)->movement_x = (char)code; - } while (code == -1024); - - do - { - code = ps2_mouse_get_scancode(); - ((struct ps2_mouse_packet_4bytes *)packet)->movement_y = (char)code; - } while (code == -1024); - - do - { - code = ps2_mouse_get_scancode(); - ((struct ps2_mouse_packet_4bytes *)packet)->byte3 = (char)code; - } while (code == -1024); - - return SUCCESS; - break; - - default: // Should not reach here - kBUG("ps2_mouse_get_packet(): Invalid ps2_mouse_id!"); - return EFAIL; - break; - } - return SUCCESS; -} - -void analyze_mousecode() -{ - if(!ps2_mouse_buf_ptr->count) - return; - else printk_color(ORANGE, BLACK, "COUNT=%d\n", ps2_mouse_buf_ptr->count); - unsigned char x = ps2_mouse_get_scancode(); - - switch (ps2_mouse_count) - { - case 0: - ps2_mouse_count++; - break; - - case 1: - pak.byte0 = x; - ps2_mouse_count++; - break; - - case 2: - pak.movement_x = (char)x; - ps2_mouse_count++; - break; - - case 3: - pak.movement_y = (char)x; - ps2_mouse_count = 1; - - printk_color(RED, GREEN, "(M:%02x,X:%3d,Y:%3d)\tcount=%d\n", pak.byte0, pak.movement_x, pak.movement_y, ps2_mouse_buf_ptr->count); - break; - - default: - break; - } + irq_register(PS2_MOUSE_INTR_VECTOR, &ps2_mouse_entry, &ps2_mouse_handler, 0, &ps2_mouse_intr_controller, "ps/2 mouse"); } \ No newline at end of file diff --git a/kernel/src/driver/mouse/ps2_mouse.h b/kernel/src/driver/mouse/ps2_mouse.h index c5878d2c..743c5430 100644 --- a/kernel/src/driver/mouse/ps2_mouse.h +++ b/kernel/src/driver/mouse/ps2_mouse.h @@ -30,79 +30,9 @@ #define KEYBOARD_FLAG_OUTBUF_FULL 0x01 // 键盘的输出缓冲区已满标志位 #define KEYBOARD_FLAG_INBUF_FULL 0x02 // 键盘的输入缓冲区已满标志位 -// 等待向键盘控制器写入信息完成 -#define wait_keyboard_write() while (io_in8(PORT_KEYBOARD_STATUS) & KEYBOARD_FLAG_INBUF_FULL) -// 等待从键盘控制器读取信息完成 -#define wait_keyboard_read() while (io_in8(PORT_KEYBOARD_STATUS) & KEYBOARD_FLAG_OUTBUF_FULL) - -#define SUCCESS 0 -#define EINVALID_ARGUMENT -1 -#define EFAIL -2 - -// =========== 定义鼠标数据包 ============== -// 其中,x、y方向的移动值用9位二进制补码表示(算上byte0中的符号位) -// 目前只用到8位,(精度要求没那么高) -struct ps2_mouse_packet_3bytes -{ - - unsigned char byte0; // 第0字节 - // [y溢出,x溢出,y符号位, x符号位, 1, 鼠标中键, 鼠标右键,鼠标左键] - - char movement_x; - char movement_y; -}; - -// ID = 3 或 ID = 4时,采用4bytes数据包 -struct ps2_mouse_packet_4bytes -{ - unsigned char byte0; // 第0字节 - // [y溢出,x溢出,y符号位, x符号位, 1, 鼠标中键, 鼠标右键,鼠标左键] - - char movement_x; - char movement_y; - - char byte3; // 当鼠标ID=3时,表示z移动值 - // 当鼠标ID=4时,表示:[0, 0, 鼠标第5键, 鼠标第4键, Z3, Z2, Z1, Z0] - // 其中,[Z3,Z0]表示鼠标滚轮滚动方向 - // Z3~Z0: 0:无滚动, 1:垂直向上滚动, F:垂直向下滚动, 2:水平向右滚动, E:水平向左滚动 -}; - -/** - * @brief 键盘循环队列缓冲区结构体 - * - */ -struct ps2_mouse_input_buffer -{ - unsigned char *ptr_head; - unsigned char *ptr_tail; - int count; - unsigned char buffer[ps2_mouse_buffer_size]; -}; /** * @brief 初始化鼠标驱动程序 * */ -void ps2_mouse_init(); - -/** - * @brief 卸载鼠标驱动程序 - * - */ -void ps2_mouse_exit(); - -/** - * @brief 设置鼠标采样率 - * - * @param hz 采样率 - */ -int ps2_mouse_set_sample_rate(unsigned int hz); - -/** - * @brief 获取鼠标数据包 - * - * @param packet 数据包的返回值 - * @return int 错误码 - */ -int ps2_mouse_get_packet(void *packet); -void analyze_mousecode(); \ No newline at end of file +void c_ps2_mouse_init();