Hello. You can use three (or more, but it's the bare minimum) of key layouts: regular, with Shift pressed and with CapsLock ON.
Basically this is what you should do in your keyboard interrupt handler:
Get the scancode from port 0x60
Check if it's a modifier key, if it's Shift then use your layout for Shift until it gets released, if it's CapsLock use your layour for CapsLock until it gets toggled off, etc
If it's not use correspondant key layout and push the character into the keyboard buffer
Your internal getchar should either wait for keyboard interrupt to fire (if buffer is empty) or just pop last pressed character.
I personally use this:
Code:
typedef struct {
uint8_t scancode;
char chr; //Character it corresponds to.
} kybd_scancode;
static kybd_scancode regular_scancodes[] = {
/* Numerical keys */
{0x02, '1'}, {0x03, '2'}, {0x04, '3'}, {0x05, '4'}, {0x06, '5'}, {0x07, '6'}, {0x08, '7'}, {0x09, '8'}, {0x0A, '9'}, {0x0B, '0'},
/* Some characters after numerical keys */
{0x0C, '-'}, {0x0D, '='}, {0x0E, '\b'}, {0x0F, '\t'},
/* Alphabet! */
{0x10, 'q'}, {0x11, 'w'}, {0x12, 'e'}, {0x13, 'r'}, {0x14, 't'}, {0x15, 'y'}, {0x16, 'u'}, {0x17, 'i'}, {0x18, 'o'}, {0x19, 'p'}, {0x1A, '['}, {0x1B, ']'}, {0x1C, '\n'},
{0x1E, 'a'}, {0x1F, 's'}, {0x20, 'd'}, {0x21, 'f'}, {0x22, 'g'}, {0x23, 'h'}, {0x24, 'j'}, {0x25, 'k'}, {0x26, 'l'}, {0x27, ';'}, {0x28, '\''}, {0x29, '`'},
{0x2B, '\\'}, {0x2C, 'z'}, {0x2D, 'x'}, {0x2E, 'c'}, {0x2F, 'v'}, {0x30, 'b'}, {0x31, 'n'}, {0x32, 'm'}, {0x33, ','}, {0x34, '.'}, {0x35, '/'}, {0x37, '*'},
{0x39, ' '}, {0x47, '7'}, {0x48, '8'}, {0x49, '9'}, {0x4A, '-'},
{0x4B, '4'}, {0x4C, '5'}, {0x4D, '6'}, {0x4E, '+'},
{0x4F, '1'}, {0x50, '2'}, {0x51, '3'},
{0x52, '0'}, {0x53, '.'}, {0x00, '\0'}
};
static kybd_scancode uppercase_scancodes[] = {
/* Numerical keys */
{0x02, '1'}, {0x03, '2'}, {0x04, '3'}, {0x05, '4'}, {0x06, '5'}, {0x07, '6'}, {0x08, '7'}, {0x09, '8'}, {0x0A, '9'}, {0x0B, '0'},
/* Some characters after numerical keys */
{0x0C, '-'}, {0x0D, '='}, {0x0E, '\b'}, {0x0F, '\t'},
/* Alphabet! */
{0x10, 'Q'}, {0x11, 'W'}, {0x12, 'E'}, {0x13, 'R'}, {0x14, 'T'}, {0x15, 'Y'}, {0x16, 'U'}, {0x17, 'I'}, {0x18, 'O'}, {0x19, 'P'}, {0x1A, '['}, {0x1B, ']'}, {0x1C, '\n'},
{0x1E, 'A'}, {0x1F, 'S'}, {0x20, 'D'}, {0x21, 'F'}, {0x22, 'G'}, {0x23, 'H'}, {0x24, 'J'}, {0x25, 'K'}, {0x26, 'L'}, {0x27, ';'}, {0x28, '\''}, {0x29, '`'},
{0x2B, '\\'}, {0x2C, 'Z'}, {0x2D, 'X'}, {0x2E, 'C'}, {0x2F, 'V'}, {0x30, 'B'}, {0x31, 'N'}, {0x32, 'M'}, {0x33, ','}, {0x34, '.'}, {0x35, '/'}, {0x37, '*'},
{0x39, ' '}, {0x47, '7'}, {0x48, '8'}, {0x49, '9'}, {0x4A, '-'},
{0x4B, '4'}, {0x4C, '5'}, {0x4D, '6'}, {0x4E, '+'},
{0x4F, '1'}, {0x50, '2'}, {0x51, '3'},
{0x52, '0'}, {0x53, '.'}, {0x00, '\0'}
};
static kybd_scancode shift_modified_scancodes[] = {
/* Numerical keys */
{0x02, '!'}, {0x03, '@'}, {0x04, '#'}, {0x05, '$'}, {0x06, '%'}, {0x07, '^'}, {0x08, '&'}, {0x09, '*'}, {0x0A, '('}, {0x0B, ')'},
/* Some characters after numerical keys */
{0x0C, '_'}, {0x0D, '+'}, {0x0E, '\b'}, {0x0F, '\t'},
/* Alphabet! */
{0x10, 'Q'}, {0x11, 'W'}, {0x12, 'E'}, {0x13, 'R'}, {0x14, 'T'}, {0x15, 'Y'}, {0x16, 'U'}, {0x17, 'I'}, {0x18, 'O'}, {0x19, 'P'}, {0x1A, '{'}, {0x1B, '}'}, {0x1C, '\n'},
{0x1E, 'A'}, {0x1F, 'S'}, {0x20, 'D'}, {0x21, 'F'}, {0x22, 'G'}, {0x23, 'H'}, {0x24, 'J'}, {0x25, 'K'}, {0x26, 'L'}, {0x27, ':'}, {0x28, '"'}, {0x29, '~'},
{0x2B, '\\'}, {0x2C, 'Z'}, {0x2D, 'X'}, {0x2E, 'C'}, {0x2F, 'V'}, {0x30, 'B'}, {0x31, 'N'}, {0x32, 'M'}, {0x33, '<'}, {0x34, '>'}, {0x35, '?'}, {0x37, '*'},
{0x39, ' '}, {0x47, '7'}, {0x48, '8'}, {0x49, '9'}, {0x4A, '-'},
{0x4B, '4'}, {0x4C, '5'}, {0x4D, '6'}, {0x4E, '+'},
{0x4F, '1'}, {0x50, '2'}, {0x51, '3'},
{0x52, '0'}, {0x53, '.'}, {0x00, '\0'}
};
typedef struct {
int lshift : 1;
int rshift : 1;
int lctrl : 1;
int rctrl : 1;
int numlk : 1;
int capslk : 1;
int scrllk : 1;
} kybd_modifier_key_states;
static kybd_modifier_key_states modifier_keys;
static char keyboard_buffer[256] = {};
static uint8_t kybd_buffer_current_position = 0; //0 to 255
static void kybd_buffer_push(char value)
{
if(kybd_buffer_current_position != 255)
keyboard_buffer[kybd_buffer_current_position++] = value;
else
{
printk("Keyboard buffer overflow! Keypresses will NOT be processed before buffer will be freed. User hit the keys randomly in Flash speed, system is too slow, or BPS monkeys just mistaken?");
return;
}
}
static char kybd_buffer_pop()
{
if(kybd_buffer_current_position > 0)
return keyboard_buffer[--kybd_buffer_current_position];
else
return 0; //we have nothing in the buffer
}
//Interrupt part of the keyboard driver.
volatile bool kbd_irq_fired=false;
void kbd_wait_irq()
{
//if(kbd_irq_fired){while(kbd_irq_fired);return;}
while(!kbd_irq_fired);
kbd_irq_fired=false;
}
char kbd_scancode_convert(uint8_t scancode)
{
if(modifier_keys.capslk)
{
for(int i=0; uppercase_scancodes[i].scancode != 0x00; i++)
if(uppercase_scancodes[i].scancode == scancode)
return uppercase_scancodes[i].chr;
return 0;
}
else if(modifier_keys.lshift || modifier_keys.rshift)
{
for(int i=0; shift_modified_scancodes[i].scancode != 0x00; i++)
if(shift_modified_scancodes[i].scancode == scancode)
return shift_modified_scancodes[i].chr;
return 0;
}
else {
for(int i=0; regular_scancodes[i].scancode != 0x00; i++)
if(regular_scancodes[i].scancode == scancode)
return regular_scancodes[i].chr;
return 0;
}
}
void kbd_handler(struct regs *UNUSED(r))
{
kbd_irq_fired=true;
//We need to put every pressed printable key to the buffer.
uint8_t scancode = inb(KBD_DATA);
switch(scancode)
{
case KEY_LSHIFT_P: modifier_keys.lshift = 1; break;
case KEY_RSHIFT_P: modifier_keys.rshift = 1; break;
case KEY_LSHIFT_R: modifier_keys.lshift = 0; break;
case KEY_RSHIFT_R: modifier_keys.rshift = 0; break;
default: kybd_buffer_push(kbd_scancode_convert(scancode)); break;
}
}
uint8_t kbd_getchar()
{
char ret=0;
while(!ret)
{
sleep(1);
kbd_wait_irq();
ret = kybd_buffer_pop();
}
return ret;
}
You can even use that code as long as you'll leave a disclaimer that it's my code