diff --git a/Cargo.lock b/Cargo.lock index 6bba807..3e329a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,6 +19,7 @@ name = "julios" version = "0.1.0" dependencies = [ "lazy_static", + "pc-keyboard", "pic8259", "spin", "volatile 0.2.7", @@ -34,6 +35,12 @@ dependencies = [ "spin", ] +[[package]] +name = "pc-keyboard" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6f2d937e3b8d63449b01401e2bae4041bc9dd1129c2e3e0d239407cf6635ac" + [[package]] name = "pic8259" version = "0.10.2" diff --git a/Cargo.toml b/Cargo.toml index 4dd8fb2..2846c1b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ volatile = "0.2.6" spin = "0.5.2" x86_64 = "0.14.2" pic8259 = "0.10.1" +pc-keyboard = "0.5.0" [dependencies.lazy_static] version = "1.0" diff --git a/src/interrupts.rs b/src/interrupts.rs index 48d05b9..0dbcdaa 100644 --- a/src/interrupts.rs +++ b/src/interrupts.rs @@ -1,18 +1,23 @@ use crate::gdt; -use crate::{println, print}; use crate::vga::{self, Color, ColorCode}; +use crate::{print, println}; use lazy_static::lazy_static; +use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1}; use pic8259::ChainedPics; -use spin; +use spin::{self, Mutex}; +use x86_64::instructions::port::Port; use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame}; pub const PIC_1_OFFSET: u8 = 32; pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8; +pub const PS2_CONTROLLER_PORT: u16 = 0x60; + #[derive(Debug, Clone, Copy)] #[repr(u8)] pub enum InterruptIndex { Timer = PIC_1_OFFSET, + Keyboard, } impl InterruptIndex { @@ -37,8 +42,8 @@ lazy_static! { .set_handler_fn(double_fault_handler) .set_stack_index(gdt::DOUBLE_FAULT_IST_INDEX); } - idt[InterruptIndex::Timer.as_usize()] - .set_handler_fn(timer_interrupt_handler); + idt[InterruptIndex::Timer.as_usize()].set_handler_fn(timer_interrupt_handler); + idt[InterruptIndex::Keyboard.as_usize()].set_handler_fn(keyboard_interrupt_handler); idt }; } @@ -46,6 +51,12 @@ lazy_static! { pub fn init_idt() { println!("Loading IDT"); IDT.load(); + + println!("Initializing PIC"); + unsafe { PICS.lock().initialize() }; + + println!("Enabling interrupts"); + x86_64::instructions::interrupts::enable(); } extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) { @@ -62,11 +73,36 @@ extern "x86-interrupt" fn double_fault_handler( panic!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame); } -extern "x86-interrupt" fn timer_interrupt_handler( - _stack_frame: InterruptStackFrame) -{ +extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFrame) { print!("."); unsafe { - PICS.lock().notify_end_of_interrupt(InterruptIndex::Timer.as_u8()); + PICS.lock() + .notify_end_of_interrupt(InterruptIndex::Timer.as_u8()); + } +} + +extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStackFrame) { + lazy_static! { + static ref KEYBOARD: Mutex> = + Mutex::new(Keyboard::new(layouts::Us104Key, ScancodeSet1, + HandleControl::Ignore) + ); + } + + let mut keyboard = KEYBOARD.lock(); + let mut port = Port::new(PS2_CONTROLLER_PORT); + let scancode: u8 = unsafe { port.read() }; + + if let Ok(Some(key_event)) = keyboard.add_byte(scancode) { + if let Some(key) = keyboard.process_keyevent(key_event) { + match key { + DecodedKey::Unicode(character) => print!("{}", character), + DecodedKey::RawKey(key) => print!("{:?}", key), + } + } + } + unsafe { + PICS.lock() + .notify_end_of_interrupt(InterruptIndex::Keyboard.as_u8()); } } diff --git a/src/lib.rs b/src/lib.rs index 446e338..8c2ddcb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,8 +28,6 @@ pub fn init() { println!("Starting init"); gdt::init_gdt(); interrupts::init_idt(); - unsafe { interrupts::PICS.lock().initialize() }; - x86_64::instructions::interrupts::enable(); vga::change_color(ColorCode::new(Color::LightGreen, Color::Black)); }