42-archive/kernel-rs/src/keyboard.rs
2018-04-12 19:37:43 +02:00

149 lines
2.8 KiB
Rust

extern crate core;
use cpuio;
use vga;
use io::Pio;
use io::Io;
const MAX_KEYS: usize = 59;
const KEYMAP_US: [[u8; 2]; MAX_KEYS] = [
*b"\0\0",
*b"\0\0",//escape
*b"1!",
*b"2@",
*b"3#",
*b"4$",
*b"5%",
*b"6^",
*b"7&",
*b"8*",
*b"9(",
*b"0)",
*b"-_",
*b"=+",
*b"\0\0",//backspace
*b"\0\0",//tab
*b"qQ",
*b"wW",
*b"eE",
*b"rR",
*b"tT",
*b"yY",
*b"uU",
*b"iI",
*b"oO",
*b"pP",
*b"[{",
*b"]}",
*b"\n\n",
*b"\0\0",//left_control
*b"aA",
*b"sS",
*b"dD",
*b"fF",
*b"gG",
*b"hH",
*b"jJ",
*b"kK",
*b"lL",
*b";:",
*b"'\"",
*b"`~",
*b"\0\0",//left shift
*b"\\|",
*b"zZ",
*b"xX",
*b"cC",
*b"vV",
*b"bB",
*b"nN",
*b"mM",
*b",<",
*b".>",
*b"/?",
*b"\0\0",//right shift
*b"**",
*b"\0\0",//left alt
*b" ",
*b"\0\0",//capslock
];
pub static mut PS2: Ps2 = Ps2::new();
pub struct Ps2 {
status: Pio<u8>,
data: Pio<u8>,
}
impl Ps2 {
pub const fn new() -> Ps2 {
Ps2 {
status: Pio::new(0x64),
data: Pio::new(0x60),
}
}
pub fn clear_buffer(&self) {
let mut buffer: u8 = 0x02;
while buffer & 0x02 != 0 {
self.data.read();
buffer = self.status.read();
}
}
pub fn ps2_8042_reset(&mut self) {
cpuio::cli();
self.clear_buffer();
self.status.write(0xFE);
}
pub fn get_scancode(&self) -> u8 {
let mut scancode = 0;
loop {
if self.data.read() != scancode {
scancode = self.data.read();
if scancode > 0 {
return scancode;
}
}
}
}
}
const TOUCH_RELEASE: u8 = 1 << 7;
fn check_key_state(key: u8) -> (bool, usize) {
if (key & TOUCH_RELEASE) == TOUCH_RELEASE {
(true, (key - TOUCH_RELEASE) as usize)
} else {
(false, key as usize)
}
}
pub fn kbd_callback() {
static mut SHIFT: bool = false;
static mut CTRL: bool = false;
static mut ALT: bool = false;
let scancode = unsafe { PS2.get_scancode() };
let (is_release, scancode) = check_key_state(scancode);
unsafe {
//TODO remove unsafe
match self::KEYMAP_US.get(scancode as usize) {
Some(b"\0\0") => match scancode {
0x2A | 0x36 => SHIFT = !is_release,
0x38 => ALT = !is_release,
0x1D => CTRL = !is_release,
0x0E if !is_release => {
vga::VGA.backspace();
}
_ => {}
},
Some(ascii) if !is_release => {
let sym = if SHIFT { ascii[1] } else { ascii[0] };
vga::VGA.keypress(sym);
}
_ => {}
}
}
}