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",
]
[[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",
]

View File

@ -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"

View File

@ -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<u8>,
status_register: PortReadOnly<u8>,
command_register: PortWriteOnly<u8>,
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<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> {
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()
}
}

View File

@ -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<Option<Ps2Controller>> = Mutex::new(None);
static CONTROLLER: OnceLock<Ps2Controller> = 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);
}
}
}