arch/x86_64: Decode keyboard scancodes
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
40f01c825d
commit
cd00e41f59
@ -51,6 +51,7 @@ if("${LUNA_ARCH}" MATCHES "x86_64")
|
||||
src/arch/x86_64/Timer.cpp
|
||||
src/arch/x86_64/Thread.cpp
|
||||
src/arch/x86_64/PCI.cpp
|
||||
src/arch/x86_64/Keyboard.cpp
|
||||
src/arch/x86_64/init/GDT.cpp
|
||||
src/arch/x86_64/init/IDT.cpp
|
||||
src/arch/x86_64/init/PIC.cpp
|
||||
|
7
kernel/src/arch/Keyboard.h
Normal file
7
kernel/src/arch/Keyboard.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include <luna/Option.h>
|
||||
|
||||
namespace Keyboard
|
||||
{
|
||||
Option<char> decode_scancode(u8 scancode);
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#include "arch/CPU.h"
|
||||
#include "Log.h"
|
||||
#include "arch/Keyboard.h"
|
||||
#include "arch/Timer.h"
|
||||
#include "arch/x86_64/CPU.h"
|
||||
#include "arch/x86_64/IO.h"
|
||||
@ -122,7 +123,8 @@ void io_thread()
|
||||
u8 scancode;
|
||||
while (!scancode_queue.try_pop(scancode)) { kernel_sleep(10); }
|
||||
|
||||
kinfoln("Read scancode: %#hhx", scancode);
|
||||
char key;
|
||||
if (Keyboard::decode_scancode(scancode).try_set_value(key)) { kdbgln("Read key: %c", key); }
|
||||
}
|
||||
}
|
||||
|
||||
|
171
kernel/src/arch/x86_64/Keyboard.cpp
Normal file
171
kernel/src/arch/x86_64/Keyboard.cpp
Normal file
@ -0,0 +1,171 @@
|
||||
#include "arch/Keyboard.h"
|
||||
|
||||
// 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 == LEFT_CONTROL || scancode == TAB ||
|
||||
scancode == LEFT_ALT || scancode == F11 || scancode == F12;
|
||||
}
|
||||
|
||||
static bool g_ignore_next { false };
|
||||
static bool g_left_shift { false };
|
||||
static bool g_right_shift { false };
|
||||
static bool g_capslock { false };
|
||||
|
||||
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()
|
||||
{
|
||||
if (g_capslock) return !(g_left_shift || g_right_shift);
|
||||
return g_left_shift || g_right_shift;
|
||||
}
|
||||
|
||||
namespace Keyboard
|
||||
{
|
||||
Option<char> decode_scancode(u8 scancode)
|
||||
{
|
||||
if (g_ignore_next)
|
||||
{
|
||||
g_ignore_next = false;
|
||||
return {};
|
||||
}
|
||||
|
||||
// FIXME: Support extended scancodes.
|
||||
if (scancode == EXTENDED_KEY_CODE)
|
||||
{
|
||||
g_ignore_next = true;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool released = is_key_released(scancode);
|
||||
|
||||
if (scancode == LEFT_SHIFT)
|
||||
{
|
||||
g_left_shift = !released;
|
||||
return {};
|
||||
}
|
||||
|
||||
if (scancode == RIGHT_SHIFT)
|
||||
{
|
||||
g_right_shift = !released;
|
||||
return {};
|
||||
}
|
||||
|
||||
if (scancode == CAPS_LOCK)
|
||||
{
|
||||
if (!released) g_capslock = !g_capslock;
|
||||
return {};
|
||||
}
|
||||
|
||||
if (should_ignore_key(scancode)) return {};
|
||||
|
||||
if (released) return {};
|
||||
|
||||
if (is_shifted()) return shifted_key_table[scancode];
|
||||
return key_table[scancode];
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user