194 lines
6.1 KiB
C++
194 lines
6.1 KiB
C++
#include "arch/Keyboard.h"
|
|
#include <luna/CType.h>
|
|
|
|
// PS/2 keyboard decoding routine.
|
|
|
|
static bool is_key_released(u8& scancode)
|
|
{
|
|
if (scancode > 0x80)
|
|
{
|
|
scancode -= 0x80;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
constexpr static u8 print_screen_pressed[] = { 0xe0, 0x2a, 0xe0, 0x37 };
|
|
constexpr static u8 print_screen_released[] = { 0xe0, 0xb7, 0xe0, 0xaa };
|
|
constexpr static u8 pause[] = { 0xe1, 0x1d, 0x45, 0xe1, 0x9d, 0xc5 };
|
|
|
|
using namespace moon;
|
|
|
|
constexpr KeyCode keycode_table[] = {
|
|
K_Unknown, K_Esc,
|
|
K_CH01, // 1
|
|
K_CH02, // 2
|
|
K_CH03, // 3
|
|
K_CH04, // 4
|
|
K_CH05, // 5
|
|
K_CH06, // 6
|
|
K_CH07, // 7
|
|
K_CH08, // 8
|
|
K_CH09, // 9
|
|
K_CH10, // 0
|
|
K_CH11, // -
|
|
K_CH12, // =
|
|
K_Backspace, K_Tab,
|
|
K_CH13, // Q
|
|
K_CH14, // W
|
|
K_CH15, // E
|
|
K_CH16, // R
|
|
K_CH17, // T
|
|
K_CH18, // Y
|
|
K_CH19, // U
|
|
K_CH20, // I
|
|
K_CH21, // O
|
|
K_CH22, // P
|
|
K_CH23, // [
|
|
K_CH24, // ]
|
|
K_Enter, K_LeftControl,
|
|
K_CH25, // A
|
|
K_CH26, // S
|
|
K_CH27, // D
|
|
K_CH28, // F
|
|
K_CH29, // G
|
|
K_CH30, // H
|
|
K_CH31, // J
|
|
K_CH32, // K
|
|
K_CH33, // L
|
|
K_CH34, // ;
|
|
K_CH35, // '
|
|
K_CH00, // `
|
|
K_LeftShift,
|
|
K_CH36, // #
|
|
K_CH38, // Z
|
|
K_CH39, // X
|
|
K_CH40, // C
|
|
K_CH41, // V
|
|
K_CH42, // B
|
|
K_CH43, // N
|
|
K_CH44, // M
|
|
K_CH45, // ,
|
|
K_CH46, // .
|
|
K_CH47, // /
|
|
K_RightShift, K_KeypadMul, K_LeftAlt,
|
|
K_CH48, // Space
|
|
K_CapsLock, K_F1, K_F2, K_F3, K_F4, K_F5, K_F6,
|
|
K_F7, K_F8, K_F9, K_F10, K_NumLock, K_ScrollLock, K_Keypad7,
|
|
K_Keypad8, K_Keypad9, K_KeypadMinus, K_Keypad4, K_Keypad5, K_Keypad6, K_KeypadPlus,
|
|
K_Keypad1, K_Keypad2, K_Keypad3, K_Keypad0, K_KeypadDot, K_Unknown, K_Unknown,
|
|
K_CH37, // Backslash
|
|
K_F11, K_F12,
|
|
};
|
|
|
|
constexpr KeyCode extended_keycode_table[] = {
|
|
K_MediaPrev, K_Unknown, K_Unknown, K_Unknown, K_Unknown, K_Unknown, K_Unknown,
|
|
K_Unknown, K_Unknown, K_MediaNext, K_Unknown, K_Unknown, K_KeypadEnter, K_RightControl,
|
|
K_Unknown, K_Unknown, K_MediaMute, K_MediaCalc, K_MediaPlay, K_Unknown, K_MediaStop,
|
|
K_Unknown, K_Unknown, K_Unknown, K_Unknown, K_Unknown, K_Unknown, K_Unknown,
|
|
K_Unknown, K_Unknown, K_MediaVolDown, K_Unknown, K_MediaVolUp, K_Unknown, K_WWWHome,
|
|
K_Unknown, K_Unknown, K_KeypadDiv, K_Unknown, K_Unknown, K_RightAlt, K_Unknown,
|
|
K_Unknown, K_Unknown, K_Unknown, K_Unknown, K_Unknown, K_Unknown, K_Unknown,
|
|
K_Unknown, K_Unknown, K_Unknown, K_Unknown, K_Unknown, K_Unknown, K_Home,
|
|
K_UpArrow, K_PageUp, K_Unknown, K_LeftArrow, K_Unknown, K_RightArrow, K_Unknown,
|
|
K_End, K_DownArrow, K_PageDown, K_Insert, K_Delete, K_Unknown, K_Unknown,
|
|
K_Unknown, K_Unknown, K_Unknown, K_Unknown, K_Unknown, K_Super, K_Super,
|
|
K_Menu, K_ACPIPower, K_ACPISleep, K_Unknown, K_Unknown, K_Unknown, K_ACPIWake,
|
|
K_Unknown, K_WWWSearch, K_WWWFavorites, K_WWWRefresh, K_WWWStop, K_WWWForward, K_WWWBack,
|
|
K_WWWMyComputer, K_WWWEmail, K_WWWSelect
|
|
};
|
|
|
|
namespace Keyboard
|
|
{
|
|
Option<KeyboardPacket> decode_scancode(u8 scancode, KeyboardState& state)
|
|
{
|
|
if (state.parsing_pause)
|
|
{
|
|
if (state.key_state.size() < 6) state.key_state.try_append(scancode).release_value();
|
|
|
|
if (state.key_state.size() == 6)
|
|
{
|
|
state.parsing_pause = state.parsing_ext = false;
|
|
if (!memcmp(state.key_state.data(), pause, 6))
|
|
{
|
|
state.key_state.clear_data();
|
|
return KeyboardPacket { K_Pause, false };
|
|
}
|
|
|
|
state.key_state.clear_data();
|
|
return KeyboardPacket { K_Unknown, false };
|
|
}
|
|
}
|
|
|
|
if (state.parsing_ext)
|
|
{
|
|
if (scancode == 0xe0 && state.key_state.size() == 2)
|
|
{
|
|
state.key_state.try_append(scancode).release_value();
|
|
return {};
|
|
}
|
|
|
|
if (state.key_state.size() == 3)
|
|
{
|
|
state.key_state.try_append(scancode).release_value();
|
|
if (!memcmp(state.key_state.data(), print_screen_pressed, 4))
|
|
{
|
|
state.parsing_ext = false;
|
|
state.key_state.clear_data();
|
|
return KeyboardPacket { K_PrtScr, false };
|
|
}
|
|
|
|
if (!memcmp(state.key_state.data(), print_screen_released, 4))
|
|
{
|
|
state.parsing_ext = false;
|
|
state.key_state.clear_data();
|
|
return KeyboardPacket { K_PrtScr, true };
|
|
}
|
|
|
|
state.parsing_ext = false;
|
|
state.key_state.clear_data();
|
|
return KeyboardPacket { K_Unknown, false };
|
|
}
|
|
|
|
if (scancode == 0x2a || scancode == 0xb7)
|
|
{
|
|
state.key_state.try_append(scancode).release_value();
|
|
return {};
|
|
}
|
|
|
|
bool released = is_key_released(scancode);
|
|
|
|
KeyCode key = KeyCode::K_Unknown;
|
|
|
|
if (scancode <= 0x6d) key = extended_keycode_table[scancode - 0x10];
|
|
|
|
state.parsing_ext = false;
|
|
state.key_state.clear_data();
|
|
|
|
return KeyboardPacket { key, released };
|
|
}
|
|
|
|
if (scancode == 0xe0)
|
|
{
|
|
state.parsing_ext = true;
|
|
state.key_state.try_append(scancode).release_value();
|
|
return {};
|
|
}
|
|
|
|
if (scancode == 0xe1)
|
|
{
|
|
state.parsing_pause = true;
|
|
state.key_state.try_append(scancode).release_value();
|
|
return {};
|
|
}
|
|
|
|
bool released = is_key_released(scancode);
|
|
|
|
KeyCode key = KeyCode::K_Unknown;
|
|
|
|
if (scancode <= 0x58) key = keycode_table[scancode];
|
|
|
|
return KeyboardPacket { key, released };
|
|
}
|
|
}
|