Files
ViperOS/VKernel/Kernel/drivers/usb/usb.vp
T
TermiNexus dcb7c5c2c0 chore(ViperOS): 落库内核侧进行中的改动(26 文件,+1573/-1805)
内容由用户产出,本次仅代为提交、未做任何语义修改;含 static 修饰符前置迁移等(新增 static 前缀 16 行)。提交消息为中性描述——如需更精确的说明请 amend。
2026-09-28 15:24:52 +08:00

332 lines
11 KiB
Plaintext

import mm.mm as mm
import string
import drivers.serial.uart.serial as serial
import drivers.usb.uhci as uhci
import drivers.usb.pci as pci
import platform.pch.timer as timer
import viperlib
define USB_DESC_DEVICE = 1
define USB_DESC_CONFIG = 2
define USB_DESC_STRING = 3
define USB_DESC_INTERFACE = 4
define USB_DESC_ENDPOINT = 5
define USB_REQ_GET_STATUS = 0
define USB_REQ_CLEAR_FEATURE = 1
define USB_REQ_SET_FEATURE = 3
define USB_REQ_SET_ADDRESS = 5
define USB_REQ_GET_DESCRIPTOR = 6
define USB_REQ_SET_DESCRIPTOR = 7
define USB_REQ_GET_CONFIGURATION = 8
define USB_REQ_SET_CONFIGURATION = 9
define USB_REQ_SET_INTERFACE = 11
define HID_CLASS = 0x03
define HID_SUBCLASS_BOOT = 0x01
define HID_PROTO_KEYBOARD = 0x01
define HID_PROTO_MOUSE = 0x02
define HID_REQ_SET_PROTOCOL = 0x0B
define HID_REQ_SET_IDLE = 0x0A
define HID_REQ_GET_REPORT = 0x01
define USB_MAX_DEVICES = 8
class usb_dev_desc:
bLength: uint8
bDescriptorType: uint8
bcdUSB: uint16
bDeviceClass: uint8
bDeviceSubClass: uint8
bDeviceProtocol: uint8
bMaxPacketSize0: uint8
idVendor: uint16
idProduct: uint16
bcdDevice: uint16
iManufacturer: uint8
iProduct: uint8
iSerialNumber: uint8
bNumConfigurations: uint8
class usb_config_desc:
bLength: uint8
bDescriptorType: uint8
wTotalLength: uint16
bNumInterfaces: uint8
bConfigurationValue: uint8
iConfiguration: uint8
bmAttributes: uint8
bMaxPower: uint8
class usb_iface_desc:
bLength: uint8
bDescriptorType: uint8
bInterfaceNumber: uint8
bAlternateSetting: uint8
bNumEndpoints: uint8
bInterfaceClass: uint8
bInterfaceSubClass: uint8
bInterfaceProtocol: uint8
iInterface: uint8
class usb_ep_desc:
bLength: uint8
bDescriptorType: uint8
bEndpointAddress: uint8
bmAttributes: uint8
wMaxPacketSize: uint16
bInterval: uint8
class usb_setup_pkt:
bmRequestType: uint8
bRequest: uint8
wValue: uint16
wIndex: uint16
wLength: uint16
class usb_device:
addr: uint8
ls: int
max_pkt0: uint8
iface_class: uint8
iface_subclass: uint8
iface_protocol: uint8
iface_num: uint8
ep_in: uint8
ep_in_max: uint16
ep_in_interval: uint8
ep_in_toggle: uint8
configured: int
_devices: [USB_MAX_DEVICES]usb_device
_device_count: int = 0
def _setup_packet(bmRequestType: uint8, bRequest: uint8, wValue: uint16, wIndex: uint16, wLength: uint16, buf: usb_setup_pkt*):
buf.bmRequestType = bmRequestType
buf.bRequest = bRequest
buf.wValue = wValue
buf.wIndex = wIndex
buf.wLength = wLength
def _send_control(dev_addr: uint8, ls: int, max_pkt: uint8, setup: usb_setup_pkt*, data_buf: rawptr, data_len: uint16, data_in: int) -> int:
return uhci.control_transfer(dev_addr, 0, ls, max_pkt, setup, data_buf, data_len, data_in)
def get_descriptor(dev_addr: uint8, ls: int, max_pkt: uint8, desc_type: uint8, desc_idx: uint8, buf: rawptr, length: uint16) -> int:
setup: usb_setup_pkt
_setup_packet(0x80, USB_REQ_GET_DESCRIPTOR, (uint16(desc_type) << 8) | desc_idx, 0, length, &setup)
return _send_control(dev_addr, ls, max_pkt, &setup, buf, length, 1)
def set_address(dev_addr: uint8, ls: int, max_pkt: uint8, new_addr: uint8) -> int:
setup: usb_setup_pkt
_setup_packet(0x00, USB_REQ_SET_ADDRESS, new_addr, 0, 0, &setup)
return _send_control(dev_addr, ls, max_pkt, &setup, None, 0, 0)
def set_configuration(dev_addr: uint8, ls: int, max_pkt: uint8, config_val: uint8) -> int:
setup: usb_setup_pkt
_setup_packet(0x00, USB_REQ_SET_CONFIGURATION, config_val, 0, 0, &setup)
return _send_control(dev_addr, ls, max_pkt, &setup, None, 0, 0)
def hid_set_protocol(dev_addr: uint8, ls: int, max_pkt: uint8, iface: uint8, protocol: uint8) -> int:
setup: usb_setup_pkt
_setup_packet(0x21, HID_REQ_SET_PROTOCOL, protocol, uint16(iface), 0, &setup)
return _send_control(dev_addr, ls, max_pkt, &setup, None, 0, 0)
def hid_set_idle(dev_addr: uint8, ls: int, max_pkt: uint8, iface: uint8, duration: uint8) -> int:
setup: usb_setup_pkt
_setup_packet(0x21, HID_REQ_SET_IDLE, uint16(duration) << 8, uint16(iface), 0, &setup)
return _send_control(dev_addr, ls, max_pkt, &setup, None, 0, 0)
def _parse_config(dev: usb_device*, config_buf: rawptr, total_len: uint16):
offset: int = 0
found_hid: int = 0
while offset < int(total_len):
p: uint8* = config_buf + uint64(offset)
desc_len: uint8 = *p
p2: uint8* = config_buf + uint64(offset) + 1
desc_type: uint8 = *p2
if desc_len == 0: break
# 边界:描述符整体须落在 config_buf(total_len 字节)内,且不得短于
# 所访问的结构体(interface=9 / endpoint=7),否则越界读。
if offset + int(desc_len) > int(total_len): break
if desc_type == USB_DESC_INTERFACE and int(desc_len) >= 9:
iface: usb_iface_desc* = usb_iface_desc*(config_buf + uint64(offset))
if iface.bInterfaceClass == HID_CLASS:
found_hid = 1
dev.iface_class = HID_CLASS
dev.iface_subclass = iface.bInterfaceSubClass
dev.iface_protocol = iface.bInterfaceProtocol
dev.iface_num = iface.bInterfaceNumber
if desc_type == USB_DESC_ENDPOINT and found_hid and int(desc_len) >= 7:
ep: usb_ep_desc* = usb_ep_desc*(config_buf + uint64(offset))
if (ep.bEndpointAddress & 0x80) != 0:
dev.ep_in = ep.bEndpointAddress & 0x0F
dev.ep_in_max = ep.wMaxPacketSize
dev.ep_in_interval = ep.bInterval
found_hid = 0
offset = offset + int(desc_len)
def enumerate_port(port: int) -> int:
global _device_count
if _device_count >= USB_MAX_DEVICES: return -1
ls: int = uhci.port_is_low_speed(port)
reset_ok: int = -1
for reset_retry in range(3):
if uhci.port_reset(port) == 0:
reset_ok = 0
break
timer.timer_msleep(50)
if reset_ok != 0:
return -2
timer.timer_msleep(10)
dev_buf: rawptr = mm.malloc(usb_dev_desc.__sizeof__())
if dev_buf is None: return -3
string.memset(dev_buf, 0, usb_dev_desc.__sizeof__())
result: int = get_descriptor(0, ls, 8, USB_DESC_DEVICE, 0, dev_buf, 8)
retry: int
for retry in range(3):
if result == 0: break
timer.timer_msleep(50)
uhci.port_reset(port)
timer.timer_msleep(10)
result = get_descriptor(0, ls, 8, USB_DESC_DEVICE, 0, dev_buf, 8)
if result != 0:
mm.free(dev_buf)
return -4
desc: usb_dev_desc* = dev_buf
max_pkt: uint8 = desc.bMaxPacketSize0
if max_pkt < 8: max_pkt = 8
new_addr: uint8 = uint8(_device_count + 1)
result = set_address(0, ls, max_pkt, new_addr)
for retry in range(3):
if result == 0: break
timer.timer_msleep(20)
result = set_address(0, ls, max_pkt, new_addr)
if result != 0:
mm.free(dev_buf)
return -5
timer.timer_msleep(10)
dev: usb_device* = &_devices[_device_count]
dev.addr = new_addr
dev.ls = ls
dev.max_pkt0 = max_pkt
dev.configured = 0
dev.iface_class = 0
dev.iface_subclass = 0
dev.iface_protocol = 0
dev.ep_in = 0
dev.ep_in_max = 0
dev.ep_in_interval = 0
dev.ep_in_toggle = 0
config_buf: rawptr = mm.malloc(256)
if config_buf is None:
mm.free(dev_buf)
return -6
string.memset(config_buf, 0, 256)
result = get_descriptor(new_addr, ls, max_pkt, USB_DESC_CONFIG, 0, config_buf, 9)
for retry in range(3):
if result == 0: break
timer.timer_msleep(50)
result = get_descriptor(new_addr, ls, max_pkt, USB_DESC_CONFIG, 0, config_buf, 9)
if result != 0:
mm.free(config_buf)
mm.free(dev_buf)
return -7
cfg: usb_config_desc* = config_buf
total_len: uint16 = cfg.wTotalLength
if total_len > 256: total_len = 256
result = get_descriptor(new_addr, ls, max_pkt, USB_DESC_CONFIG, 0, config_buf, total_len)
for retry in range(3):
if result == 0: break
timer.timer_msleep(50)
result = get_descriptor(new_addr, ls, max_pkt, USB_DESC_CONFIG, 0, config_buf, total_len)
if result != 0:
mm.free(config_buf)
mm.free(dev_buf)
return -8
_parse_config(dev, config_buf, total_len)
result = set_configuration(new_addr, ls, max_pkt, cfg.bConfigurationValue)
if result != 0:
mm.free(config_buf)
mm.free(dev_buf)
return -9
dev.configured = 1
if dev.iface_class == HID_CLASS:
hid_set_protocol(new_addr, ls, max_pkt, dev.iface_num, 0)
hid_set_idle(new_addr, ls, max_pkt, dev.iface_num, 0)
_device_count = _device_count + 1
mm.free(config_buf)
mm.free(dev_buf)
return int(new_addr)
def init() -> int:
global _device_count
_device_count = 0
io_base: uint16 = pci.find_uhci()
if io_base == 0:
serial.puts("[usb] UHCI controller not found\n")
return -1
buf: [64]char
viperlib.snprintf(&buf, 64, "[usb] UHCI at I/O 0x%04X\n", uint32(io_base))
serial.puts(buf)
if uhci.init(io_base) != 0:
serial.puts("[usb] UHCI init failed\n")
return -2
serial.puts("[usb] UHCI initialized\n")
timer.timer_msleep(50)
for port in range(2):
if uhci.port_is_connected(port):
viperlib.snprintf(&buf, 64, "[usb] port %d connected\n", uint32(port))
serial.puts(buf)
dev_id: int = enumerate_port(port)
if dev_id > 0:
dev: usb_device* = &_devices[dev_id - 1]
viperlib.snprintf(&buf, 64, "[usb] device addr=%d class=%02X proto=%02X ep=%d\n",
uint32(dev.addr), uint32(dev.iface_class),
uint32(dev.iface_protocol), uint32(dev.ep_in))
serial.puts(buf)
else:
viperlib.snprintf(&buf, 64, "[usb] enumerate port %d failed: %d\n", uint32(port), int32(dev_id))
serial.puts(buf)
return _device_count
def find_hid_device(protocol: uint8) -> usb_device*:
i: int
for i in range(_device_count):
dev: usb_device* = &_devices[i]
if dev.iface_class == HID_CLASS:
if dev.iface_protocol == protocol:
if dev.configured != 0:
return dev
return None
def read_interrupt(dev: usb_device*, buf: rawptr) -> int:
return 0