use crate::arch::interrupts::{idt_set_gate, InterruptIndex}; // Shitty keyboard driver #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] use crate::arch::{ interrupts, io::{inb, outb}, }; use core::sync::atomic::{AtomicBool, Ordering}; const KBD_DATA_PORT: u16 = 0x60; const KBD_COMMAND_AND_STATUS_PORT: u16 = 0x64; pub struct Key<'a> { pub pressed: bool, pub name: &'a str, pub character: Option, } static EXTENDED_KEY: AtomicBool = AtomicBool::new(false); #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub extern "x86-interrupt" fn keyboard_interrupt_handler() { interrupts::PICS .lock() .write() .notify_end_of_interrupt(interrupts::InterruptIndex::Keyboard.as_u8()); let scancode = inb(KBD_DATA_PORT); let key = parse_key(scancode); if let Some(key) = key { crate::usr::shell::handle_key(key) } } #[derive(Debug)] pub enum KBDError { TestFailed, } pub fn init() -> Result<(), KBDError> { // flush output buffer while (inb(KBD_COMMAND_AND_STATUS_PORT) & 1) != 0 { inb(KBD_DATA_PORT); } // Disable PS/2 Devices (second then first) outb(KBD_COMMAND_AND_STATUS_PORT, 0xA7); outb(KBD_COMMAND_AND_STATUS_PORT, 0xAD); // TODO: Test the controller correctly idt_set_gate( InterruptIndex::Keyboard.as_u8(), crate::drivers::keyboard::keyboard_interrupt_handler as u64, ); // Enable PS/2 Devices (second then first) outb(KBD_COMMAND_AND_STATUS_PORT, 0xA8); outb(KBD_COMMAND_AND_STATUS_PORT, 0xAE); // Reset Devices inb(KBD_COMMAND_AND_STATUS_PORT); return Ok(()); } #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn set_leds(led_byte: u8) { // Command bytes outb(KBD_DATA_PORT, 0xED); while !(inb(KBD_DATA_PORT) == 0xfa) {} // Data byte outb(KBD_DATA_PORT, led_byte); } fn parse_key(mut scancode: u8) -> Option> { if scancode == 0xE0 { EXTENDED_KEY.store(!EXTENDED_KEY.load(Ordering::SeqCst), Ordering::SeqCst); return None; } let pressed = scancode & 0x80 == 0x0; scancode &= !(1 << 7); let key: Option>; match scancode { 0x01 => { key = Some(Key { pressed, name: "Esc", character: Some('\u{001B}'), }); } 0x02 => { return Some(Key { pressed, name: "1", character: Some('1'), }); } 0x03 => { return Some(Key { pressed, name: "2", character: Some('2'), }); } 0x04 => { return Some(Key { pressed, name: "3", character: Some('3'), }); } 0x05 => { return Some(Key { pressed, name: "4", character: Some('4'), }); } 0x06 => { return Some(Key { pressed, name: "5", character: Some('5'), }); } 0x07 => { return Some(Key { pressed, name: "6", character: Some('6'), }); } 0x08 => { return Some(Key { pressed, name: "7", character: Some('7'), }); } 0x09 => { return Some(Key { pressed, name: "8", character: Some('8'), }); } 0x0A => { return Some(Key { pressed, name: "9", character: Some('9'), }); } 0x0B => { return Some(Key { pressed, name: "0", character: Some('0'), }); } 0x0C => { return Some(Key { pressed, name: "-", character: Some('-'), }); } 0x0D => { return Some(Key { pressed, name: "=", character: Some('='), }); } 0x0E => { return Some(Key { pressed, name: "Backspace", character: Some('\u{0008}'), }); } 0x0F => { return Some(Key { pressed, name: "Tab", character: Some('\u{0009}'), }); } 0x10 => { return Some(Key { pressed, name: "q", character: Some('q'), }); } 0x11 => { return Some(Key { pressed, name: "w", character: Some('w'), }); } 0x12 => { return Some(Key { pressed, name: "e", character: Some('e'), }); } 0x13 => { return Some(Key { pressed, name: "r", character: Some('r'), }); } 0x14 => { return Some(Key { pressed, name: "t", character: Some('t'), }); } 0x15 => { return Some(Key { pressed, name: "y", character: Some('y'), }); } 0x16 => { return Some(Key { pressed, name: "u", character: Some('u'), }); } 0x17 => { return Some(Key { pressed, name: "i", character: Some('i'), }); } 0x18 => { return Some(Key { pressed, name: "o", character: Some('o'), }); } 0x19 => { return Some(Key { pressed, name: "p", character: Some('p'), }); } 0x1A => { return Some(Key { pressed, name: "[", character: Some('['), }); } 0x1B => { return Some(Key { pressed, name: "]", character: Some(']'), }); } 0x1C => { return Some(Key { pressed, name: "Enter", character: Some('\u{000A}'), }); } 0x1D => { if EXTENDED_KEY.load(Ordering::SeqCst) == true { return Some(Key { pressed, name: "RCtrl", character: None, }); } return Some(Key { pressed, name: "LCtrl", character: None, }); } 0x1E => { return Some(Key { pressed, name: "a", character: Some('a'), }); } 0x1F => { return Some(Key { pressed, name: "s", character: Some('s'), }); } 0x20 => { return Some(Key { pressed, name: "d", character: Some('d'), }); } 0x21 => { return Some(Key { pressed, name: "f", character: Some('f'), }); } 0x22 => { return Some(Key { pressed, name: "g", character: Some('g'), }); } 0x23 => { return Some(Key { pressed, name: "h", character: Some('h'), }); } 0x24 => { return Some(Key { pressed, name: "j", character: Some('j'), }); } 0x25 => { return Some(Key { pressed, name: "k", character: Some('k'), }); } 0x26 => { return Some(Key { pressed, name: "l", character: Some('l'), }); } 0x27 => { return Some(Key { pressed, name: ";", character: Some(';'), }); } 0x28 => { return Some(Key { pressed, name: "'", character: Some('\''), }); } 0x29 => { return Some(Key { pressed, name: "`", character: Some('`'), }); } 0x2A => { return Some(Key { pressed, name: "LShift", character: None, }); } 0x2B => { return Some(Key { pressed, name: "\\", character: Some('\\'), }); } 0x2C => { return Some(Key { pressed, name: "z", character: Some('z'), }); } 0x2D => { return Some(Key { pressed, name: "x", character: Some('x'), }); } 0x2E => { return Some(Key { pressed, name: "c", character: Some('c'), }); } 0x2F => { return Some(Key { pressed, name: "v", character: Some('v'), }); } 0x30 => { return Some(Key { pressed, name: "b", character: Some('b'), }); } 0x31 => { return Some(Key { pressed, name: "n", character: Some('n'), }); } 0x32 => { return Some(Key { pressed, name: "m", character: Some('m'), }); } 0x33 => { return Some(Key { pressed, name: ",", character: Some(','), }); } 0x34 => { return Some(Key { pressed, name: ".", character: Some('.'), }); } 0x35 => { return Some(Key { pressed, name: "/", character: Some('/'), }); } 0x36 => { return Some(Key { pressed, name: "RShift", character: None, }); } 0x37 => { return Some(Key { pressed, name: "*", character: Some('*'), }); } 0x38 => { return Some(Key { pressed, name: "Alt", character: None, }); } 0x39 => { return Some(Key { pressed, name: " ", character: Some(' '), }); } 0x3A => { return Some(Key { pressed, name: "CapsLock", character: None, }); } 0x3B => { return Some(Key { pressed, name: "F1", character: None, }); } 0x3C => { return Some(Key { pressed, name: "F2", character: None, }); } 0x3D => { return Some(Key { pressed, name: "F3", character: None, }); } 0x3E => { return Some(Key { pressed, name: "F4", character: None, }); } 0x3F => { return Some(Key { pressed, name: "F5", character: None, }); } 0x40 => { return Some(Key { pressed, name: "F6", character: None, }); } 0x41 => { return Some(Key { pressed, name: "F7", character: None, }); } 0x42 => { return Some(Key { pressed, name: "F8", character: None, }); } 0x43 => { return Some(Key { pressed, name: "F9", character: None, }); } 0x44 => { return Some(Key { pressed, name: "F10", character: None, }); } 0x45 => { return Some(Key { pressed, name: "NumLock", character: None, }); } 0x46 => { return Some(Key { pressed, name: "ScrLock", character: None, }); } 0x47 => { if EXTENDED_KEY.load(Ordering::SeqCst) == true { return Some(Key { pressed, name: "Home", character: None, }); } return Some(Key { pressed, name: "Keypad 7", character: Some('7'), }); } 0x48 => { if EXTENDED_KEY.load(Ordering::SeqCst) == true { return Some(Key { pressed, name: "CurUp", character: None, }); } return Some(Key { pressed, name: "Keypad 8", character: Some('8'), }); } 0x49 => { if EXTENDED_KEY.load(Ordering::SeqCst) == true { return Some(Key { pressed, name: "PgUp", character: None, }); } return Some(Key { pressed, name: "Keypad 9", character: Some('9'), }); } 0x4A => { return Some(Key { pressed, name: "-", character: Some('-'), }); } 0x4B => { if EXTENDED_KEY.load(Ordering::SeqCst) == true { return Some(Key { pressed, name: "CurLeft", character: None, }); } return Some(Key { pressed, name: "Keypad 4", character: Some('4'), }); } 0x4C => { return Some(Key { pressed, name: "Keypad 5", character: Some('5'), }); } 0x4D => { if EXTENDED_KEY.load(Ordering::SeqCst) == true { return Some(Key { pressed, name: "CurRight", character: None, }); } return Some(Key { pressed, name: "Keypad 6", character: Some('6'), }); } 0x4E => { return Some(Key { pressed, name: "+", character: Some('+'), }); } 0x4F => { if EXTENDED_KEY.load(Ordering::SeqCst) == true { return Some(Key { pressed, name: "End", character: None, }); } return Some(Key { pressed, name: "Keypad 1", character: Some('1'), }); } 0x50 => { if EXTENDED_KEY.load(Ordering::SeqCst) == true { return Some(Key { pressed, name: "CurDown", character: None, }); } return Some(Key { pressed, name: "Keypad 2", character: Some('2'), }); } 0x51 => { if EXTENDED_KEY.load(Ordering::SeqCst) == true { return Some(Key { pressed, name: "PgDn", character: None, }); } return Some(Key { pressed, name: "Keypad 3", character: Some('3'), }); } 0x52 => { if EXTENDED_KEY.load(Ordering::SeqCst) == true { return Some(Key { pressed, name: "Insert", character: None, }); } return Some(Key { pressed, name: "Keypad 0", character: Some('0'), }); } 0x53 => { if EXTENDED_KEY.load(Ordering::SeqCst) == true { return Some(Key { pressed, name: "Del", character: None, }); } return Some(Key { pressed, name: "Keypad .", character: Some('.'), }); } 0x57 => { return Some(Key { pressed, name: "F11", character: None, }); } 0x58 => { return Some(Key { pressed, name: "F12", character: None, }); } _ => key = None, } return key; }