VHCI 虚拟主机控制器与导入路径
1. HCD注册
vhci_hcd.c为每个配置的controller创建一个vhci_hcd.N平台设备。Probe依次:
usb_create_hcd()创建primary USB2 HCD;usb_add_hcd()注册USB2 Root Hub;usb_create_shared_hcd()创建USB3 shared HCD;usb_add_hcd()注册USB3 Root Hub;- 第一个primary HCD创建sysfs控制属性。
它没有MMIO、IRQ和DMA硬件,所有端口状态及传输完成由软件维护。
2. HCD接口
vhci_hc_driver实现:
start/stop;urb_enqueue/urb_dequeue;hub_status_data/hub_control;bus_suspend/bus_resume;alloc_streams/free_streams;get_frame_number。
get_frame_number()仍报告未实现;PM代码也有明确FIXME。依赖精确frame或真实Host调度的驱动需谨慎。
3. 虚拟Root Hub
每个USB2和USB3 Root Hub分别有VHCI_HC_PORTS个端口。port_status[]模拟:
- connection/change;
- enable/suspend/reset;
- power;
- low/full/high/super speed。
Attach成功调用rh_port_connect()设置连接与变化位,再调用usb_hcd_poll_rh_status()。USB Core的Hub线程随后走标准枚举,读取远端设备descriptor并创建本地usb_device。
4. Attach sysfs
用户态向attach写四个整数:
1 | port sockfd devid speed |
内核:
- 将全局port映射到controller、USB2/USB3 HCD和rhport;
- 验证speed与Hub类型匹配;
sockfd_lookup()取得stream socket;- 创建
vhci_rx与vhci_tx线程; - 设置远端devid和连接状态;
- 模拟Root Hub connect。
status/status.N输出hub类型、port、状态、speed、devid、sockfd和本地busid。源码特意不输出socket内核指针,避免地址泄漏。
5. URB enqueue
本地class driver提交URB后:
1 | vhci_urb_enqueue |
TX线程从priv_tx取请求,组装CMD_SUBMIT并发送;成功后转入priv_rx等待完成。OUT数据随请求发送,IN只发送期望长度。
枚举阶段对地址0设备的SET_ADDRESS由VHCI本地完成,并将状态从VDEV_ST_NOTASSIGNED转为VDEV_ST_USED,该请求不上网;其它descriptor/control URB仍通过远端取得。
6. Completion
vhci_rx_loop()收到RET_SUBMIT后:
- 按seqnum从
priv_rx找到vhci_priv; - 解包status、actual length和ISO结果;
- 接收IN payload;
- 清除
urb->hcpriv并从endpoint unlink; usb_hcd_giveback_urb()。
从class driver角度,这与真实HCD异步完成没有API区别,但完成时延由网络和服务端HCD共同决定。
7. URB dequeue
若请求尚在priv_tx、还未发出,可本地移除并立即giveback。若已在priv_rx,创建vhci_unlink:
1 | new unlink seqnum + target submit seqnum |
必须同时处理“取消回复先到”和“原URB已完成”两种顺序,确保每个URB只giveback一次。
8. Detach和网络错误
detach写port号,触发VDEV_EVENT_DOWN。EH关闭socket、停止线程、将所有未完成URB以-ENODEV完成,清空unlink链表并模拟Root Hub disconnect。
网络错误不会透明重连。重新attach会产生一次新的USB枚举,原class device实例已经销毁。
9. 容量
默认1个controller、USB2和USB3 Root Hub各8口,nports共16个全局端口位置;设备按speed分配到对应Hub。Kconfig可扩大controller和每类Hub的端口数量,但会增加静态对象、sysfs输出和并发连接资源。
正在加载留言…