fix(vkernel): 键盘无法输入 - 键盘/鼠标共享 0x60 统一为单一消费者(IRQ1 ISR→buffer→desktop 轮询),IRQ1 只收键盘字节

This commit is contained in:
TermiNexus committed 2026-10-15 17:24:17 +08:00
1 parent 6e78a08797
commit 0d0dba476f
2 files changed
+19 -6

No files matched your search

@@ -64,6 +64,11 @@ def _wait_write():
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
+14 -6
View File
@@ -739,7 +739,9 @@ def _update_keyboard():
global _ps2_e0_pending
# Quick check: skip if no PS/2 data and no USB data
ps2_status: uint8 = asm.inb(0x64)
if (ps2_status & 0x01) == 0 and not usb_kbd.has_data():
# keyboard 的缓冲也要算"有数据":键盘字节是由 IRQ1 收进 buffer 的,
# 此时 0x64 bit0 往往已被 ISR 读空,若只看 0x64 就会漏掉整批按键。
if (ps2_status & 0x01) == 0 and not usb_kbd.has_data() and keyboard.has_data() == 0:
_check_key_repeat()
return
if _kbd_irq_masked == 0:
@@ -788,17 +790,23 @@ def _update_keyboard():
rel_evt._pad1 = 0
rel_evt._pad2 = 0
_push_event(rel_evt)
# AUX(鼠标)字节:本层只负责丢弃。键盘字节**绝不在这里 inb(0x60)** ——
# 0x60 是键盘/鼠标共享的输出缓冲,IRQ1 ISR 已把键盘字节收进 keyboard 缓冲,
# 这里再读一次会把 ISR 的字节抢走(现场:ki=2,键盘完全无法输入)。
ps2_poll_count: int = 0
while ps2_poll_count < 16:
ps2_status: uint8 = asm.inb(0x64)
if (ps2_status & 0x01) == 0:
break
if (ps2_status & 0x20) != 0:
asm.inb(0x60)
ps2_poll_count += 1
continue
sc: uint8 = asm.inb(0x60)
if (ps2_status & 0x20) == 0:
break
asm.inb(0x60)
ps2_poll_count += 1
# 键盘扫描码的唯一消费者:keyboard 驱动缓冲(IRQ1 → buffer → 这里取)
kbd_scan_cnt: int = 0
while keyboard.has_data() and kbd_scan_cnt < 16:
sc: uint8 = keyboard.read_scancode()
kbd_scan_cnt += 1
if sc == 0x00 or sc == 0xFA or sc == 0xFE or sc == 0xFF:
_ps2_e0_pending = 0
continue