X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=bootcensus;a=blobdiff_plain;f=src%2Fkeyb.c;fp=src%2Fkeyb.c;h=c5a672c840bde879761f38ff589c980b43b36d4b;hp=0000000000000000000000000000000000000000;hb=a2f94f569a4c99204de02814a20098a71527e913;hpb=d1e8a437c1fab4535f82c4c214ec3330ac32e48d diff --git a/src/keyb.c b/src/keyb.c new file mode 100644 index 0000000..c5a672c --- /dev/null +++ b/src/keyb.c @@ -0,0 +1,132 @@ +#include "keyb.h" +#include "intr.h" +#include "asmops.h" + +#define KB_IRQ 1 +#define KB_PORT 0x60 + +/* table with rough translations from set 1 scancodes to ASCII-ish */ +static int scantbl[] = { + 0, KB_ESC, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', /* 0 - e */ + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* f - 1c */ + KB_LCTRL, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', /* 1d - 29 */ + KB_LSHIFT, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', KB_RSHIFT, /* 2a - 36 */ + KB_NUM_MUL, KB_LALT, ' ', KB_CAPSLK, KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6, KB_F7, KB_F8, KB_F9, KB_F10, /* 37 - 44 */ + KB_NUMLK, KB_SCRLK, KB_NUM_7, KB_NUM_8, KB_NUM_9, KB_NUM_MINUS, KB_NUM_4, KB_NUM_5, KB_NUM_6, KB_NUM_PLUS, /* 45 - 4e */ + KB_NUM_1, KB_NUM_2, KB_NUM_3, KB_NUM_0, KB_NUM_DOT, KB_SYSRQ, 0, 0, KB_F11, KB_F12, /* 4d - 58 */ + 0, 0, 0, 0, 0, 0, 0, /* 59 - 5f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 70 - 7f */ +}; + +static void kbintr(); + +#define BUFSZ 64 +#define ADVANCE(x) ((x) = ((x) + 1) & (BUFSZ - 1)) + +static int buffer[BUFSZ]; +static int buf_ridx, buf_widx; + +static unsigned int num_pressed; +static unsigned char keystate[256]; + +void kb_init(void) +{ + interrupt(IRQ_TO_INTR(KB_IRQ), kbintr); +} + +int kb_isdown(int key) +{ + switch(key) { + case KB_ANY: + return num_pressed; + + case KB_ALT: + return keystate[KB_LALT] + keystate[KB_RALT]; + + case KB_CTRL: + return keystate[KB_LCTRL] + keystate[KB_RCTRL]; + } + return keystate[key]; +} + +void kb_wait(void) +{ + int key; + while((key = kb_getkey()) == -1) { + /* put the processor to sleep while waiting for keypresses, but first + * make sure interrupts are enabled, or we'll sleep forever + */ + enable_intr(); + halt_cpu(); + } + kb_putback(key); +} + +int kb_getkey(void) +{ + int res; + + if(buf_ridx == buf_widx) { + return -1; + } + res = buffer[buf_ridx]; + ADVANCE(buf_ridx); + return res; +} + +void kb_putback(int key) +{ + /* go back a place */ + if(--buf_ridx < 0) { + buf_ridx += BUFSZ; + } + + /* if the write end hasn't caught up with us, go back one place + * and put it there, otherwise just overwrite the oldest key which + * is right where we were. + */ + if(buf_ridx == buf_widx) { + ADVANCE(buf_ridx); + } + + buffer[buf_ridx] = key; +} + +static void kbintr() +{ + unsigned char code; + int key, press; + + code = inb(KB_PORT); + + if(code >= 128) { + press = 0; + code -= 128; + + if(num_pressed > 0) { + num_pressed--; + } + } else { + press = 1; + + num_pressed++; + } + + key = scantbl[code]; + + if(press) { + /* append to buffer */ + buffer[buf_widx] = key; + ADVANCE(buf_widx); + /* if the write end overtook the read end, advance the read end + * too, to discard the oldest keypress from the buffer + */ + if(buf_widx == buf_ridx) { + ADVANCE(buf_ridx); + } + } + + /* and update keystate table */ + keystate[key] = press; +}