Files
ViperOS/VKernel/Kernel/drivers/usb/hid/usb_kbd.vp
T
TermiNexus 5b4bab59cc chore(ViperOS): 合并落库内核侧在途改动并移除 vpsdk wiki 拷贝
VKernel / vpsdk / Apps / Libs 共 30 个源文件:内核与 SDK 侧的新语法适配及编译修正(含 bootinfo.vp / main.vp 位宽改 uint64、gfx.vp 前向引用改指针、devfs.vp 指针解引用赋值、elf.vp 跨模块函数取值等)。删除 vpsdk/wiki/*.md(14 文件,约 -8100 行):与仓库根 wiki 重复的拷贝,统一以根 wiki 为唯一来源。
2026-10-07 19:04:33 +08:00

120 lines
4.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import t, c
import drivers.usb.usb as usb
import drivers.usb.hid.hid as hid
import drivers.usb.uhci as uhci
import drivers.serial.uart.serial as serial
define KBD_BUF_SIZE = 1024
define KBD_EVT_PRESS = 0
define KBD_EVT_RELEASE = 1
class usb_kbd_event:
modifier: uint8
keycode: uint8
event_type: uint8
kbd_buf: [KBD_BUF_SIZE]usb_kbd_event
kbd_buf_head: int = 0
kbd_buf_tail: int = 0
kbd_buf_count: int = 0
kbd_dev: usb.usb_device* = None
kbd_report: hid.hid_kbd_report
kbd_prev_keycodes: [6]uint8
kbd_initialized: int = 0
kbd_slot_id: int = -1
def init() -> int:
global kbd_dev, kbd_initialized, kbd_slot_id
dev: usb.usb_device* = usb.find_hid_device(0x01)
if dev is None:
serial.puts("[usb_kbd] no USB keyboard found\n")
return -1
kbd_dev = dev
if hid.init_keyboard(dev) != 0:
serial.puts("[usb_kbd] init failed\n")
return -2
kbd_initialized = 1
serial.puts("[usb_kbd] initialized\n")
kbd_slot_id = uhci.register_int_callback(&_on_int_complete)
if kbd_slot_id < 0:
serial.puts("[usb_kbd] register callback failed\n")
kbd_initialized = 0
return -3
# 中断传输长度不得超过 kbd_report(8 字节),否则 DMA 越界写全局
kbd_pkt_len: uint8 = 8
if dev.ep_in_max < 8: kbd_pkt_len = uint8(dev.ep_in_max)
uhci.schedule_int_transfer(kbd_slot_id, dev.addr, dev.ep_in, dev.ls, kbd_pkt_len, dev.ep_in_toggle, &kbd_report)
return 0
def _on_int_complete() -> int:
global kbd_buf_head, kbd_buf_tail, kbd_buf_count, kbd_prev_keycodes
if kbd_initialized == 0: return 0
j: int
for i in range(6):
code: uint8 = kbd_report.keycode[i]
if code == 0: continue
found: int = 0
for j in range(6):
if code == kbd_prev_keycodes[j]:
found = 1
break
if found == 0:
if kbd_buf_count < KBD_BUF_SIZE:
kbd_buf[kbd_buf_tail].modifier = kbd_report.modifier
kbd_buf[kbd_buf_tail].keycode = code
kbd_buf[kbd_buf_tail].event_type = KBD_EVT_PRESS
kbd_buf_tail = kbd_buf_tail + 1
if kbd_buf_tail >= KBD_BUF_SIZE:
kbd_buf_tail = 0
kbd_buf_count += 1
for i in range(6):
prev: uint8 = kbd_prev_keycodes[i]
if prev == 0: continue
found2: int = 0
for j in range(6):
if prev == kbd_report.keycode[j]:
found2 = 1
break
if found2 == 0:
if kbd_buf_count < KBD_BUF_SIZE:
kbd_buf[kbd_buf_tail].modifier = kbd_report.modifier
kbd_buf[kbd_buf_tail].keycode = prev
kbd_buf[kbd_buf_tail].event_type = KBD_EVT_RELEASE
kbd_buf_tail = kbd_buf_tail + 1
if kbd_buf_tail >= KBD_BUF_SIZE:
kbd_buf_tail = 0
kbd_buf_count += 1
for i in range(6):
kbd_prev_keycodes[i] = kbd_report.keycode[i]
dev: usb.usb_device* = kbd_dev
if dev is not None and kbd_slot_id >= 0:
kbd_pkt_len2: uint8 = 8
if dev.ep_in_max < 8: kbd_pkt_len2 = uint8(dev.ep_in_max)
# 推进 DATA0/DATA1 翻转位:本回调表示上一次中断 IN 事务已结束(IRQ 中 TD 不再
# ACTIVE),翻转后本次重排使用另一 PID。全仓仅此处推进 ep_in_toggle;不推进
# 则 TD token 的 toggle 位恒为 DATA0,DATA toggle 永不交替。
dev.ep_in_toggle = uint8(dev.ep_in_toggle ^ 1)
uhci.schedule_int_transfer(kbd_slot_id, dev.addr, dev.ep_in, dev.ls, kbd_pkt_len2, dev.ep_in_toggle, &kbd_report)
return 0
def has_data() -> int:
if kbd_buf_count > 0: return 1
return 0
def poll() -> int:
if kbd_initialized == 0: return 0
if kbd_buf_count > 0: return 1
return 0
def read_event(out: usb_kbd_event*) -> int:
global kbd_buf_head, kbd_buf_count
if kbd_buf_count == 0: return -1
out.modifier = kbd_buf[kbd_buf_head].modifier
out.keycode = kbd_buf[kbd_buf_head].keycode
out.event_type = kbd_buf[kbd_buf_head].event_type
kbd_buf_head = kbd_buf_head + 1
if kbd_buf_head >= KBD_BUF_SIZE:
kbd_buf_head = 0
kbd_buf_count -= 1
return 0