import asm import intr.idt as idt import drivers.serial.uart.serial as serial import viperstring as string import t, c KBD_DATA: t.CDefine = 0x60 KBD_STATUS: t.CDefine = 0x64 KBD_COMMAND: t.CDefine = 0x64 KBD_BUF_SIZE: t.CDefine = 1024 KEY_RELEASED: t.CDefine = 0x80 buffer: t.CArray[t.CUInt8T, KBD_BUF_SIZE] buf_head: t.CStatic | t.CUInt32T = 0 buf_tail: t.CStatic | t.CUInt32T = 0 buf_count: t.CStatic | t.CUInt32T = 0 shift_l: t.CStatic | t.CUInt8T = 0 shift_r: t.CStatic | t.CUInt8T = 0 ctrl_l: t.CStatic | t.CUInt8T = 0 alt_l: t.CStatic | t.CUInt8T = 0 caps_lock: t.CStatic | t.CUInt8T = 0 scancode_set1: t.CArray[t.CChar, 128] = [ '\0', '\x1b', '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', '-', '8', '6', '2', '\0', '1', '+', '4', '5', '3', '0', '.', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' ] scancode_set1_shift: t.CArray[t.CChar, 128] = [ '\0', '\x1b', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\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', '-', '8', '6', '2', '\0', '1', '+', '4', '5', '3', '0', '.', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' ] def _wait_read(): timeout: t.CUInt32T = 100000 while timeout > 0: if (asm.inb(KBD_STATUS) & 0x01) != 0: return timeout -= 1 def _wait_write(): timeout: t.CUInt32T = 100000 while timeout > 0: if (asm.inb(KBD_STATUS) & 0x02) == 0: return timeout -= 1 def irq_handler() -> t.CInt: global buf_head, buf_tail, buf_count scancode: t.CUInt8T = asm.inb(KBD_DATA) if buf_count < KBD_BUF_SIZE: buffer[buf_tail] = scancode buf_tail = buf_tail + 1 if buf_tail >= KBD_BUF_SIZE: buf_tail = 0 buf_count += 1 return 0 def read_scancode() -> t.CUInt8T: global buf_head, buf_count asm.cli() if buf_count == 0: asm.sti() return 0 code: t.CUInt8T = buffer[buf_head] buf_head = buf_head + 1 if buf_head >= KBD_BUF_SIZE: buf_head = 0 buf_count -= 1 asm.sti() return code def scancode_to_ascii(scancode: t.CUInt8T) -> t.CChar: code: t.CUInt8T = scancode & ~t.CUInt8T(KEY_RELEASED) if code >= 128: return '\0' shifted: bool = (shift_l or shift_r) != 0 if caps_lock and code >= 0x10 and code <= 0x32: shifted = not shifted if shifted: return scancode_set1_shift[code] return scancode_set1[code] def has_data() -> t.CInt: return buf_count def init(): drain: t.CUInt32T drain = 0 while (asm.inb(KBD_STATUS) & 0x01) != 0: asm.inb(KBD_DATA) drain += 1 if drain > 1000: break _wait_write() asm.outb(KBD_COMMAND, 0xAD) drain = 0 while (asm.inb(KBD_STATUS) & 0x01) != 0: asm.inb(KBD_DATA) drain += 1 if drain > 1000: break _wait_write() asm.outb(KBD_COMMAND, 0x20) _wait_read() ccb: t.CUInt8T = asm.inb(KBD_DATA) ccb = ccb | 0x01 ccb = ccb | 0x40 ccb = ccb & 0xEF _wait_write() asm.outb(KBD_COMMAND, 0x60) _wait_write() asm.outb(KBD_DATA, ccb) _wait_write() asm.outb(KBD_COMMAND, 0xAE) drain = 0 while (asm.inb(KBD_STATUS) & 0x01) != 0: asm.inb(KBD_DATA) drain += 1 if drain > 1000: break _wait_write() asm.outb(KBD_DATA, 0xF4) _wait_read() asm.inb(KBD_DATA) idt.irqInstallHandler(1, irq_handler, "keyboard")