forked from Bananymous/banan-os
Kernel: Properly handle finnish keyboard layout.
You can now type any basic ascii character from keyboard. Multimedia keys are not yet handled.
This commit is contained in:
parent
5ba7af2cf6
commit
817de9f359
|
@ -32,10 +32,10 @@ BUILDDIR=$(abspath build)
|
|||
KERNEL_OBJS=\
|
||||
$(KERNEL_ARCH_OBJS) \
|
||||
kernel/kernel.o \
|
||||
kernel/Keyboard.o \
|
||||
kernel/kmalloc.o \
|
||||
kernel/PIC.o \
|
||||
kernel/PIT.o \
|
||||
kernel/PS2.o \
|
||||
kernel/SSP.o \
|
||||
|
||||
OBJS=\
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Keyboard
|
||||
{
|
||||
|
||||
enum class Key : uint8_t
|
||||
{
|
||||
INVALID, None,
|
||||
_0, _1, _2, _3, _4, _5, _6, _7, _8, _9,
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
|
||||
A_Dot, A_Dots, O_Dots,
|
||||
|
||||
Comma, Colon, Period, Semicolon, Hyphen, Underscore, SingleQuote, Asterix, Caret, Tilde,
|
||||
ExclamationMark, QuestionMark, DoubleQuote, Hashtag, Percent, Ampersand, Slash, BackSlash, Plus, Equals,
|
||||
OpenParen, CloseParen, OpenBracket, CloseBracket, OpenBrace, CloseBrace,
|
||||
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,
|
||||
|
||||
LeftShift, RightShift, CapsLock, Ctrl, Alt, NumLock, Escape,
|
||||
|
||||
Numpad0, Numpad1, Numpad2, Numpad3, Numpad4, Numpad5, Numpad6, Numpad7, Numpad8, Numpad9,
|
||||
NumpadComma, NumpadPlus, NumpadMult, NumpadDiv, NumpadMinus,
|
||||
|
||||
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
|
||||
|
||||
Count
|
||||
};
|
||||
|
||||
void initialize(void (*callback)(Key, uint8_t, bool));
|
||||
|
||||
char key_to_ascii(Key, uint8_t);
|
||||
|
||||
}
|
|
@ -0,0 +1,416 @@
|
|||
#pragma once
|
||||
|
||||
#include <kernel/Keyboard.h>
|
||||
|
||||
namespace Keyboard
|
||||
{
|
||||
|
||||
static Key scs2_to_key_altgr[0xFF]
|
||||
{
|
||||
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::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::At,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
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::INVALID,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
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::INVALID,
|
||||
Key::None,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
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::NumpadPlus,
|
||||
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]
|
||||
{
|
||||
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::Half,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::Alt,
|
||||
Key::LeftShift,
|
||||
Key::INVALID,
|
||||
Key::Ctrl,
|
||||
Key::Q,
|
||||
Key::ExclamationMark,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::Z,
|
||||
Key::S,
|
||||
Key::A,
|
||||
Key::W,
|
||||
Key::DoubleQuote,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::C,
|
||||
Key::X,
|
||||
Key::D,
|
||||
Key::E,
|
||||
Key::Currency,
|
||||
Key::Hashtag,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::Space,
|
||||
Key::V,
|
||||
Key::F,
|
||||
Key::T,
|
||||
Key::R,
|
||||
Key::Percent,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::N,
|
||||
Key::B,
|
||||
Key::H,
|
||||
Key::G,
|
||||
Key::Y,
|
||||
Key::Ampersand,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::M,
|
||||
Key::J,
|
||||
Key::U,
|
||||
Key::Slash,
|
||||
Key::OpenParen,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::Semicolon,
|
||||
Key::K,
|
||||
Key::I,
|
||||
Key::O,
|
||||
Key::Equals,
|
||||
Key::CloseParen,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::Colon,
|
||||
Key::Underscore,
|
||||
Key::L,
|
||||
Key::O_Dots,
|
||||
Key::P,
|
||||
Key::QuestionMark,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::A_Dots,
|
||||
Key::INVALID,
|
||||
Key::A_Dot,
|
||||
Key::BackTick,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::CapsLock,
|
||||
Key::RightShift,
|
||||
Key::Enter,
|
||||
Key::Caret,
|
||||
Key::INVALID,
|
||||
Key::Asterix,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
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::Right,
|
||||
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]
|
||||
{
|
||||
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::Section,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::Alt,
|
||||
Key::LeftShift,
|
||||
Key::INVALID,
|
||||
Key::Ctrl,
|
||||
Key::Q,
|
||||
Key::_1,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::Z,
|
||||
Key::S,
|
||||
Key::A,
|
||||
Key::W,
|
||||
Key::_2,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::C,
|
||||
Key::X,
|
||||
Key::D,
|
||||
Key::E,
|
||||
Key::_4,
|
||||
Key::_3,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::Space,
|
||||
Key::V,
|
||||
Key::F,
|
||||
Key::T,
|
||||
Key::R,
|
||||
Key::_5,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::N,
|
||||
Key::B,
|
||||
Key::H,
|
||||
Key::G,
|
||||
Key::Y,
|
||||
Key::_6,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::M,
|
||||
Key::J,
|
||||
Key::U,
|
||||
Key::_7,
|
||||
Key::_8,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::Comma,
|
||||
Key::K,
|
||||
Key::I,
|
||||
Key::O,
|
||||
Key::_0,
|
||||
Key::_9,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::Period,
|
||||
Key::Hyphen,
|
||||
Key::L,
|
||||
Key::O_Dots,
|
||||
Key::P,
|
||||
Key::Plus,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::A_Dots,
|
||||
Key::INVALID,
|
||||
Key::A_Dot,
|
||||
Key::Tick,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::CapsLock,
|
||||
Key::RightShift,
|
||||
Key::Enter,
|
||||
Key::Caret,
|
||||
Key::INVALID,
|
||||
Key::SingleQuote,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
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::NumpadPlus,
|
||||
Key::Numpad3,
|
||||
Key::NumpadMinus,
|
||||
Key::NumpadMult,
|
||||
Key::Numpad9,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::INVALID,
|
||||
Key::F7,
|
||||
};
|
||||
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
namespace PS2
|
||||
{
|
||||
|
||||
void initialize();
|
||||
|
||||
}
|
|
@ -0,0 +1,244 @@
|
|||
#include <kernel/IDT.h>
|
||||
#include <kernel/IO.h>
|
||||
#include <kernel/Keyboard.h>
|
||||
#include <kernel/PIC.h>
|
||||
#include <kernel/kprint.h>
|
||||
|
||||
#include <kernel/KeyboardLayout/FI.h>
|
||||
|
||||
#define I8042_DATA_PORT 0x60
|
||||
#define I8042_STATUS_REGISTER 0x64
|
||||
#define I8042_COMMAND_REGISTER 0x64
|
||||
|
||||
#define I8042_READ_BYTE0 0x20
|
||||
#define I8042_WRITE_BYTE0 0x60
|
||||
|
||||
#define I8042_ENABLE_FIRST 0xAE
|
||||
#define I8042_ENABLE_SECOND 0xA8
|
||||
#define I8042_DISABLE_FIRST 0xAD
|
||||
#define I8042_DISABLE_SECOND 0xA7
|
||||
|
||||
#define I8042_TEST_CONTROLLER 0xAA
|
||||
#define I8042_CONTROLLER_TEST_PASS 0x55
|
||||
|
||||
#define I8042_TEST_FIRST_PORT 0xAB
|
||||
#define I8042_FIRST_PORT_TEST_PASS 0x00
|
||||
|
||||
#define I8042_TEST_SECOND 0xA9
|
||||
#define I8042_SECOND_PORT_TEST_PASS 0x00
|
||||
|
||||
#define I8042_ACK 0xfa
|
||||
|
||||
#define KEYBOARD_IRQ 0x01
|
||||
|
||||
#define MOD_ALT 0b0001
|
||||
#define MOD_CTRL 0b0010
|
||||
#define MOD_SHIFT 0b0100
|
||||
#define MOD_ALTGR 0b1000
|
||||
|
||||
#define KEYBOARD_FI
|
||||
|
||||
namespace Keyboard
|
||||
{
|
||||
|
||||
static bool s_keyboard_state[0xFF] = {};
|
||||
static uint8_t s_modifiers = 0;
|
||||
|
||||
static void (*s_key_callback)(Key, uint8_t, bool) = nullptr;
|
||||
|
||||
static char s_key_to_char[]
|
||||
{
|
||||
'\0', '\0',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'A', 'A', 'O',
|
||||
|
||||
',', ':', '.', ';', '-', '_', '\'', '*', '^', '~',
|
||||
'!', '?', '"', '#', '%', '&', '/', '\\', '+', '=',
|
||||
'(', ')', '[', ']', '{', '}',
|
||||
'$', '\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', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
',', '+', '*', '/', '-',
|
||||
|
||||
'\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 uint8_t kb_read()
|
||||
{
|
||||
while (!(IO::inb(I8042_STATUS_REGISTER) & 0x01))
|
||||
continue;
|
||||
return IO::inb(I8042_DATA_PORT);
|
||||
}
|
||||
|
||||
static bool kb_try_read(uint8_t& out)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static void kb_command(uint8_t command, uint8_t data)
|
||||
{
|
||||
IO::io_wait();
|
||||
IO::outb(I8042_COMMAND_REGISTER, command);
|
||||
IO::io_wait();
|
||||
IO::outb(I8042_DATA_PORT, data);
|
||||
}
|
||||
|
||||
void irq_handler()
|
||||
{
|
||||
uint8_t ch;
|
||||
while (kb_try_read(ch))
|
||||
{
|
||||
bool multimedia = false, pressed = true;
|
||||
|
||||
if (ch == 0xE0)
|
||||
{
|
||||
multimedia = true;
|
||||
ch = kb_read();
|
||||
}
|
||||
|
||||
if (ch == 0xF0)
|
||||
{
|
||||
pressed = false;
|
||||
ch = kb_read();
|
||||
}
|
||||
|
||||
// TODO: Handle multimedia keys
|
||||
if (multimedia)
|
||||
{
|
||||
if (ch == 17)
|
||||
pressed ? (s_modifiers |= MOD_ALTGR) : (s_modifiers &= ~MOD_ALTGR);
|
||||
if (pressed && false)
|
||||
kprint("<M{}>", ch);
|
||||
continue;
|
||||
}
|
||||
|
||||
s_keyboard_state[ch] = pressed;
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case 17:
|
||||
pressed ? (s_modifiers |= MOD_ALT) : (s_modifiers &= ~MOD_ALT);
|
||||
break;
|
||||
case 18:
|
||||
case 89:
|
||||
pressed ? (s_modifiers |= MOD_SHIFT) : (s_modifiers &= ~MOD_SHIFT);
|
||||
break;
|
||||
case 20:
|
||||
pressed ? (s_modifiers |= MOD_CTRL) : (s_modifiers &= ~MOD_CTRL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Key key;
|
||||
if (s_modifiers & MOD_ALTGR)
|
||||
key = scs2_to_key_altgr[ch];
|
||||
else if (s_modifiers & MOD_SHIFT)
|
||||
key = scs2_to_key_shift[ch];
|
||||
else
|
||||
key = scs2_to_key[ch];
|
||||
|
||||
// Debug print for unregistered keys
|
||||
if (key == Key::INVALID && pressed)
|
||||
kprint("<{}>", ch);
|
||||
|
||||
s_key_callback(key, s_modifiers, pressed);
|
||||
}
|
||||
}
|
||||
|
||||
void initialize(void (*callback)(Key, uint8_t, bool))
|
||||
{
|
||||
// https://wiki.osdev.org/%228042%22_PS/2_Controller
|
||||
|
||||
// TODO: support dual channel
|
||||
|
||||
// Step 1: Initialize USB Controllers
|
||||
// TODO
|
||||
|
||||
// Stem 2: Determine if the PS/2 Controller Exists
|
||||
// TODO
|
||||
|
||||
// Step 3: Disable Devices
|
||||
kb_command(I8042_DISABLE_FIRST);
|
||||
kb_command(I8042_DISABLE_SECOND);
|
||||
|
||||
// Step 4: Flush The Ouput Buffer
|
||||
uint8_t tmp;
|
||||
while(kb_try_read(tmp))
|
||||
continue;
|
||||
|
||||
// Step 5: Set the Controller Configuration Byte
|
||||
kb_command(I8042_READ_BYTE0);
|
||||
uint8_t conf = kb_read();
|
||||
conf &= 0b10111100;
|
||||
kb_command(I8042_WRITE_BYTE0, conf);
|
||||
|
||||
// Step 6: Perform Controller Self Test
|
||||
kb_command(I8042_TEST_CONTROLLER);
|
||||
uint8_t resp = kb_read();
|
||||
if (resp != I8042_CONTROLLER_TEST_PASS)
|
||||
{
|
||||
kprint("ERROR: PS/2 self test failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 7: Determine If There Are 2 Channels
|
||||
|
||||
// Step 8: Perform Interface Tests
|
||||
kb_command(I8042_TEST_FIRST_PORT);
|
||||
resp = kb_read();
|
||||
if (resp != I8042_FIRST_PORT_TEST_PASS)
|
||||
{
|
||||
kprint("ERROR: PS/2 interface test failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 9: Enable Devices
|
||||
kb_command(I8042_WRITE_BYTE0, conf | 0x01); // enable IRQs
|
||||
kb_command(I8042_ENABLE_FIRST);
|
||||
|
||||
// Step 10: Reset Devices
|
||||
/* TODO: doesnt seem to respond
|
||||
kb_command(0xFF);
|
||||
resp = kb_read();
|
||||
if (resp != PS2_ACK)
|
||||
{
|
||||
kprint("ERROR: PS/2 could not restart devices\n");
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
// Register callback and IRQ
|
||||
s_key_callback = callback;
|
||||
IDT::register_irq_handler(KEYBOARD_IRQ, irq_handler);
|
||||
PIC::unmask(KEYBOARD_IRQ);
|
||||
}
|
||||
|
||||
char key_to_ascii(Key key, uint8_t modifiers)
|
||||
{
|
||||
char res = s_key_to_char[static_cast<uint8_t>(key)];
|
||||
|
||||
if (!(modifiers & MOD_SHIFT))
|
||||
if (res >= 'A' && res <= 'Z')
|
||||
res = res - 'A' + 'a';
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,361 +0,0 @@
|
|||
#include <kernel/IDT.h>
|
||||
#include <kernel/IO.h>
|
||||
#include <kernel/PIC.h>
|
||||
#include <kernel/PS2.h>
|
||||
#include <kernel/kprint.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define PS2_DATA_PORT 0x60
|
||||
#define PS2_STATUS_REGISTER 0x64
|
||||
#define PS2_COMMAND_REGISTER 0x64
|
||||
|
||||
#define PS2_ACK 0xfa
|
||||
|
||||
#define PS2_IRQ 0x01
|
||||
|
||||
#define ALT 0
|
||||
#define CTRL 1
|
||||
#define SHIFT 2
|
||||
|
||||
#define KEYBOARD_FI
|
||||
|
||||
namespace PS2
|
||||
{
|
||||
|
||||
static bool s_keyboard_state[0x7f];
|
||||
static uint8_t s_modifiers = 0;
|
||||
|
||||
#ifdef KEYBOARD_FI
|
||||
enum class Key
|
||||
{
|
||||
Key_INVALID,
|
||||
Key_ESC,
|
||||
Key_1,
|
||||
Key_2,
|
||||
Key_3,
|
||||
Key_4,
|
||||
Key_5,
|
||||
Key_6,
|
||||
Key_7,
|
||||
Key_8,
|
||||
Key_9,
|
||||
Key_0,
|
||||
Key_Plus,
|
||||
Key_Tick,
|
||||
Key_Backspace,
|
||||
Key_Tab,
|
||||
Key_Q,
|
||||
Key_W,
|
||||
Key_E,
|
||||
Key_R,
|
||||
Key_T,
|
||||
Key_Y,
|
||||
Key_U,
|
||||
Key_I,
|
||||
Key_O,
|
||||
Key_P,
|
||||
Key_Å,
|
||||
Key_Caret,
|
||||
Key_Enter,
|
||||
Key_Control,
|
||||
Key_A,
|
||||
Key_S,
|
||||
Key_D,
|
||||
Key_F,
|
||||
Key_G,
|
||||
Key_H,
|
||||
Key_J,
|
||||
Key_K,
|
||||
Key_L,
|
||||
Key_Ö,
|
||||
Key_Ä,
|
||||
Key_Section, // §
|
||||
Key_LeftShift,
|
||||
Key_SingleQuote,
|
||||
Key_Z,
|
||||
Key_X,
|
||||
Key_C,
|
||||
Key_V,
|
||||
Key_B,
|
||||
Key_N,
|
||||
Key_M,
|
||||
Key_Comma,
|
||||
Key_Period,
|
||||
Key_Hyphen,
|
||||
Key_RightShift,
|
||||
Key_Unknown, // Maybe other alt
|
||||
Key_Alt,
|
||||
Key_Space,
|
||||
Key_CapsLock,
|
||||
Key_F1,
|
||||
Key_F2,
|
||||
Key_F3,
|
||||
Key_F4,
|
||||
Key_F5,
|
||||
Key_F6,
|
||||
Key_F7,
|
||||
Key_F8,
|
||||
Key_F9,
|
||||
Key_F10,
|
||||
// TODO
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
char fi_keymap[0x7f]
|
||||
{
|
||||
'\0',
|
||||
'\0', // esc
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'0',
|
||||
'+',
|
||||
'`',
|
||||
'\b',
|
||||
'\t', // tab
|
||||
'q',
|
||||
'w',
|
||||
'e',
|
||||
'r',
|
||||
't',
|
||||
'y',
|
||||
'u',
|
||||
'i',
|
||||
'o',
|
||||
'p',
|
||||
'?',
|
||||
'^',
|
||||
'\n', // enter
|
||||
'\0',
|
||||
'a',
|
||||
's',
|
||||
'd',
|
||||
'f',
|
||||
'g',
|
||||
'h',
|
||||
'j',
|
||||
'k',
|
||||
'l',
|
||||
'\0', // ö
|
||||
'\0', // ä
|
||||
'\0', // §
|
||||
'\0',
|
||||
'\'',
|
||||
'z',
|
||||
'x',
|
||||
'c',
|
||||
'v',
|
||||
'b',
|
||||
'n',
|
||||
'm',
|
||||
',',
|
||||
'.',
|
||||
'-',
|
||||
'\0',
|
||||
'\0',
|
||||
'\0',
|
||||
' ',
|
||||
};
|
||||
|
||||
char fi_keymap_shift[0x7f]
|
||||
{
|
||||
'\0',
|
||||
'\0', // esc
|
||||
'!',
|
||||
'"',
|
||||
'#',
|
||||
'\0', // ¤
|
||||
'%',
|
||||
'&',
|
||||
'/',
|
||||
'(',
|
||||
')',
|
||||
'=',
|
||||
'?',
|
||||
'`',
|
||||
'\b',
|
||||
'\t', // tab
|
||||
'Q',
|
||||
'W',
|
||||
'E',
|
||||
'R',
|
||||
'T',
|
||||
'Y',
|
||||
'U',
|
||||
'I',
|
||||
'O',
|
||||
'P',
|
||||
'?',
|
||||
'^',
|
||||
'\n', // enter
|
||||
'\0',
|
||||
'A',
|
||||
'S',
|
||||
'D',
|
||||
'F',
|
||||
'G',
|
||||
'H',
|
||||
'J',
|
||||
'K',
|
||||
'L',
|
||||
'\0', // ö
|
||||
'\0', // ä
|
||||
'\0', // ½
|
||||
'\0',
|
||||
'*',
|
||||
'Z',
|
||||
'X',
|
||||
'C',
|
||||
'V',
|
||||
'B',
|
||||
'N',
|
||||
'M',
|
||||
';',
|
||||
':',
|
||||
'_',
|
||||
'\0',
|
||||
'\0',
|
||||
'\0',
|
||||
' ',
|
||||
};
|
||||
|
||||
void irq_handler()
|
||||
{
|
||||
while (IO::inb(PS2_STATUS_REGISTER) & 0x01)
|
||||
{
|
||||
uint8_t raw = IO::inb(PS2_DATA_PORT);
|
||||
uint8_t ch = raw & 0x7f;
|
||||
bool pressed = !(raw & 0x80);
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case 0x38: pressed ? (s_modifiers |= 1 << ALT ) : (s_modifiers &= ~(1 << ALT )); break;
|
||||
case 0x1d: pressed ? (s_modifiers |= 1 << CTRL ) : (s_modifiers &= ~(1 << CTRL )); break;
|
||||
case 0x2a: pressed ? (s_modifiers |= 1 << SHIFT) : (s_modifiers &= ~(1 << SHIFT)); break;
|
||||
default:
|
||||
s_keyboard_state[ch] = pressed;
|
||||
}
|
||||
|
||||
if (pressed)
|
||||
{
|
||||
char c = s_modifiers & (1 << SHIFT) ? fi_keymap_shift[ch] : fi_keymap[ch];
|
||||
if (c) kprint("{}", c);
|
||||
}
|
||||
|
||||
IO::io_wait();
|
||||
}
|
||||
}
|
||||
|
||||
void initialize()
|
||||
{
|
||||
// Clear keyboard buffer
|
||||
while (IO::inb(PS2_STATUS_REGISTER) & 0x01)
|
||||
IO::inb(PS2_DATA_PORT);
|
||||
|
||||
memset(s_keyboard_state, 0, sizeof(s_keyboard_state));
|
||||
|
||||
IDT::register_irq_handler(PS2_IRQ, irq_handler);
|
||||
PIC::unmask(PS2_IRQ);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
#include <kernel/GDT.h>
|
||||
#include <kernel/IDT.h>
|
||||
#include <kernel/Keyboard.h>
|
||||
#include <kernel/kmalloc.h>
|
||||
#include <kernel/multiboot.h>
|
||||
#include <kernel/panic.h>
|
||||
#include <kernel/PIC.h>
|
||||
#include <kernel/PIT.h>
|
||||
#include <kernel/PS2.h>
|
||||
#include <kernel/tty.h>
|
||||
#include <kernel/kprint.h>
|
||||
#include <kernel/IO.h>
|
||||
|
@ -18,6 +18,16 @@
|
|||
|
||||
multiboot_info_t* s_multiboot_info;
|
||||
|
||||
void on_key_press(Keyboard::Key key, uint8_t modifiers, bool pressed)
|
||||
{
|
||||
if (pressed)
|
||||
{
|
||||
char ascii = Keyboard::key_to_ascii(key, modifiers);
|
||||
if (ascii)
|
||||
kprint("{}", ascii);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void kernel_main(multiboot_info_t* mbi, uint32_t magic)
|
||||
{
|
||||
|
@ -37,7 +47,7 @@ void kernel_main(multiboot_info_t* mbi, uint32_t magic)
|
|||
IDT::initialize();
|
||||
|
||||
PIT::initialize();
|
||||
PS2::initialize();
|
||||
Keyboard::initialize(on_key_press);
|
||||
|
||||
kprint("Hello from the kernel!\n");
|
||||
|
||||
|
|
Loading…
Reference in New Issue