#include "arch/Keyboard.h" #include // 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 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 }; } }