- 去掉不再需要的 import t, c - class → struct(纯数据聚合) - t.CArray[T, N] → [N]T - static 修饰符移到类型前 - @__attribute(packed) → @__attribute__(packed) - UHCI 中断回调参数改用 callable[[], int] - 同步 CPUID 注释中的旧类型名
87 lines
3.2 KiB
Plaintext
87 lines
3.2 KiB
Plaintext
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 MOUSE_BUF_SIZE = 1024
|
||
|
||
struct usb_mouse_packet:
|
||
buttons: uint8
|
||
dx: int16
|
||
dy: int16
|
||
wheel: int8
|
||
|
||
mse_buf: [MOUSE_BUF_SIZE]usb_mouse_packet
|
||
mse_buf_head: int = 0
|
||
mse_buf_tail: int = 0
|
||
mse_buf_count: int = 0
|
||
mse_dev: usb.usb_device* = None
|
||
mse_report: hid.hid_mouse_report
|
||
mse_initialized: int = 0
|
||
mse_slot_id: int = -1
|
||
|
||
def init() -> int:
|
||
global mse_dev, mse_initialized, mse_slot_id
|
||
dev: usb.usb_device* = usb.find_hid_device(0x02)
|
||
if dev is None:
|
||
serial.puts("[usb_mse] no USB mouse found\n")
|
||
return -1
|
||
mse_dev = dev
|
||
if hid.init_mouse(dev) != 0:
|
||
serial.puts("[usb_mse] init failed\n")
|
||
return -2
|
||
mse_initialized = 1
|
||
serial.puts("[usb_mse] initialized\n")
|
||
mse_slot_id = uhci.register_int_callback(_on_int_complete)
|
||
if mse_slot_id < 0:
|
||
serial.puts("[usb_mse] register callback failed\n")
|
||
mse_initialized = 0
|
||
return -3
|
||
# 中断传输长度不得超过 mse_report(4 字节),否则 DMA 越界写全局
|
||
mse_pkt_len: uint8 = 4
|
||
if dev.ep_in_max < 4: mse_pkt_len = uint8(dev.ep_in_max)
|
||
uhci.schedule_int_transfer(mse_slot_id, dev.addr, dev.ep_in, dev.ls, mse_pkt_len, dev.ep_in_toggle, &mse_report)
|
||
return 0
|
||
|
||
def _on_int_complete() -> int:
|
||
global mse_buf_head, mse_buf_tail, mse_buf_count
|
||
if mse_initialized == 0: return 0
|
||
if mse_report.dx != 0 or mse_report.dy != 0 or mse_report.buttons != 0:
|
||
if mse_buf_count < MOUSE_BUF_SIZE:
|
||
mse_buf[mse_buf_tail].buttons = mse_report.buttons
|
||
mse_buf[mse_buf_tail].dx = int16(mse_report.dx)
|
||
mse_buf[mse_buf_tail].dy = int16(mse_report.dy)
|
||
mse_buf[mse_buf_tail].wheel = mse_report.wheel
|
||
mse_buf_tail = mse_buf_tail + 1
|
||
if mse_buf_tail >= MOUSE_BUF_SIZE:
|
||
mse_buf_tail = 0
|
||
mse_buf_count += 1
|
||
dev: usb.usb_device* = mse_dev
|
||
if dev is not None and mse_slot_id >= 0:
|
||
mse_pkt_len2: uint8 = 4
|
||
if dev.ep_in_max < 4: mse_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(mse_slot_id, dev.addr, dev.ep_in, dev.ls, mse_pkt_len2, dev.ep_in_toggle, &mse_report)
|
||
return 0
|
||
|
||
def has_data() -> int:
|
||
if mse_buf_count > 0: return 1
|
||
return 0
|
||
|
||
def read_packet(out: usb_mouse_packet*) -> int:
|
||
global mse_buf_head, mse_buf_count
|
||
if mse_buf_count == 0: return -1
|
||
out.buttons = mse_buf[mse_buf_head].buttons
|
||
out.dx = mse_buf[mse_buf_head].dx
|
||
out.dy = mse_buf[mse_buf_head].dy
|
||
out.wheel = mse_buf[mse_buf_head].wheel
|
||
mse_buf_head = mse_buf_head + 1
|
||
if mse_buf_head >= MOUSE_BUF_SIZE:
|
||
mse_buf_head = 0
|
||
mse_buf_count -= 1
|
||
return 0
|