154 lines
4.6 KiB
Plaintext
154 lines
4.6 KiB
Plaintext
import asm
|
|
import intr.idt as idt
|
|
import drivers.serial.uart.serial as serial
|
|
import string
|
|
import t, c
|
|
|
|
|
|
define KBD_DATA = 0x60
|
|
define KBD_STATUS = 0x64
|
|
define KBD_COMMAND = 0x64
|
|
|
|
define KBD_BUF_SIZE = 1024
|
|
|
|
define KEY_RELEASED = 0x80
|
|
|
|
buffer: [KBD_BUF_SIZE]uint8
|
|
buf_head: static uint32 = 0
|
|
buf_tail: static uint32 = 0
|
|
buf_count: static uint32 = 0
|
|
kbd_irq_cnt: static uint64 = 0
|
|
|
|
shift_l: static uint8 = 0
|
|
shift_r: static uint8 = 0
|
|
ctrl_l: static uint8 = 0
|
|
alt_l: static uint8 = 0
|
|
caps_lock: static uint8 = 0
|
|
|
|
scancode_set1: [128]char = [
|
|
'\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: [128]char = [
|
|
'\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: uint32 = 100000
|
|
while timeout > 0:
|
|
if (asm.inb(KBD_STATUS) & 0x01) != 0: return
|
|
timeout -= 1
|
|
|
|
def _wait_write():
|
|
timeout: uint32 = 100000
|
|
while timeout > 0:
|
|
if (asm.inb(KBD_STATUS) & 0x02) == 0: return
|
|
timeout -= 1
|
|
|
|
def irq_handler() -> int:
|
|
global buf_head, buf_tail, buf_count, kbd_irq_cnt
|
|
kbd_irq_cnt += 1
|
|
# 0x60 是键盘/鼠标**共享**的输出缓冲:AUX 位(0x64 bit5)置位表示这是鼠标字节,
|
|
# 不属于键盘 —— 直接读走会让鼠标驱动永远拿不到(本 ISR 只收键盘字节)。
|
|
st: uint8 = asm.inb(KBD_STATUS)
|
|
if (st & 0x20) != 0:
|
|
return 0
|
|
scancode: uint8 = 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() -> uint8:
|
|
global buf_head, buf_count
|
|
asm.cli()
|
|
if buf_count == 0:
|
|
asm.sti()
|
|
return 0
|
|
code: uint8 = 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: uint8) -> char:
|
|
code: uint8 = uint8(scancode & ~uint8(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() -> int:
|
|
return buf_count
|
|
|
|
def init():
|
|
drain: uint32
|
|
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: uint8 = 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")
|