147 lines
4.3 KiB
Python
147 lines
4.3 KiB
Python
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")
|