From c4935a14776b447dc7f533102e4e2b4679a92606 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Sun, 18 Nov 2018 19:20:26 +0800 Subject: [PATCH] use `pc-keyboard` crate and enable keyboard again for x86 --- kernel/Cargo.lock | 7 + kernel/Cargo.toml | 1 + kernel/src/arch/x86_64/driver/keyboard.rs | 36 ++++ .../arch/x86_64/driver/keyboard/keyboard.c | 165 ------------------ kernel/src/arch/x86_64/driver/keyboard/mod.rs | 15 -- kernel/src/arch/x86_64/driver/pit.rs | 4 +- kernel/src/arch/x86_64/interrupt/handler.rs | 7 +- 7 files changed, 49 insertions(+), 186 deletions(-) create mode 100644 kernel/src/arch/x86_64/driver/keyboard.rs delete mode 100644 kernel/src/arch/x86_64/driver/keyboard/keyboard.c delete mode 100644 kernel/src/arch/x86_64/driver/keyboard/mod.rs diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index ca9d5a1..8042f17 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -146,6 +146,11 @@ name = "os_bootinfo" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "pc-keyboard" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "pulldown-cmark" version = "0.0.3" @@ -280,6 +285,7 @@ dependencies = [ "linked_list_allocator 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "once 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "pc-keyboard 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "riscv 0.3.0 (git+https://github.com/riscv-and-rust-and-decaf/riscv)", @@ -415,6 +421,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum once 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "931fb7a4cf34610cf6cbe58d52a8ca5ef4c726d4e2e178abd0dc13a6551c6d73" "checksum os_bootinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "66481dbeb5e773e7bd85b63cd6042c30786f834338288c5ec4f3742673db360a" +"checksum pc-keyboard 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fff50ab09ba31bcebc0669f4e64c0952fae1acdca9e6e0587e68e4e8443808ac" "checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "checksum raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "30a9d219c32c9132f7be513c18be77c9881c7107d2ab5569d205a6a0f0e6dc7d" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index d37a0d1..8e4b8ab 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -38,6 +38,7 @@ x86_64 = "0.3" raw-cpuid = "6.0" redox_syscall = "0.1" uart_16550 = "0.1" +pc-keyboard = "0.3" [target.'cfg(target_arch = "riscv32")'.dependencies] riscv = { git = "https://github.com/riscv-and-rust-and-decaf/riscv" } diff --git a/kernel/src/arch/x86_64/driver/keyboard.rs b/kernel/src/arch/x86_64/driver/keyboard.rs new file mode 100644 index 0000000..2ccac9e --- /dev/null +++ b/kernel/src/arch/x86_64/driver/keyboard.rs @@ -0,0 +1,36 @@ +extern crate pc_keyboard; + +use spin::Mutex; +use x86_64::instructions::port::Port; +use self::pc_keyboard::{Keyboard, ScancodeSet1, DecodedKey, layouts}; + +pub fn init() { + assert_has_not_been_called!("keyboard::init must be called only once"); + + use arch::interrupt::consts::*; + use arch::interrupt::enable_irq; + enable_irq(IRQ_KBD); +} + +/// Receive character from keyboard +/// Should be called on every interrupt +pub fn receive() -> Option { + lazy_static! { + static ref KEYBOARD: Mutex> = + Mutex::new(Keyboard::new(layouts::Us104Key, ScancodeSet1)); + } + + let mut keyboard = KEYBOARD.lock(); + let port = Port::::new(0x60); + + let scancode = 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) => return Some(character), + DecodedKey::RawKey(key) => {}, // TODO: handle RawKey from keyboard + } + } + } + None +} \ No newline at end of file diff --git a/kernel/src/arch/x86_64/driver/keyboard/keyboard.c b/kernel/src/arch/x86_64/driver/keyboard/keyboard.c deleted file mode 100644 index d8b75ff..0000000 --- a/kernel/src/arch/x86_64/driver/keyboard/keyboard.c +++ /dev/null @@ -1,165 +0,0 @@ -// xv6 x86_64 kbd.c - -// PC keyboard interface constants - -#define KBSTATP 0x64 // kbd controller status port(I) -#define KBS_DIB 0x01 // kbd data in buffer -#define KBDATAP 0x60 // kbd data port(I) - -#define NO 0 - -#define SHIFT (1<<0) -#define CTL (1<<1) -#define ALT (1<<2) - -#define CAPSLOCK (1<<3) -#define NUMLOCK (1<<4) -#define SCROLLLOCK (1<<5) - -#define E0ESC (1<<6) - -// Special keycodes -#define KEY_HOME 0xE0 -#define KEY_END 0xE1 -#define KEY_UP 0xE2 -#define KEY_DN 0xE3 -#define KEY_LF 0xE4 -#define KEY_RT 0xE5 -#define KEY_PGUP 0xE6 -#define KEY_PGDN 0xE7 -#define KEY_INS 0xE8 -#define KEY_DEL 0xE9 - -// C('A') == Control-A -#define C(x) (x - '@') - -typedef unsigned char uchar; -typedef unsigned short ushort; -typedef unsigned int uint; - -static inline uchar -inb(ushort port) -{ - uchar data; - - asm volatile("in %1,%0" : "=a" (data) : "d" (port)); - return data; -} - -static uchar shiftcode[256] = - { - [0x1D] = CTL, - [0x2A] = SHIFT, - [0x36] = SHIFT, - [0x38] = ALT, - [0x9D] = CTL, - [0xB8] = ALT - }; - -static uchar togglecode[256] = - { - [0x3A] = CAPSLOCK, - [0x45] = NUMLOCK, - [0x46] = SCROLLLOCK - }; - -static uchar normalmap[256] = - { - NO, 0x1B, '1', '2', '3', '4', '5', '6', // 0x00 - '7', '8', '9', '0', '-', '=', '\b', '\t', - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', // 0x10 - 'o', 'p', '[', ']', '\n', NO, 'a', 's', - 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', // 0x20 - '\'', '`', NO, '\\', 'z', 'x', 'c', 'v', - 'b', 'n', 'm', ',', '.', '/', NO, '*', // 0x30 - NO, ' ', NO, NO, NO, NO, NO, NO, - NO, NO, NO, NO, NO, NO, NO, '7', // 0x40 - '8', '9', '-', '4', '5', '6', '+', '1', - '2', '3', '0', '.', NO, NO, NO, NO, // 0x50 - [0x9C] = '\n', // KP_Enter - [0xB5] = '/', // KP_Div - [0xC8] = KEY_UP, [0xD0] = KEY_DN, - [0xC9] = KEY_PGUP, [0xD1] = KEY_PGDN, - [0xCB] = KEY_LF, [0xCD] = KEY_RT, - [0x97] = KEY_HOME, [0xCF] = KEY_END, - [0xD2] = KEY_INS, [0xD3] = KEY_DEL - }; - -static uchar shiftmap[256] = - { - NO, 033, '!', '@', '#', '$', '%', '^', // 0x00 - '&', '*', '(', ')', '_', '+', '\b', '\t', - 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', // 0x10 - 'O', 'P', '{', '}', '\n', NO, 'A', 'S', - 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', // 0x20 - '"', '~', NO, '|', 'Z', 'X', 'C', 'V', - 'B', 'N', 'M', '<', '>', '?', NO, '*', // 0x30 - NO, ' ', NO, NO, NO, NO, NO, NO, - NO, NO, NO, NO, NO, NO, NO, '7', // 0x40 - '8', '9', '-', '4', '5', '6', '+', '1', - '2', '3', '0', '.', NO, NO, NO, NO, // 0x50 - [0x9C] = '\n', // KP_Enter - [0xB5] = '/', // KP_Div - [0xC8] = KEY_UP, [0xD0] = KEY_DN, - [0xC9] = KEY_PGUP, [0xD1] = KEY_PGDN, - [0xCB] = KEY_LF, [0xCD] = KEY_RT, - [0x97] = KEY_HOME, [0xCF] = KEY_END, - [0xD2] = KEY_INS, [0xD3] = KEY_DEL - }; - -static uchar ctlmap[256] = - { - NO, NO, NO, NO, NO, NO, NO, NO, - NO, NO, NO, NO, NO, NO, NO, NO, - C('Q'), C('W'), C('E'), C('R'), C('T'), C('Y'), C('U'), C('I'), - C('O'), C('P'), NO, NO, '\r', NO, C('A'), C('S'), - C('D'), C('F'), C('G'), C('H'), C('J'), C('K'), C('L'), NO, - NO, NO, NO, C('\\'), C('Z'), C('X'), C('C'), C('V'), - C('B'), C('N'), C('M'), NO, NO, C('/'), NO, NO, - [0x9C] = '\r', // KP_Enter - [0xB5] = C('/'), // KP_Div - [0xC8] = KEY_UP, [0xD0] = KEY_DN, - [0xC9] = KEY_PGUP, [0xD1] = KEY_PGDN, - [0xCB] = KEY_LF, [0xCD] = KEY_RT, - [0x97] = KEY_HOME, [0xCF] = KEY_END, - [0xD2] = KEY_INS, [0xD3] = KEY_DEL - }; - -int -kbdgetc(void) { - static uint shift; - static uchar *charcode[4] = { - normalmap, shiftmap, ctlmap, ctlmap - }; - uint st, data, c; - - st = inb(KBSTATP); - if ((st & KBS_DIB) == 0) - return -1; - data = inb(KBDATAP); - - if (data == 0xE0) { - shift |= E0ESC; - return 0; - } else if (data & 0x80) { - // Key released - data = (shift & E0ESC ? data : data & 0x7F); - shift &= ~(shiftcode[data] | E0ESC); - return 0; - } else if (shift & E0ESC) { - // Last character was an E0 escape; or with 0x80 - data |= 0x80; - shift &= ~E0ESC; - } - - shift |= shiftcode[data]; - shift ^= togglecode[data]; - c = charcode[shift & (CTL | SHIFT)][data]; - if (shift & CAPSLOCK) { - if ('a' <= c && c <= 'z') - c += 'A' - 'a'; - else if ('A' <= c && c <= 'Z') - c += 'a' - 'A'; - } - return c; -} \ No newline at end of file diff --git a/kernel/src/arch/x86_64/driver/keyboard/mod.rs b/kernel/src/arch/x86_64/driver/keyboard/mod.rs deleted file mode 100644 index 88012ba..0000000 --- a/kernel/src/arch/x86_64/driver/keyboard/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -pub fn init() { - assert_has_not_been_called!("keyboard::init must be called only once"); - - use arch::interrupt::consts::*; - use arch::interrupt::enable_irq; - enable_irq(IRQ_KBD); -} - -pub fn get() -> i32 { - 0 -} - -extern { - fn kbdgetc() -> i32; -} \ No newline at end of file diff --git a/kernel/src/arch/x86_64/driver/pit.rs b/kernel/src/arch/x86_64/driver/pit.rs index 2b85923..83e9532 100644 --- a/kernel/src/arch/x86_64/driver/pit.rs +++ b/kernel/src/arch/x86_64/driver/pit.rs @@ -1,10 +1,8 @@ use super::redox_syscall::io::{Io, Pio}; -static mut PIT: Pit = Pit::new(0x40); - pub fn init() { assert_has_not_been_called!("pit::init must be called only once"); - unsafe{ PIT.init(100); } + Pit::new(0x40).init(100); info!("pit: init end"); } diff --git a/kernel/src/arch/x86_64/interrupt/handler.rs b/kernel/src/arch/x86_64/interrupt/handler.rs index 23027e3..4d60f68 100644 --- a/kernel/src/arch/x86_64/interrupt/handler.rs +++ b/kernel/src/arch/x86_64/interrupt/handler.rs @@ -121,9 +121,10 @@ fn page_fault(tf: &mut TrapFrame) { fn keyboard() { use arch::driver::keyboard; - info!("\nInterupt: Keyboard"); - let c = keyboard::get(); - info!("Key = '{}' {}", c as u8 as char, c); + trace!("\nInterupt: Keyboard"); + if let Some(c) = keyboard::receive() { + ::trap::serial(c); + } } fn com1() {