首页/目录/全部文章

全部文章

八个专题的源码、算法与协议笔记都在这里。

笔记列表

USBMon、DebugFS、Trace 与故障排查

USBMon、DebugFS、Trace 与故障排查

1. 枚举

1
2
3
4
5
lsusb
lsusb -t
lsusb -v -d VID:PID
usb-devices
dmesg -w

lsusb -t确认速度、拓扑、driver和root hub。

2. Sysfs

1
2
3
readlink -f /sys/bus/usb/devices/1-1/driver
cat /sys/bus/usb/devices/1-1/{speed,version,authorized}
cat /sys/bus/usb/devices/1-1/power/{control,runtime_status,wakeup}

3. usbmon

Defconfig列出USB_MON。挂载debugfs后:

1
2
modprobe usbmon
cat /sys/kernel/debug/usb/usbmon/0u

Wireshark可读usbmon binary接口。抓包含payload和控制请求,需按敏感数据保护。

4. Trace

USB/DWC3/xHCI tracepoints可通过tracefs启用,适合分析URB延迟、role切换、endpoint和controller events。

5. DebugFS

可用节点依配置:

  • DWC3 registers/events/link state;
  • xHCI rings/contexts;
  • usbmon;
  • gadget/UDC;
  • Type-C/TCPM trace。

Gadget debug files已在defconfig列出,但最终 .config仍需核对。

6. 枚举失败阶段

日志/现象 重点
无connect VBUS、D+/D-、PHY、role
device descriptor read error 电源、信号、reset、线材
address失败 controller/Hub/设备firmware
config descriptor错误 设备描述符
driver未绑定 ID/class/Kconfig/module
USB2正常USB3失败 SS lane、orientation、PHY、线材

7. 常见errno

  • -71 EPROTO;
  • -110 timeout;
  • -32 EPIPE/stall;
  • -19 ENODEV;
  • -108 ESHUTDOWN;
  • -75 EOVERFLOW。

同一errno不是唯一根因,需结合发生阶段。

8. RK3588检查

1
2
dmesg | grep -Ei 'dwc3|xhci|ehci|ohci|usb2phy|usbdp|typec|tcpm'
cat /sys/kernel/debug/clk/clk_summary | grep -Ei 'usb|utmi|pipe'

同时确认regulator、GPIO、power domain和PHY状态。

9. 性能

使用fio/iperf/实际UVC workload并记录:

  • negotiated speed;
  • UAS/BOT;
  • xHCI errors;
  • CPU/IRQ affinity;
    -IOMMU/DMA;
    -autosuspend;
    -线材/Hub;
    -thermal throttling。

10. 方法

先固定单端口、短线、无Hub、autosuspend临时关闭,再逐项恢复变量,避免同时修改DTS quirk和driver参数。

USB 安全、授权、USB/IP 与产品加固

USB 安全、授权、USB/IP 与产品加固

1. 威胁

USB设备可提供恶意:

  • descriptors;
  • class protocol;
  • HID输入;
  • network interface;
  • storage内容;
  • firmware updater;
  • composite interfaces;
    -PD/Type-C行为。

物理接入不应等同信任。

2. Authorization

Sysfs:

1
2
/sys/bus/usb/devices/usbN/authorized_default
/sys/bus/usb/devices/X-Y/authorized

可默认不授权新设备,再由策略daemon按port/VID/PID/class批准。VID/PID可伪造,不能作为高安全唯一身份。

3. USBGuard/LSM

用户态USBGuard可建立设备策略;结合lockdown、SELinux/AppArmor和udev权限限制usbfs、serial、storage及HID设备节点。

4. usbfs

/dev/bus/usb/* ioctl允许control/bulk传输、claim interface和reset。权限过宽可绕过高层daemon策略或攻击firmware。

5. Gadget安全

ConfigFS可改变设备身份和functions。限制写权限,量产仅暴露必要ACM/FunctionFS/UVC等。ADB、RNDIS/ECM、可写Mass Storage均扩大攻击面。

6. USB/IP

usbip/

  • stub导出物理USB device;
  • VHCI在客户端导入;
  • VUDC导出gadget controller。

USB/IP把USB信任边界扩展到网络。原生协议不应被视为提供强认证/机密性,应置于受控网络/VPN并限制daemon权限。

7. Type-C/PD

限制source功率、电压和role swap;不可信充电器不应自动获得data role。可采用charge-only策略或数据授权。

8. DMA

USB device一般通过Host controller DMA,外设本身不像PCIe直接DMA主内存,但恶意数据仍可攻击HCD/class parser。IOMMU可限制controller DMA故障影响,但不能替代协议安全。

本树RK3588 USB controller DT节点未声明iommus属性,不能假定xHCI/DWC3 DMA已受IOMMU隔离;应以运行时IOMMU group、boot log和最终DTB核实。

9. 固件

USB设备firmware loader会从 /lib/firmware下载blob。使用只读、签名/校验、版本受控的镜像。

10. 裁剪

产品禁用不需要的:

  • USB/IP;
  • VHCI/VUDC;
  • legacy class;
  • generic USB serial;
  • Gadget functions;
  • usbtest;
  • debugfs/verbose logs;
    -自动授权。

11. Cables与阻断器

Charge-only cable/data blocker只能作为物理策略补充;Type-C PD、Alt Mode和e-marker仍需考虑。

12. 审计

记录最终 .config、DTB、allowed classes、port策略、Gadget配置、PD PDO和firmware hash,并对插拔/畸形descriptor/fuzz进行回归。

RK3588 kernel-6.1:drivers/usb/atm 功能与实现要点

RK3588 kernel-6.1:drivers/usb/atm 功能与实现要点

源码基准:rk3588/kernel-6.1/drivers/usb/atm/

1. 目录定位

该目录实现 通过 USB 连接的 xDSL(ADSL 等)调制解调器 与 Linux ATM 子系统CONFIG_ATM)之间的桥梁:硬件把 ATM 信元流(常以 AAL5 封装)放在 USB bulk(少数 isoc)管道上,内核侧完成 URB 收发、SAR(分段与重组)、atm_dev 注册,供 pppoatm/br2684 等栈拨号或桥接。

典型用户:上世纪末至本世纪初 SpeedTouch / Conexant AccessRunner / ADI EagleUSB“宽带猫”(固件多由用户空间工具解压加载)。

与 RK3588:嵌入式 RK 平台几乎不用此类 USB DSL;目录属于 遗留宽带接入,默认内核常 CONFIG_USB_ATM=n


2. Kconfig / Makefile 结构

选项 对象 说明
USB_ATM usbatm.o 核心框架,依赖 ATMselect CRC32
USB_SPEEDTOUCH speedtch.o Alcatel SpeedTouch(需 FW_LOADER
USB_CXACRU cxacru.o Conexant AccessRunner
USB_UEAGLEATM ueagle-atm.o ADI 930 / Eagle
USB_XUSBATM xusbatm.o 通用占位:模块参数指定 VID/PID/端点

mini-driver 调用 usbatm_usb_probe() / usbatm_usb_disconnect()(导出符号),填入 struct usbatm_driver


3. 核心:usbatm.c / usbatm.h

3.1 struct usbatm_driver(mini-driver 契约)

生命周期(注释约定顺序):bindheavy_initatm_start → … → atm_stopunbind

  • bind:探测阶段初始化(可 sleep),通常 找 bulk IN/OUT(或 isoc)端点、申请资源。
  • heavy_init较慢 的步骤(如等待固件就绪),可在 probe 延后工作队列 里跑。
  • atm_start/atm_stop:对接 struct atm_dev(速率、类型等)。
  • bulk_in/bulk_out/isoc_in:端点地址编号;rx_padding/tx_padding:部分 Modem 在信元外加填充。

标志:UDSL_SKIP_HEAVY_INITUDSL_USE_ISOCUDSL_IGNORE_EILSEQ

3.2 数据通路

  • struct usbatm_channelRX/TXURB(模块参数 num_rcv_urbs/num_snd_urbs、缓冲大小)、tasklet 处理完成队列。
  • 接收:从 USB 缓冲中解析 ATM 信元AAL5 SARatm_skb_data、CRC32、分片重组 usbatm_vcc_data)。
  • 发送:将 atm_vcc 下发的 sk_buff 编码进 bulk 缓冲提交 URB
  • atm_dev_register:注册 atm_dev,与 atm_ioctl/proc 等 ATM 核心交互。

3.3 usbatm_usb_probe

统一 usb_driver 入口:引用计数、heavy_init 工作项、绑定通道、最终 atm_start;断开路径对称释放 URBatm_dev


4. 各 mini-driver 要点

  • speedtch.c厂商控制消息轮询、request_firmware 加载 两段固件(与 linux-usb.org/SpeedTouch 文档一致),再落到标准 usbatm RX/TX。
  • cxacru.c / ueagle-atm.c:类似模式——Vendor 控制传输 + 固件/CMV,细节各异。
  • xusbatm.c:无专用协议;通过 module_param_array 绑定最多 8VID/PID/端点/altsetting,适合 用户态已初始化 的冷门机型。

5. 小结

层次 职责
ATM 核心 atm_devVCCAAL5 统计与 ioctl
usbatm 核心 URB 环信元 SARtasklet/线程协作
mini-driver USB 描述符/固件/控制面

整体上这是 「USB 大块传输 + ATM SAR」 的经典分层;现代宽带多为 以太网 WAN / PCI-E / SoC 内置 PHY,该类驱动维护热度已很低。

RK3588 kernel-6.1:drivers/usb/c67x00 功能与实现要点

RK3588 kernel-6.1:drivers/usb/c67x00 功能与实现要点

源码基准:rk3588/kernel-6.1/drivers/usb/c67x00/。配置入口:CONFIG_USB_C67X00_HCD(定义于 drivers/usb/host/Kconfig),模块名 c67x00

1. 硬件与驱动定位

Cypress C67x00(如 EZ-Host/EZ-OTG 一类芯片族)是带有 两个 SIE(Serial Interface Engine) 的 USB 控制器,每个 SIE 可配置为 主机 / 外设 / 空闲。芯片通过 HPI(主机并行接口) 等与 MPU 相连(寄存器 include/linux/usb/c67x00.h 中的 hpi_regstep)。

本 Linux 驱动仅实现主机模式c67x00_probe_sie 里对 C67X00_SIE_HOST 调用 c67x00_hcd_probeC67X00_SIE_PERIPHERAL_* 会落入 unsupported 分支(设备侧需依赖芯片内部固件/其它栈,不在此目录)。

hc_driver 标志 HCD_USB11 | HCD_MEMORY:面向 USB 1.1 全速 主机场景(调度里以 12000 bit/ms 一类参数描述帧带宽)。

与 RK3588:RK3588 不使用该系列桥片;目录适用于 遗留嵌入式主板外挂 Cypress USB 或学习 非 OHCI/UHCI/EHCI 的专有 TD 主机实现


2. 源码文件分工

文件 职责
c67x00-drv.c platform probe:映射 HPI MMIO、注册 IRQ;struct c67x00_device 内含 sie[2]c67x00_irqc67x00_ll_irq → 按 SIEMSGFlgSIE message,分发 sie->irq
c67x00-ll-hpi.c 底层寄存器/HPI 读写**COMM_*** 信箱协议、执行芯片 BIOS 软件中断(如 HUSB_SIE_INIT_INT)、读写 TD 列表指针/EOT、清除状态位
c67x00-hcd.c hc_driverroot hub 描述符与 hub_control双端口 C67X00_PORTS=2)、urb_enqueue/dequeuec67x00_hcd_irqTDListDone / SOF-EOPc67x00_sched_kick
c67x00-sched.c TD 调度struct c67x00_td(12 字节硬件格式 + 软件链表)、四类 URB 队列(iso/int/ctrl/bulk)、片内 TD/BUFFER 基址分配、带宽MAX_FRAME_BW_STD vs ISO**)、**work** 推进 **giveback`
c67x00.h 寄存器位域、CY_HCD_BUF_ADDR/SIE_TD_* 偏移、struct c67x00_sie

3. 实现原理概要

3.1 分层模型

  1. USB core 只看到 usb_hcd + c67x00_hc_driver
  2. struct c67x00_hcd(置于 hcd->hcd_priv)绑定单个 c67x00_sie(主机实例),维护 urb 列表与 片内 TD/缓冲区游标td_base_addrnext_buf_addr)。
  3. c67x00_ll_* 通过 HPITD 链表 写入芯片 RAM(基址 CY_HCD_BUF_ADDR 起),并 ARM 主机传输(HOST_CTL_REGARM_EN 等)。

3.2 中断与调度

  • HPI 状态 中出现 DONE_FLG/SIEMSG_FLG/SOFEOP_FLG 等 → c67x00_hcd_irq
  • HUSB_TDListDone一轮 TD 处理完毕,唤醒 c67x00_sched_kick,在 workqueue 路径解析 c67x00_td 状态位(ACK/NAK/STALL/SEQ…),完成 urb 或重试。
  • SOF:用于 周期性调度 与帧对齐。

3.3 Root Hub

软件实现 2 端口 hub(无外部 hub IC):GetPortStatus 组合 USB_STAT_REG/USB_CTL_REG连接/低速/使能 位;USB_PORT_FEAT_RESET 调用 c67x00_ll_husb_reset + husb_reset_port

3.4 平台数据

struct c67x00_platform_data

  • sie_config:4 bit × 2,指定每个 SIE HOST / UNUSED / PERIPHERAL(仅 HOST 路径可用)。
  • hpi_regstep:HPI 寄存器间距。

4. 限制与设计备注

  • 仅 HPI:注释写明 SPI/HSS不能在 IRQ 上下文安全访问 而未支持。
  • Gadget/OTG 主机协商:芯片虽标 OTG,Linux 侧未实现 peripheral SIE 驱动
  • 调度ISO 与 BULK 帧带宽 通过 max_frame_bw 等切换策略折中(见 c67x00-hcd.h 头部注释)。

5. 小结

c67x00 是一套 专有序列引擎 + 片内 TD RAM + HPI 信箱USB1.1 主机 HCDsched 负责把 urb 切成 c67x00_td 并填入芯片存储器,ll-hpi 负责与固件协助的 低速总线协议hcd 对接 usbcore双端口 root hub

RK3588 kernel-6.1:drivers/usb/cdns3 功能与实现要点

RK3588 kernel-6.1:drivers/usb/cdns3 功能与实现要点

源码基准:rk3588/kernel-6.1/drivers/usb/cdns3/。涵盖 Cadence USBSS(USB3 DRD)USBSSP / CDNSP(第二代,PCI 多见) 两条产品线,由 CONFIG_USB_CDNS_SUPPORT 总控。

1. 构建产物与选项

配置 产物 / 说明
USB_CDNS_SUPPORT 共同点:select USB_XHCI_PLATFORM(主机)、USB_ROLE_SWITCH;公共代码 cdns-usb-commoncore.odrd.o,可选 host.o
USB_CDNS3 cdns3.kocdns3-plat.o +(可选)cdns3-gadget.ocdns3-ep0.ocdns3-trace.o
USB_CDNS3_PCI_WRAP cdns3-pci-wrap.o(ACPI PCIe)
USB_CDNS3_TI / USB_CDNS3_IMX SoC glue:cdns3-ti.ccdns3-imx.c
USB_CDNSP_PCI cdnsp-udc-pci.koPCI 双功能(HOST/DEV + OTG);_gadget 侧 cdnsp-ring/gadget/mem/ep0(与 xHCI 环/TRB 思路相近

主机符合 xHCI,由 host.c 动态 platform_device_alloc("xhci-hcd") 挂载 drivers/usb/host/xhci-plat,不再重复实现调度器。
设备USB3cdns3-gadget.c(寄存器窗 dev);CDNSPcdnsp-*.c(支持 SSP,注释说明算法借鉴主机)。


2. 核心抽象:struct cdnscore.h

  • 资源分区xHCI MMIO + IRQxhci_res[])、Device 控制器 MMIOdev_regs)、OTG 控制 MMIOotg_v0 / otg_v1 / otg_cdnsp 之一)、可选 wakeup IRQ
  • 版本CDNS3_CONTROLLER_V{0,1}CDNSP_CONTROLLER_V2,决定 OTG 寄存器布局与 workaround(见 drd.c)。
  • 角色roles[USB_ROLE_HOST]roles[USB_ROLE_DEVICE]roles[USB_ROLE_NONE](idle),每角色 cdns_role_driverstart/stop/suspend/resume
  • PHYusb2_phy/usb3_phygeneric_phy)。
  • gadget_init:USB3 平台为 cdns3_gadget_init;CDNSP PCI 为 cdnsp_gadget_init(在 glue 中赋值)。

core.ccdns_initcdns_core_init_role:综合 usb_get_dr_mode、硬件 strap(cdns->dr_mode)、Kconfig,调用 cdns_host_init(注册 host role,真正 start 时再 platform_device_add(xhci))、gadget_init,最后 cdns_drd_update_modecdns_role_start(idle → 按 OTG/host/peripheral 启动)。


3. 主机侧(host.c

  1. cdns_drd_host_on:DRD 逻辑切到 主机可用(电源/时钟由 drd.c 协调)。
  2. 分配 xhci-hcd 子设备:资源为 IRQ + xhci MEM
  3. xhci_plat_priv
    • USBSS(CDNS3)XHCI_SKIP_PHY_INIT | XHCI_AVOID_BEIplat_startCMD_PM_INDEX扩展寄存器 XECP_AUX_CTRL_REG1/XECP_PORT_CAP_REG(LPM/RxDet 等 Cadence 专有项)。
    • USBSSP(CDNSP)XHCI_CDNS_SCTX_QUIRK
  4. resume_quirk:恢复后重做 plat_start

即:Cadence 只做 glue + quirk,协议与调度全在 内核 xhci 栈


4. DRD / OTG(drd.c

  • cdns_set_modeOTG 时配置 ID pull-up、部分版本的 PHYRST workaround;满足手册 ID 采样延时
  • cdns_get_id/cdns_get_vbus:读 OTGSTS
  • cdns_hw_role_switchusb_role_switch_register,与 Type‑C 或其它策略模块联动。
  • 中断/workqueue:根据 ID/VBUS 切换 cdns_role_start/stop(停 xHCIgadget,避免双角色同时抢占)。

5. Gadget 侧(USB3:cdns3-gadget.c + cdns3-ep0.c

  • 操作 cdns3_usb_regs(与 xHCI 窗口分离)。
  • TRB 环、doorbell、link TRB 等与 USB3 SuperSpeed 设备协议一致;源码注释详细记录 控制器版本相关的 DMA/TRB 竞争 workaround(共享片内 OUT buffer 等)。
  • Kconfig:支持 FS/HS/SS不支持 LS(与芯片一致)。

6. 平台示例(cdns3-plat.c

  • 解析 host/peripheral/otg/wakeup 命名 IRQ;xhci/dev/otg 命名 MEM
  • cdns3,usb2-phy / cdns3,usb3-phyphy_init + phy_power_on
  • gadget_init = cdns3_gadget_initcdns_init

i.MX / TI glue 在对应文件中补充 时钟、复位、pdata quirks


7. CDNSP PCI(cdnsp-pci.c

  • 双 PCI function:function0 HOST+DEV BAR,function1 OTG;probe 时配对另一 function
  • BAR 映射:主机侧与设备侧寄存器分离(宏 PCI_BAR_*)。
  • 适用于 Cadence 评估 FPGA / USBSSP IP 等。

8. 与 RK3588 的关系

RK3588(Rockchip)片上 USB 通常为 Synopsys DWC3不是 Cadence CDNS3。本目录对 RK3588 树的意义主要是:对照「xHCI 主机 + 独立 DEV 寄存器 + DRD」 的软件拆分方式。


9. 小结

维度 说明
主机 标准 xHCI + xhci_plat_priv quirks
设备 专用 gadget 驱动(USB3 cdns3;USBSSP cdnsp 更接近 xhci ring 模型)
切换 USB_ROLE_SWITCH + drd.c OTG 寄存器 + PHY
依赖 USB_CDNS_SUPPORT、DMA、(主机)USB_XHCI_PLATFORM

调试主机问题时优先看 host.c 的 XECP 寄存器xHCI dmesg;调试 device 时看 cdns3-gadget/cdnsp 的 TRB 与中断路径

RK3588 kernel-6.1:drivers/usb/chipidea 功能与实现要点

RK3588 kernel-6.1:drivers/usb/chipidea 功能与实现要点

源码基准:rk3588/kernel-6.1/drivers/usb/chipidea/。目标模块 ci_hdrcCONFIG_USB_CHIPIDEA)。

1. 驱动定位

ChipIdea USB HS OTG / Dual-Role Controller(也常写作 Chipidea CI HDRC)是 MIPS/NXP 系商用 USB2 主机 + 设备双角色 IP。Linux drivers/usb/chipidea 在同一寄存器窗口上实现:

  • 主机:作为 EHCI 变种 挂接到 usbcore(共享 drivers/usb/host/ehci*.h 基础设施)。
  • 设备usb_gadget(UDC),基于硬件 Queue Head / Transfer Descriptor(DTD) 环形结构与 dma_pool
  • 角色切换USB_ROLE_SWITCHextcon、可选 USB_OTG_FSMotg_fsm.c)。

与 RK3588:Rockchip 片上 USB 以 DWC3 等为主,一般不启用 Chipidea。本分析面向 i.MX / MSM / Tegra / PCI evaluation 等使用该 IP 的平台。


2. 构建分层(Makefile

组件 文件 作用
核心 core.c 寄存器 hw_bank/regmap(Cap + Op)、复位、时钟/phyUSBMODE、中断分发、probe/移除、usb_role_switchpm_runtime/LPM
OTG otg.c ID/VBUS、OTGSC 协作
OTG FSM otg_fsm.cCONFIG_USB_OTG_FSM 协议状态机定时器
ULPI ulpi.c OP_ULPI_VIEWPORT 访问外部 PHY
Debug debug.c debugfs
Host host.c ehci_hcd + ehci_driver_overrides(端口供电、reset 回调 ci_platform_configure
Gadget udc.ctrace.c usb_gadget/usb_epci_hw_ephw_ep_prime/DTD
Glue ci_hdrc_imx.cusbmisc_imx.cci_hdrc_usb2.cci_hdrc_pci.cci_hdrc_msm.cci_hdrc_tegra.c SoC 时钟、USB_MISC、复位、pdata/DT

Kconfig 依赖:USB_EHCI_HCD(主机)USB_GADGET(设备) 按裁剪组合;整包 select EXTCONRESET_CONTROLLERUSB_ULPI_BUSUSB_ROLE_SWITCH


3. 寄存器与硬件抽象(ci.h / core.c

  • struct hw_bankcap / op 两套指针 + regmap[],按 是否 LPM 选用 ci_regs_nolpm[]ci_regs_lpm[]OTGSC/USBMODE/EP 寄存器偏移 在 LPM 版上移址)。
  • CAP_DCCPARAMS:区分是否同时具备 HC/DC
  • OP_USBMODE:主机 / 设备 / 静止模式切换的核心之一。
  • OP_PORTSC:主机端口状态、测试模式(hw_port_test_set)等。
  • struct ci_hdrc:当前 enum ci_roleroles[] 指向 ci_role_driverstart/stop/irq)、gadgethcdqh_pool/td_poolplatdatalinux/usb/chipidea.hphyusb_phyflagsdr_modenotify_event**)。

4. 主机侧原理(host.c

  • 静态 ci_ehci_hc_driverehci_init_driver + ehci_ci_overrides 生成:
    • port_powerregulator 与可选 usb_phy_vbus_on/offCI_HDRC_PHY_VBUS_CONTROL);HSIC 时用 port test 强拉高速。
    • resetehci_setupci_platform_configure 及 SoC notify_event(CONTROLLER_RESET)
  • IRQhost_irqusb_hcd_irq(与 gadget 共享中断时在 core 里仲裁)。

本质:利用内核已有 EHCI 调度(QH/qTD),只补上 Chipidea 特有的 PHY/VBUS/复位钩子


5. 设备侧原理(udc.c

  • EP0 + EPnci_hw_ep 内含 usb_epqh(队列与 DMA 地址)、td_pool 分配的 DTD 节点
  • hw_device_state:配置 ENDPTLISTADDR、开门禁中断(UI/UEI/PCI/URI)。
  • hw_ep_prime/flush/complete:对齐芯片手册 Prime / Complete / Flush 模型推进传输。
  • drivers/usb/gadget composite 驱动对接标准 usb_endpoint_descriptor

6. 角色与电源(core.cotg*.c

  • usb_role_switch_registerset/get 映射 enum usb_roleenum ci_role,便于 Type‑C 控制器或其它策略模块切换。
  • struct ci_hdrc_cableextcon 监听 VBUS/ID,驱动 workci_hdrc_role_change 一类路径。
  • CONFIG_USB_OTG_FSMotg_fsm.c 维护 struct otg_fsm,与 OTGSC、定时器协作。

7. 平台数据(include/linux/usb/chipidea.h

ci_hdrc_platform_data 汇集 glue 差异:共享寄存器CI_HDRC_REGS_SHARED)、流模式关闭IMX28 写 workaroundHSICDMA 对齐要求dr_modeVBUS regulatornotify_event 回调等。DT platform_device 常与 ci_hdrc_imx 等绑定生成该结构。


8. 小结

维度 说明
对上接口 Host:usb_hcd(EHCI);Device:usb_gadget
数据通路 Host:EHCI QH/qTD;Device:硬件 QH + DTD(dma_pool)
PHY 内置寄存器 + ulpi.cplatdata->phy/usb_phy
DRD USBMODE + role drivers + role_switch/extcon (+ OTG FSM)

深入调试建议:对照芯片手册 USBCMD/USBSTS/PORTSC/USBMODE/ENDPTCTRL;主机栈抓 usbmon;设备栈开 drivers/usb/chipidea/trace.c(若 CONFIG_TRACING)。

RK3588 kernel-6.1 drivers/usb/core 详细分析

RK3588 kernel-6.1 drivers/usb/core 详细分析

1. 范围与源码基准

  • 目录rk3588/kernel-6.1/drivers/usb/core/
  • 产物:与 CONFIG_USB 对应的核心模块 usbcore(通常模块名为 usbcore)。
  • Makefile 编译列表(节选):
1
2
3
4
5
6
7
8
usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o
usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
usbcore-y += devio.o notify.o generic.o quirks.o devices.o
usbcore-y += phy.o port.o

usbcore-$(CONFIG_OF) += of.o
usbcore-$(CONFIG_USB_PCI) += hcd-pci.o
usbcore-$(CONFIG_ACPI) += usb-acpi.o

本文按 文件职责相互关系典型调用链 说明;更完整的 枚举步骤与 Hub 函数级追踪 可与同目录 rk3588-kernel-6.1-USB总线枚举匹配与数据传输分析.md 对照阅读。


2. 设计目标:usbcore 在内核 USB 主机栈中的位置

usbcore 不是某一种 USB 设备的「功能驱动」,而是 主机侧通用层

层次 主要职责
接口级驱动(如 usb-storage 绑定 usb_interface,完成类协议与上层子系统对接
usbcore(本目录) 设备模型、URB、同步消息封装、Hub 逻辑、HCD 框架、描述符解析、sysfs/usbfs、电源与异常策略
具体 HCDdrivers/usb/host/dwc3 等) 寄存器、调度环、DMA、硬件中断

分层原则hcd.c 头部注释概括):错误检查、URB 与设备跟踪、虚拟 Root Hub 的共性逻辑尽量留在 usbcore;只有必须区分硬件的部分才下沉到各 hc_driver


3. 模块依赖关系(逻辑)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
             usb_register() / 设备枚举

┌──────────────┼──────────────┐
▼ ▼ ▼
driver.c hub.c generic.c
(匹配/probe) (拓扑/枚举) (选配置/通用设备侧)
│ │ │
└──────────────┼──────────────┘

urb.c ◄──► message.c(同步封装)


hcd.c ◄──► buffer.c(DMA 缓冲)


各 HCD(ehci/xhci/dwc3-host…)

用户态旁路devio.c 实现 usbfs(历史上 /proc/bus/usb,现为 /dev/bus/usb/BBB/DDD),可在无内核类驱动时直接提交 URB(需权限)。


4. 逐文件说明

4.1 usb.c — 「USB 库」与杂项辅助

文件头明确:不是带回调的驱动,而是一组通用辅助例程

典型内容包括:

  • usb_disabled() / nousb:内核命令行或模块参数层面关闭 USB。
  • 自动挂起默认延时CONFIG_PMusb_autosuspend_delay)。
  • usb_find_common_endpoints() / _reverse:在给定 altsetting 中查找首个或末个 bulk-in/out、interrupt-in/out,供驱动简化端点发现。
  • 其它散布的字符串、描述符、电源相关辅助(与 config.cgeneric.c 协同)。

定位:上层驱动常用的 工具函数集合,减轻重复解析描述符的代码。


4.2 hcd.c — Host Controller Driver 框架与 Root Hub

核心职责:

  1. struct usb_hcd / struct hc_driver 生命周期
    • 典型入口:usb_add_hcd() / usb_remove_hcd()(HCD 驱动在 probe 中调用)。
  2. 虚拟 Root Hub
    • USB2/3/3.1 等 Root Hub 设备描述符静态表;软件模拟 Hub 行为,使上层 hub 驱动 能以统一方式处理根端口与外置 Hub。
  3. URB 与总线的桥接
    • usb_hcd_giveback_urb():HCD 完成传输后将 URB 交回 usbcore(触发完成回调)。
    • usb_hcd_unmap_urb_for_dma() 等与 DMA 映射协作。
  4. 端口 resume、RH 状态轮询
    • 例如 usb_hcd_poll_rh_status()usb_hcd_{start,end}_port_resume()
  5. 总线号管理
    • usb_bus_idr、全局 usb_hcds_loaded 位图等。

设计要点:把「所有主机控制器都要做的事」收拢到此文件,减少各 HCD 复制粘贴;硬实时寄存器操作仍在具体 HCD。


4.3 hub.c — Hub 驱动与设备枚举主干

体积最大,承担 USB 即插即用 的核心:

  • Hub 作为内核里的 usb_driver:匹配 Hub 接口,管理 struct usb_hub
  • hub_wq 工作队列hub_event() 路径处理端口状态变化、供电、速度协商、TT 等,避免在硬中断里做重逻辑。
  • 枚举关键步骤(与 usb_device 生命周期紧密耦合):端口连接/断开、debounce、分配设备号、复位、读描述符、usb_new_device() 一带的设备注册等。
  • Hub 特性:MTT、TT buffer、电源管理、大量 quirks(特定厂商 Hub 行为)。
  • 导出符号:如 usb_hub_claim_port / usb_hub_release_portusb_root_hub_lost_power 等供电源或其它子系统使用。

原理:无论 Root Hub 还是外置 Hub,端口上的设备发现与状态机都收敛到 Hub 子系统,从而 接口驱动不必关心「设备怎样被挂上总线」


4.4 urb.c — URB 生命周期与提交入口

  • 分配/释放usb_alloc_urb() / usb_free_urb(),引用计数 kref,可选 URB_FREE_BUFFER 连带释放传输缓冲。
  • 初始化usb_init_urb()、各类 usb_fill_*_urb()(control/bulk/int/isoc)。
  • 锚点usb_anchor_*,便于驱动批量跟踪或取消一组 URB。
  • 核心入口usb_submit_urb() —— 校验设备状态、端点类型、wMaxPacketSize、SuperSpeed isoc 突发等,然后转入 HCD 队列;usb_kill_urb() / usb_unlink_urb() 用于同步取消或异步unlink。

原理URB 是主机侧异步 I/O 原语;usbcore 在此集中做 一致性校验,减轻各 HCD 重复判断。


4.5 message.c — 同步传输与控制路径

  • usb_start_wait_urb():提交 URB 后用 completion 阻塞等待(带超时则 usb_kill_urb())。
  • usb_control_msg() 及一组 usb_control_msg_*:封装 SETUP + DATA + STATUS 流程。
  • 批量/中断等同步读写:基于上述等待模型封装。
  • 配置相关:内部 cancel_async_set_config 等与 usb_set_configuration 异步路径协作。
  • 字符串描述符usb_string() 等(依赖 NLS)。

注意:注释强调 usb_control_msg() 不可中断、不适合中断上下文;中断上下文应 usb_submit_urb()


4.6 driver.c — USB 设备模型与驱动绑定

  • usb_register() / usb_deregister()(接口驱动)、usb_register_device_driver() 等。
  • usb_device_id 匹配:静态表 + 动态 new_id sysfs(usb_store_new_id())。
  • probe / disconnect / suspend / resume 与内核 device_driver 绑定的封装。
  • USB device driver(针对 whole device)interface driver 的分支逻辑。
  • generic.c、授权(authorize)、forced unbind 等协作(部分符号在 usb.h 声明)。

原理:USB 设备常含 多接口,默认绝大多数驱动绑定 interface;少数场景使用 device driver


4.7 config.c — 配置/接口/端点描述符解析

  • GET_DESCRIPTOR 得到的原始缓冲区walk:解析 configuration → interface → endpoint,处理 IADSuperSpeed Endpoint CompanionSSP isoc companion 等扩展描述符。
  • find_next_descriptor() 等跳过未知描述符,保证前向兼容。
  • usb_parse_configuration()usb_get_configuration()(与 message.c 协作获取完整描述符树)。
  • 限制:USB_MAXALTSETTINGUSB_MAXCONFIG 等硬上限,防止畸形描述符耗尽内核内存。

定位:把 Chapter 9 二进制描述符变成 usb_host_config / usb_host_interface / usb_host_endpoint 等内核结构。


4.8 buffer.c — HCD 级 DMA 一致缓冲

  • hcd_buffer_create() / destroy():按档位创建 dma_pool(默认最大长度档位见 pool_max[]),供该总线上驱动共享;初始化阶段 usb_init_pool_max() 对照 ARCH_KMALLOC_MINALIGN
  • hcd_buffer_alloc() / free()
    • 若有 localmem_pool(局部内存池),走 gen_pool_dma_*
    • 若控制器 !hcd_uses_dma,退化为 kmalloc / kfreedma 填哨兵值;
    • 否则优先命中 pool,否则 dma_alloc_coherent
  • hcd_buffer_alloc_pages() / free_pages():页级大块路径。

原理:小额 DMA 分配高频,用 per-HCD pool 降低 dma_alloc_coherent 碎片与开销;PIO 主机不走 DMA。


4.9 endpoint.c — 端点 sysfs

  • 为每个 usb_host_endpoint 创建 ep_device 子设备,导出 地址、类型、方向、wMaxPacketSize、解码后的 interval只读属性

便于调试与调试策略脚本,不参与传输调度。


4.10 sysfs.c — 设备与接口 sysfs

  • usb 设备节点:厂商、产品、序列号、bConfigurationValue 读写(切换配置)、authorized、速度、quirks、OTG 相关等。
  • 接口节点modaliasdriver 绑定链接等。

driver.c 的配置切换、quirks.c 标志联动密切。


4.11 devices.c — debugfs /sys/kernel/debug/usb/devices 拓扑文本

  • 总线—拓扑—带宽—描述符—接口—端点—驱动名 格式化为 人类可读文本(类 UNIX usbfs devices 的现代等价物)。
  • poll 支持唤醒监听进程。

适用于 lsusb -v 之外的内核视角快照


4.12 devio.c — usbfs(/dev/bus/usb/*/*

  • struct usb_dev_state:每个打开的文件描述符对应的状态;维护异步 URB 链表、内存映射列表、mmap DMA 等。
  • ioctl:提交 URB、** reap **、批量释放、disconnect notify 信号、CAPTURE 权限退化等。
  • USB_SG_SIZE 等对大包拆分逻辑。

安全模型:直接对外开放 USB 需要 capability;历史上多起 CVE 与此路径有关,内核在此有大量锁与校验。


4.13 file.c — USB 主设备号与 USB minor 转发

  • 注册 USB 主字符设备:open 时根据 minor 查找 usb_minors[] 中注册的 file_operations(通常由 usb-serial、audiousb_class_driver 注册)。
  • usb_register_dev() / usb_deregister_dev() 的配合实现。

定位USB 字符设备类驱动 共用的 动态 minor 调度,不是 usbfs。


4.14 generic.c — USB 设备级通用驱动

  • usb_choose_configuration():无专用 whole-device 驱动时,按供电、接口类(RNDIS、ActiveSync、音频 UAC3 等)启发式挑选配置。
  • usb_generic_driver_*probe/disconnect/suspend/resume 钩子,让 未绑定专用 device driver 的设备仍能 选配置、绑定接口驱动

这是 「先看接口驱动,设备侧兜底」 的关键。


4.15 quirks.c — VID/PID 与工作区标志

  • 静态表 + 模块参数 quirks 动态追加 USB_QUIRK_*
  • usb_detect_quirks() / usb_detect_interface_quirks():枚举后打上 udev->quirks,影响 message.c(如延迟控制传输)、hubHCD 路径。
  • usb_endpoint_is_ignored():极端畸形设备上忽略某端点。

原理:USB 生态有大量固件瑕疵,quirks 是在标准之上的必要补丁层


4.16 notify.c — USB 通知链

  • usb_register_notify() / unregisterblocking notifier,事件如 USB_DEVICE_ADD / USB_DEVICE_REMOVE / USB_BUS_ADD / USB_BUS_REMOVE
  • 典型订阅者:电源管理、桌面会话、调试工具。

4.17 phy.c / phy.h — Root Hub 多 PHY 封装

  • usb_phy_roothub_alloc():从 DT phys 列表 devm_of_phy_get_by_index,聚合多条 PHY。
  • usb_phy_roothub_{init,exit,pwr_on,pwr_off,set_mode}:统一遍历调用 phy_*,保证 USB2 + USB3 PHY 等同生命周期。

HCD/platform 驱动在 probe 时按需取用,避免散落重复代码。


4.18 port.cusb_port 设备与端口 sysfs

  • Hub 下每个 物理端口 对应 struct usb_port 设备(可与 peerUSB4 等概念交互)。
  • disable链路伙伴component master 等与电源、Type‑C 协作的属性(依配置)。

端口级策略hub 内部静态结构 抽到 device model,便于 sysfs/udev。


4.19 of.c — 设备树辅助(CONFIG_OF

  • usb_of_get_device_node():按 hub 子节点 reg == port 查找挂接在该端口上的 device node
  • usb_of_has_combined_node():判断是否 device/interface 共用 DT 节点(单配置单接口等条件)。
  • usb_of_get_interface_node():接口级节点查找。

用于 固件描述固定插入设备(无枚举或枚举后匹配)。


4.20 hcd-pci.c — PCI USB 主机配角协同(CONFIG_USB_PCI

  • Companion controller(同一 PCI slot 上 EHCI + UHCI/OHCI)之间的 handoff:防止 EHCI probe 时抢夺端口导致 companion 状态不一致。
  • pci_get_drvdata 遍历 for_each_companion 等逻辑。

嵌入式 RK3588 若无非 PCIe USB,此文件可能不参与链接,但属于 usbcore 对 PC 架构历史兼容 的重要部分。


4.21 usb-acpi.c — ACPI glue(CONFIG_ACPI

  • usb_acpi_power_manageable():端口是否有 ACPI 电源资源。
  • usb_acpi_port_lpm_incapable():通过 _DSM 判定 USB3 U1/U2 是否应禁用(retimer 等场景)。
  • 其它 Hub 端口 ACPI handle、功耗辅助。

4.22 usb.h — core 内部 API 头

对本目录各 .c 声明

  • sysfs 创建/删除、端点 enable/disable、usb_set_configuration、generic driver、hub_wq kick、PM 路径、usb_device_match_id 等。
  • usb_get_max_power():按速度区分 2mA / 8mA 单位。

不对外导出给用户驱动,仅为 drivers/usb/core 内部解耦编译单元。


4.23 hub.h

Hub 驱动与其它 .c(如 port.c、usb-acpi.c)共享的结构体与内联;外部模块一般不直接 include。


4.24 ledtrig-usbport.cCONFIG_USB_LEDS_TRIGGER_USBPORT

USB 端口活动 映射到 LED trigger,独立目标文件,非 usbcore 本体。


4.25 otg_productlist.h

Hub 等使用的 OTG/HNP 相关产品列表数据(宏展开),供 hub.c include。


5. 关键调用链速查

5.1 异步传输(驱动常见路径)

1
2
3
4
5
6
usb_submit_urb()
-> usb_hcd_submit_urb()(hcd.c)
-> hcd->driver->urb_enqueue()(具体 HCD)
… 硬件完成 …
usb_hcd_giveback_urb()
-> urb->complete()

5.2 枚举(简化)

1
2
3
4
hub_irq → kick hub_wq → hub_event → hub_port_connect_change
→ hub_port_connect → usb_new_device → usb_enumerate_device
→ usb_get_configuration → config.c 解析
→ device_add → driver core → usb_driver.probe

5.3 同步控制传输

1
2
usb_control_msg() → usb_internal_control_msg() → usb_start_wait_urb()
→ usb_submit_urb() → … → completion

6. 阅读源码的建议顺序

  1. hcd.c 头部注释 + usb_add_hcd / giveback_urb
  2. urb.cusb_submit_urb 校验逻辑
  3. driver.c注册与 match
  4. hub.chub_eventhub_port_connect(可配合上文枚举文档)
  5. config.c:描述符解析
  6. message.cbuffer.c:同步 IO 与 DMA 缓冲策略
  7. devio.c(若关心 usbfs 与安全模型)

7. 与仓库内其它文档的关系

文档 侧重点
rk3588-kernel-6.1-drivers-usb目录结构与分层原理.md 整个 drivers/usb 子目录地图
rk3588-kernel-6.1-USB总线枚举匹配与数据传输分析.md 枚举、匹配、URB、RK3588 DWC3/xHCI 衔接
本文 drivers/usb/core 每个编译单元职责与设计取舍

基于 rk3588/kernel-6.1/drivers/usb/core 源码阅读整理;内核版本以树内 Makefile / 符号为准。

RK3588 kernel-6.1 drivers/usb/dwc2 详细分析:与 USB 2.0 协议的关系及实现方式

RK3588 kernel-6.1 drivers/usb/dwc2 详细分析:与 USB 2.0 协议的关系及实现方式

1. 文档范围与重要前提

  • 目录rk3588/kernel-6.1/drivers/usb/dwc2/
  • 硬件 IP:Synopsys DesignWare USB 2.0 HS OTG(DWC_otg),内核配置项 CONFIG_USB_DWC2(模块常为 dwc2.ko,另有 dwc2_platform.ko / dwc2_pci.ko 视平台而定)。

1.1 「如何实现 USB 2.0 协议」应怎样理解

USB 2.0 规范涵盖 物理层、链路层事务(TOKEN/DATA/HANDSHAKE)、设备框架(Chapter 9)、Hub、类协议 等多层。

在内核里 分层如下

层级 主要由谁完成
枚举、Hub 拓扑、URB、驱动绑定 drivers/usb/corehub.chcd.curb.c 等)
Root Hub IOCTL(端口电源、复位、状态) DWC2 HCD 通过 hc_driver->hub_control / hub_status_data 与硬件寄存器交互
将 URB 转为 USB 2.0 事务调度(控制/批量/中断/同步,HS/FS/LS,Split,SOF 对齐) dwc2 主机代码hcd*.chcd_queue.chcd_intr.chcd_ddma.c)+ 片内 DWC_otg 硬件
Gadget:作为设备响应主机 gadget.c + core*.c,对接 usb_gadget

也就是说:DWC2 驱动并不在用户空间「重写一整份 USB 2.0 规范文档」,而是通过 Linux hc_driver APIusbcore 协作,并对 DWC_otg 寄存器/DMA 描述符 编程,使硬件在总线上发出符合 USB 2.0 的 包与事务设备描述符、SET_ADDRESS、SET_CONFIGURATION逻辑流程 仍以 usbcore 为主。


2. 源码文件与编译关系

依据 Makefile

目标 源文件 作用概要
dwc2 core.c Host/Device 共用:全局寄存器、模式、FIFO、挂起恢复备份、电源相关 等。
core_intr.c 共用中断分发:OTG、模式不匹配、端口、再委托 Host/Device。
platform.c platform driver:DT、dr_mode、时钟/复位/PHY、注册 HCD 或 UDC。
params.c 硬件参数 / quirks 解析与默认策略。
drd.c(dual-role) usb_role_switch:Host/Device 角色切换、GOTGCTL 覆盖等。
主机 hcd.c struct hc_driver 实现:urb_enqueue、Root Hub、端口、启动停止、DMA 映射钩子。
hcd_intr.c 主机中断:SOF、通道完成、NAK、Split、TT clear、帧号。
hcd_queue.c QH/QTD周期带宽位图主机通道分配与事务入队。
hcd_ddma.c Descriptor DMA:描述符链、帧列表(与 dma_desc_enable 等参数相关)。
设备 gadget.c USB Gadget UDC:端点、usb_request、EP0 状态机、DMA/PIO。
其它 pci.c PCI 绑定 EHCI companion 协调(若启用 USB_DWC2_PCI)。
debugfs.c 调试接口。
hw.h 寄存器偏移与位域常量(硬件手册级别)。

主机与 Gadget 互斥或共存KconfigUSB_DWC2_HOST / PERIPHERAL / DUAL_ROLE 决定。


3. 主机模式:从 URB 到 USB 2.0 事务

3.1 Linux 侧的入口:hc_driver

hcd.cdwc2_hc_driver 声明了 DWC2 作为 USB 2.0 主机控制器usbcore 的回调(节选语义):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
static struct hc_driver dwc2_hc_driver = {
.description = "dwc2_hsotg",
.product_desc = "DWC OTG Controller",
.hcd_priv_size = sizeof(struct wrapper_priv_data),

.irq = _dwc2_hcd_irq,
.flags = HCD_MEMORY | HCD_USB2 | HCD_BH,

.start = _dwc2_hcd_start,
.stop = _dwc2_hcd_stop,
.urb_enqueue = _dwc2_hcd_urb_enqueue,
.urb_dequeue = _dwc2_hcd_urb_dequeue,
.endpoint_disable = _dwc2_hcd_endpoint_disable,
.endpoint_reset = _dwc2_hcd_endpoint_reset,
.get_frame_number = _dwc2_hcd_get_frame_number,

.hub_status_data = _dwc2_hcd_hub_status_data,
.hub_control = _dwc2_hcd_hub_control,
.clear_tt_buffer_complete = _dwc2_hcd_clear_tt_buffer_complete,
...
.map_urb_for_dma = dwc2_map_urb_for_dma,
.unmap_urb_for_dma = dwc2_unmap_urb_for_dma,
};
  • HCD_USB2:向核心声明这是 USB 2.0 主机控制器。
  • urb_enqueueusb_submit_urb() 最终会把 URB 交给这里。
  • hub_*:软件 Root Hub 行为由 usbcore 的 Hub 逻辑驱动,端口级硬件操作hub_control 里通过 HPRT 等寄存器 完成。

3.2 内部抽象:dwc2_hcd_urb → QH → QTD → Host Channel

hcd.h 中说明:HCD 负责把 USB Driver(此处即 usbcore + 设备驱动) 的请求转换为 DWC_otg 上的动作。

典型链路:

  1. _dwc2_hcd_urb_enqueue()struct urb 包装为 struct dwc2_hcd_urb,并挂到 dwc2_qh(队列头)dwc2_qtd(传输描述)
  2. dwc2_hcd_urb_enqueue() 调用 dwc2_hcd_qtd_init / dwc2_hcd_qtd_add,必要时触发 dwc2_hcd_select_transactionsdwc2_hcd_queue_transactions,把事务发到 主机通道(Host Channel)
  3. struct dwc2_host_chan 承载 USB 2.0 事务参数:设备地址、端点号、方向、速度(LS/FS/HS)传输类型(控制/同步/批量/中断)max_packetDATA0/DATA1/SETUP/PING、以及 Splitdo_splithub_addrhub_portcomplete_splitxact_pos)——对应规范里经 Hub TT 访问 低速/全速 设备的 分割事务

硬件在每个 帧/微帧 内执行通道上的事务;驱动负责 不与周期带宽冲突正确拆分 Split、处理 NAK/PING/STALL 等。

3.3 SOF 与周期调度

hcd_intr.cdwc2_sof_intr()(注释):SOF 中断到来时更新帧号,把满足 next_active_frame 的周期 QHperiodic_sched_inactive 移到 periodic_sched_ready,再 dwc2_hcd_select_transactions / dwc2_hcd_queue_transactions

这对应 USB 2.0 高速微帧 125µs 下的 中断/同步传输调度;全速/低速则在 1ms 帧 视角下配合 Split

3.4 周期带宽:hcd_queue.c

dwc2_check_periodic_bandwidth() 等函数按 高速约 80%/帧微帧、全速约 90%/帧 的惯例预留 微秒级带宽(注释中与规范常用比例一致),并用 pmap_schedule() 一类 位图 在多个 interval 上占位,避免周期传输饿死。

3.5 Descriptor DMA:hcd_ddma.c

参数启用 Descriptor DMA 时,由 hcd_ddma.c 维护 DMA 描述符链表帧列表索引 等,减轻 CPU 逐包配置通道的负担;等价的「协议含义」仍是 USB 2.0 事务,只是 提交方式 由硬件扫描描述符完成。

3.6 PIO / Slave 与 Internal DMA

hcd.cdwc2_gahbcfg_init():区分 Slave-onlyInternal DMAhost_dma 为假时会启用 GINTSTS_RXFLVL 等路径依赖 FIFO 中断搬运——事务语义不变,数据路径不同。

3.7 TT 与 clear_tt_buffer

低速/全速设备挂在高速 Hub 下时,usbcore 维护 usb_tt;DWC2 在 hcd_intr.c(如 dwc2_hc_handle_tt_clear)中与 usb_hub_clear_tt_buffer() 协作,满足规范对 TT 缓冲区 的要求。


4. Root Hub 与端口(与 Chapter 9 / Hub 章节的关系)

  • 逻辑枚举(读描述符、SET_ADDRESS、选配置)在 usbcore/hub.c
  • 物理端口(供电、复位、连接检测、速度指示)由 dwc2hub_control/hub_status_dataHPRT0 等完成。
  • core_intr.cdwc2_handle_usb_port_intr 处理端口相关 PRTINT 状态清除。

因此:协议状态机在软件上层,电气与端口状态在 DWC2 + PHY。


5. Gadget 模式:作为 USB 2.0 设备

gadget.c(历史继承自 Samsung/Openmoko S3C HSOTG)实现 struct usb_gadget

  • EP0:SETUP 解析、状态阶段、与 composite 上层协作。
  • 其它端点批量/中断/同步 请求队列,DMA 描述符链dwc2_hsotg_ep 中的 desc_list)或 PIO。
  • core.hEP0_MPS_LIMIT 等注释反映 硬件对 EP0 IN 长度的限制,属于 实现约束,不是协议重写。

此时 USB 2.0「设备侧」 行为由 硬件 + gadget.c 响应主机令牌与数据阶段。


6. DRD 与 OTG:drd.ccore_intr.c

drd.cdual-role 下配合 usb_role_switch,通过 GOTGCTLoverride 位强制 A-session/B-session VALID,并 dwc2_force_mode 切换 Host/Device。

core_intr.c 处理 OTG、会话、ID、连接 ID 变化 等与 OTG 补充规范 相关的事件(具体取决于硬件能力与 DTS)。


7. 平台初始化:platform.cparams.c

  • dwc2_get_dr_mode():对齐 硬件模式 / Kconfig / DT dr_mode(与 DWC3 dwc3_get_dr_mode 思想类似)。
  • 时钟、复位、phy_init供电 regululatorusb_create_hcd / usb_add_hcdusb_gadget_register_driver 均在 platform.c 路径串联。

params.c 根据 HWCFG 或 DT 填充 dwc2_core_params(通道数、FIFO、DMA 模式等),直接影响 能否支撑 HS 高带宽同步Split 等。


8. 小结表:DWC2 与 USB 2.0「协议栈」的对应

USB 2.0 相关内容 主要实现位置
设备枚举、Hub 树、URB drivers/usb/core
Root Hub 端口寄存器、SOF、通道事务、Split、PING/NAK dwc2 HCD + DWC_otg 硬件
描述符 DMA / 帧列表(可选) hcd_ddma.c
PHY、FIFO、时钟 platform.ccore.cphy
设备模式 EP0/数据传输 gadget.c + IP
OTG/双角色 drd.ccore_intr.c

9. 延伸阅读(本仓库)

文档
drivers-usb-core详细分析.md
USB总线枚举匹配与数据传输分析.md
drivers-usb目录结构与分层原理.md

基于 rk3588/kernel-6.1/drivers/usb/dwc2 源码整理;寄存器细节以 Synopsys DWC_otg 数据手册与 SoC TRM 为准。

RK3588 kernel-6.1 drivers/usb/dwc3 详细分析:与 USB 3.0 协议的关系及实现方式

RK3588 kernel-6.1 drivers/usb/dwc3 详细分析:与 USB 3.0 协议的关系及实现方式

1. 文档范围

  • 目录rk3588/kernel-6.1/drivers/usb/dwc3/
  • 配置CONFIG_USB_DWC3(模块化时常为 dwc3.ko
  • 硬件:Synopsys DesignWare USB3 Dual-Role Device(DWC_usb3 / DWC_usb31 等) IP。

本文说明:该目录代码如何实现「接上一套 USB3 主机/设备」,以及 USB 3.0 / SuperSpeed 协议内核分工——这一点与 dwc2(自带完整 USB2 HCD显著不同


2. 关键结论:USB 3.0「协议」主要由谁实现?

2.1 主机模式(SuperSpeed Host)

drivers/usb/dwc3 在主机模式下不是另一套 USB3 协议栈,而是:

  1. 配置 DWC3 IP:端口能力 Host、PHY、时钟、全局寄存器、部分 errata。
  2. 把片上 xHCI 寄存器窗口 作为子设备资源交给内核标准 xHCI 主机驱动

host.c 文件头即为 Host Glue,实现 dwc3_host_init():创建 platform_device 名称 "xhci-hcd",填入 MMIO + IRQ,并挂上 xhci_plat_priv 等数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int dwc3_host_init(struct dwc3 *dwc)
{
...
xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO);
...
xhci->dev.parent = dwc->dev;

dwc->xhci = xhci;

ret = platform_device_add_resources(xhci, dwc->xhci_resources,
DWC3_XHCI_RESOURCES_NUM);
...
props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-sg-trb-cache-size-quirk");

if (dwc->usb3_lpm_capable)
props[prop_idx++] = PROPERTY_ENTRY_BOOL("usb3-lpm-capable");
...
if (DWC3_VER_IS_WITHIN(DWC3, ANY, 300A))
props[prop_idx++] = PROPERTY_ENTRY_BOOL("quirk-broken-port-ped");
...
ret = platform_device_add_data(xhci, &dwc3_xhci_plat_quirk,
sizeof(struct xhci_plat_priv));
...
ret = platform_device_add(xhci);

因此:链路训练(LTSSM)、SuperSpeed 端点上下文、TRB 环、U1/U2/U3 等,主要由 drivers/usb/host/xhci*.c + 片内 xHCI 逻辑 完成;dwc3/host.c 负责 集成与 quirk 属性,而非重写规范全文。

2.2 设备模式(SuperSpeed Device / Gadget)

gadget.cep0.c 实现 struct usb_gadget,通过 设备寄存器区core.hDWC3_DEVICE_REGS_*)下发 DEPCMD(如 STARTTRANSFER)、构造 TRB,处理 事件缓冲(Event Buffer) 中的 CONNECT / RESET / LINK STATUS 等事件。

这里更接近 USB 3.0 设备控制器编程模型(SuperSpeed 链路状态控制传输阶段批量/中断/同步 TRB),但仍与 linux/usb/gadget、复合设备上层协作,而不是在用户态单独实现完整协议栈。

2.3 USB 2.0 兼容路径(主机)

DWC3 + xHCI 集成方案中,USB2 Root Hub 端口同样由 xHCI 调度(含 HS/FS/LS 分裂事务等),dwc3 侧主要通过 PHY(USB2/UTMI)GUSB2PHYCFG 等与电气层协作。


3. 寄存器内存布局(理解 Host/Device 分界)

core.h 定义(节选):

1
2
3
4
5
6
7
8
#define DWC3_XHCI_REGS_START		0x0
#define DWC3_XHCI_REGS_END 0x7fff
#define DWC3_GLOBALS_REGS_START 0xc100
#define DWC3_GLOBALS_REGS_END 0xc6ff
#define DWC3_DEVICE_REGS_START 0xc700
#define DWC3_DEVICE_REGS_END 0xcbff
#define DWC3_OTG_REGS_START 0xcc00
#define DWC3_OTG_REGS_END 0xccff
偏移区间 典型用途
0x00000x7fff xHCI MMIO(由 xhci-hcd 映射)
0xc100 全局控制GCTL、FIFO、事件缓冲地址、PHY 配置等)
0xc700 设备模式端点命令与状态
0xcc00 OTG(双角色、会话等)

core.cdwc3_probe 刻意 不把整段 MEM 都 map 给 dwc3,而是:

  • xhci_resources[0]:整段物理内存资源里 低地址部分 交给子设备 xHCI
  • dwc_res.start += DWC3_GLOBALS_REGS_START仅从全局寄存器起始 ioremap,供 dwc3 读写 非 xHCI 区域。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
dwc->xhci_resources[0].start = res->start;
dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
DWC3_XHCI_REGS_END;
dwc->xhci_resources[0].flags = res->flags;
dwc->xhci_resources[0].name = res->name;

/*
* Request memory region but exclude xHCI regs,
* since it will be requested by the xhci-plat driver.
*/
dwc_res = *res;
dwc_res.start += DWC3_GLOBALS_REGS_START;

regs = devm_ioremap_resource(dev, &dwc_res);

这样避免 父驱动与子 xHCI 重复映射同一 MMIO


4. core.c — DRD 核心初始化与模式切换

4.1 dwc3_core_init()

典型步骤包括:GUIDPHY(USB2/USB3 + generic phy)软复位全局控制 dwc3_core_setup_global_control端点数量 dwc3_core_num_epsScratch Buffer帧长/参考时钟burst 类型事件缓冲 dwc3_event_buffers_setup 等。

Gadget 与部分全局特性依赖 事件缓冲;主机侧 xHCI 由子驱动自行初始化。

4.2 dwc3_core_init_mode() / dwc3_set_prtcap() / __dwc3_set_mode

根据 dr_mode(或 OTG)选择 DWC3_GCTL_PRTCAP_HOST / DEVICE / OTG

  • Hostdwc3_host_init(),设置 PHY PHY_MODE_USB_HOST,可选 GUCTL3_SPLITDISABLE 等 quirk。
  • Device:软复位设备侧、dwc3_event_buffers_setup()PHY Devicedwc3_gadget_init()
  • OTGdwc3_otg_init()(见 drd.c)。

dwc3_set_mode() 在 OTG 下通过 workqueue 异步切换到期望角色,必要时 CoreSoftReset(代码针对不同 IP 版本有时间等待说明)。


5. 各源文件职责一览

文件 作用
core.c Probe/remove、时钟/复位、xHCI 资源拆分dwc3_core_*Rockchip RK3588 utmi/pipe 时钟、电源/runtime、与 drd/gadget/host 衔接。
core.h / io.h 寄存器与位域、内联读写。
host.c 注册 xhci-hcd platform 设备、IRQ 名字 fallback、plat_startdwc3_enable_susphy、向 xHCI 注入 software node properties(quirk/LPM)
gadget.c Gadget 主体:端点启用/停用、TRB链路状态、ISO/批量队列、事件处理与会 usb_gadget API 对接。
ep0.c EP0 控制传输:SETUP/DATA/STATUSdwc3_ep0_prepare_one_trbSTARTTRANSFER
gadget.h Gadget 内部结构与声明。
drd.c OTGOEVT 中断、extcon、与 dwc3_set_mode 协作;OTGRELATED 注释说明避免 xHCI HCRST 误伤 PHY/OTG(OCFG_SFTRSTMASK)。
ulpi.c ULPI PHY 路径(可选 USB_DWC3_ULPI)。
debugfs.c 调试。
trace.c / trace.h tracepoint(CONFIG_TRACING)。
dwc3-*.c 板级 glue:时钟树、供电、wrapper 节点差异(如 dwc3-of-simple.crockchip,rk3399-dwc3 的 reset 顺序等)。

6. Gadget 侧与 USB 3.0 设备的对应关系(精简)

  • 链路dwc3_gadget_get_link_state / set_link_state 对应 DSTS 中的 USB LINK STATE(规范中的 U0/U1/U2/U3 等),用于电源管理与恢复。
  • 传输:非 EP0 端点在 gadget.c 中构造 TRB,通过 dwc3_send_gadget_ep_cmd 提交 端点命令;SuperSpeed 大包默认 burst 等与 DWC3_DEPCFG 建立的端点属性一致。
  • EP0ep0.c 使用专用 ep0_trb,与 Chapter 9 控制传输 三阶段对齐。

core.h 中的 设备事件类型(如 CONNECT_DONE、LINK_STATUS_CHANGE、WAKEUP、Suspend)对应 DWC3 事件缓冲解析(SuperSpeed 连接完成复位后的速度协商结果等由硬件上报,驱动转成交互)。


7. RK3588 / Rockchip 相关代码位置

  • dwc3_get_clocks():注释 「specific to Rockchip RK3588」,增加 utmipipe 可选时钟。
  • dwc3_probe 末尾:对 Rockchip OTG 兼容字符串(rockchip,rk3399-dwc3rockchip,rk3576-dwc3)有 runtime / extcon 特殊路径(RK3588 常与类似 glue 共用策略,需结合具体 DTS)。
  • dwc3-of-simple.crockchip,rk3399-dwc3PHY 初始化前 可能需要 usb3-otg reset

板级仍以 snps,dwc3 子节点 + dwc3-of-simple(或厂商 wrapper)为准。


8. 与 dwc2usbcore 的对比记忆

项目 DWC3(主机) DWC2(主机)
USB3 SuperSpeed xHCI 驱动 + IP 内 xHCI 不适用(USB2-only IP)
drivers/usb/dwc3 主机代码量 glue(host.c)为主 完整 hcd*.c 队列/通道
枚举 / Hub / URB(逻辑) drivers/usb/core 同左

9. 延伸阅读(本仓库)

文档
drivers-usb-dwc2详细分析.md
drivers-usb-core详细分析.md
USB总线枚举匹配与数据传输分析.md

内核主线中与 SuperSpeed 主机强相关的另一目录:drivers/usb/host/xhci*.c)。


基于 rk3588/kernel-6.1/drivers/usb/dwc3core.h/host.c/core.c 整理;IP 级细节以 Synopsys DWC_usb3 编程手册与 SoC TRM 为准。

RK3588 kernel-6.1:drivers/usb/image 功能与实现要点

RK3588 kernel-6.1:drivers/usb/image 功能与实现要点

源码基准:rk3588/kernel-6.1/drivers/usb/image/

1. 目录定位

drivers/usb/image 收录 成像类 USB 外设 的内核驱动,与 drivers/usb/storage(大容量存储)media/usb(UVC 等)不同:这里的设备 不按 Mass Storage 工作,而是 厂商自定义 bulk/int 协议把 SCSI 封在 USB bulk 管道里

本树仅 两个驱动(见 Makefile / Kconfig):

选项 文件 设备类型
CONFIG_USB_MDC800 mdc800.c Mustek MDC800 数码相机
CONFIG_USB_MICROTEK microtek.c + microtek.h Microtek X6USBUSB 扫描仪

与 RK3588:均为 老旧专有硬件,一般嵌入式产品内核可 N;分析目的是理解 「非标准类成像设备」在内核里的两类接入方式


2. mdc800.c(Mustek MDC800)

2.1 功能

  • 绑定 VID 0x055f / PID 0xa800
  • usb_driver + probe/disconnect:严格校验 单 configuration、接口 Class 0xff(Vendor)4 个端点 的布局是否与 mdc800_ed[] 一致。
  • 全局仅支持一台相机(静态 mdc800 实例,probe 里若已有 dev 则拒绝第二台)。

2.2 对上接口(用户态)

  • 使用 usb_register_dev(intf, &mdc800_class),归属 struct usb_class_driver(动态 usb_minor),不再是注释里的静态 major 180)。
  • file_operationsopen/release/read/write/ioctl/poll 等,通过 mutexwait_queueUSB URB 同步。
  • 传输中断 URB(状态/就绪)、批量 OUT/IN URB 下发相机命令与取图像数据;状态机 mdc800_stateNOT_CONNECTED / READY / WORKING / DOWNLOAD

2.3 原理小结

典型 「Vendor 类 + 字符设备」:用户态(历史上 gphoto)按私有协议填缓冲区,经 ioctl/write/read 驱动 URB 与相机对话。


3. microtek.c(Microtek USB 扫描仪)

3.1 功能

  • 逆向工程 的 USB 协议:注释描述 EP 0x01 OUT 下发命令与写出数据;0x82 IN 读状态与普通数据;0x83 IN 读大块图像(与 READ IMAGE 类 SCSI 相关)。
  • 前缀约定mts_usb_* 为 USB 侧,mts_scsi_* 为 SCSI 中间层接口。

3.2 对上接口(内核 SCSI)

  • scsi_host_alloc 分配 struct Scsi_Host,模板 mts_scsi_host_templatequeuecommandDEF_SCSI_QCMD 包装的 mts_scsi_queuecommand_lck
  • queuecommandscsi_cmnd 转成 USB bulk/int(URB) 序列:先发 CDB 到 EP1,再按注释规则从 0x830x82 收数据,最后读 状态字节
  • depends on SCSI:对用户表现为 /dev/sg*scsi_generic),SANE 等通过 SG ioctl 或后端扫描栈访问。

3.3 原理小结

典型 「USB-SCSI 胶水」:硬件 不把 SCSI 封成 BOT/UASP,而是在几条 bulk 管道上演 SCSI 语义;内核侧 自建迷你主机适配层,而不是 usb-storage


4. 与通用 USB 子系统的关系

  • 二者都用 usb_enable/disable_autosuspendusb_kill_urbusb_submit_urb 等标准 API。
  • 均未实现 USB Imaging Class 的现代标准路径;若新硬件,应优先 UVC / USB Still Image Class / vendor userspace (libusb),而不是仿照本目录风格新增内核驱动。

5. 小结

维度 MDC800 Microtek
设备模型 usb_interfaceusb char class usb_interfaceScsi_Host
协议 Vendor bulk + int 逆向 bulk 管道上的 类 SCSI
用户态 字符节点 + ioctl/read/write SG / 扫描栈

目录体量小但覆盖了 成像外设在 Linux 里的两种经典挂载方式直连 misc/usb-class伪装成 SCSI generic