VKernel / vpsdk / Apps / Libs 共 30 个源文件:内核与 SDK 侧的新语法适配及编译修正(含 bootinfo.vp / main.vp 位宽改 uint64、gfx.vp 前向引用改指针、devfs.vp 指针解引用赋值、elf.vp 跨模块函数取值等)。删除 vpsdk/wiki/*.md(14 文件,约 -8100 行):与仓库根 wiki 重复的拷贝,统一以根 wiki 为唯一来源。
120 lines
4.3 KiB
Plaintext
120 lines
4.3 KiB
Plaintext
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
|