Add kernel::keyboard module

This commit is contained in:
Vincent Ollivier 2020-01-05 20:32:20 +01:00
parent 44c4cfdbd9
commit e36bfbf3de
4 changed files with 82 additions and 21 deletions

View File

@ -1,8 +1,7 @@
use crate::print;
use crate::kernel::{gdt, clock, console};
use crate::{print, kernel};
use lazy_static::lazy_static;
use pic8259_simple::ChainedPics;
use spin;
use spin::Mutex;
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
pub const PIC_1_OFFSET: u8 = 32;
@ -25,14 +24,14 @@ impl InterruptIndex {
}
}
pub static PICS: spin::Mutex<ChainedPics> = spin::Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) });
pub static PICS: Mutex<ChainedPics> = Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) });
lazy_static! {
static ref IDT: InterruptDescriptorTable = {
let mut idt = InterruptDescriptorTable::new();
idt.breakpoint.set_handler_fn(breakpoint_handler);
unsafe {
idt.double_fault.set_handler_fn(double_fault_handler).set_stack_index(gdt::DOUBLE_FAULT_IST_INDEX);
idt.double_fault.set_handler_fn(double_fault_handler).set_stack_index(kernel::gdt::DOUBLE_FAULT_IST_INDEX);
}
idt[InterruptIndex::Timer.as_usize()].set_handler_fn(timer_interrupt_handler);
idt[InterruptIndex::Keyboard.as_usize()].set_handler_fn(keyboard_interrupt_handler);
@ -53,7 +52,7 @@ extern "x86-interrupt" fn double_fault_handler(stack_frame: &mut InterruptStackF
}
extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: &mut InterruptStackFrame) {
clock::tick();
kernel::clock::tick();
unsafe {
PICS.lock().notify_end_of_interrupt(InterruptIndex::Timer.as_u8());
@ -61,23 +60,11 @@ extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: &mut InterruptSt
}
extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: &mut InterruptStackFrame) {
use pc_keyboard::{Keyboard, ScancodeSet1, HandleControl, layouts};
use spin::Mutex;
use x86_64::instructions::port::Port;
lazy_static! {
static ref KEYBOARD: Mutex<Keyboard<layouts::Dvorak104Key, ScancodeSet1>> = Mutex::new(
Keyboard::new(layouts::Dvorak104Key, ScancodeSet1, HandleControl::MapLettersToUnicode)
);
}
let mut keyboard = KEYBOARD.lock();
let mut port = Port::new(0x60);
let scancode: u8 = unsafe { port.read() };
let mut keyboard = kernel::keyboard::KEYBOARD.lock();
let scancode = kernel::keyboard::read_scancode();
if let Ok(Some(key_event)) = keyboard.add_byte(scancode) {
if let Some(key) = keyboard.process_keyevent(key_event) {
console::key_handle(key);
kernel::console::key_handle(key);
}
}

72
src/kernel/keyboard.rs Normal file
View File

@ -0,0 +1,72 @@
//use crate::{print, kernel};
use lazy_static::lazy_static;
use pc_keyboard::{Keyboard, ScancodeSet1, HandleControl, layouts};
use spin::Mutex;
use x86_64::instructions::port::Port;
lazy_static! {
// NOTE: Replace `Dvorak104Key` with `Us104Key` for Qwerty keyboards
// TODO: Support layout change from userspace
pub static ref KEYBOARD: Mutex<Keyboard<layouts::Dvorak104Key, ScancodeSet1>> = Mutex::new(
Keyboard::new(layouts::Dvorak104Key, ScancodeSet1, HandleControl::MapLettersToUnicode)
);
}
/*
pub fn init() {
let mut port = Port::new(0x60);
// Identify
let res = unsafe {
port.write(0xF2 as u8); // Identify
port.read()
};
if res != 0xFA { // 0xFA == ACK, 0xFE == Resend
return init();
}
let res = unsafe {
port.read()
};
print!("[{:.6}] keyboard: identify 0x{:X}\n", kernel::clock::clock_monotonic(), res);
let res = unsafe {
port.read()
};
print!("[{:.6}] keyboard: identify 0x{:X}\n", kernel::clock::clock_monotonic(), res);
// Self-test
let res = unsafe {
port.write(0xFF as u8); // Reset and self-test
port.read()
};
if res != 0xFA { // 0xFA == ACK, 0xFE == Resend
return init();
}
let res = unsafe {
port.read()
};
if res == 0xAA { // 0xAA == Passed, 0xFC or 0xFD == Failed, 0xFE == Resend
print!("[{:.6}] keyboard: self test passed\n", kernel::clock::clock_monotonic());
} else {
print!("[{:.6}] keyboard: self test failed (0x{:X})\n", kernel::clock::clock_monotonic(), res);
}
// Switch to scancode set 2
// TODO: Not working because PS/2 controller is configured to do the translation (0xAB, 0x41)
let res = unsafe {
port.write(0xF0 as u8); // Set current scancode set
port.write(0x02 as u8); // to 2
port.read()
};
if res != 0xFA { // 0xFA == ACK, 0xFE == Resend
return init();
}
print!("[{:.6}] keyboard: switch to scancode set 2\n", kernel::clock::clock_monotonic());
}
*/
pub fn read_scancode() -> u8 {
let mut port = Port::new(0x60);
unsafe {
port.read()
}
}

View File

@ -4,6 +4,7 @@ pub mod console;
pub mod fs;
pub mod gdt;
pub mod interrupts;
pub mod keyboard;
pub mod random;
pub mod sleep;
pub mod vga;

View File

@ -5,6 +5,7 @@ pub mod kernel;
pub mod user;
pub fn init() {
//kernel::keyboard::init();
kernel::gdt::init();
kernel::interrupts::init_idt();
unsafe { kernel::interrupts::PICS.lock().initialize() };