RK3588 kernel-6.1 drivers/usb/usbip 代码功能与实现原理

RK3588 kernel-6.1 drivers/usb/usbip 代码功能与实现原理

1. USB/IP 是什么

USB/IPUSB 传输语义封装成 网络报文,使:

  • 设备所在机器(Server):真实 USB 设备仍插在本机,由 stub(usbip-host) 绑定并转发 URB;
  • 使用方机器(Client):加载 VHCI(虚拟主机控制器),对 usbcore 与应用而言像本地接了 USB 设备,实际通过 TCP 与对端通信。

用户态工具(如 usbip bind/attach)负责建连与协商;内核模块负责 URB ↔ 网络 PDU 的转换与 虚拟 Root Hub / 端口状态 维护。


2. 内核模块划分(Makefile / Kconfig

配置项 生成模块 作用
CONFIG_USBIP_CORE usbip-core 公共协议头、调试、socket 收发辅助、事件处理(eh)
CONFIG_USBIP_VHCI_HCD vhci-hcd 客户端虚拟 HCD + 虚拟 Root Hub
CONFIG_USBIP_HOST usbip-host 服务端 stub:抢占指定 busid 设备并导出
CONFIG_USBIP_VUDC usbip-vudc 虚拟 UDC:本机作为 USB 设备 通过 USB/IP 对远端暴露(依赖 Gadget

均依赖 NETUSBIP_COREselect USB_COMMONSGL_ALLOC


3. 网络协议与 URB 的对应(usbip_common.h

内核侧 PDU 与 include/uapi/linux/usbip.h 对齐,核心命令四类:

命令 方向 含义
USBIP_CMD_SUBMIT (0x0001) Client → Server 等价 usb_submit_urb():携带 pipe 衍生的 ep/dirtransfer_flags、长度、(控制传输)setup[8]
USBIP_RET_SUBMIT (0x0003) Server → Client SUBMIT 完成:status、actual_length、ISO 相关字段
USBIP_CMD_UNLINK (0x0002) Client → Server 等价 usb_unlink_urb(),按 seqnum 取消
USBIP_RET_UNLINK (0x0004) Server → Client UNLINK 结果

usbip_header_basicseqnum(每连接递增)、devid(stub 侧常为 (busnum<<16)|devnum,用于在多设备导出场景中区分设备)、directionep

实现原理:USB/IP 不改变 USB 逻辑协议,只是把 usbcore 已构造好的 URB 序列化到网络上;远端 stub填充真实 URB 并调用本地 usb_submit_urb


4. 公共层:usbip_common.c + usbip_event.c

4.1 usbip_common.c

  • 调试usbip_debug_flag、按模块细分 usbip_debug_*
  • usbip_pack_pdu / unpack:在 usbip_headerstruct urb 之间拷贝字段(含 ISO 包描述符等)。
  • Socketkernel_sock*kernel_sendmsg/recvmsg 等封装(用于内核线程收发)。
  • PDU dump:开发时打印管道类型、设备等。

4.2 usbip_event.c — Event Handler(EH)

usbip_device 上挂载 eh_opsshutdown / reset / unusable)。
usbip_event_add() 把事件放入全局链表,由 usbip_event 单线程 workqueue 顺序执行:

  • USBIP_EH_SHUTDOWN:连接拆除、清理;
  • USBIP_EH_RESET:复位路径;
  • USBIP_EH_UNUSABLE:标记不可用。

原理:网络断开或异常时 不能与 ISR 杂糅,统一落到 workqueue + mutex,避免与 sysfs 并发冲突(注释强调 shutdown 优先)。


5. 客户端:vhci-hcdvhci_hcd.c + vhci_tx.c + vhci_rx.c + vhci_sysfs.c

5.1 虚拟主机控制器

vhci_hcd.c 注册 hc_driver(名称 vhci_hcd),提供与其它 HCD 相同的:

  • urb_enqueue / urb_dequeue
  • hub_control / hub_status_data软件 Root Hub(端口连接、速度、复位、SuperSpeed 端口状态扩展 bit_desc_ss 等)

rh_port_connect() 等函数模拟 端口 CONNECT:更新 port_status,唤醒 hub 枚举 —— 与真实控制器 PRTSC 中断效果类似,只是状态由 USB/IP 守护者与内核线程 驱动。

5.2 发送路径 vhci_tx.c

setup_cmd_submit_pdu()urb 打成 USBIP_CMD_SUBMIT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static void setup_cmd_submit_pdu(struct usbip_header *pdup,  struct urb *urb)
{
struct vhci_priv *priv = ((struct vhci_priv *)urb->hcpriv);
struct vhci_device *vdev = priv->vdev;
...
pdup->base.command = USBIP_CMD_SUBMIT;
pdup->base.seqnum = priv->seqnum;
pdup->base.devid = vdev->devid;
pdup->base.direction = usb_pipein(urb->pipe) ?
USBIP_DIR_IN : USBIP_DIR_OUT;
pdup->base.ep = usb_pipeendpoint(urb->pipe);

usbip_pack_pdu(pdup, urb, USBIP_CMD_SUBMIT, 1);

if (urb->setup_packet)
memcpy(pdup->u.cmd_submit.setup, urb->setup_packet, 8);
}

随后 kernel_sendmsg 发送 header +(OUT 时)scatter-gather 数据vhci_priv 维护 seqnumpriv_tx/priv_rx 链表,保证 请求与完成 配对。

5.3 接收路径 vhci_rx.c

解析 USBIP_RET_*,根据 seqnum 找到 vhci_priv,回填 urb->statusactual_length,必要时拷贝 IN 数据,调用 usb_hcd_giveback_urb()

5.4 Sysfs vhci_sysfs.c

导出 控制器/端口 属性,与用户态 usbip attach 协作(绑定远端 busid、触发 vdev 创建等)。

KconfigUSBIP_VHCI_HC_PORTSUSBIP_VHCI_NR_HCS 决定 虚拟端口数 / 虚拟 HCD 个数,等价「多块虚拟 USB 主控」。


6. 服务端:usbip-hoststub_main.c + stub_dev.c + stub_rx.c + stub_tx.c

6.1 busid 表 stub_main.c

最多 MAX_BUSID 个条目,记录可被 bind/exportbusid(形如 1-1.2)。match_busid sysfs 与用户态约定格式,动态增删 允许导出的设备

6.2 stub_dev.c

stub 注册为 USB device driver(绑定 整个设备 而非单接口),在 export接管设备,使本地其它接口驱动 detach,转由 stub_rx/stub_tx 线程完成 IO。

6.3 stub_rx.c

内核线程 接收 USBIP_CMD_*

  • SUBMIT:构造 struct urb(必要时 tweak_* 修正 clear_halt、set_interface 等与远程 devnum/pipe 不一致的控制传输),usb_submit_urb真实总线
  • UNLINKusb_unlink_urb
  • reset port 等控制语义做识别(is_reset_device_cmd 等)。

6.4 stub_tx.c

URB 完成回调 中组装 USBIP_RET_SUBMIT/RET_UNLINK,把 状态与数据 发回客户端。

原理小结stub = 真实 HCD 之上的「代理驱动」VHCI = 无线的 fake HCD。二者通过 PDU + seqnum 保持 URB 语义一致


7. usbip-vudc(可选)

vudc_main.c 注册 platform_driver,可实例化多个 虚拟 UDC
vudc_*.c:在 Gadget 框架下模拟设备控制器,RX/TX/transfer 与 USB/IP 对端交互,使 本机可作为 USB 设备 出现在远端 usbip client 上。

适用场景:反向共享、测试、嵌入式扮演复合设备等。


8. 数据流简图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[Client 应用 / usb-storage 等]
│ urb

usbcore ──► vhci_hcd.urb_enqueue
│ │
│ ├─► vhci_tx: USBIP_CMD_SUBMIT ──► TCP socket
│ │
│ └─► vhci_rx: ◄── USBIP_RET_SUBMIT

(虚拟 Root Hub 枚举出的「远程设备」)

═══════ 网络 ═══════

stub_rx: ◄── CMD_SUBMIT


usb_submit_urb(真实控制器)


真实 USB 设备


stub_tx: RET_SUBMIT ──► socket

9. 局限与安全提示(实现层面)

  • 加密与鉴权:传统 USB/IP 多为 明文 TCP,需在部署层用 VPN/SSH 隧道 或替换传输。
  • 延迟与 ISO:同步传输对 时延抖动 敏感,USB/IP 通常不适合 硬实时音频 等场景。
  • 权限:绑定导出设备涉及 物理安全,需配合用户态 特权工具 与策略。

10. 延伸阅读

  • 用户态项目历史主页(Kconfig 引用):http://usbip.sourceforge.net/
  • 本仓库 USB 文档:linuxDoc/usb/core / dwc2 / dwc3 / 枚举 等笔记。

基于 rk3588/kernel-6.1/drivers/usb/usbip 源码归纳。

文章互动

阅读 --

留言

0 条留言

正在加载留言…