os/keyboard.c
2024-05-25 19:20:33 +03:00

203 lines
5.0 KiB
C

#include <stddef.h>
#include <stdint.h>
#include "interrupts.h"
#include "io.h"
#include "keyboard.h"
unsigned char us_layout[] = {
/* SHIFT CTRL ALT */
0x1B, 0x1B, 0x1B, 0x1B, /* esc (0x01) */
'1', '!', '1', '1',
'2', '@', '2', '2',
'3', '#', '3', '3',
'4', '$', '4', '4',
'5', '%', '5', '5',
'6', '^', '6', '6',
'7', '&', '7', '7',
'8', '*', '8', '8',
'9', '(', '9', '9',
'0', ')', '0', '0',
'-', '_', '-', '-',
'=', '+', '=', '=',
0x08, 0x08, 0x7F, 0x08, /* backspace */
0x09, 0x09, 0x09, 0x09, /* tab */
'q', 'Q', 'q', 'q',
'w', 'W', 'w', 'w',
'e', 'E', 'e', 'e',
'r', 'R', 'r', 'r',
't', 'T', 't', 't',
'y', 'Y', 'y', 'y',
'u', 'U', 'u', 'u',
'i', 'I', 'i', 'i',
'o', 'O', 'o', 'o',
'p', 'P', 'p', 'p',
'[', '{', '[', '[',
']', '}', ']', ']',
0x0A, 0x0A, 0x0A, 0x0A, /* enter */
0xFF, 0xFF, 0xFF, 0xFF, /* ctrl */
'a', 'A', 'a', 'a',
's', 'S', 's', 's',
'd', 'D', 'd', 'd',
'f', 'F', 'f', 'f',
'g', 'G', 'g', 'g',
'h', 'H', 'h', 'h',
'j', 'J', 'j', 'j',
'k', 'K', 'k', 'k',
'l', 'L', 'l', 'l',
';', ':', ';', ';',
0x27, 0x22, 0x27, 0x27, /* '" */
'`', '~', '`', '`', /* `~ */
0xFF, 0xFF, 0xFF, 0xFF, /* Lshift (0x2a) */
'\\', '|', '\\', '\\',
'z', 'Z', 'z', 'z',
'x', 'X', 'x', 'x',
'c', 'C', 'c', 'c',
'v', 'V', 'v', 'v',
'b', 'B', 'b', 'b',
'n', 'N', 'n', 'n',
'm', 'M', 'm', 'm',
0x2C, 0x3C, 0x2C, 0x2C, /* ,< */
0x2E, 0x3E, 0x2E, 0x2E, /* .> */
0x2F, 0x3F, 0x2F, 0x2F, /* /? */
0xFF, 0xFF, 0xFF, 0xFF, /* Rshift (0x36) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x37) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x38) */
' ', ' ', ' ', ' ', /* space */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x3a) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x3b) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x3c) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x3d) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x3e) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x3f) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x40) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x41) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x42) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x43) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x44) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x45) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x46) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x47) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x48) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x49) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x4a) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x4b) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x4c) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x4d) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x4e) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x4f) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x50) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x51) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x52) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x53) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x54) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x55) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x56) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x57) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x58) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x59) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x5a) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x5b) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x5c) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x5d) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x5e) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x5f) */
0xFF, 0xFF, 0xFF, 0xFF, /* (0x60) */
0xFF, 0xFF, 0xFF, 0xFF /* (0x61) */
};
volatile unsigned char buffer[KEYBOARD_BUFFER_SIZE];
volatile size_t buffer_index;
volatile size_t read_index;
void keyboard_clear_buffer(void)
{
buffer_index = 0;
read_index = 0;
}
int keyboard_getchar(void)
{
while (read_index == buffer_index)
;
int c = (int)buffer[read_index];
++read_index;
return c;
}
unsigned char keyboard_getscancode(void)
{
uint8_t scancode;
uint16_t index;
static uint8_t offset = 0;
scancode = inb(KEYBOARD_DATA);
--scancode;
if (scancode < 0x80)
{
switch (scancode)
{
case LSHIFT:
offset = 1;
break;
case RSHIFT:
offset = 1;
break;
case CTRL:
offset = 2;
break;
case ALT:
offset = 3;
break;
/* Character */
default:
index = scancode * 4 + offset;
return us_layout[index];
}
}
else
{
scancode -= 0x80;
switch (scancode)
{
case LSHIFT:
offset = 0;
break;
case RSHIFT:
offset = 0;
break;
case CTRL:
offset = 0;
break;
case ALT:
offset = 0;
break;
}
}
return 0;
}
void keyboard_handler(Stack *registers)
{
(void)(registers);
unsigned char c = keyboard_getscancode();
if (c)
{
buffer[buffer_index] = c;
++buffer_index;
if (buffer_index == KEYBOARD_BUFFER_SIZE)
keyboard_clear_buffer();
}
}
void keyboard_install(void)
{
keyboard_clear_buffer();
irq_install_handler(1, keyboard_handler);
}