quinn-os/keyboard.c
2021-12-21 16:51:29 +10:00

165 lines
2.6 KiB
C

#include "interrupts.h"
#include "io.h"
#include "console.h"
unsigned char ack;
void (*keyboard_dest)(unsigned char scancode, unsigned char state) = (void *)0;
unsigned char numlock = 0;
unsigned char key_leds = 0;
void keyboard_update_leds() {
outportb(0x60, 0xed);
while (inportb(0x60) != 0xFA);
outportb(0x60, key_leds);
}
void keyboard_numlock(int state) {
if (state == 0) {
key_leds &= ~(0x02);
} else {
key_leds |= 0x02;
}
keyboard_update_leds();
}
void keyboard_handler(struct regs *r) {
unsigned char scancode;
static int gotescape = 0;
if (keyboard_dest == (void *)0) return;
while(1) {
scancode = inportb(0x60);
if (scancode == 0xFA) {
ack = 1;
return;
}
if (scancode == 0xe0) {
gotescape = 1;
continue;
} else {
break;
}
}
if (scancode & 0x80) {
scancode &= 0x7F;
if (scancode == 0x45) {
numlock = !numlock;
// keyboard_numlock(numlock);
return;
}
if (numlock) {
switch (scancode) {
case 0x52:
scancode = 0x39;
break;
case 0x4f:
scancode = 0x02;
break;
case 0x50:
scancode = 0x03;
break;
case 0x51:
scancode = 0x04;
break;
case 0x4b:
scancode = 0x05;
break;
case 0x4c:
scancode = 0x06;
break;
case 0x4d:
scancode = 0x07;
break;
case 0x47:
scancode = 0x08;
break;
case 0x48:
scancode = 0x09;
break;
case 0x49:
scancode = 0x0a;
break;
default:
break;
}
}
if (gotescape) {
keyboard_dest(0xe0, 0);
gotescape = 0;
}
keyboard_dest(scancode, 0);
} else {
if (scancode == 0x45) {
return;
}
if (numlock) {
switch (scancode) {
case 0x52:
scancode = 0x39;
break;
case 0x4f:
scancode = 0x02;
break;
case 0x50:
scancode = 0x03;
break;
case 0x51:
scancode = 0x04;
break;
case 0x4b:
scancode = 0x05;
break;
case 0x4c:
scancode = 0x06;
break;
case 0x4d:
scancode = 0x07;
break;
case 0x47:
scancode = 0x08;
break;
case 0x48:
scancode = 0x09;
break;
case 0x49:
scancode = 0x0a;
break;
default:
break;
}
}
if (gotescape == 1) {
keyboard_dest(0xe0, 1);
gotescape = 0;
}
keyboard_dest(scancode, 1);
}
}
void keyboard_scancode_set2(void) {
ack = 0;
outportb(0x60, 0xF0);
while (ack == 0);
ack = 0;
outportb(0x60, 0x02);
while (ack == 0);
ack = 0;
}
void keyboard_set_handler(void (*keyboard_d)(unsigned char scancode, unsigned char state)) {
keyboard_dest = keyboard_d;
}
void init_keyboard() {
irq_install_handler(1, keyboard_handler, 0);
}