Some cleanup, moved PS2 code to drivers folder in the shared sources.

This commit is contained in:
2024-01-18 16:46:40 +01:00
parent 04d25d498d
commit c097da920d
7 changed files with 41 additions and 31 deletions

View File

@@ -33,6 +33,10 @@ extern const unsigned {symbol}_SIZE;
env.Command([f'{res}.s', f'{res}.hpp'.replace('src/', 'include/')], res, action = _generate_s)
env.AddMethod(_resource, 'Resource')
irs_sources = Split('''
src/drivers/pic.cpp
src/drivers/ps2.cpp
''')
any_target_sources = Split('''
src/app/main.cpp
@@ -51,5 +55,6 @@ any_target_sources = Split('''
env.Resource(env.File('src/os/resources/lat9-08.psf').abspath, 'LAT9_08')
env.Append(KERNEL_SOURCES = [env.File(f) for f in any_target_sources])
env.Append(KERNEL_ISR_SOURCES = [env.File(f) for f in irs_sources])
Return('env')

View File

@@ -0,0 +1,41 @@
#pragma once
#if !defined(BAD_APPLE_OS_KERNEL_PIC_HPP_INCLUDED)
#define BAD_APPLE_OS_KERNEL_PIC_HPP_INCLUDED
#include <cstdint>
#include "os/port.hpp"
inline constexpr std::uint16_t PORT_PIC1 = 0x20;
inline constexpr std::uint16_t PORT_PIC2 = 0xA0;
inline constexpr std::uint8_t PIC_CMD_EOI = 0x20;
[[nodiscard]] bool initPICs(std::uint8_t masterOffset, std::uint8_t slaveOffset) noexcept;
__attribute__((no_caller_saved_registers))
void sendEndOfInterrupt(std::uint8_t irq) noexcept;
void maskIRQ(std::uint8_t irq) noexcept;
void unmaskIRQ(std::uint8_t irq) noexcept;
[[nodiscard]] std::uint16_t readPICIRR() noexcept;
[[nodiscard]] std::uint16_t readPICISR() noexcept;
[[nodiscard]] constexpr bool isValidPICOffset(std::uint8_t offset) noexcept
{
return (offset & 7) == 0;
}
#if defined(__x86_64__)
struct InterruptFrame
{
std::uint64_t ip;
std::uint64_t cs;
std::uint64_t flags;
std::uint64_t sp;
std::uint64_t ss;
};
#endif
using interrupt_handler_t = __attribute__((interrupt)) void(*)(InterruptFrame*);
#endif // !defined(BAD_APPLE_OS_KERNEL_PIC_HPP_INCLUDED)

View File

@@ -0,0 +1,159 @@
#pragma once
#if !defined(BAD_APPLE_OS_DRIVERS_PS2_HPP_INCLUDED)
#define BAD_APPLE_OS_DRIVERS_PS2_HPP_INCLUDED
#include "drivers/pic.hpp"
namespace baos::ps2
{
enum class Scancode
{
INVALID = 0,
F9 = 0x01,
F5 = 0x03,
F3 = 0x04,
F1 = 0x05,
F2 = 0x06,
F12 = 0x07,
F10 = 0x09,
F8 = 0x0A,
F6 = 0x0B,
F4 = 0x0C,
TAB = 0x0D,
BACKTICK = 0x0E,
LEFT_ALT = 0x11,
LEFT_SHIFT = 0x12,
LEFT_CONTROL = 0x14,
Q = 0x15,
_1 = 0x16,
Z = 0x1A,
S = 0x1B,
A = 0x1C,
W = 0x1D,
_2 = 0x1E,
C = 0x21,
X = 0x22,
D = 0x23,
E = 0x24,
_4 = 0x25,
_3 = 0x26,
SPACE = 0x29,
V = 0x2A,
F = 0x2B,
T = 0x2C,
R = 0x2D,
_5 = 0x2E,
N = 0x31,
B = 0x32,
H = 0x33,
G = 0x34,
Y = 0x35,
_6 = 0x36,
M = 0x3A,
J = 0x3B,
U = 0x3C,
_7 = 0x3D,
_8 = 0x3E,
COMMA = 0x41,
K = 0x42,
I = 0x43,
O = 0x44,
_0 = 0x45,
_9 = 0x46,
DOT = 0x49,
SLASH = 0x4A,
L = 0x4B,
SEMICOLON = 0x4C,
P = 0x4D,
MINUS = 0x4E,
APOSTROPHE = 0x52,
BRACKET_OPEN = 0x54,
EQUALS = 0x55,
CAPSLOCK = 0x58,
RIGHT_SHIFT = 0x59,
ENTER = 0x5A,
BRACKET_CLOSE = 0x5B,
BACKSLASH = 0x5D,
BACKSPACE = 0x66,
KP_1 = 0x69,
KP_4 = 0x6B,
KP_7 = 0x6C,
KP_0 = 0x70,
KP_DOT = 0x71,
KP_2 = 0x72,
KP_5 = 0x73,
KP_6 = 0x74,
KP_8 = 0x75,
ESCAPE = 0x76,
NUMLOCK = 0x77,
F11 = 0x78,
KP_PLUS = 0x79,
KP_3 = 0x7A,
KP_MINUS = 0x7B,
KP_ASTERISK = 0x7C,
KP_9 = 0x7D,
SCROLLOCK = 0x7E,
F7 = 0x83,
MM_WWW_SEARCH = 0xE010,
RIGHT_ALT = 0xE011,
RIGHT_CONTROL = 0xE014,
MM_PREV_TRACK = 0xE015,
LEFT_GUI = 0xE01F,
MM_WWW_FAVORITES = 0xE020,
MM_VOLUME_DOWN = 0xE021,
MM_MUTE = 0xE023,
RIGHT_GUI = 0xE027,
MM_WWW_STOP = 0xE028,
MM_CALCULATOR = 0xE02B,
APPS = 0xE02F,
MM_WWW_FORWARD = 0xE030,
MM_VOLUME_UP = 0xE032,
MM_PLAY_PAUSE = 0xE034,
ACPI_POWER = 0xE037,
MM_WWW_BACK = 0xE038,
MM_WWW_HOME = 0xE03A,
MM_STOP = 0xE03B,
ACPI_SLEEP = 0xE03F,
MM_MY_COMPUTER = 0xE040,
MM_EMAIL = 0xE048,
KP_SLASH = 0xE04A,
MM_NEXT_TRACK = 0xE04D,
MM_MEDIA_SELECT = 0xE050,
KP_ENTER = 0xE05A,
ACPI_WAKE = 0xE05E,
END = 0xE069,
ARROW_LEFT = 0xE06B,
HOME = 0xE06C,
INSERT = 0xE070,
DELETE = 0xE071,
ARROW_DOWN = 0xE072,
ARROW_RIGHT = 0xE074,
ARROW_UP = 0xE075,
PAGE_DOWN = 0xE07A,
PAGE_UP = 0xE07D,
PRINT_SCREEN = 0xF000,
PAUSE = 0xF001
};
struct KeyEvent
{
Scancode scancode = Scancode::INVALID;
bool down : 1 = false;
bool repeat : 1 = false;
};
[[nodiscard]] bool initialize() noexcept;
__attribute__((interrupt))
void isrKeyboard(InterruptFrame* interruptFrame) noexcept;
[[nodiscard]] bool readKey(KeyEvent& outEvent) noexcept;
[[nodiscard]] const char* keyName(Scancode scancode) noexcept;
}
#endif // !defined(BAD_APPLE_OS_DRIVERS_PS2_HPP_INCLUDED)

View File

@@ -0,0 +1,121 @@
#include "drivers/pic.hpp"
namespace
{
inline constexpr std::uint8_t PIC_CMD_INIT = 0x10;
inline constexpr std::uint8_t PIC_CMD_READ_IRR = 0x0a;
inline constexpr std::uint8_t PIC_CMD_READ_ISR = 0x0b;
inline constexpr std::uint8_t PIC_INIT_WITH_ICW4 = 0x01;
inline constexpr std::uint8_t PIC_CFG_8086 = 0x01;
void picWriteCmd(std::uint16_t port, std::uint8_t command) noexcept
{
writePortByte(port, command);
}
[[nodiscard]] std::uint8_t picReadResponse(std::uint8_t port) noexcept
{
return readPortByte(port);
}
void picWriteData(std::uint16_t port, std::uint8_t data) noexcept
{
writePortByte(port + 1, data);
}
[[nodiscard]] std::uint8_t picReadData(std::uint16_t port) noexcept
{
return readPortByte(port + 1);
}
[[nodiscard]] std::uint16_t readPICIRQRegisters(std::uint8_t readCommand) noexcept
{
picWriteCmd(PORT_PIC1, readCommand);
picWriteCmd(PORT_PIC2, readCommand);
return (picReadResponse(PORT_PIC1) << 8) | picReadResponse(PORT_PIC2);
}
}
bool initPICs(std::uint8_t masterOffset, std::uint8_t slaveOffset) noexcept
{
if (!isValidPICOffset(masterOffset) || !isValidPICOffset(slaveOffset))
{
return false;
}
const uint8_t mask1 = picReadData(PORT_PIC1);
const uint8_t mask2 = picReadData(PORT_PIC2);
// ICW1 - init command
picWriteCmd(PORT_PIC1, PIC_CMD_INIT | PIC_INIT_WITH_ICW4);
ioWait();
picWriteCmd(PORT_PIC2, PIC_CMD_INIT | PIC_INIT_WITH_ICW4);
ioWait();
// ICW2 - offset
picWriteData(PORT_PIC1, masterOffset);
ioWait();
picWriteData(PORT_PIC2, slaveOffset);
ioWait();
// ICW3 - master/slave config
picWriteData(PORT_PIC1, (1 << 2)); // there is a slave at IRQ2
ioWait();
picWriteData(PORT_PIC2, 2); // you are slave no. 2
ioWait();
// ICW3 - additional config
picWriteData(PORT_PIC1, PIC_CFG_8086);
ioWait();
picWriteData(PORT_PIC2, PIC_CFG_8086);
ioWait();
// restore masks
picWriteData(PORT_PIC1, mask1);
picWriteData(PORT_PIC2, mask2);
return true;
}
void sendEndOfInterrupt(std::uint8_t irq) noexcept
{
if (irq >= 8) {
writePortByte(PORT_PIC2, PIC_CMD_EOI);
}
writePortByte(PORT_PIC1, PIC_CMD_EOI);
}
void maskIRQ(std::uint8_t irq) noexcept
{
std::uint16_t port = PORT_PIC1;
if (irq >= 8)
{
port = PORT_PIC2;
irq -= 8;
}
const std::uint8_t currentMask = picReadData(port);
picWriteData(port, currentMask | (1 << irq));
}
void unmaskIRQ(std::uint8_t irq) noexcept
{
std::uint16_t port = PORT_PIC1;
if (irq >= 8)
{
port = PORT_PIC2;
irq -= 8;
}
const std::uint8_t currentMask = picReadData(port);
picWriteData(port, currentMask & ~(1 << irq));
}
std::uint16_t readPICIRR() noexcept
{
return readPICIRQRegisters(PIC_CMD_READ_IRR);
}
std::uint16_t readPICISR() noexcept
{
return readPICIRQRegisters(PIC_CMD_READ_ISR);
}

View File

@@ -0,0 +1,564 @@
#include "drivers/ps2.hpp"
#include <cstdint>
#include "drivers/pic.hpp"
#include "os/port.hpp"
namespace
{
inline constexpr std::uint16_t PORT_PS2_DATA = 0x60;
inline constexpr std::uint16_t PORT_PS2_STATUS = 0x64;
inline constexpr std::uint8_t FLAG_PS2_OUTPUT_FULL = (1 << 0);
inline constexpr std::uint8_t FLAG_PS2_INPUT_FULL = (1 << 1);
inline constexpr std::uint8_t PS2_CMD_DISABLE_FIRST = 0xAD;
inline constexpr std::uint8_t PS2_CMD_ENABLE_FIRST = 0xAE;
inline constexpr std::uint8_t PS2_CMD_DISABLE_SECOND = 0xA7;
inline constexpr std::uint8_t PS2_CMD_ENABLE_SECOND = 0xA8;
inline constexpr std::uint8_t PS2_CMD_READ_CONF_BYTE = 0x20;
inline constexpr std::uint8_t PS2_CMD_WRITE_CONF_BYTE = 0x60;
inline constexpr std::uint8_t PS2_CMD_SELFTEST = 0xAA;
inline constexpr std::uint8_t PS2_CMD_PORTTEST_FIRST = 0xAB;
inline constexpr std::uint8_t PS2_CMD_PORTTEST_SECOND = 0xA9;
inline constexpr std::uint8_t PS2_CMD_WRITE_TO_SECOND = 0xD4;
inline constexpr std::uint8_t PS2_DEVICE_CMD_RESET = 0xFF;
inline constexpr std::uint8_t PS2_RESPONSE_ACK = 0xFA;
inline constexpr std::uint8_t PS2_RESPONSE_RESEND = 0xFE;
inline constexpr std::uint8_t PS2_RESPONSE_SELFTEST_PASSED = 0x55;
inline constexpr std::uint8_t PS2_RESPONSE_SELFTEST_FAILED = 0xFC;
inline constexpr std::uint8_t PS2_RESPONSE_PORTTEST_PASSED = 0x00;
inline constexpr std::uint8_t PS2_CONFIGFLAG_IRQ_ENABLE_FIRST = (1 << 0);
inline constexpr std::uint8_t PS2_CONFIGFLAG_IRQ_ENABLE_SECOND = (1 << 1);
inline constexpr std::uint8_t PS2_CONFIGFLAG_CLOCK_FIRST = (1 << 4);
inline constexpr std::uint8_t PS2_CONFIGFLAG_CLOCK_SECOND = (1 << 5);
inline constexpr std::uint8_t PS2_CONFIGFLAG_TRANSLATION = (1 << 6);
inline constexpr unsigned KEY_BUFFER_LENGTH = 16;
std::uint8_t gKeyboardBuffer[KEY_BUFFER_LENGTH];
unsigned gBufferedKeys = 0;
unsigned gKeyPos = 0;
__attribute__((no_caller_saved_registers))
void pushKey(std::uint8_t data) noexcept
{
if (gBufferedKeys == KEY_BUFFER_LENGTH) {
return;
}
gKeyboardBuffer[gKeyPos] = data;
++gBufferedKeys;
gKeyPos = (gKeyPos + 1) % KEY_BUFFER_LENGTH;
}
}
namespace baos::ps2
{
inline bool waitForResponse(unsigned tries = -1) noexcept
{
for (unsigned t = 0; t < tries; ++t)
{
if (readPortByte(PORT_PS2_STATUS) & FLAG_PS2_OUTPUT_FULL) {
return true;
}
}
return false;
}
inline void waitForInputFree() noexcept
{
while (readPortByte(PORT_PS2_STATUS) & FLAG_PS2_INPUT_FULL);
}
inline std::uint8_t cmdWithResponse(std::uint8_t cmd) noexcept
{
writePortByte(PORT_PS2_STATUS, cmd);
waitForResponse();
return readPortByte(PORT_PS2_DATA);
}
inline void cmdWithData(std::uint8_t cmd, std::uint8_t data) noexcept
{
writePortByte(PORT_PS2_STATUS, cmd);
waitForInputFree();
writePortByte(PORT_PS2_DATA, data);
}
inline void sendToFirstDevice(std::uint8_t cmd) noexcept
{
waitForInputFree();
writePortByte(PORT_PS2_DATA, cmd);
}
inline void sendToSecondDevice(std::uint8_t cmd) noexcept
{
cmdWithData(PS2_CMD_WRITE_TO_SECOND, cmd);
waitForResponse();
}
bool initialize() noexcept
{
// disable PS2
writePortByte(PORT_PS2_STATUS, PS2_CMD_DISABLE_FIRST);
writePortByte(PORT_PS2_STATUS, PS2_CMD_DISABLE_SECOND);
// flush output register
readPortByte(PORT_PS2_DATA);
// read configuration
std::uint8_t config = cmdWithResponse(PS2_CMD_READ_CONF_BYTE);
// adjust configuration
const bool secondDevice = (config & PS2_CONFIGFLAG_CLOCK_SECOND) != 0;
config &= ~PS2_CONFIGFLAG_IRQ_ENABLE_FIRST;
config &= ~PS2_CONFIGFLAG_IRQ_ENABLE_SECOND;
config &= ~PS2_CONFIGFLAG_TRANSLATION;
// write configuration
cmdWithData(PS2_CMD_WRITE_CONF_BYTE, config);
// run self-test
const std::uint8_t testResult = cmdWithResponse(PS2_CMD_SELFTEST);
if (testResult != PS2_RESPONSE_SELFTEST_PASSED) {
return false;
}
// write configuration again, in case it was reset
cmdWithData(PS2_CMD_WRITE_CONF_BYTE, config);
// check if dual-channel
bool dualChannel = false;
if ((config & PS2_CONFIGFLAG_CLOCK_SECOND) != 0) // it may be
{
writePortByte(PORT_PS2_STATUS, PS2_CMD_ENABLE_SECOND);
dualChannel = (cmdWithResponse(PS2_CMD_READ_CONF_BYTE) & PS2_CONFIGFLAG_CLOCK_SECOND) == 0;
if (dualChannel)
{
writePortByte(PORT_PS2_STATUS, PS2_CMD_DISABLE_SECOND);
}
}
// test interfaces
if (cmdWithResponse(PS2_CMD_PORTTEST_FIRST) != PS2_RESPONSE_PORTTEST_PASSED)
{
return false;
}
if (dualChannel && cmdWithResponse(PS2_CMD_PORTTEST_SECOND) != PS2_RESPONSE_PORTTEST_PASSED)
{
return false;
}
// enable devices
writePortByte(PORT_PS2_STATUS, PS2_CMD_ENABLE_FIRST);
if (dualChannel) {
writePortByte(PORT_PS2_STATUS, PS2_CMD_ENABLE_SECOND);
}
// enable interrupts
config |= PS2_CONFIGFLAG_IRQ_ENABLE_FIRST;
if (dualChannel) {
config |= PS2_CONFIGFLAG_IRQ_ENABLE_SECOND;
}
cmdWithData(PS2_CMD_WRITE_CONF_BYTE, config);
// reset
sendToFirstDevice(PS2_DEVICE_CMD_RESET);
bool firstOk = false;
while (waitForResponse(10))
{
const std::uint8_t response = readPortByte(PORT_PS2_DATA);
if (response == PS2_RESPONSE_SELFTEST_FAILED) {
return false;
}
firstOk = true;
}
if (!firstOk) {
return false;
}
if (dualChannel)
{
sendToSecondDevice(PS2_DEVICE_CMD_RESET);
bool secondOk = false;
while (waitForResponse(10))
{
const std::uint8_t response = readPortByte(PORT_PS2_DATA);
if (response == PS2_RESPONSE_SELFTEST_FAILED) {
return false;
}
secondOk = true;
}
if (!secondOk) {
return false;
}
}
return true;
}
__attribute__((interrupt))
void isrKeyboard(InterruptFrame* interruptFrame) noexcept
{
(void) interruptFrame;
const std::uint8_t data = readPortByte(PORT_PS2_DATA);
if (data != 0)
{
pushKey(data);
}
sendEndOfInterrupt(1);
}
[[nodiscard]] bool readRaw(std::uint8_t& outData) noexcept
{
maskIRQ(1);
bool result = false;
if (gBufferedKeys > 0)
{
outData = gKeyboardBuffer[(gKeyPos + KEY_BUFFER_LENGTH - gBufferedKeys) % KEY_BUFFER_LENGTH];
--gBufferedKeys;
result = true;
}
unmaskIRQ(1);
return result;
}
bool gNextIsRelease = false;
bool gNextIsExtended = false;
bool gNextIsMoreExtended = false;
bool gNextIsExtendedest = false;
bool gPrevWasExtendedest = false;
bool readKey(KeyEvent& outEvent) noexcept
{
if (gPrevWasExtendedest)
{
gPrevWasExtendedest = gNextIsExtended = gNextIsMoreExtended = gNextIsExtendedest = false;
outEvent.scancode = Scancode::PAUSE;
outEvent.down = false;
outEvent.repeat = false;
return true;
}
std::uint8_t data = 0;
if (!readRaw(data)) {
return false;
}
if (gNextIsExtendedest)
{
if (data == 0x77)
{
// second 0x77, our most special key is done
if (gNextIsExtended)
{
gPrevWasExtendedest = true; // the next scan will return the key up event
outEvent.scancode = Scancode::PAUSE;
outEvent.down = true;
outEvent.repeat = false;
return true;
}
else
{
// first 0x77 in sequence, wait for the second one
gNextIsExtended = true;
return false;
}
}
return false; // ignore everything else until we finished the most special key
}
switch (data)
{
case 0xF0:
gNextIsRelease = true;
return false;
case 0xE0:
gNextIsExtended = true;
return false;
case 0x12:
if (gNextIsExtended)
{
gNextIsMoreExtended = true;
return false;
}
break;
case 0xE1:
gNextIsExtendedest = true;
return false;
default: break;
}
std::uint16_t scancode = data;
if (gNextIsExtended)
{
if (gNextIsMoreExtended)
{
scancode = static_cast<std::uint16_t>(Scancode::PRINT_SCREEN);
}
else
{
scancode |= 0xE000;
}
}
outEvent.scancode = static_cast<Scancode>(scancode);
outEvent.down = !gNextIsRelease;
outEvent.repeat = false; // TODO
// reset state
gNextIsExtendedest = gNextIsMoreExtended = gNextIsRelease = gNextIsExtended = false;
return true;
}
const char* keyName(Scancode scancode) noexcept
{
switch (scancode)
{
case Scancode::INVALID:
default:
return "INVALID";
case Scancode::F9:
return "F9";
case Scancode::F5:
return "F5";
case Scancode::F3:
return "F3";
case Scancode::F1:
return "F1";
case Scancode::F2:
return "F2";
case Scancode::F12:
return "F12";
case Scancode::F10:
return "F10";
case Scancode::F8:
return "F8";
case Scancode::F6:
return "F6";
case Scancode::F4:
return "F4";
case Scancode::TAB:
return "TAB";
case Scancode::BACKTICK:
return "BACKTICK";
case Scancode::LEFT_ALT:
return "LEFT_ALT";
case Scancode::LEFT_SHIFT:
return "LEFT_SHIFT";
case Scancode::LEFT_CONTROL:
return "LEFT_CONTROL";
case Scancode::Q:
return "Q";
case Scancode::_1:
return "_1";
case Scancode::Z:
return "Z";
case Scancode::S:
return "S";
case Scancode::A:
return "A";
case Scancode::W:
return "W";
case Scancode::_2:
return "_2";
case Scancode::C:
return "C";
case Scancode::X:
return "X";
case Scancode::D:
return "D";
case Scancode::E:
return "E";
case Scancode::_4:
return "_4";
case Scancode::_3:
return "_3";
case Scancode::SPACE:
return "SPACE";
case Scancode::V:
return "V";
case Scancode::F:
return "F";
case Scancode::T:
return "T";
case Scancode::R:
return "R";
case Scancode::_5:
return "_5";
case Scancode::N:
return "N";
case Scancode::B:
return "B";
case Scancode::H:
return "H";
case Scancode::G:
return "G";
case Scancode::Y:
return "Y";
case Scancode::_6:
return "_6";
case Scancode::M:
return "M";
case Scancode::J:
return "J";
case Scancode::U:
return "U";
case Scancode::_7:
return "_7";
case Scancode::_8:
return "_8";
case Scancode::COMMA:
return "COMMA";
case Scancode::K:
return "K";
case Scancode::I:
return "I";
case Scancode::O:
return "O";
case Scancode::_0:
return "_0";
case Scancode::_9:
return "_9";
case Scancode::DOT:
return "DOT";
case Scancode::SLASH:
return "SLASH";
case Scancode::L:
return "L";
case Scancode::SEMICOLON:
return "SEMICOLON";
case Scancode::P:
return "P";
case Scancode::MINUS:
return "MINUS";
case Scancode::APOSTROPHE:
return "APOSTROPHE";
case Scancode::BRACKET_OPEN:
return "BRACKET_OPEN";
case Scancode::EQUALS:
return "EQUALS";
case Scancode::CAPSLOCK:
return "CAPSLOCK";
case Scancode::RIGHT_SHIFT:
return "RIGHT_SHIFT";
case Scancode::ENTER:
return "ENTER";
case Scancode::BRACKET_CLOSE:
return "BRACKET_CLOSE";
case Scancode::BACKSLASH:
return "BACKSLASH";
case Scancode::BACKSPACE:
return "BACKSPACE";
case Scancode::KP_1:
return "KP_1";
case Scancode::KP_4:
return "KP_4";
case Scancode::KP_7:
return "KP_7";
case Scancode::KP_0:
return "KP_0";
case Scancode::KP_DOT:
return "KP_DOT";
case Scancode::KP_2:
return "KP_2";
case Scancode::KP_5:
return "KP_5";
case Scancode::KP_6:
return "KP_6";
case Scancode::KP_8:
return "KP_8";
case Scancode::ESCAPE:
return "ESCAPE";
case Scancode::NUMLOCK:
return "NUMLOCK";
case Scancode::F11:
return "F11";
case Scancode::KP_PLUS:
return "KP_PLUS";
case Scancode::KP_3:
return "KP_3";
case Scancode::KP_MINUS:
return "KP_MINUS";
case Scancode::KP_ASTERISK:
return "KP_ASTERISK";
case Scancode::KP_9:
return "KP_9";
case Scancode::SCROLLOCK:
return "SCROLLOCK";
case Scancode::F7:
return "F7";
case Scancode::MM_WWW_SEARCH:
return "MM_WWW_SEARCH";
case Scancode::RIGHT_ALT:
return "RIGHT_ALT";
case Scancode::RIGHT_CONTROL:
return "RIGHT_CONTROL";
case Scancode::MM_PREV_TRACK:
return "MM_PREV_TRACK";
case Scancode::LEFT_GUI:
return "LEFT_GUI";
case Scancode::MM_WWW_FAVORITES:
return "MM_WWW_FAVORITES";
case Scancode::MM_VOLUME_DOWN:
return "MM_VOLUME_DOWN";
case Scancode::MM_MUTE:
return "MM_MUTE";
case Scancode::RIGHT_GUI:
return "RIGHT_GUI";
case Scancode::MM_WWW_STOP:
return "MM_WWW_STOP";
case Scancode::MM_CALCULATOR:
return "MM_CALCULATOR";
case Scancode::APPS:
return "APPS";
case Scancode::MM_WWW_FORWARD:
return "MM_WWW_FORWARD";
case Scancode::MM_VOLUME_UP:
return "MM_VOLUME_UP";
case Scancode::MM_PLAY_PAUSE:
return "MM_PLAY_PAUSE";
case Scancode::ACPI_POWER:
return "ACPI_POWER";
case Scancode::MM_WWW_BACK:
return "MM_WWW_BACK";
case Scancode::MM_WWW_HOME:
return "MM_WWW_HOME";
case Scancode::MM_STOP:
return "MM_STOP";
case Scancode::ACPI_SLEEP:
return "ACPI_SLEEP";
case Scancode::MM_MY_COMPUTER:
return "MM_MY_COMPUTER";
case Scancode::MM_EMAIL:
return "MM_EMAIL";
case Scancode::KP_SLASH:
return "KP_SLASH";
case Scancode::MM_NEXT_TRACK:
return "MM_NEXT_TRACK";
case Scancode::MM_MEDIA_SELECT:
return "MM_MEDIA_SELECT";
case Scancode::KP_ENTER:
return "KP_ENTER";
case Scancode::ACPI_WAKE:
return "ACPI_WAKE";
case Scancode::END:
return "END";
case Scancode::ARROW_LEFT:
return "ARROW_LEFT";
case Scancode::HOME:
return "HOME";
case Scancode::INSERT:
return "INSERT";
case Scancode::DELETE:
return "DELETE";
case Scancode::ARROW_DOWN:
return "ARROW_DOWN";
case Scancode::ARROW_RIGHT:
return "ARROW_RIGHT";
case Scancode::ARROW_UP:
return "ARROW_UP";
case Scancode::PAGE_DOWN:
return "PAGE_DOWN";
case Scancode::PAGE_UP:
return "PAGE_UP";
case Scancode::PRINT_SCREEN:
return "PRINT_SCREEN";
case Scancode::PAUSE:
return "PAUSE";
}
}
}