forked from Bananymous/banan-os
Kernel: Improve keyboard input by a lot
Seems to work on my 2 computerss
This commit is contained in:
parent
7ebe727a29
commit
e62a626b39
|
@ -36,6 +36,7 @@ kernel/Keyboard.o \
|
||||||
kernel/kmalloc.o \
|
kernel/kmalloc.o \
|
||||||
kernel/PIC.o \
|
kernel/PIC.o \
|
||||||
kernel/PIT.o \
|
kernel/PIT.o \
|
||||||
|
kernel/RTC.o \
|
||||||
kernel/Serial.o \
|
kernel/Serial.o \
|
||||||
kernel/SSP.o \
|
kernel/SSP.o \
|
||||||
icxxabi.o \
|
icxxabi.o \
|
||||||
|
|
|
@ -18,18 +18,30 @@ namespace Keyboard
|
||||||
Dollar, Pound, Euro, Currency, Enter, Space, Tab, Backspace, LessThan, MoreThan, Tick, BackTick, Section, Half, At, Pipe,
|
Dollar, Pound, Euro, Currency, Enter, Space, Tab, Backspace, LessThan, MoreThan, Tick, BackTick, Section, Half, At, Pipe,
|
||||||
End, Home, Insert, Delete, Super, PageUp, PageDown, PrintScreen, Left, Right, Up, Down,
|
End, Home, Insert, Delete, Super, PageUp, PageDown, PrintScreen, Left, Right, Up, Down,
|
||||||
|
|
||||||
LeftShift, RightShift, CapsLock, Ctrl, Alt, NumLock, Escape,
|
LeftShift, RightShift, CapsLock, LeftCtrl, RightCtrl, LeftAlt, RightAlt, NumLock, ScrollLock, Escape,
|
||||||
|
|
||||||
Numpad0, Numpad1, Numpad2, Numpad3, Numpad4, Numpad5, Numpad6, Numpad7, Numpad8, Numpad9,
|
Numpad0, Numpad1, Numpad2, Numpad3, Numpad4, Numpad5, Numpad6, Numpad7, Numpad8, Numpad9,
|
||||||
NumpadComma, NumpadPlus, NumpadMult, NumpadDiv, NumpadMinus,
|
NumpadSep, NumpadPlus, NumpadMult, NumpadDiv, NumpadMinus, NumpadEnter,
|
||||||
|
|
||||||
|
Mute, VolumeDown, VolumeUp, Calculator, PlayPause, Stop, PreviousTrack, NextTrack,
|
||||||
|
|
||||||
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
|
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
|
||||||
|
|
||||||
Count
|
Count
|
||||||
};
|
};
|
||||||
|
|
||||||
void initialize(void (*callback)(Key, uint8_t, bool));
|
struct KeyEvent
|
||||||
|
{
|
||||||
|
Key key;
|
||||||
|
uint8_t modifiers;
|
||||||
|
bool pressed;
|
||||||
|
};
|
||||||
|
|
||||||
char key_to_ascii(Key, uint8_t);
|
bool initialize(void (*callback)(KeyEvent));
|
||||||
|
void update_keyboard();
|
||||||
|
|
||||||
|
char key_event_to_ascii(KeyEvent);
|
||||||
|
|
||||||
|
void led_disco();
|
||||||
|
|
||||||
}
|
}
|
|
@ -5,412 +5,519 @@
|
||||||
namespace Keyboard
|
namespace Keyboard
|
||||||
{
|
{
|
||||||
|
|
||||||
static Key scs2_to_key_altgr[0xFF]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
constexpr Key scan_code_to_key_extended[0xFF]
|
||||||
{
|
{
|
||||||
Key::INVALID,
|
Key::INVALID,
|
||||||
Key::F9,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::F5,
|
|
||||||
Key::F3,
|
|
||||||
Key::F1,
|
|
||||||
Key::F2,
|
|
||||||
Key::F12,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::F10,
|
|
||||||
Key::F8,
|
|
||||||
Key::F6,
|
|
||||||
Key::F4,
|
|
||||||
Key::Tab,
|
|
||||||
Key::None,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Alt,
|
|
||||||
Key::LeftShift,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Ctrl,
|
|
||||||
Key::Q,
|
|
||||||
Key::None,
|
|
||||||
Key::INVALID,
|
Key::INVALID,
|
||||||
Key::INVALID,
|
Key::INVALID,
|
||||||
Key::INVALID,
|
Key::INVALID,
|
||||||
Key::None,
|
Key::INVALID,
|
||||||
Key::None,
|
Key::INVALID,
|
||||||
Key::None,
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::PreviousTrack,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::NextTrack,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::NumpadEnter,
|
||||||
|
Key::RightCtrl,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::Mute,
|
||||||
|
Key::Calculator,
|
||||||
|
Key::PlayPause,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::Stop,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::VolumeDown,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::VolumeUp,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::NumpadDiv,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::RightAlt,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::Home,
|
||||||
|
Key::Up,
|
||||||
|
Key::PageUp,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::Left,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::Right,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::End,
|
||||||
|
Key::Down,
|
||||||
|
Key::PageDown,
|
||||||
|
Key::Insert,
|
||||||
|
Key::Delete,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::Super,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
Key::INVALID,
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr Key scan_code_to_key_altgr[0xFF]
|
||||||
|
{
|
||||||
|
Key::INVALID,
|
||||||
|
Key::Escape,
|
||||||
Key::None,
|
Key::None,
|
||||||
Key::At,
|
Key::At,
|
||||||
Key::INVALID,
|
Key::Pound,
|
||||||
Key::INVALID,
|
Key::Dollar,
|
||||||
Key::None,
|
Key::None,
|
||||||
Key::None,
|
Key::None,
|
||||||
|
Key::OpenBracket,
|
||||||
|
Key::OpenBrace,
|
||||||
|
Key::CloseBrace,
|
||||||
|
Key::CloseBracket,
|
||||||
|
Key::BackSlash,
|
||||||
|
Key::BackTick,
|
||||||
|
Key::Backspace,
|
||||||
|
Key::Tab,
|
||||||
|
Key::None,
|
||||||
Key::None,
|
Key::None,
|
||||||
Key::Euro,
|
Key::Euro,
|
||||||
Key::Dollar,
|
|
||||||
Key::Pound,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Space,
|
|
||||||
Key::None,
|
|
||||||
Key::None,
|
|
||||||
Key::None,
|
|
||||||
Key::None,
|
|
||||||
Key::None,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::None,
|
Key::None,
|
||||||
Key::None,
|
Key::None,
|
||||||
Key::None,
|
Key::None,
|
||||||
Key::None,
|
Key::None,
|
||||||
Key::None,
|
Key::None,
|
||||||
Key::None,
|
Key::None,
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::None,
|
Key::None,
|
||||||
Key::None,
|
Key::None,
|
||||||
Key::None,
|
|
||||||
Key::OpenBrace,
|
|
||||||
Key::OpenBracket,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::None,
|
|
||||||
Key::None,
|
|
||||||
Key::None,
|
|
||||||
Key::None,
|
|
||||||
Key::CloseBrace,
|
|
||||||
Key::CloseBracket,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::None,
|
|
||||||
Key::None,
|
|
||||||
Key::None,
|
|
||||||
Key::None,
|
|
||||||
Key::None,
|
|
||||||
Key::BackSlash,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::None,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::None,
|
|
||||||
Key::None,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::CapsLock,
|
|
||||||
Key::RightShift,
|
|
||||||
Key::Enter,
|
|
||||||
Key::Tilde,
|
Key::Tilde,
|
||||||
Key::INVALID,
|
Key::Enter,
|
||||||
|
Key::LeftCtrl,
|
||||||
Key::None,
|
Key::None,
|
||||||
Key::INVALID,
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::LeftShift,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::RightShift,
|
||||||
|
Key::NumpadMult,
|
||||||
|
Key::LeftAlt,
|
||||||
|
Key::Space,
|
||||||
|
Key::CapsLock,
|
||||||
|
Key::F1,
|
||||||
|
Key::F2,
|
||||||
|
Key::F3,
|
||||||
|
Key::F4,
|
||||||
|
Key::F5,
|
||||||
|
Key::F6,
|
||||||
|
Key::F7,
|
||||||
|
Key::F8,
|
||||||
|
Key::F9,
|
||||||
|
Key::F10,
|
||||||
|
Key::NumLock,
|
||||||
|
Key::ScrollLock,
|
||||||
|
Key::Numpad7,
|
||||||
|
Key::Numpad8,
|
||||||
|
Key::Numpad9,
|
||||||
|
Key::NumpadMinus,
|
||||||
|
Key::Numpad4,
|
||||||
|
Key::Numpad5,
|
||||||
|
Key::Numpad6,
|
||||||
|
Key::NumpadPlus,
|
||||||
|
Key::Numpad1,
|
||||||
|
Key::Numpad2,
|
||||||
|
Key::Numpad3,
|
||||||
|
Key::Numpad0,
|
||||||
|
Key::NumpadSep,
|
||||||
Key::INVALID,
|
Key::INVALID,
|
||||||
Key::INVALID,
|
Key::INVALID,
|
||||||
Key::Pipe,
|
Key::Pipe,
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Backspace,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Numpad1,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Numpad4,
|
|
||||||
Key::Numpad7,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Numpad0,
|
|
||||||
Key::NumpadComma,
|
|
||||||
Key::Numpad2,
|
|
||||||
Key::Numpad5,
|
|
||||||
Key::Numpad6,
|
|
||||||
Key::Numpad8,
|
|
||||||
Key::Escape,
|
|
||||||
Key::NumLock,
|
|
||||||
Key::F11,
|
Key::F11,
|
||||||
Key::NumpadPlus,
|
Key::F12,
|
||||||
Key::Numpad3,
|
|
||||||
Key::NumpadMinus,
|
|
||||||
Key::NumpadMult,
|
|
||||||
Key::Numpad9,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::F7,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static Key scs2_to_key_shift[0xFF]
|
constexpr Key scan_code_to_key_shift[0xFF]
|
||||||
{
|
{
|
||||||
Key::INVALID,
|
Key::INVALID,
|
||||||
Key::F9,
|
Key::Escape,
|
||||||
Key::INVALID,
|
|
||||||
Key::F5,
|
|
||||||
Key::F3,
|
|
||||||
Key::F1,
|
|
||||||
Key::F2,
|
|
||||||
Key::F12,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::F10,
|
|
||||||
Key::F8,
|
|
||||||
Key::F6,
|
|
||||||
Key::F4,
|
|
||||||
Key::Tab,
|
|
||||||
Key::Half,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Alt,
|
|
||||||
Key::LeftShift,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Ctrl,
|
|
||||||
Key::Q,
|
|
||||||
Key::ExclamationMark,
|
Key::ExclamationMark,
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Z,
|
|
||||||
Key::S,
|
|
||||||
Key::A,
|
|
||||||
Key::W,
|
|
||||||
Key::DoubleQuote,
|
Key::DoubleQuote,
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::C,
|
|
||||||
Key::X,
|
|
||||||
Key::D,
|
|
||||||
Key::E,
|
|
||||||
Key::Currency,
|
|
||||||
Key::Hashtag,
|
Key::Hashtag,
|
||||||
Key::INVALID,
|
Key::Currency,
|
||||||
Key::INVALID,
|
|
||||||
Key::Space,
|
|
||||||
Key::V,
|
|
||||||
Key::F,
|
|
||||||
Key::T,
|
|
||||||
Key::R,
|
|
||||||
Key::Percent,
|
Key::Percent,
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::N,
|
|
||||||
Key::B,
|
|
||||||
Key::H,
|
|
||||||
Key::G,
|
|
||||||
Key::Y,
|
|
||||||
Key::Ampersand,
|
Key::Ampersand,
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::M,
|
|
||||||
Key::J,
|
|
||||||
Key::U,
|
|
||||||
Key::Slash,
|
Key::Slash,
|
||||||
Key::OpenParen,
|
Key::OpenParen,
|
||||||
Key::INVALID,
|
Key::CloseParen,
|
||||||
Key::INVALID,
|
Key::Equals,
|
||||||
Key::Semicolon,
|
Key::QuestionMark,
|
||||||
Key::K,
|
Key::BackTick,
|
||||||
|
Key::Backspace,
|
||||||
|
Key::Tab,
|
||||||
|
Key::Q,
|
||||||
|
Key::W,
|
||||||
|
Key::E,
|
||||||
|
Key::R,
|
||||||
|
Key::T,
|
||||||
|
Key::Y,
|
||||||
|
Key::U,
|
||||||
Key::I,
|
Key::I,
|
||||||
Key::O,
|
Key::O,
|
||||||
Key::Equals,
|
Key::P,
|
||||||
Key::CloseParen,
|
Key::A_Dot,
|
||||||
Key::INVALID,
|
Key::Caret,
|
||||||
Key::INVALID,
|
Key::Enter,
|
||||||
Key::Colon,
|
Key::LeftCtrl,
|
||||||
Key::Underscore,
|
Key::A,
|
||||||
|
Key::S,
|
||||||
|
Key::D,
|
||||||
|
Key::F,
|
||||||
|
Key::G,
|
||||||
|
Key::H,
|
||||||
|
Key::J,
|
||||||
|
Key::K,
|
||||||
Key::L,
|
Key::L,
|
||||||
Key::O_Dots,
|
Key::O_Dots,
|
||||||
Key::P,
|
|
||||||
Key::QuestionMark,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::A_Dots,
|
Key::A_Dots,
|
||||||
Key::INVALID,
|
Key::Half,
|
||||||
Key::A_Dot,
|
Key::LeftShift,
|
||||||
Key::BackTick,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::CapsLock,
|
|
||||||
Key::RightShift,
|
|
||||||
Key::Enter,
|
|
||||||
Key::Caret,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Asterix,
|
Key::Asterix,
|
||||||
Key::INVALID,
|
Key::Z,
|
||||||
|
Key::X,
|
||||||
|
Key::C,
|
||||||
|
Key::V,
|
||||||
|
Key::B,
|
||||||
|
Key::N,
|
||||||
|
Key::M,
|
||||||
|
Key::Semicolon,
|
||||||
|
Key::Colon,
|
||||||
|
Key::Underscore,
|
||||||
|
Key::RightShift,
|
||||||
|
Key::NumpadMult,
|
||||||
|
Key::LeftAlt,
|
||||||
|
Key::Space,
|
||||||
|
Key::CapsLock,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::None,
|
||||||
|
Key::NumLock,
|
||||||
|
Key::ScrollLock,
|
||||||
|
Key::Home,
|
||||||
|
Key::Up,
|
||||||
|
Key::PageUp,
|
||||||
|
Key::NumpadMinus,
|
||||||
|
Key::Left,
|
||||||
|
Key::None,
|
||||||
|
Key::Right,
|
||||||
|
Key::NumpadPlus,
|
||||||
|
Key::End,
|
||||||
|
Key::Down,
|
||||||
|
Key::PageDown,
|
||||||
|
Key::Insert,
|
||||||
|
Key::Delete,
|
||||||
Key::INVALID,
|
Key::INVALID,
|
||||||
Key::INVALID,
|
Key::INVALID,
|
||||||
Key::MoreThan,
|
Key::MoreThan,
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Backspace,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::End,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Left,
|
|
||||||
Key::Right,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Insert,
|
|
||||||
Key::Delete,
|
|
||||||
Key::Down,
|
|
||||||
Key::None,
|
Key::None,
|
||||||
Key::Right,
|
Key::None,
|
||||||
Key::Up,
|
|
||||||
Key::Escape,
|
|
||||||
Key::NumLock,
|
|
||||||
Key::F11,
|
|
||||||
Key::NumpadPlus,
|
|
||||||
Key::PageDown,
|
|
||||||
Key::NumpadMinus,
|
|
||||||
Key::NumpadMult,
|
|
||||||
Key::PageUp,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::F7,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static Key scs2_to_key[0xFF]
|
constexpr Key scan_code_to_key_normal[0xFF]
|
||||||
{
|
{
|
||||||
Key::INVALID,
|
Key::INVALID,
|
||||||
Key::F9,
|
Key::Escape,
|
||||||
Key::INVALID,
|
|
||||||
Key::F5,
|
|
||||||
Key::F3,
|
|
||||||
Key::F1,
|
|
||||||
Key::F2,
|
|
||||||
Key::F12,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::F10,
|
|
||||||
Key::F8,
|
|
||||||
Key::F6,
|
|
||||||
Key::F4,
|
|
||||||
Key::Tab,
|
|
||||||
Key::Section,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Alt,
|
|
||||||
Key::LeftShift,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Ctrl,
|
|
||||||
Key::Q,
|
|
||||||
Key::_1,
|
Key::_1,
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Z,
|
|
||||||
Key::S,
|
|
||||||
Key::A,
|
|
||||||
Key::W,
|
|
||||||
Key::_2,
|
Key::_2,
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::C,
|
|
||||||
Key::X,
|
|
||||||
Key::D,
|
|
||||||
Key::E,
|
|
||||||
Key::_4,
|
|
||||||
Key::_3,
|
Key::_3,
|
||||||
Key::INVALID,
|
Key::_4,
|
||||||
Key::INVALID,
|
|
||||||
Key::Space,
|
|
||||||
Key::V,
|
|
||||||
Key::F,
|
|
||||||
Key::T,
|
|
||||||
Key::R,
|
|
||||||
Key::_5,
|
Key::_5,
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::N,
|
|
||||||
Key::B,
|
|
||||||
Key::H,
|
|
||||||
Key::G,
|
|
||||||
Key::Y,
|
|
||||||
Key::_6,
|
Key::_6,
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::M,
|
|
||||||
Key::J,
|
|
||||||
Key::U,
|
|
||||||
Key::_7,
|
Key::_7,
|
||||||
Key::_8,
|
Key::_8,
|
||||||
Key::INVALID,
|
Key::_9,
|
||||||
Key::INVALID,
|
Key::_0,
|
||||||
Key::Comma,
|
Key::Plus,
|
||||||
Key::K,
|
Key::Tick,
|
||||||
|
Key::Backspace,
|
||||||
|
Key::Tab,
|
||||||
|
Key::Q,
|
||||||
|
Key::W,
|
||||||
|
Key::E,
|
||||||
|
Key::R,
|
||||||
|
Key::T,
|
||||||
|
Key::Y,
|
||||||
|
Key::U,
|
||||||
Key::I,
|
Key::I,
|
||||||
Key::O,
|
Key::O,
|
||||||
Key::_0,
|
Key::P,
|
||||||
Key::_9,
|
Key::A_Dot,
|
||||||
Key::INVALID,
|
Key::Caret,
|
||||||
Key::INVALID,
|
Key::Enter,
|
||||||
Key::Period,
|
Key::LeftCtrl,
|
||||||
Key::Hyphen,
|
Key::A,
|
||||||
|
Key::S,
|
||||||
|
Key::D,
|
||||||
|
Key::F,
|
||||||
|
Key::G,
|
||||||
|
Key::H,
|
||||||
|
Key::J,
|
||||||
|
Key::K,
|
||||||
Key::L,
|
Key::L,
|
||||||
Key::O_Dots,
|
Key::O_Dots,
|
||||||
Key::P,
|
|
||||||
Key::Plus,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::A_Dots,
|
Key::A_Dots,
|
||||||
Key::INVALID,
|
Key::Section,
|
||||||
Key::A_Dot,
|
Key::LeftShift,
|
||||||
Key::Tick,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::CapsLock,
|
|
||||||
Key::RightShift,
|
|
||||||
Key::Enter,
|
|
||||||
Key::Caret,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::SingleQuote,
|
Key::SingleQuote,
|
||||||
Key::INVALID,
|
Key::Z,
|
||||||
|
Key::X,
|
||||||
|
Key::C,
|
||||||
|
Key::V,
|
||||||
|
Key::B,
|
||||||
|
Key::N,
|
||||||
|
Key::M,
|
||||||
|
Key::Comma,
|
||||||
|
Key::Period,
|
||||||
|
Key::Hyphen,
|
||||||
|
Key::RightShift,
|
||||||
|
Key::NumpadMult,
|
||||||
|
Key::LeftAlt,
|
||||||
|
Key::Space,
|
||||||
|
Key::CapsLock,
|
||||||
|
Key::F1,
|
||||||
|
Key::F2,
|
||||||
|
Key::F3,
|
||||||
|
Key::F4,
|
||||||
|
Key::F5,
|
||||||
|
Key::F6,
|
||||||
|
Key::F7,
|
||||||
|
Key::F8,
|
||||||
|
Key::F9,
|
||||||
|
Key::F10,
|
||||||
|
Key::NumLock,
|
||||||
|
Key::ScrollLock,
|
||||||
|
Key::Numpad7,
|
||||||
|
Key::Numpad8,
|
||||||
|
Key::Numpad9,
|
||||||
|
Key::NumpadMinus,
|
||||||
|
Key::Numpad4,
|
||||||
|
Key::Numpad5,
|
||||||
|
Key::Numpad6,
|
||||||
|
Key::NumpadPlus,
|
||||||
|
Key::Numpad1,
|
||||||
|
Key::Numpad2,
|
||||||
|
Key::Numpad3,
|
||||||
|
Key::Numpad0,
|
||||||
|
Key::NumpadSep,
|
||||||
Key::INVALID,
|
Key::INVALID,
|
||||||
Key::INVALID,
|
Key::INVALID,
|
||||||
Key::LessThan,
|
Key::LessThan,
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Backspace,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Numpad1,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Numpad4,
|
|
||||||
Key::Numpad7,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::Numpad0,
|
|
||||||
Key::NumpadComma,
|
|
||||||
Key::Numpad2,
|
|
||||||
Key::Numpad5,
|
|
||||||
Key::Numpad6,
|
|
||||||
Key::Numpad8,
|
|
||||||
Key::Escape,
|
|
||||||
Key::NumLock,
|
|
||||||
Key::F11,
|
Key::F11,
|
||||||
Key::NumpadPlus,
|
Key::F12,
|
||||||
Key::Numpad3,
|
|
||||||
Key::NumpadMinus,
|
|
||||||
Key::NumpadMult,
|
|
||||||
Key::Numpad9,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::INVALID,
|
|
||||||
Key::F7,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,17 +1,29 @@
|
||||||
#include <kernel/IDT.h>
|
#include <kernel/IDT.h>
|
||||||
#include <kernel/IO.h>
|
#include <kernel/IO.h>
|
||||||
#include <kernel/Keyboard.h>
|
#include <kernel/Keyboard.h>
|
||||||
#include <kernel/PIC.h>
|
|
||||||
#include <kernel/kprint.h>
|
#include <kernel/kprint.h>
|
||||||
|
#include <kernel/PIC.h>
|
||||||
|
#include <kernel/PIT.h>
|
||||||
|
#include <kernel/Queue.h>
|
||||||
|
#include <kernel/Serial.h>
|
||||||
|
|
||||||
#include <kernel/KeyboardLayout/FI.h>
|
#include <kernel/KeyboardLayout/FI.h>
|
||||||
|
|
||||||
|
#define KB_DEBUG_PRINT 1
|
||||||
|
|
||||||
#define I8042_DATA_PORT 0x60
|
#define I8042_DATA_PORT 0x60
|
||||||
#define I8042_STATUS_REGISTER 0x64
|
#define I8042_STATUS_REGISTER 0x64
|
||||||
#define I8042_COMMAND_REGISTER 0x64
|
#define I8042_COMMAND_REGISTER 0x64
|
||||||
|
|
||||||
#define I8042_READ_BYTE0 0x20
|
#define I8042_STATUS_OUT_FULL (1 << 0)
|
||||||
#define I8042_WRITE_BYTE0 0x60
|
#define I8042_STATUS_IN_FULL (1 << 1)
|
||||||
|
|
||||||
|
#define I8042_READ_CONFIG 0x20
|
||||||
|
#define I8042_WRITE_CONFIG 0x60
|
||||||
|
|
||||||
|
#define I8042_CONFING_IRQ_FIRST (1 << 0)
|
||||||
|
#define I8042_CONFING_IRQ_SECOND (1 << 1)
|
||||||
|
#define I8042_CONFING_TRANSLATION (1 << 6)
|
||||||
|
|
||||||
#define I8042_ENABLE_FIRST 0xAE
|
#define I8042_ENABLE_FIRST 0xAE
|
||||||
#define I8042_ENABLE_SECOND 0xA8
|
#define I8042_ENABLE_SECOND 0xA8
|
||||||
|
@ -19,32 +31,59 @@
|
||||||
#define I8042_DISABLE_SECOND 0xA7
|
#define I8042_DISABLE_SECOND 0xA7
|
||||||
|
|
||||||
#define I8042_TEST_CONTROLLER 0xAA
|
#define I8042_TEST_CONTROLLER 0xAA
|
||||||
#define I8042_CONTROLLER_TEST_PASS 0x55
|
#define I8042_TEST_CONTROLLER_PASS 0x55
|
||||||
|
|
||||||
#define I8042_TEST_FIRST_PORT 0xAB
|
#define I8042_TEST_FIRST_PORT 0xAB
|
||||||
#define I8042_FIRST_PORT_TEST_PASS 0x00
|
#define I8042_TEST_FIRST_PORT_PASS 0x00
|
||||||
|
|
||||||
#define I8042_TEST_SECOND 0xA9
|
#define I8042_TEST_SECOND_PORT 0xA9
|
||||||
#define I8042_SECOND_PORT_TEST_PASS 0x00
|
#define I8042_TEST_SECOND_PORT_PASS 0x00
|
||||||
|
|
||||||
#define I8042_ACK 0xfa
|
#define I8042_KB_ACK 0xFA
|
||||||
|
#define I8042_KB_RESEND 0xFE
|
||||||
|
#define I8042_KB_RESET 0xFF
|
||||||
|
#define I8042_KB_SELF_TEST_PASS 0xAA
|
||||||
|
#define I8042_KB_SET_SCAN_CODE_SET 0xF0
|
||||||
|
#define I8042_KB_SET_LEDS 0xED
|
||||||
|
#define I8042_KB_TIMEOUT_MS 1000
|
||||||
|
#define I8042_KB_LED_SCROLL_LOCK (1 << 0)
|
||||||
|
#define I8042_KB_LED_NUM_LOCK (1 << 1)
|
||||||
|
#define I8042_KB_LED_CAPS_LOCK (1 << 2)
|
||||||
|
|
||||||
#define KEYBOARD_IRQ 0x01
|
#define KEYBOARD_IRQ 0x01
|
||||||
|
|
||||||
#define MOD_ALT 0b0001
|
#define MOD_ALT (1 << 0)
|
||||||
#define MOD_CTRL 0b0010
|
#define MOD_CTRL (1 << 1)
|
||||||
#define MOD_SHIFT 0b0100
|
#define MOD_SHIFT (1 << 2)
|
||||||
#define MOD_ALTGR 0b1000
|
#define MOD_ALTGR (1 << 3)
|
||||||
|
#define MOD_CAPS (1 << 4)
|
||||||
#define KEYBOARD_FI
|
|
||||||
|
|
||||||
namespace Keyboard
|
namespace Keyboard
|
||||||
{
|
{
|
||||||
|
|
||||||
static bool s_keyboard_state[0xFF] = {};
|
static bool s_keyboard_state[0xFF] = {};
|
||||||
static uint8_t s_modifiers = 0;
|
|
||||||
|
|
||||||
static void (*s_key_callback)(Key, uint8_t, bool) = nullptr;
|
struct Command
|
||||||
|
{
|
||||||
|
uint8_t command = 0;
|
||||||
|
uint8_t data = 0;
|
||||||
|
bool has_data = false;
|
||||||
|
bool extra = false;
|
||||||
|
uint8_t _sent = 0;
|
||||||
|
uint8_t _ack = 0;
|
||||||
|
bool _done = false;
|
||||||
|
};
|
||||||
|
static Queue<Command> s_keyboard_command_queue;
|
||||||
|
static uint8_t s_keyboard_command_extra = 0x00;
|
||||||
|
|
||||||
|
static Queue<KeyEvent> s_key_event_queue;
|
||||||
|
static uint8_t s_keyboard_key_buffer[10] = {};
|
||||||
|
static uint8_t s_keyboard_key_buffer_size = 0;
|
||||||
|
|
||||||
|
static uint8_t s_led_states = 0b000;
|
||||||
|
static uint8_t s_modifiers = 0x00;
|
||||||
|
|
||||||
|
static void (*s_key_callback)(KeyEvent) = nullptr;
|
||||||
|
|
||||||
static char s_key_to_char[]
|
static char s_key_to_char[]
|
||||||
{
|
{
|
||||||
|
@ -59,110 +98,263 @@ namespace Keyboard
|
||||||
'$', '\0', '\0', '\0', '\n', ' ', '\t', '\b', '<', '>', '\0', '`', '\0', '\0', '@', '|',
|
'$', '\0', '\0', '\0', '\n', ' ', '\t', '\b', '<', '>', '\0', '`', '\0', '\0', '@', '|',
|
||||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||||
|
|
||||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||||
|
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||||
',', '+', '*', '/', '-',
|
',', '+', '*', '/', '-', '\n',
|
||||||
|
|
||||||
|
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||||
|
|
||||||
|
|
||||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||||
};
|
};
|
||||||
static_assert(sizeof(s_key_to_char) == static_cast<int>(Key::Count));
|
static_assert(sizeof(s_key_to_char) == static_cast<int>(Key::Count));
|
||||||
|
|
||||||
static uint8_t kb_read()
|
static uint8_t wait_and_read()
|
||||||
{
|
{
|
||||||
while (!(IO::inb(I8042_STATUS_REGISTER) & 0x01))
|
while ((IO::inb(I8042_STATUS_REGISTER) & I8042_STATUS_OUT_FULL) == 0)
|
||||||
continue;
|
continue;
|
||||||
return IO::inb(I8042_DATA_PORT);
|
return IO::inb(I8042_DATA_PORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool kb_try_read(uint8_t& out)
|
static void i8042_controller_command(uint8_t command)
|
||||||
{
|
{
|
||||||
if (IO::inb(I8042_STATUS_REGISTER) & 0x01)
|
|
||||||
{
|
|
||||||
out = IO::inb(I8042_DATA_PORT);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void kb_command(uint8_t command)
|
|
||||||
{
|
|
||||||
IO::io_wait();
|
|
||||||
IO::outb(I8042_COMMAND_REGISTER, command);
|
IO::outb(I8042_COMMAND_REGISTER, command);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kb_command(uint8_t command, uint8_t data)
|
static void i8042_controller_command(uint8_t command, uint8_t data)
|
||||||
{
|
{
|
||||||
IO::io_wait();
|
|
||||||
IO::outb(I8042_COMMAND_REGISTER, command);
|
IO::outb(I8042_COMMAND_REGISTER, command);
|
||||||
IO::io_wait();
|
while ((IO::inb(I8042_STATUS_REGISTER) & I8042_STATUS_IN_FULL) != 0)
|
||||||
|
continue;
|
||||||
IO::outb(I8042_DATA_PORT, data);
|
IO::outb(I8042_DATA_PORT, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void irq_handler()
|
static bool i8042_keyboard_command(uint8_t command)
|
||||||
{
|
{
|
||||||
uint8_t ch;
|
auto timeout = PIT::ms_since_boot() + I8042_KB_TIMEOUT_MS;
|
||||||
while (kb_try_read(ch))
|
|
||||||
{
|
|
||||||
bool multimedia = false, pressed = true;
|
|
||||||
|
|
||||||
if (ch == 0xE0)
|
while (PIT::ms_since_boot() < timeout)
|
||||||
{
|
{
|
||||||
multimedia = true;
|
if ((IO::inb(I8042_STATUS_REGISTER) & I8042_STATUS_IN_FULL) == 0)
|
||||||
ch = kb_read();
|
{
|
||||||
|
IO::outb(I8042_DATA_PORT, command);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch == 0xF0)
|
return false;
|
||||||
{
|
|
||||||
pressed = false;
|
|
||||||
ch = kb_read();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Handle multimedia keys
|
void update_keyboard()
|
||||||
if (multimedia)
|
|
||||||
{
|
{
|
||||||
if (ch == 17)
|
if (!s_keyboard_command_queue.Empty())
|
||||||
pressed ? (s_modifiers |= MOD_ALTGR) : (s_modifiers &= ~MOD_ALTGR);
|
{
|
||||||
if (pressed && false)
|
auto& command = s_keyboard_command_queue.Front();
|
||||||
kprint("<M{}>", ch);
|
|
||||||
continue;
|
if (command._sent == 0 && command._ack == 0)
|
||||||
|
{
|
||||||
|
if (!i8042_keyboard_command(command.command))
|
||||||
|
Kernel::panic("oof 1");
|
||||||
|
command._sent++;
|
||||||
}
|
}
|
||||||
|
|
||||||
s_keyboard_state[ch] = pressed;
|
if (command._sent == 1 && command._ack == 1 && command.has_data)
|
||||||
|
|
||||||
switch (ch)
|
|
||||||
{
|
{
|
||||||
case 17:
|
if (!i8042_keyboard_command(command.data))
|
||||||
pressed ? (s_modifiers |= MOD_ALT) : (s_modifiers &= ~MOD_ALT);
|
Kernel::panic("oof 2");
|
||||||
|
command._sent++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command._done)
|
||||||
|
{
|
||||||
|
switch (command.command)
|
||||||
|
{
|
||||||
|
case I8042_KB_RESET:
|
||||||
|
if (s_keyboard_command_extra != I8042_KB_SELF_TEST_PASS)
|
||||||
|
Kernel::panic("PS/2 Keyboard self test failed");
|
||||||
break;
|
break;
|
||||||
case 18:
|
case I8042_KB_SET_SCAN_CODE_SET:
|
||||||
case 89:
|
|
||||||
pressed ? (s_modifiers |= MOD_SHIFT) : (s_modifiers &= ~MOD_SHIFT);
|
|
||||||
break;
|
break;
|
||||||
case 20:
|
case I8042_KB_SET_LEDS:
|
||||||
pressed ? (s_modifiers |= MOD_CTRL) : (s_modifiers &= ~MOD_CTRL);
|
break;
|
||||||
|
}
|
||||||
|
s_keyboard_command_queue.Pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!s_key_event_queue.Empty())
|
||||||
|
{
|
||||||
|
s_key_callback(s_key_event_queue.Front());
|
||||||
|
s_key_event_queue.Pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void keyboard_new_key()
|
||||||
|
{
|
||||||
|
uint8_t index = 0;
|
||||||
|
bool extended = (s_keyboard_key_buffer[index] == 0xE0);
|
||||||
|
if (extended)
|
||||||
|
index++;
|
||||||
|
|
||||||
|
bool pressed = (s_keyboard_key_buffer[index] & 0x80) == 0;
|
||||||
|
uint8_t ch = s_keyboard_key_buffer[index] & ~0x80;
|
||||||
|
|
||||||
|
Key key = Key::INVALID;
|
||||||
|
|
||||||
|
if (extended)
|
||||||
|
{
|
||||||
|
key = scan_code_to_key_extended[ch];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (s_modifiers & MOD_SHIFT)
|
||||||
|
key = scan_code_to_key_shift[ch];
|
||||||
|
else if (s_modifiers & MOD_ALTGR)
|
||||||
|
key = scan_code_to_key_altgr[ch];
|
||||||
|
else
|
||||||
|
key = scan_code_to_key_normal[ch];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((s_led_states & I8042_KB_LED_NUM_LOCK))
|
||||||
|
{
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case Key::Numpad0: key = Key::Insert; break;
|
||||||
|
case Key::Numpad1: key = Key::End; break;
|
||||||
|
case Key::Numpad2: key = Key::Down; break;
|
||||||
|
case Key::Numpad3: key = Key::PageDown; break;
|
||||||
|
case Key::Numpad4: key = Key::Left; break;
|
||||||
|
case Key::Numpad5: key = Key::None; break;
|
||||||
|
case Key::Numpad6: key = Key::Right; break;
|
||||||
|
case Key::Numpad7: key = Key::Home; break;
|
||||||
|
case Key::Numpad8: key = Key::Up; break;
|
||||||
|
case Key::Numpad9: key = Key::PageUp; break;
|
||||||
|
case Key::NumpadSep: key = Key::Delete; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if KB_DEBUG_PRINT
|
||||||
|
if (key == Key::INVALID)
|
||||||
|
kprintln("{} {}", ch, extended ? 'E' : ' ');
|
||||||
|
#endif
|
||||||
|
|
||||||
|
s_keyboard_state[static_cast<int>(key)] = pressed;
|
||||||
|
|
||||||
|
bool update_leds = false;
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case Key::ScrollLock:
|
||||||
|
update_leds = pressed;
|
||||||
|
if (update_leds)
|
||||||
|
s_led_states ^= I8042_KB_LED_SCROLL_LOCK;
|
||||||
|
break;
|
||||||
|
case Key::NumLock:
|
||||||
|
update_leds = pressed;
|
||||||
|
if (update_leds)
|
||||||
|
s_led_states ^= I8042_KB_LED_NUM_LOCK;
|
||||||
|
break;
|
||||||
|
case Key::CapsLock:
|
||||||
|
update_leds = pressed;
|
||||||
|
if (update_leds)
|
||||||
|
s_led_states ^= I8042_KB_LED_CAPS_LOCK;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Key key;
|
if (update_leds)
|
||||||
if (s_modifiers & MOD_ALTGR)
|
{
|
||||||
key = scs2_to_key_altgr[ch];
|
s_keyboard_command_queue.Push({
|
||||||
else if (s_modifiers & MOD_SHIFT)
|
.command = I8042_KB_SET_LEDS,
|
||||||
key = scs2_to_key_shift[ch];
|
.data = s_led_states,
|
||||||
|
.has_data = true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t modifiers = 0;
|
||||||
|
if (s_keyboard_state[(int)Key::LeftShift] || s_keyboard_state[(int)Key::RightShift])
|
||||||
|
modifiers |= MOD_SHIFT;
|
||||||
|
if (s_keyboard_state[(int)Key::LeftCtrl] || s_keyboard_state[(int)Key::RightCtrl])
|
||||||
|
modifiers |= MOD_CTRL;
|
||||||
|
if (s_keyboard_state[(int)Key::LeftAlt])
|
||||||
|
modifiers |= MOD_ALT;
|
||||||
|
if (s_keyboard_state[(int)Key::RightAlt])
|
||||||
|
modifiers |= MOD_ALTGR;
|
||||||
|
if (s_led_states & I8042_KB_LED_CAPS_LOCK)
|
||||||
|
modifiers |= MOD_CAPS;
|
||||||
|
s_modifiers = modifiers;
|
||||||
|
|
||||||
|
if (key != Key::INVALID)
|
||||||
|
{
|
||||||
|
auto error_or = s_key_event_queue.Push({ .key = key, .modifiers = modifiers, .pressed = pressed });
|
||||||
|
if (error_or.HasError())
|
||||||
|
dprintln("PS/2 Keyboard: {}", error_or.GetError().message);
|
||||||
|
}
|
||||||
|
s_keyboard_key_buffer_size -= index + 1;
|
||||||
|
memmove(s_keyboard_key_buffer, s_keyboard_key_buffer + index, s_keyboard_key_buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyboard_irq_handler()
|
||||||
|
{
|
||||||
|
uint8_t raw = IO::inb(I8042_DATA_PORT);
|
||||||
|
|
||||||
|
bool command_waiting = false;
|
||||||
|
if (!s_keyboard_command_queue.Empty())
|
||||||
|
{
|
||||||
|
auto& command = s_keyboard_command_queue.Front();
|
||||||
|
command_waiting = (command._sent > 0 && !command._done);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command_waiting)
|
||||||
|
{
|
||||||
|
auto& command = s_keyboard_command_queue.Front();
|
||||||
|
if (raw == I8042_KB_RESEND)
|
||||||
|
{
|
||||||
|
dprintln("PS/2 Keyboard: Resend 0x{H}", command._sent == 2 ? command.data : command.command);
|
||||||
|
command._sent--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (raw == I8042_KB_ACK)
|
||||||
|
{
|
||||||
|
command._ack++;
|
||||||
|
if (command.extra > 0)
|
||||||
|
return;
|
||||||
|
command._done = command.has_data ? (command._ack == 2) : true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (raw == 0x00)
|
||||||
|
{
|
||||||
|
dprintln("\e[33mKey detection error or internal buffer overrun\e[m");
|
||||||
|
command._sent = 0;
|
||||||
|
command._ack = 0;
|
||||||
|
command._done = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (raw == 0xEE && command.command == 0xEE)
|
||||||
|
{
|
||||||
|
s_keyboard_command_queue.Pop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_keyboard_command_extra = raw;
|
||||||
|
command._done = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
key = scs2_to_key[ch];
|
{
|
||||||
|
s_keyboard_key_buffer[s_keyboard_key_buffer_size++] = raw;
|
||||||
// Debug print for unregistered keys
|
if (raw != 0xE0)
|
||||||
if (key == Key::INVALID && pressed)
|
keyboard_new_key();
|
||||||
kprint("<{}>", ch);
|
|
||||||
|
|
||||||
s_key_callback(key, s_modifiers, pressed);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize(void (*callback)(Key, uint8_t, bool))
|
bool initialize(void (*callback)(KeyEvent))
|
||||||
{
|
{
|
||||||
// https://wiki.osdev.org/%228042%22_PS/2_Controller
|
// https://wiki.osdev.org/%228042%22_PS/2_Controller
|
||||||
|
|
||||||
|
@ -175,74 +367,102 @@ namespace Keyboard
|
||||||
// TODO
|
// TODO
|
||||||
|
|
||||||
// Step 3: Disable Devices
|
// Step 3: Disable Devices
|
||||||
kb_command(I8042_DISABLE_FIRST);
|
i8042_controller_command(I8042_DISABLE_FIRST);
|
||||||
kb_command(I8042_DISABLE_SECOND);
|
i8042_controller_command(I8042_DISABLE_SECOND);
|
||||||
|
|
||||||
// Step 4: Flush The Ouput Buffer
|
// Step 4: Flush The Ouput Buffer
|
||||||
uint8_t tmp;
|
while ((IO::inb(I8042_STATUS_REGISTER) & I8042_STATUS_OUT_FULL) != 0)
|
||||||
while(kb_try_read(tmp))
|
IO::inb(I8042_DATA_PORT);
|
||||||
continue;
|
|
||||||
|
|
||||||
// Step 5: Set the Controller Configuration Byte
|
// Step 5: Set the Controller Configuration Byte
|
||||||
kb_command(I8042_READ_BYTE0);
|
i8042_controller_command(I8042_READ_CONFIG);
|
||||||
uint8_t conf = kb_read();
|
uint8_t config = wait_and_read();
|
||||||
conf &= 0b10111100;
|
config &= ~(I8042_CONFING_IRQ_FIRST | I8042_CONFING_IRQ_SECOND);
|
||||||
kb_command(I8042_WRITE_BYTE0, conf);
|
i8042_controller_command(I8042_WRITE_CONFIG, config);
|
||||||
|
|
||||||
// Step 6: Perform Controller Self Test
|
// Step 6: Perform Controller Self Test
|
||||||
kb_command(I8042_TEST_CONTROLLER);
|
i8042_controller_command(I8042_TEST_CONTROLLER);
|
||||||
uint8_t resp = kb_read();
|
if (wait_and_read() != I8042_TEST_CONTROLLER_PASS)
|
||||||
if (resp != I8042_CONTROLLER_TEST_PASS)
|
|
||||||
{
|
{
|
||||||
kprint("ERROR: PS/2 self test failed\n");
|
kprintln("\e[33mERROR: PS/2 controller self test failed\e[m");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 7: Determine If There Are 2 Channels
|
// Step 7: Determine If There Are 2 Channels
|
||||||
|
|
||||||
// Step 8: Perform Interface Tests
|
// Step 8: Perform Interface Tests
|
||||||
kb_command(I8042_TEST_FIRST_PORT);
|
i8042_controller_command(I8042_TEST_FIRST_PORT);
|
||||||
resp = kb_read();
|
if (wait_and_read() != I8042_TEST_FIRST_PORT_PASS)
|
||||||
if (resp != I8042_FIRST_PORT_TEST_PASS)
|
|
||||||
{
|
{
|
||||||
kprint("ERROR: PS/2 interface test failed\n");
|
kprintln("\e[33mERROR: PS/2 first port test failed\e[m");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 9: Enable Devices
|
// Step 9: Enable Devices
|
||||||
kb_command(I8042_WRITE_BYTE0, conf | 0x01); // enable IRQs
|
config |= I8042_CONFING_IRQ_FIRST;
|
||||||
kb_command(I8042_ENABLE_FIRST);
|
i8042_controller_command(I8042_WRITE_CONFIG, config);
|
||||||
|
i8042_controller_command(I8042_ENABLE_FIRST);
|
||||||
|
|
||||||
// Step 10: Reset Devices
|
// Step 10: Reset Devices
|
||||||
/* TODO: doesnt seem to respond
|
MUST(s_keyboard_command_queue.Push({
|
||||||
kb_command(0xFF);
|
.command = I8042_KB_RESET,
|
||||||
resp = kb_read();
|
.extra = true,
|
||||||
if (resp != PS2_ACK)
|
}));
|
||||||
{
|
|
||||||
kprint("ERROR: PS/2 could not restart devices\n");
|
// Set scan code set 2
|
||||||
return;
|
MUST(s_keyboard_command_queue.Push({
|
||||||
}
|
.command = I8042_KB_SET_SCAN_CODE_SET,
|
||||||
*/
|
.data = 0x02,
|
||||||
|
.has_data = true,
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Turn LEDs off
|
||||||
|
MUST(s_keyboard_command_queue.Push({
|
||||||
|
.command = I8042_KB_SET_LEDS,
|
||||||
|
.data = s_led_states,
|
||||||
|
.has_data = true,
|
||||||
|
}));
|
||||||
|
|
||||||
// Register callback and IRQ
|
// Register callback and IRQ
|
||||||
s_key_callback = callback;
|
s_key_callback = callback;
|
||||||
IDT::register_irq_handler(KEYBOARD_IRQ, irq_handler);
|
IDT::register_irq_handler(KEYBOARD_IRQ, keyboard_irq_handler);
|
||||||
PIC::unmask(KEYBOARD_IRQ);
|
PIC::unmask(KEYBOARD_IRQ);
|
||||||
|
|
||||||
kb_command(0xED, 0b111);
|
return true;
|
||||||
IO::io_wait();
|
|
||||||
while (kb_try_read(tmp));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char key_to_ascii(Key key, uint8_t modifiers)
|
char key_event_to_ascii(KeyEvent event)
|
||||||
{
|
{
|
||||||
char res = s_key_to_char[static_cast<uint8_t>(key)];
|
char res = s_key_to_char[static_cast<uint8_t>(event.key)];
|
||||||
|
|
||||||
if (!(modifiers & MOD_SHIFT))
|
if (!(event.modifiers & (MOD_SHIFT | MOD_CAPS)))
|
||||||
if (res >= 'A' && res <= 'Z')
|
if (res >= 'A' && res <= 'Z')
|
||||||
res = res - 'A' + 'a';
|
res = res - 'A' + 'a';
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void led_disco()
|
||||||
|
{
|
||||||
|
uint64_t time = PIT::ms_since_boot();
|
||||||
|
uint64_t freq = 100;
|
||||||
|
bool state = false;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if (PIT::ms_since_boot() > time + freq)
|
||||||
|
{
|
||||||
|
time += freq;
|
||||||
|
state = !state;
|
||||||
|
|
||||||
|
MUST(s_keyboard_command_queue.Push({
|
||||||
|
.command = I8042_KB_SET_LEDS,
|
||||||
|
.data = (uint8_t)(state ? 0b111 : 0b000),
|
||||||
|
.has_data = true,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
update_keyboard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -62,7 +62,8 @@ void kernel_main(multiboot_info_t* mbi, uint32_t magic)
|
||||||
IDT::initialize();
|
IDT::initialize();
|
||||||
|
|
||||||
PIT::initialize();
|
PIT::initialize();
|
||||||
Keyboard::initialize(on_key_press);
|
if (!Keyboard::initialize(on_key_press))
|
||||||
|
return;
|
||||||
|
|
||||||
auto time = RTC::GetCurrentTime();
|
auto time = RTC::GetCurrentTime();
|
||||||
kprintln("Today is {2}:{2}:{2} {2}.{2}.{4}", time.hour, time.minute, time.second, time.day, time.month, time.year);
|
kprintln("Today is {2}:{2}:{2} {2}.{2}.{4}", time.hour, time.minute, time.second, time.day, time.month, time.year);
|
||||||
|
@ -71,8 +72,9 @@ void kernel_main(multiboot_info_t* mbi, uint32_t magic)
|
||||||
|
|
||||||
ENABLE_INTERRUPTS();
|
ENABLE_INTERRUPTS();
|
||||||
|
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
asm("hlt");
|
Keyboard::update_keyboard();
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue