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",
|
"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",
|
||||||
]
|
]
|
||||||
|
@ -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"
|
||||||
|
@ -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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
69
src/main.rs
69
src/main.rs
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user