// 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 #include #include #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; }