Files
nt-lite/code/hal/hal_keyboard.c
T

72 lines
1.9 KiB
C

// hal_keyboard.c - PS/2 keyboard, interrupt-driven, 256-entry ring buffer
#include "hal_api.h"
#include "hal_apic.h"
#include "hal_debug.h"
#include <stdint.h>
#include <stdbool.h>
#include <intrin.h>
#define PS2_DATA 0x60
#define PS2_STAT 0x64
#define PS2_CMD 0x64
#define KBD_BUF_SIZE 256
static uint8_t gBuf[KBD_BUF_SIZE];
static volatile int gHead = 0, gTail = 0;
static void (*gCallback)(uint8_t) = (void *)0;
// Minimal Set-2 to ASCII translation (unshifted only).
static const char gScanToAscii[128] = {
0,0,'1','2','3','4','5','6','7','8','9','0','-','=','\b',
'\t','q','w','e','r','t','y','u','i','o','p','[',']','\n',
0,'a','s','d','f','g','h','j','k','l',';','\'','`',
0,'\\','z','x','c','v','b','n','m',',','.','/',0,'*',
0,' ',0,0,0,0,0,0,0,0,0,0,0,0,0,
'7','8','9','-','4','5','6','+','1','2','3','0','.',0,0,0,
};
static void KbdIsr(void) {
uint8_t sc = __inbyte(PS2_DATA);
if (sc & 0x80) return; // key-up, ignore
int next = (gTail + 1) % KBD_BUF_SIZE;
if (next != gHead) {
gBuf[gTail] = sc;
gTail = next;
}
if (gCallback) gCallback(sc);
}
static bool KbdPoll(void) {
return gHead != gTail;
}
static uint8_t KbdReadScancode(void) {
while (gHead == gTail) { _mm_pause(); }
uint8_t sc = gBuf[gHead];
gHead = (gHead + 1) % KBD_BUF_SIZE;
return sc;
}
static char KbdReadChar(void) {
uint8_t sc = KbdReadScancode();
if (sc < 128) return gScanToAscii[sc];
return 0;
}
static void KbdSetCallback(void (*cb)(uint8_t sc)) {
gCallback = cb;
}
void HalKeyboardInitialize(HAL_KEYBOARD *out) {
// Flush PS/2 output buffer
while (__inbyte(PS2_STAT) & 1) __inbyte(PS2_DATA);
out->Poll = KbdPoll;
out->ReadScancode = KbdReadScancode;
out->ReadChar = KbdReadChar;
out->SetCallback = KbdSetCallback;
out->Isr = KbdIsr;
out->IrqNumber = 1;
}