Linux USB调试

USB设备是linux常用设备,以下是针对USB设备协议分析、数据抓取和常见问题调试方法

设备识别与基础信息

  • 查看USB设备树
1
lsusb 

输出示例:

1
2
3
4
5
Bus 001 Device 004: ID 2a63:0001
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 003: ID 0e0f:0002 VMware, Inc. Virtual USB Hub
Bus 002 Device 002: ID 0e0f:0003 VMware, Inc. Virtual Mouse
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

Bus 001 Device 004: ID 2a63:0001
Bus 001 : 指明设备连接到哪条总线
Device 004 : 表明这是连接到总线上的第二台设备
ID : 设备的ID
Linux Foundation 2.0 root hub :生产商名字和设备名

  • 查看详细设备描述符
1
usb-devices

输出示例:

1
2
3
4
5
6
7
8
T:  Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=480 MxCh=16
D: Ver= 2.00 Cls=09(hub ) Sub=00 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=1d6b ProdID=0002 Rev=05.15
S: Manufacturer=Linux 5.15.0-138-generic xhci-hcd
S: Product=xHCI Host Controller
S: SerialNumber=0000:00:14.0
C: #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=0mA
I: If#=0x0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub

描述符全解

拓扑信息(T开头行)
T: Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=480 MxCh=16

Bus=01:设备连接在主板第一个USB控制器(编号从1开始)
Lev=00:设备层级(0表示根层级设备)
Prnt=00:父设备编号(0表示无父设备)
Port=00:连接端口号(物理端口对应主板接口)
Cnt=00:子设备计数(当前无连接子设备)
Dev#=1:系统分配的设备序号(系统启动后递增)
Spd=480:工作速率(480Mbps,符合USB2.0高速标准)
MxCh=16:最大子设备容量(可级联16个设备)

设备描述符(D开头行)
D: Ver= 2.00 Cls=09(hub ) Sub=00 Prot=01 MxPS=64 #Cfgs= 1

Ver=2.00:USB规范版本(2.0对应USB2.0)
Cls=09:设备类代码(09表示USB集线器)
Sub=00:子类代码(标准集线器子类)
Prot=01:协议版本(单TT协议,用于高速集线器)
MxPS=64:端点0最大包大小(64字节)
#Cfgs=1:设备配置数量(仅一种配置可用)

厂商信息(P开头行)
P: Vendor=1d6b ProdID=0002 Rev=05.15

Vendor=1d6b:厂商ID(1d6b为Linux Foundation保留ID)
ProdID=0002:产品ID(0002对应USB2.0根集线器)
Rev=05.15:硬件版本号(主版本5,次版本15)

字符串描述符(S开头行)
S: Manufacturer=Linux 5.15.0-138-generic xhci-hcd

S: Product=xHCI Host Controller
S: SerialNumber=0000:00:14.0
Manufacturer:驱动模块信息(xhci-hcd为USB3.0控制器驱动)
Product:设备功能描述(xHCI表示扩展主机控制器接口)
SerialNumber:PCI设备地址(domain:bus:device.function格式)

配置描述符(C开头行)
C: #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=0mA

#Ifs=1:接口数量(集线器只需一个控制接口)
Cfg#=1:当前激活的配置编号
Atr=e0:配置特性(D7:总线供电,D6:远程唤醒,D5:保留)
MxPwr=0mA:最大功耗(实际由总线供电)

接口描述符(I开头行)
I: If#=0x0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub

If#=0x0:接口编号(0号接口)
Alt=0:备用设置编号(默认设置)
#EPs=1:端点数量(仅需一个控制端点)
Cls=09:接口类(集线器类)
Sub=00:接口子类(无特殊子类)
Prot=00:接口协议(无特殊协议)
Driver=hub:绑定驱动(通用集线器驱动)

数据抓取与协议分析

1、调试 USB 协议层数据时,需要内核已经开启 usbmon。

1
2
sudo modprobe usbmon

2、确保 debugfs 挂载

1
2
sudo mount -t debugfs none /sys/kernel/debug

3、查看当前可用的 USB 总线监控接口

1
2
ls /sys/kernel/debug/usb/usbmon

输出示例

1
2
0s 0u 1s 1u 2s 2u ... (s 表示summary, u 表示usbmon格式文本输出)

4、实时抓取 USB1 总线数据

1
sudo cat /sys/kernel/debug/usb/usbmon/1u

也可以安装wireshark抓包工具抓去

常见问题与调试建议

1、设备未识别
查看 dmesg 是否存在识别日志,确认是否加载驱动

2、驱动加载失败
需要跟踪内核代码,是否加载成功或者编译成功

3、冲突问题
需要查看是否生成节点

4、HOST与OTG切换
rk3568 otg模式切换

1
echo host > /sys/devices/platform/fe8a0000.usb2-phy/otg_mode