diff --git a/Cargo.lock b/Cargo.lock index 8245173..4ab03f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -127,6 +127,12 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "pc-keyboard" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed089a1fbffe3337a1a345501c981f1eb1e47e69de5a40e852433e12953c3174" + [[package]] name = "postcard" version = "1.0.10" @@ -155,6 +161,7 @@ version = "0.1.0" dependencies = [ "bitflags", "parking_lot", + "pc-keyboard", "syslog_rpc", "x86_64", ] diff --git a/Cargo.toml b/Cargo.toml index df25e6b..e14bfa2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,5 +6,6 @@ edition = "2021" [dependencies] bitflags = "2.6.0" parking_lot = "0.12.3" +pc-keyboard = "0.7.0" syslog_rpc = { version = "0.1.0", path = "../syslog/syslog_rpc" } x86_64 = "0.15.1" diff --git a/src/controller.rs b/src/controller.rs index d2cdc93..8805b51 100644 --- a/src/controller.rs +++ b/src/controller.rs @@ -1,4 +1,7 @@ +use std::{collections::VecDeque, os::mikros::ipc}; + use bitflags::bitflags; +use parking_lot::Mutex; use x86_64::instructions::port::{Port, PortReadOnly, PortWriteOnly}; #[derive(Copy, Clone, Debug)] @@ -118,29 +121,18 @@ bitflags! { } } -pub struct Ps2Controller { +pub struct Ps2Ports { data_port: Port, status_register: PortReadOnly, command_register: PortWriteOnly, - two_ports: bool, - port1_ok: bool, - port2_ok: bool, } -#[derive(Clone, Copy, Debug)] -pub enum Ps2InitFailure { - SelfTestFailed, -} - -impl Ps2Controller { - pub unsafe fn new(base: u16) -> Self { +impl Ps2Ports { + unsafe fn new(base: u16) -> Self { Self { data_port: Port::new(base), status_register: PortReadOnly::new(base + 0x4), command_register: PortWriteOnly::new(base + 0x4), - two_ports: false, // This is determined during initialiation - port1_ok: false, // This is determined during initialiation - port2_ok: false, // This is determined during initialiation } } @@ -173,24 +165,53 @@ impl Ps2Controller { fn set_config_byte(&mut self, config_byte: Ps2ConfigByte) { self.send_command(Ps2ControllerCommand::WriteRAM(0, config_byte.bits())); } +} + +pub struct Ps2Controller { + ports: Mutex, + two_ports: bool, + port1_ok: bool, + port2_ok: bool, + port1_output_bytes: Mutex>, +} + +#[derive(Clone, Copy, Debug)] +pub enum Ps2InitFailure { + SelfTestFailed, +} + +impl Ps2Controller { + pub unsafe fn new(base: u16) -> Self { + Self { + ports: Mutex::new(unsafe { Ps2Ports::new(base) }), + two_ports: false, // This is determined during initialiation + port1_ok: false, // This is determined during initialiation + port2_ok: false, // This is determined during initialiation + port1_output_bytes: Mutex::new(VecDeque::new()), + } + } + + pub fn initialize(&mut self) -> Result<(), Ps2InitFailure> { - self.send_command(Ps2ControllerCommand::DisablePort1); - self.send_command(Ps2ControllerCommand::DisablePort2); + let mut ports = self.ports.lock(); + + ports.send_command(Ps2ControllerCommand::DisablePort1); + ports.send_command(Ps2ControllerCommand::DisablePort2); // Flush the output buffer - unsafe { self.data_port.read() }; + unsafe { ports.data_port.read() }; - let mut config_byte = self.get_config_byte(); + let mut config_byte = ports.get_config_byte(); config_byte.set(Ps2ConfigByte::Port1Interrupt, false); config_byte.set(Ps2ConfigByte::Port1ClockDisable, false); config_byte.set(Ps2ConfigByte::Port1Translation, false); - self.set_config_byte(config_byte); + ports.set_config_byte(config_byte); // Flush the output buffer - unsafe { self.data_port.read() }; + unsafe { ports.data_port.read() }; - let self_test_result = self + let self_test_result = ports .send_command(Ps2ControllerCommand::TestController) .unwrap(); if self_test_result != 0x55 { @@ -198,44 +219,44 @@ impl Ps2Controller { } // Testing the controller can reset it, so redo early initialization to be safe. - self.send_command(Ps2ControllerCommand::DisablePort1); - self.send_command(Ps2ControllerCommand::DisablePort2); + ports.send_command(Ps2ControllerCommand::DisablePort1); + ports.send_command(Ps2ControllerCommand::DisablePort2); // Flush the output buffer - unsafe { self.data_port.read() }; + unsafe { ports.data_port.read() }; - self.set_config_byte(config_byte); + ports.set_config_byte(config_byte); - self.send_command(Ps2ControllerCommand::EnablePort2); - if !self + ports.send_command(Ps2ControllerCommand::EnablePort2); + if !ports .get_config_byte() .contains(Ps2ConfigByte::Port2ClockDisable) { self.two_ports = true; - self.send_command(Ps2ControllerCommand::DisablePort2); - let mut config_byte = self.get_config_byte(); + ports.send_command(Ps2ControllerCommand::DisablePort2); + let mut config_byte = ports.get_config_byte(); config_byte.set(Ps2ConfigByte::Port2Interrupt, false); config_byte.set(Ps2ConfigByte::Port2ClockDisable, false); - self.set_config_byte(config_byte); + ports.set_config_byte(config_byte); } - let port1_test_result = self.send_command(Ps2ControllerCommand::TestPort1).unwrap(); + let port1_test_result = ports.send_command(Ps2ControllerCommand::TestPort1).unwrap(); if port1_test_result == 0x0 { self.port1_ok = true; - self.send_command(Ps2ControllerCommand::EnablePort1); - let mut config_byte = self.get_config_byte(); + ports.send_command(Ps2ControllerCommand::EnablePort1); + let mut config_byte = ports.get_config_byte(); config_byte.set(Ps2ConfigByte::Port1Interrupt, true); - self.set_config_byte(config_byte); + ports.set_config_byte(config_byte); } if self.two_ports { - let port2_test_result = self.send_command(Ps2ControllerCommand::TestPort2).unwrap(); + let port2_test_result = ports.send_command(Ps2ControllerCommand::TestPort2).unwrap(); if port2_test_result == 0x0 { self.port2_ok = true; - self.send_command(Ps2ControllerCommand::EnablePort2); - let mut config_byte = self.get_config_byte(); + ports.send_command(Ps2ControllerCommand::EnablePort2); + let mut config_byte = ports.get_config_byte(); config_byte.set(Ps2ConfigByte::Port2Interrupt, true); - self.set_config_byte(config_byte); + ports.set_config_byte(config_byte); } } @@ -254,20 +275,31 @@ impl Ps2Controller { self.port2_ok } - pub fn write_port1(&mut self, data: u8) { - self.send_command(Ps2ControllerCommand::WritePort1Input(data)); + pub fn write_port1(&self, data: u8) { + self.ports.lock().send_command(Ps2ControllerCommand::WritePort1Input(data)); } - pub fn write_port2(&mut self, data: u8) { - self.send_command(Ps2ControllerCommand::WritePort2Input(data)); + pub fn write_port2(&self, data: u8) { + self.ports.lock().send_command(Ps2ControllerCommand::WritePort2Input(data)); } - pub fn handle_interrupt(&mut self) { - if self.get_status().contains(Ps2Status::OutputBufFull) { - println!("Data: {:#x}", unsafe {self.data_port.read()}); - } else { - println!("Spurious interrupt"); + pub fn handle_interrupt(&self) { + let mut ports = self.ports.lock(); + if ports.get_status().contains(Ps2Status::OutputBufFull) { + let data = unsafe {ports.data_port.read()}; + self.port1_output_bytes.lock().push_back(data); } } + + pub fn flush_output_buffer(&self) { + unsafe { self.ports.lock().data_port.read() }; + } + + pub fn read_port1(&self) -> u8 { + while self.port1_output_bytes.lock().is_empty() { + ipc::process_messages(); + } + self.port1_output_bytes.lock().pop_front().unwrap() + } } diff --git a/src/main.rs b/src/main.rs index bdbfc3f..057341f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,11 @@ mod controller; -use std::os::mikros::{ipc, syscalls}; +use std::{os::mikros::{ipc, syscalls}, sync::OnceLock}; use controller::Ps2Controller; -use parking_lot::Mutex; +use pc_keyboard::{ScancodeSet, ScancodeSet2}; -static CONTROLLER: Mutex> = Mutex::new(None); +static CONTROLLER: OnceLock = OnceLock::new(); fn main() { dbg!(syscalls::get_pid()); @@ -53,20 +53,69 @@ fn main() { } } - if controller.port1_ok() { - controller.write_port1(0xFF); - } + syscalls::irq_register(1).unwrap(); - *CONTROLLER.lock() = Some(controller); + controller.flush_output_buffer(); + + CONTROLLER.get_or_init(move || controller); + + let controller = CONTROLLER.get().unwrap(); ipc::register_callback(2, |_msg| { - println!("Keyboard interrupt"); - if let Some(controller) = CONTROLLER.lock().as_mut() { + if let Some(controller) = CONTROLLER.get() { controller.handle_interrupt(); } }); + syslog_client.send_text_message("ps2", "Setting keyboard to scan code set 2").unwrap(); + + controller.write_port1(0xF5); loop { - ipc::process_messages() + let kbd_data = controller.read_port1(); + if kbd_data != 0xFA && kbd_data != 0xFE { + continue; + } + if kbd_data == 0xFE { + controller.write_port1(0xF5); + } + break; + } + + controller.write_port1(0xF0); + controller.write_port1(2); + loop { + let kbd_data = controller.read_port1(); + if kbd_data != 0xFA && kbd_data != 0xFE { + continue; + } + if kbd_data == 0xFE { + controller.write_port1(0xF0); + controller.write_port1(2); + } + break; + } + + controller.write_port1(0xF4); + loop { + let kbd_data = controller.read_port1(); + if kbd_data != 0xFA && kbd_data != 0xFE { + continue; + } + if kbd_data == 0xFE { + controller.write_port1(0xF4); + } + break; + } + + syslog_client.send_text_message("ps2", "Set keyboard to scan code set 2").unwrap(); + + let mut scancode_decoder = ScancodeSet2::new(); + + loop { + let byte = controller.read_port1(); + let event = scancode_decoder.advance_state(byte).unwrap(); + if let Some(event) = event { + dbg!(event); + } } }