//! Intel 8042 PS/2 controller driver implemenation use abi::{ error::Error, io::{KeyboardKey, KeyboardKeyEvent}, }; use alloc::sync::Arc; use device_api::{ device::Device, interrupt::{InterruptHandler, Irq}, }; use kernel_arch_x86::{ intrinsics::{IoPort, IoPortAccess}, ISA_IRQ_OFFSET, }; use libk::device::external_interrupt_controller; use libk_util::sync::IrqSafeSpinlock; use codeset::{CODE_SET_1_00, CODE_SET_1_E0}; mod codeset; struct Inner { command: IoPort, data: IoPort, } /// PS/2 controller driver pub struct PS2Controller { primary_irq: Irq, #[allow(unused)] auxiliary_irq: Irq, inner: IrqSafeSpinlock, } fn translate(e0: bool, key: u8) -> KeyboardKey { debug_assert!(key < 0x80); if e0 { CODE_SET_1_E0[key as usize] } else { CODE_SET_1_00[key as usize] } } impl Inner { const STATUS_OUTPUT_FULL: u8 = 1 << 0; const STATUS_INPUT_FULL: u8 = 1 << 1; fn send_command(&mut self, cmd: u8) { while self.command.read() & Self::STATUS_INPUT_FULL != 0 { core::hint::spin_loop(); } self.command.write(cmd); } // fn recv_timeout(&mut self, timeout: u64) -> Option { // let mut counter = 0; // while self.command.read() & Self::STATUS_OUTPUT_FULL == 0 { // counter += 1; // if counter > timeout { // return None; // } // core::hint::spin_loop(); // } // Some(self.data.read()) // } fn try_recv(&mut self) -> Option { if self.command.read() & Inner::STATUS_OUTPUT_FULL != 0 { Some(self.data.read()) } else { None } } } impl InterruptHandler for PS2Controller { fn handle_irq(self: Arc, _vector: Option) -> bool { let mut count = 0; let mut inner = self.inner.lock(); loop { let Some(mut scancode) = inner.try_recv() else { break; }; count += 1; let e0 = scancode == 0xE0; let release = scancode >= 0x80; if release { scancode -= 0x80; } let key = translate(e0, scancode); let event = if release { KeyboardKeyEvent::Released(key) } else { KeyboardKeyEvent::Pressed(key) }; ygg_driver_input::send_event(event); } count != 0 } } impl Device for PS2Controller { fn display_name(&self) -> &'static str { "PS/2 Controller" } unsafe fn init(self: Arc) -> Result<(), Error> { Ok(()) } unsafe fn init_irq(self: Arc) -> Result<(), Error> { let intc = external_interrupt_controller()?; let mut inner = self.inner.lock(); // let intc = PLATFORM.interrupt_controller(); intc.register_irq(self.primary_irq, Default::default(), self.clone())?; // Disable PS/2 devices from sending any further data inner.send_command(0xAD); inner.send_command(0xA7); // Flush the buffer while inner.command.read() & Inner::STATUS_OUTPUT_FULL != 0 { inner.data.read(); } // Enable primary port inner.send_command(0xAE); intc.enable_irq(self.primary_irq)?; intc.enable_irq(self.auxiliary_irq)?; Ok(()) } } impl PS2Controller { /// Constructs a new instance of the device const fn new(primary_irq: Irq, auxiliary_irq: Irq, cmd_port: u16, data_port: u16) -> Self { let inner = Inner { command: IoPort::new(cmd_port), data: IoPort::new(data_port), }; Self { primary_irq, auxiliary_irq, inner: IrqSafeSpinlock::new(inner), } } pub fn setup() -> Result, Error> { let this = Arc::new(PS2Controller::new( Irq::External(ISA_IRQ_OFFSET + 1), Irq::External(ISA_IRQ_OFFSET + 12), 0x64, 0x60, )); unsafe { this.clone().init_irq() }?; Ok(this) } } // pub static PS2: PS2Controller = PS2Controller::new( // Irq::External(ISA_IRQ_OFFSET + 1), // Irq::External(ISA_IRQ_OFFSET + 12), // 0x64, // 0x60, // );