Keyboard driver portability
Posted: Fri Dec 30, 2016 12:59 pm
(This is my first post here. Hi.)
I've been working on a bootloader, and just got my keyboard "driver" to (barely) work on QEMU. It just disables the translator on the PS/2 controller and then each time it read a key press it writes the applicable ASCII character to the screen. However, just booted up on an old Athlon 64 desktop, and the driver doesn't look like it can correctly translate key presses. It "works" in the sense that it doesn't crash or do anything crazy, but the characters that show up on the screen have nothing to do with what I'm pressing.
The driver expects scan code set 2; since I've cleared the translate bit, isn't that what I should be getting? If I'm getting codes from another set, what do I need to do to ensure that I get set 2 on most systems?
For reference, here are a few keystrokes and what I see on screen:
Pause : "W)"
LShift: "V"
Right Arrow: "VP "
Since I can't get this problem in an emulator, it would be really cumbersome to try to test. I'm hoping someone here has dealt with it.
Keyboard "driver" w/o irrelevant parts:
And if it's relevant, the translator (with my spreadsheet):
https://docs.google.com/spreadsheets/d/ ... edit#gid=0
I've been working on a bootloader, and just got my keyboard "driver" to (barely) work on QEMU. It just disables the translator on the PS/2 controller and then each time it read a key press it writes the applicable ASCII character to the screen. However, just booted up on an old Athlon 64 desktop, and the driver doesn't look like it can correctly translate key presses. It "works" in the sense that it doesn't crash or do anything crazy, but the characters that show up on the screen have nothing to do with what I'm pressing.
The driver expects scan code set 2; since I've cleared the translate bit, isn't that what I should be getting? If I'm getting codes from another set, what do I need to do to ensure that I get set 2 on most systems?
For reference, here are a few keystrokes and what I see on screen:
Pause : "W)"
LShift: "V"
Right Arrow: "VP "
Since I can't get this problem in an emulator, it would be really cumbersome to try to test. I'm hoping someone here has dealt with it.
Keyboard "driver" w/o irrelevant parts:
Code: Select all
#include "keyboard.h"
#include "keyboardtranslator.h"
#include "keyboardevent.h"
#include "pio.h"
#include "system.h"
bool Keyboard::keyflags[128];
void Keyboard::initialize()
{
waitForBuffer(BUFFER_INPUT, false);
outb(0x64, 0x20);
waitForBuffer(BUFFER_OUTPUT, true);
uint8_t config = inb(0x60);
config &= 0xBF;
waitForBuffer(BUFFER_INPUT, false);
outb(0x64, 0x60);
outb(0x60, config);
}
void Keyboard::sendEvent(KeyboardEvent event)
{
keyflags[event.getKeycode()] = event.isPressed();
if(event.isPressed() && KeyboardTranslator::keycodeToAscii(event.getKeycode()) != '\0')
System::putChar(KeyboardTranslator::keycodeToAscii(keyflags[0x33] ? event.getKeycode() + 0x60 : event.getKeycode()));
}
void Keyboard::scan()
{
uint8_t scancode[8] = {0};
int scancodeLength = 0;
bool pressed = true;
uint8_t byte = 0;
do
{
byte = readByte();
if(byte != 0)
{
scancode[scancodeLength] = byte;
scancodeLength++;
}
} while(byte != 0);
if(scancode[0] == 0xF0)
{
pressed = false;
}
else if(scancode[0] == 0xE0)
{
if(scancode[1] == 0xF0)
{
pressed = false;
}
}
if(scancodeLength > 0)
{
uint8_t lookup = scancode[scancodeLength - 1] + (scancode[0] == 0xE0 ? 0x80 : 0x00);
KeyboardEvent event(KeyboardTranslator::lookupToKeycode(lookup), pressed);
sendEvent(event);
}
}
uint8_t Keyboard::readByte()
{
if(waitForBuffer(BUFFER_OUTPUT, true))
{
uint8_t b = inb(0x60);
return b;
}
else
return 0;
}
bool Keyboard::waitForBuffer(uint8_t buffer, bool state)
{
int counter = 0;
uint8_t status = 0x00;
do
{
status = inb(0x64);
io_wait();
counter++;
if(counter > 16)
return false;
} while((status & buffer) != (state ? buffer : 0));
return true;
}
https://docs.google.com/spreadsheets/d/ ... edit#gid=0
Code: Select all
#include "keyboardtranslator.h"
#include "system.h"
uint8_t KeyboardTranslator::keycodeLookup[256];
uint8_t KeyboardTranslator::asciiLookup[256];
void KeyboardTranslator::initialize()
{
uint8_t keycodes[256] =
{
0xFF, 0x2C, 0xFF, 0x28, 0x26, 0x24, 0x25, 0x2F, 0xFF, 0x2D, 0x2B, 0x29, 0x27, 0x30, 0x3D, 0xFF, // 0
0xFF, 0x32, 0x33, 0xFF, 0x34, 0x10, 0x1B, 0xFF, 0xFF, 0xFF, 0x19, 0x12, 0x00, 0x16, 0x1C, 0xFF, // 1
0xFF, 0x02, 0x17, 0x03, 0x04, 0x1E, 0x1D, 0xFF, 0xFF, 0x31, 0x15, 0x05, 0x13, 0x11, 0x1F, 0xFF, // 2
0xFF, 0x0D, 0x01, 0x07, 0x06, 0x18, 0x20, 0xFF, 0xFF, 0xFF, 0x0C, 0x09, 0x14, 0x21, 0x22, 0xFF, // 3
0xFF, 0x36, 0x0A, 0x08, 0x0E, 0x1A, 0x23, 0xFF, 0xFF, 0x35, 0x37, 0x0B, 0x39, 0x0F, 0x38, 0xFF, // 4
0xFF, 0xFF, 0x3E, 0xFF, 0x3A, 0x3C, 0xFF, 0xFF, 0x3F, 0x40, 0x41, 0x3B, 0xFF, 0x42, 0xFF, 0xFF, // 5
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x43, 0xFF, 0xFF, 0x45, 0xFF, 0x48, 0x4B, 0xFF, 0xFF, 0xFF, // 6
0x44, 0x4E, 0x46, 0x49, 0x4A, 0x4C, 0x52, 0x53, 0x2E, 0x4F, 0x47, 0x50, 0x51, 0x4D, 0x54, 0xFF, // 7
0xFF, 0xFF, 0xFF, 0x2A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 8
0x55, 0x56, 0xFF, 0xFF, 0x57, 0x58, 0xFF, 0xFF, 0x59, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5A, // 9
0x5B, 0x5C, 0xFF, 0x5D, 0xFF, 0xFF, 0xFF, 0x5E, 0x5F, 0xFF, 0xFF, 0x60, 0xFF, 0xFF, 0xFF, 0x61, // A
0x62, 0xFF, 0x63, 0xFF, 0x64, 0xFF, 0xFF, 0x65, 0x66, 0xFF, 0x67, 0x68, 0xFF, 0xFF, 0xFF, 0x69, // B
0x6A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6B, 0xFF, 0x6C, 0xFF, 0xFF, 0x6D, 0xFF, 0xFF, // C
0x6E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0xFF, 0xFF, 0xFF, 0x70, 0xFF, // D
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x71, 0xFF, 0x72, 0x73, 0xFF, 0xFF, 0xFF, // E
0x74, 0x75, 0x76, 0xFF, 0x77, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0x79, 0xFF, 0xFF, 0x7A, 0xFF, 0xFF // F
};
uint8_t ascii[256] =
{// 0 1 2 3 4 5 6 7 8 9 A B C D E F
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', // 0
'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', // 1
'6', '7', '8', '9', '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0', // 2
'\t',' ', '\0','\0','\0','.', ',', '/', '-', ';', '[', ']', '=', '`', '\'','\0', // 3
'\0','\n','\\','\0','0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '+', // 4
'-', '*', '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0', // 5
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 6
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ')', '!', '@', '#', '$', '%', // 7
'^', '&', '*', '(', '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0', // 8
'\t',' ', '\0','\0','\0','>', '<', '?', '_', ':', '{', '}', '+', '~', '"', '\0', // 9
'\0','\n','|', '\0','0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '+', // A
'-', '*', '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0', // B
'\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0', // C
'\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0', // D
'\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0', // E
'\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0', // F
};
for(int i = 0; i < 256; i++)
{
keycodeLookup[i] = keycodes[i];
asciiLookup[i] = ascii[i];
}
}
uint8_t KeyboardTranslator::lookupToKeycode(uint8_t lookupID)
{
return keycodeLookup[lookupID];
}
uint8_t KeyboardTranslator::keycodeToAscii(uint8_t keycode)
{
return asciiLookup[keycode];
}
uint8_t KeyboardTranslator::asciiToKeycode(uint8_t ascii)
{
}