Set scancode set 2 and read incoming scancodes

This commit is contained in:
pjht 2024-09-11 11:51:46 -05:00
parent 89345100c9
commit 7b7f3e9a23
Signed by: pjht
GPG Key ID: CA239FC6934E6F3A
4 changed files with 146 additions and 57 deletions

7
Cargo.lock generated
View File

@ -127,6 +127,12 @@ dependencies = [
"windows-targets", "windows-targets",
] ]
[[package]]
name = "pc-keyboard"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed089a1fbffe3337a1a345501c981f1eb1e47e69de5a40e852433e12953c3174"
[[package]] [[package]]
name = "postcard" name = "postcard"
version = "1.0.10" version = "1.0.10"
@ -155,6 +161,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"parking_lot", "parking_lot",
"pc-keyboard",
"syslog_rpc", "syslog_rpc",
"x86_64", "x86_64",
] ]

View File

@ -6,5 +6,6 @@ edition = "2021"
[dependencies] [dependencies]
bitflags = "2.6.0" bitflags = "2.6.0"
parking_lot = "0.12.3" parking_lot = "0.12.3"
pc-keyboard = "0.7.0"
syslog_rpc = { version = "0.1.0", path = "../syslog/syslog_rpc" } syslog_rpc = { version = "0.1.0", path = "../syslog/syslog_rpc" }
x86_64 = "0.15.1" x86_64 = "0.15.1"

View File

@ -1,4 +1,7 @@
use std::{collections::VecDeque, os::mikros::ipc};
use bitflags::bitflags; use bitflags::bitflags;
use parking_lot::Mutex;
use x86_64::instructions::port::{Port, PortReadOnly, PortWriteOnly}; use x86_64::instructions::port::{Port, PortReadOnly, PortWriteOnly};
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
@ -118,29 +121,18 @@ bitflags! {
} }
} }
pub struct Ps2Controller { pub struct Ps2Ports {
data_port: Port<u8>, data_port: Port<u8>,
status_register: PortReadOnly<u8>, status_register: PortReadOnly<u8>,
command_register: PortWriteOnly<u8>, command_register: PortWriteOnly<u8>,
two_ports: bool,
port1_ok: bool,
port2_ok: bool,
} }
#[derive(Clone, Copy, Debug)] impl Ps2Ports {
pub enum Ps2InitFailure { unsafe fn new(base: u16) -> Self {
SelfTestFailed,
}
impl Ps2Controller {
pub unsafe fn new(base: u16) -> Self {
Self { Self {
data_port: Port::new(base), data_port: Port::new(base),
status_register: PortReadOnly::new(base + 0x4), status_register: PortReadOnly::new(base + 0x4),
command_register: PortWriteOnly::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) { fn set_config_byte(&mut self, config_byte: Ps2ConfigByte) {
self.send_command(Ps2ControllerCommand::WriteRAM(0, config_byte.bits())); self.send_command(Ps2ControllerCommand::WriteRAM(0, config_byte.bits()));
} }
}
pub struct Ps2Controller {
ports: Mutex<Ps2Ports>,
two_ports: bool,
port1_ok: bool,
port2_ok: bool,
port1_output_bytes: Mutex<VecDeque<u8>>,
}
#[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> { pub fn initialize(&mut self) -> Result<(), Ps2InitFailure> {
self.send_command(Ps2ControllerCommand::DisablePort1); let mut ports = self.ports.lock();
self.send_command(Ps2ControllerCommand::DisablePort2);
ports.send_command(Ps2ControllerCommand::DisablePort1);
ports.send_command(Ps2ControllerCommand::DisablePort2);
// Flush the output buffer // 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::Port1Interrupt, false);
config_byte.set(Ps2ConfigByte::Port1ClockDisable, false); config_byte.set(Ps2ConfigByte::Port1ClockDisable, false);
config_byte.set(Ps2ConfigByte::Port1Translation, false); config_byte.set(Ps2ConfigByte::Port1Translation, false);
self.set_config_byte(config_byte); ports.set_config_byte(config_byte);
// Flush the output buffer // 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) .send_command(Ps2ControllerCommand::TestController)
.unwrap(); .unwrap();
if self_test_result != 0x55 { if self_test_result != 0x55 {
@ -198,44 +219,44 @@ impl Ps2Controller {
} }
// Testing the controller can reset it, so redo early initialization to be safe. // Testing the controller can reset it, so redo early initialization to be safe.
self.send_command(Ps2ControllerCommand::DisablePort1); ports.send_command(Ps2ControllerCommand::DisablePort1);
self.send_command(Ps2ControllerCommand::DisablePort2); ports.send_command(Ps2ControllerCommand::DisablePort2);
// Flush the output buffer // 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); ports.send_command(Ps2ControllerCommand::EnablePort2);
if !self if !ports
.get_config_byte() .get_config_byte()
.contains(Ps2ConfigByte::Port2ClockDisable) .contains(Ps2ConfigByte::Port2ClockDisable)
{ {
self.two_ports = true; self.two_ports = true;
self.send_command(Ps2ControllerCommand::DisablePort2); ports.send_command(Ps2ControllerCommand::DisablePort2);
let mut config_byte = self.get_config_byte(); let mut config_byte = ports.get_config_byte();
config_byte.set(Ps2ConfigByte::Port2Interrupt, false); config_byte.set(Ps2ConfigByte::Port2Interrupt, false);
config_byte.set(Ps2ConfigByte::Port2ClockDisable, 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 { if port1_test_result == 0x0 {
self.port1_ok = true; self.port1_ok = true;
self.send_command(Ps2ControllerCommand::EnablePort1); ports.send_command(Ps2ControllerCommand::EnablePort1);
let mut config_byte = self.get_config_byte(); let mut config_byte = ports.get_config_byte();
config_byte.set(Ps2ConfigByte::Port1Interrupt, true); config_byte.set(Ps2ConfigByte::Port1Interrupt, true);
self.set_config_byte(config_byte); ports.set_config_byte(config_byte);
} }
if self.two_ports { 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 { if port2_test_result == 0x0 {
self.port2_ok = true; self.port2_ok = true;
self.send_command(Ps2ControllerCommand::EnablePort2); ports.send_command(Ps2ControllerCommand::EnablePort2);
let mut config_byte = self.get_config_byte(); let mut config_byte = ports.get_config_byte();
config_byte.set(Ps2ConfigByte::Port2Interrupt, true); 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 self.port2_ok
} }
pub fn write_port1(&mut self, data: u8) { pub fn write_port1(&self, data: u8) {
self.send_command(Ps2ControllerCommand::WritePort1Input(data)); self.ports.lock().send_command(Ps2ControllerCommand::WritePort1Input(data));
} }
pub fn write_port2(&mut self, data: u8) { pub fn write_port2(&self, data: u8) {
self.send_command(Ps2ControllerCommand::WritePort2Input(data)); self.ports.lock().send_command(Ps2ControllerCommand::WritePort2Input(data));
} }
pub fn handle_interrupt(&mut self) { pub fn handle_interrupt(&self) {
if self.get_status().contains(Ps2Status::OutputBufFull) { let mut ports = self.ports.lock();
println!("Data: {:#x}", unsafe {self.data_port.read()}); if ports.get_status().contains(Ps2Status::OutputBufFull) {
} else { let data = unsafe {ports.data_port.read()};
println!("Spurious interrupt"); 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()
}
} }

View File

@ -1,11 +1,11 @@
mod controller; mod controller;
use std::os::mikros::{ipc, syscalls}; use std::{os::mikros::{ipc, syscalls}, sync::OnceLock};
use controller::Ps2Controller; use controller::Ps2Controller;
use parking_lot::Mutex; use pc_keyboard::{ScancodeSet, ScancodeSet2};
static CONTROLLER: Mutex<Option<Ps2Controller>> = Mutex::new(None); static CONTROLLER: OnceLock<Ps2Controller> = OnceLock::new();
fn main() { fn main() {
dbg!(syscalls::get_pid()); dbg!(syscalls::get_pid());
@ -53,20 +53,69 @@ fn main() {
} }
} }
if controller.port1_ok() { syscalls::irq_register(1).unwrap();
controller.write_port1(0xFF);
}
*CONTROLLER.lock() = Some(controller); controller.flush_output_buffer();
CONTROLLER.get_or_init(move || controller);
let controller = CONTROLLER.get().unwrap();
ipc::register_callback(2, |_msg| { ipc::register_callback(2, |_msg| {
println!("Keyboard interrupt"); if let Some(controller) = CONTROLLER.get() {
if let Some(controller) = CONTROLLER.lock().as_mut() {
controller.handle_interrupt(); controller.handle_interrupt();
} }
}); });
syslog_client.send_text_message("ps2", "Setting keyboard to scan code set 2").unwrap();
controller.write_port1(0xF5);
loop { 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);
}
} }
} }