Luna/kernel/src/arch/x86_64/Keyboard.cpp

188 lines
4.4 KiB
C++
Raw Normal View History

2023-03-19 10:17:43 +00:00
#include "arch/Keyboard.h"
#include <luna/CType.h>
2023-03-19 10:17:43 +00:00
// PS/2 keyboard decoding routine.
static bool is_key_released(u8& scancode)
{
if (scancode > 0x80)
{
scancode -= 0x80;
return true;
}
return false;
}
constexpr u8 EXTENDED_KEY_CODE = 0xe0;
constexpr u8 LEFT_SHIFT = 0x2a;
constexpr u8 RIGHT_SHIFT = 0x36;
constexpr u8 CAPS_LOCK = 0x3a;
constexpr u8 LEFT_CONTROL = 0x1D;
constexpr u8 TAB = 0x0F;
constexpr u8 LEFT_ALT = 0x38;
constexpr u8 F11 = 0x57;
constexpr u8 F12 = 0x58;
static bool should_ignore_key(u8 scancode)
{
return (scancode > 0x3A && scancode < 0x47) || scancode == TAB || scancode == F11 || scancode == F12;
2023-03-19 10:17:43 +00:00
}
constexpr char key_table[] = {
'\0',
'\1', // escape
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',
'\0', // tab
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',
'\0', // left ctrl
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
'\0', // left shift
'\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
'\0', // right shift
'*', // keypad *
'\0', // left alt
' ',
'\0', // caps lock
'\0', // f1
'\0', // f2
'\0', // f3
'\0', // f4
'\0', // f5
'\0', // f6
'\0', // f7
'\0', // f8
'\0', // f9
'\0', // f10
'\0', // num lock
'\0', // scroll lock
'7', // keypad 7
'8', // keypad 8
'9', // keypad 9
'-', // keypad -
'4', // keypad 4
'5', // keypad 5
'6', // keypad 6
'+', // keypad +
'1', // keypad 1
'2', // keypad 2
'3', // keypad 3
'0', // keypad 0
'.', // keypad .
};
constexpr char shifted_key_table[] = {
'\0',
'\1', // escape
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\b',
'\0', // tab
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n',
'\0', // left ctrl
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~',
'\0', // left shift
'|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?',
'\0', // right shift
'*', // keypad *
'\0', // left alt
' ',
'\0', // caps lock
'\0', // f1
'\0', // f2
'\0', // f3
'\0', // f4
'\0', // f5
'\0', // f6
'\0', // f7
'\0', // f8
'\0', // f9
'\0', // f10
'\0', // num lock
'\0', // scroll lock
'7', // keypad 7
'8', // keypad 8
'9', // keypad 9
'-', // keypad -
'4', // keypad 4
'5', // keypad 5
'6', // keypad 6
'+', // keypad +
'1', // keypad 1
'2', // keypad 2
'3', // keypad 3
'0', // keypad 0
'.', // keypad .
};
static bool is_shifted(const Keyboard::KeyboardState& state)
2023-03-19 10:17:43 +00:00
{
if (state.capslock) return !(state.left_shift || state.right_shift);
return state.left_shift || state.right_shift;
2023-03-19 10:17:43 +00:00
}
namespace Keyboard
{
Option<char> decode_scancode_tty(u8 scancode, KeyboardState& state)
2023-03-19 10:17:43 +00:00
{
if (state.ignore_next)
2023-03-19 10:17:43 +00:00
{
state.ignore_next = false;
2023-03-19 10:17:43 +00:00
return {};
}
// FIXME: Support extended scancodes.
if (scancode == EXTENDED_KEY_CODE)
{
state.ignore_next = true;
2023-03-19 10:17:43 +00:00
return {};
}
bool released = is_key_released(scancode);
if (scancode == LEFT_SHIFT)
{
state.left_shift = !released;
2023-03-19 10:17:43 +00:00
return {};
}
if (scancode == RIGHT_SHIFT)
{
state.right_shift = !released;
2023-03-19 10:17:43 +00:00
return {};
}
if (scancode == CAPS_LOCK)
{
if (!released) state.capslock = !state.capslock;
return {};
}
if (scancode == LEFT_CONTROL)
{
if (released) state.left_control = false;
else
state.left_control = true;
return {};
}
2023-03-19 10:17:43 +00:00
if (should_ignore_key(scancode)) return {};
if (released) return {};
if (state.left_control)
{
char key;
if (is_shifted(state)) key = shifted_key_table[scancode];
else
key = key_table[scancode];
if (_islower(key)) key = (char)_toupper(key);
if (_isupper(key)) return key - 0x40;
if (key == '@') return key - 0x40;
if (key > 'Z' && key < '`') return key - 0x40;
if (key == '?') return 0x7f;
}
if (is_shifted(state)) return shifted_key_table[scancode];
return key_table[scancode];
}
2023-03-19 10:17:43 +00:00
}