Set scancode set 2 and read incoming scancodes
This commit is contained in:
parent
89345100c9
commit
7b7f3e9a23
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -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",
|
||||
]
|
||||
|
@ -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"
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
69
src/main.rs
69
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<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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user