4. USB Gadget驱动加载日志分析:从modprobe到gadget注册成功的关键日志行解读
USB Gadget 驱动的加载过程涉及多个内核子系统:USB 核心层、UDC(USB Device Controller)驱动、Gadget 功能驱动以及 ConfigFS 配置层。当执行 modprobe 或通过 ConfigFS 绑定驱动时,内核会按顺序打印一系列日志。理解这些日志行的含义,是快速定位驱动加载失败、UDC 未匹配、端点分配错误等问题的核心技能。
4.1 驱动加载全流程与日志阶段划分
从执行 modprobe g_serial(或通过 ConfigFS 创建 gadget)到设备在主机端枚举成功,内核日志通常经历以下四个阶段:
关键日志阶段速查表
| 阶段 | 典型日志前缀 | 含义 | 故障关注点 |
|---|---|---|---|
| ① UDC 驱动探测 | dwc2 / musb / dwc3 |
UDC 控制器驱动初始化,注册到 USB 核心层 | UDC 是否成功注册 gadget |
| ② Gadget 驱动加载 | g_serial / g_ether / g_zero |
Gadget 功能驱动初始化,分配端点、注册 USB 描述符 | 端点分配失败、内存不足 |
| ③ UDC 与 Gadget 绑定 | udc_bind_to_driver / bind |
Gadget 驱动找到匹配的 UDC,执行 bind 回调 | UDC 名称不匹配、bind 回调返回错误 |
| ④ USB 设备枚举 | new high-speed USB device / gadget |
主机检测到设备,发送 SET_CONFIGURATION | 描述符错误、配置请求失败 |
4.2 关键日志行逐行解读
4.2.1 UDC 驱动探测阶段
UDC 驱动通常在系统启动时由设备树或 ACPI 匹配后自动加载。典型日志如下:
[ 2.345678] dwc2 3f980000.usb: supply vusb_d not found, using dummy regulator
[ 2.352345] dwc2 3f980000.usb: supply vusb_a not found, using dummy regulator
[ 2.359012] dwc2 3f980000.usb: EPs: 16, dedicated fifos, 4080 entries in SPRAM
[ 2.366789] dwc2 3f980000.usb: DWC OTG Controller
[ 2.371456] dwc2 3f980000.usb: new USB bus registered, assigned bus number 1
[ 2.378123] dwc2 3f980000.usb: irq 33, io mem 0x3f980000
解读要点:
EPs: 16表示该 UDC 支持 16 个端点(含端点 0),若后续 Gadget 驱动需要的端点数超过此值,bind 会失败。new USB bus registered表示 UDC 已向 USB 核心层注册,但此时尚未与任何 Gadget 驱动绑定。- 若缺少此段日志,说明 UDC 驱动未加载或设备树节点未使能。
4.2.2 Gadget 驱动加载阶段
当执行 modprobe g_serial 或通过 ConfigFS 创建 gadget 时,内核加载对应的功能驱动模块:
[ 5.123456] g_serial gadget: Gadget Serial v2.4
[ 5.128901] g_serial gadget: g_serial ready
[ 5.133456] g_serial gadget: high-speed config #1: CDC ACM config
对于 ConfigFS 方式,日志会显示更多细节:
[ 5.145678] configfs-gadget gadget: high-speed config #1: my_config
[ 5.152345] configfs-gadget gadget: uevent: sent uevent for gadget my_gadget
常见故障: 若日志中只出现
g_serial ready 但没有后续的 high-speed config,说明 Gadget 驱动虽然初始化成功,但尚未收到 UDC 的绑定请求。此时应检查 UDC 名称是否匹配。
4.2.3 UDC 与 Gadget 绑定阶段
这是最关键的一步。Gadget 驱动通过 usb_gadget_probe_driver 查找匹配的 UDC:
[ 5.167890] udc_bind_to_driver: binding gadget driver 'g_serial' to UDC '3f980000.usb'
[ 5.175678] g_serial gadget: bind to driver 3f980000.usb
[ 5.181234] g_serial gadget: endpoint index 2: ep1in (IN) maxpacket 512
[ 5.187890] g_serial gadget: endpoint index 3: ep2out (OUT) maxpacket 512
若绑定失败,常见日志如下:
[ 5.190123] udc_bind_to_driver: failed to bind gadget 'g_serial' to UDC '3f980000.usb': -22
[ 5.198901] g_serial gadget: probe of 3f980000.usb failed with error -22
错误码速查:
-22(EINVAL):端点描述符配置错误,或 UDC 不支持请求的端点类型。-12(ENOMEM):内存分配失败,通常端点 FIFO 或 DMA 缓冲区不足。-16(EBUSY):UDC 已被其他 Gadget 驱动占用。-19(ENODEV):UDC 设备未就绪或已移除。
4.2.4 USB 设备枚举阶段
绑定成功后,主机端(或作为主机时的另一侧)会检测到设备并开始枚举:
[ 5.234567] usb 1-1: new high-speed USB device number 2 using dwc2
[ 5.289012] usb 1-1: New USB device found, idVendor=0525, idProduct=a4a7, bcdDevice= 2.04
[ 5.296789] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 5.303456] usb 1-1: Product: Gadget Serial v2.4
[ 5.308123] usb 1-1: Manufacturer: Linux 5.10.0 with 3f980000.usb
[ 5.314890] usb 1-1: SerialNumber: 000000000000
[ 5.319567] cdc_acm 1-1:1.0: ttyACM0: USB ACM device
解读要点:
new high-speed USB device表示主机检测到设备并开始复位和枚举流程。idVendor=0525, idProduct=a4a7是 Linux 基金会为 Gadget 驱动分配的默认 VID/PID,若与实际产品不符,需检查描述符配置。ttyACM0: USB ACM device表示主机端成功加载了 CDC ACM 驱动,Gadget 功能正常。
4.3 常见故障日志模式与排查清单
以下表格总结了实际调试中最常见的日志模式及其根因:
| 日志模式 | 可能原因 | 排查方向 |
|---|---|---|
failed to bind ... -22 |
端点配置错误 / UDC 不支持 | 检查端点数量、类型、最大包大小 |
no UDC available |
UDC 未注册或名称不匹配 | 检查 /sys/class/udc/ 目录内容 |
config failed |
SET_CONFIGURATION 请求处理失败 | 检查描述符中的配置值是否一致 |
dma_alloc_coherent failed |
DMA 内存不足 | 增大 CMA 区域或减少端点缓冲区 |
gadget registered but no host |
USB 线缆 / 主机驱动问题 | 检查硬件连接和主机端 dmesg |
4.4 实战:从日志中定位 ConfigFS Gadget 绑定失败
以下是一个典型的 ConfigFS Gadget 绑定失败案例,日志如下:
[ 10.123456] configfs-gadget gadget: high-speed config #1: my_config
[ 10.130123] configfs-gadget gadget: bind to driver 3f980000.usb
[ 10.136789] dwc2 3f980000.usb: failed to enable ep1in: -22
[ 10.142345] configfs-gadget gadget: failed to bind gadget 'my_gadget' to UDC '3f980000.usb': -22
分析步骤:
- 日志显示
bind to driver成功,说明 UDC 名称匹配。 failed to enable ep1in: -22指向具体的端点使能失败。- 检查 ConfigFS 中该端点的配置:
/sys/kernel/config/usb_gadget/my_gadget/configs/my_config/下的端点链接。 - 确认端点类型(bulk/interrupt/isochronous)和最大包大小是否在 UDC 能力范围内。
- 修正后重新绑定,日志应显示
enabled ep1in成功。
4.5 日志分析工具与技巧
- 实时监控: 使用
dmesg -w或journalctl -f -k实时观察 Gadget 加载日志。 - 日志过滤:
dmesg | grep -E "gadget|udc|dwc2|musb|configfs"快速提取相关行。 - 时间戳对齐: 使用
dmesg -T将时间戳转换为可读时间,便于与硬件抓包工具(如 Wireshark)的时间戳对齐。 - UDC 状态检查:
cat /sys/class/udc/3f980000.usb/state查看当前 UDC 状态(应为configured或waiting)。
重要提示: 内核日志的详细程度受
printk 级别控制。若日志信息不足,可通过 echo 8 > /proc/sys/kernel/printk 临时提高日志级别,或使用 dyndbg 动态开启 USB Gadget 子系统的调试信息。