详解usbmon抓取的log各字段的含义

本文深入讲解USB协议基础知识,包括USB包类型、事务概念与传输类型,详细解析usbmon抓取日志字段含义,如URB标签、时间戳、事件类型等,通过实例演示如何利用usbmon解决实际问题。

详解 usbmon 抓取的 log 各字段的含义

在上篇文章中,我们已经介绍了如何在 linux 下使用 usbmon 抓取 usb 总线上数据的方法。(https://www.cnblogs.com/shiwenjie/p/8467057.html

数据抓取到了,但是放眼一看,密密麻麻的全是数字,它们代表什么含义呢?本文将为你揭晓答案。

1. 预备知识

  在解读 usbmon 抓取的数据包的含义之前,我们需要了解一下与 usb 传输有关的基础知识,这样才能更好的理解数据包的各个字段所代表的含义。

  务必要明确一点:usb 总线上传输的数据是以包为基本单位的,但是不能随意的使用包来传输数据,必须按照一定的关系把这些不同的包组织成事务(transaction)进行传输。

1.1 usb 包的种类

  介绍一下 usb 包的种类,总体上分为四类:令牌包、数据包、握手包、特殊包。

1)令牌包

  令牌包用来发起一次 usb 传输,因为 usb 是主从结构的拓扑结构,所有的数据传输都是由主机发起的,设备只能被动的响应,这就需要主机发送一个令牌包来通知哪个设备进行响应,如何响应。

  令牌包有 4 种,分别为输出(OUT)、输入(IN)、建立(SETUP)和帧起始(SOF)。各个包的功能见下表:

      

2)数据包:顾名思义,数据包就是用来传输数据的,可以从主机到设备,也可以从设备到主机,方向由令牌包来指定。

3)握手包:握手包的发送者一般为数据接收者,用来表示一个传输是否被对方确认。在传输正常的情况下,主机/设备会发送一个表示传输正确的 ACK 握手包。

4)特殊包:特殊包用在一些特殊的场合,这里就不介绍了。

1.2 usb 的事务

  介绍了 usb 包的分类,下面就要着重介绍 usb 的事务(transaction)及传输类型。前面已经说了,我们不能随意的使用 usb 包来传输数据,必须按照一定的关系把这些不同的包组织成事务才能传输数据。

  那么事务是什么呢? 事务通常由三个包组成:令牌包、数据包和握手包。

        

  ※注意:usbmon 只抓取事务(transaction)中的数据包,不会抓取令牌包和握手包。

  usb 协议规定了 4 种传输类型:批量传输、等时传输、中断传输和控制传输。其中,批量传输、等时传输、中断传输每传输一次数据都是一个事务;控制传输包括三个过程,建立过程和状态过程分别是一个事务,数据过程可能包含多个事务。

1.3 usb 的四种传输类型

  下面用图来简单的表示这四种传输的过程

1)批量传输

  

2)等时传输

  

3)中断传输

  

4)控制传输

     

2. 分析 usbmon 抓取的 log

  前面介绍了 usb 协议的一些基础知识,下面就开始分析 usbmon 抓取的 log。

  贴一张在 ubuntu 下抓取的 4G 模块拨号上网的 log。

    

下面从左到右分析这些字段代表的含义:

1)URB Tag - URB 标签

  该字段表示驱动中定义的struct urb 结构体变量在内核空间的地址,可以使用该字段区分不同的 URB 数据包。

  下面两张图分别是在 64 位和 32 位 系统上抓取的数据包。可以看到 URB Tag 字段的长度和系统的位数相同。

  

2)Timestamp - 时间戳

  该字段表示的是时间戳,单位是微秒。1微秒 = 10^(-6)秒。

3)Event Type - 事件的类型

  S - submission,向 usb controller 提交 URB

  C - callback,URB 提交完成后的回调

  E - submission error,向 usb controller 提交 URB 发生错误

4)Address word - 地址字段

  这个字段包含 4 部分,各个部分之间使用分号隔开,这 4 部分分别是 URB 类型及传输方向usb 总线号usb 设备地址端点号

  

  URB 类型及传输方向:usb 有四种传输方式,分别是控制传输(Control)、批量传输(Bulk)、等时传输(Isochronous)和中断传输(Interrupt)。usb 数据的传输方向是以 Host 端为参考对象的,Host 向 usb 设备发送数据那么传输方向就是 Output,Host 读取 usb 设备的数据那么传输方向就是 Input。

  usb 总线号:该字段表示 usb 总线号,Host 端一般有多个usb controller,每个usb controller 都有一条对应的 usb 总线,使用 usb 总线号区分它们,usb 设备可以挂接到某条总线上。

  usb 设备地址:该字段表示 usb 设备的地址,每一个 usb 设备经过枚举后在 Host 端都有一个唯一的地址。

  端点号:表明该次数据传输是 Input/Output 到设备的哪个端点。上图中该字段是 0,就表示这次数据传输使用的是设备的端点 0(控制端点)。

5)URB Status word - URB 的状态

  这个字段有两种表示形式: 

  ① s + 一串数字

  ② 一串以分号间隔的数字(或单个数字)构成的,这串数字包含下面几个部分:URB status、interval、start frame 和 error count。特别注意一点,该字段不同于 "Address word" 字段,对于不同的传输方式这几部分是可选的,并非所有部分都是必须的,下图是不同的传输方式包含的信息。

    

  下面分析不同的传输方式所包含的信息:

  批量传输:只包含 URB status 这个字段,它对应着 struct urb 结构体中的 status 成员变量,表示 URB 的状态。URB status 仅仅对 Event Type 中的 Callback 有意义,对于 Submission 是无意义的,之所以这么做是为了统一格式,方便使用脚本分析 usbmon 的 log。URB status 的具体含义见内核对于该成员变量的注释。

     

  中断传输:URB status 和 Interval,URB status 见前面的分析,Interval 表示该 URB 对端点轮询的间隔时间。
  等时传输:URB status、Interval、start frame 和 error count。等时传输包含了所有部分,start frame 和 error count 是等时传输所特有的字段,但因为我们的驱动程序中不使用等时传输这种方式,因此这里不做过多的分析。
  控制传输:控制传输在提交时(S:submission)这个字段是 s,这里的 s 后面紧跟的数据是控制传输的建立过程主机发送的数据包,可以参考前面控制传输的示意图。控制传输在回调时(C:callback),这个字段代表的是 URB status。

6)Setup packet - 控制传输建立阶段的数据包

  如果是控制传输,这个字段表示控制传输建立阶段主机发给设备的数据包。

    

  该字段从左到右的格式如下,括号中的数字表示该部分占用的字节大小:

    bmRequestType(1) + bRequest(1) + wvalue(2) + wIndex(2) + wLength(2)

  每个字段的含义可以在 usb2.0 规范中找到,这部分与 usb 的标准请求等相关。

7)Data Length - 数据包的长度

  对于 S(Submission),Data Length 字段是主机请求发送/读取的数据长度,但是设备并不一定能够接收/发送主机请求的数据长度。实际接收/发送的数据长度在 C(Callback)中的 Data Length 字段。

  

  

8)Data tag - 数据标签

  ”=” 后面紧跟数据流
  “>” 表示这是一次 Output 数据传输
  “<” 表示这是一次 Input 数据传输

9)Data words follow - 数据流

  这个字段就是一个事务(transaction)中的数据包,我们平时分析 usbmon 的 log 定位问题,也主要是看这个字段。注意一点,这个字段实际显示的数据 <= Data Length 的值。

3. 使用 usbmon 分析解决问题

  下面举一个使用 usbmon 定位问题的小例子:
  客户由于没有正确的根据文档移植驱动,可能在 qmi_wwan 驱动中没有剥除以太网头,就导致 quectel-CM 在通过 dhcp 获取 IP 地址阶段失败,可以通过抓取的 usbmon 的 log 快速的定位问题。
  下图是 usbmon 抓取的 log,可以看到在 dhcp 阶段,主机发送的数据包是以太网包而非 IP 包,从而导致获取 IP 失败,进而定位到是驱动没有正确的移植。

    

 

参考资料:

【1】linux内核自带的官方文档:https://www.kernel.org/doc/Documentation/usb/usbmon.txt

【2】《圈圈教你玩USB》

【3】《Linux那些事之我是USB》 

上面两本书的百度网盘资源(仅供学习,不可商用):链接:https://pan.baidu.com/s/1skpSqALFwi8h94AO3Gx1RQ 密码:65b9

 

<think> 我们正在讨论如何使用usbmon在Linux上抓取USB通信日志。根据引用内容,usbmon是Linux内核内置的USB抓包工具,可以捕获USB总线上传输的数据。以下是具体步骤: 1. **加载usbmon内核模块**: 首先需要确保usbmon模块已经加载。使用以下命令加载模块: ```bash sudo modprobe usbmon ``` 这会将usbmon模块加载到内核中。可以通过`lsmod | grep usbmon`来验证。 2. **挂载debugfs文件系统(如果尚未挂载)**: usbmon通过debugfs文件系统提供接口。挂载debugfs: ```bash sudo mount -t debugfs none_debugfs /sys/kernel/debug ``` 注意:在某些系统中,debugfs可能已经挂载,可以检查`/sys/kernel/debug`目录是否存在。 3. **识别目标USB设备**: 使用以下命令列出当前连接的USB设备: ```bash cat /sys/kernel/debug/usb/devices ``` 在输出中,找到你想抓包的设备。注意设备的`Bus`编号(例如`Bus=02`)和`Dev#`(设备号)。引用[2]中给出了一个输出示例。 4. **确定usbmon接口**: usbmon为每个USB总线提供一个捕获接口。接口文件位于`/sys/kernel/debug/usb/usbmon`目录下,命名为`uXc`(捕获控制端点)和`uXs`(捕获所有端点),其中`X`是总线号。例如,总线2对应的文件是`u2c`和`u2s`。 5. **开始抓包**: 使用`cat`命令或专门的工具(如wireshark)读取usbmon接口文件。例如,捕获总线2的所有通信: ```bash sudo cat /sys/kernel/debug/usb/usbmon/u2s > usbmon.log ``` 或者,使用`tcpdump`(需要安装): ```bash sudo tcpdump -i usbmon2 -w usbmon.pcap ``` 这里`usbmon2`表示总线2的usbmon接口。使用tcpdump可以生成pcap格式的文件,便于用Wireshark分析。 6. **触发USB通信**: 进行你想要捕获的操作(如连接设备、传输数据等)。 7. **停止抓包**: 按`Ctrl+C`停止`cat`或`tcpdump`。 8. **分析日志**: 如果使用`cat`直接捕获,日志是文本格式,可以查看。如果使用tcpdump,可以用Wireshark打开pcap文件进行图形化分析。 **注意事项**: - **权限问题**:通常需要root权限来访问usbmon接口。 - **多总线**:如果设备连接到USB集线器,注意正确的总线号。 - **实时监控**:可以使用`tail -f`实时监控: ```bash sudo tail -f /sys/kernel/debug/usb/usbmon/u2s ``` **示例输出解释**(参考引用[3]): 一条典型的usbmon日志如下: ``` d118002d 3661788724 C Ii:1:001:1 0:2048 2 = 55534253 00000000 00000800 ``` 其中: - `d118002d`:设备标识(vendor id和product id的组合,这里是0x18d1和0x002d) - `C`:提交回调(表示一个完成的URB) - `Ii:1:001:1`:URB类型(`I`表示中断传输)、总线号、设备地址、端点号 - `0:2048`:状态和长度 - `2 = 55534253 ...`:数据(十六进制格式) 通过以上步骤,你就可以捕获并分析USB通信数据了。 §§相关问题§§ 1. 如何解析usbmon捕获的原始文本日志? 2. 在Wireshark中如何分析usbmon捕获的pcap文件? 3. 除了usbmon,Linux下还有哪些USB抓包工具? 4. 如何通过usbmon捕获特定端点的数据? </think> 在 Linux 系统中使用 `usbmon` 抓取 USB 通信日志的完整步骤如下: ### 一、准备工作 1. **内核模块检查** 确认系统已包含 `usbmon` 模块: ```bash $ ls /lib/modules/$(uname -r)/kernel/drivers/usb/mon/ | grep usbmon.ko ``` 若未安装,需先编译内核启用 `CONFIG_USB_MON=y` 选项[^1]。 2. **挂载 debugfs** 挂载内核调试文件系统: ```bash $ sudo mount -t debugfs none_debugfs /sys/kernel/debug ``` ### 二、启用 usbmon ```bash # 加载内核模块 $ sudo modprobe usbmon # 验证模块状态 $ dmesg | tail [ +0.000005] usbmon: debugfs is not available [ +0.000003] usbmon: registered ``` ### 三、识别目标 USB 设备 1. **列出所有 USB 设备** ```bash $ cat /sys/kernel/debug/usb/devices ``` 输出示例: ```plaintext T: Bus=02 Lev=02 Prnt=03 Port=00 Cnt=01 Dev#=6 Spd=12 MxCh=0 D: Ver=1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=8 #Cfgs=1 P: Vendor=0400 ProdID=c35a Rev=0.63 C:* #Ifs=1 Cfg#=1 Atr=c0 MxPwr=100mA I:* If#=0 Alt=0 #EPs=2 Cls=00(>ifc) Sub=00 Prot=00 Driver=(none) E: Ad=81(I) Atr=02(Bulk) MxPS=64 Ivl=0ms # 输入端点 E: Ad=02(O) Atr=02(Bulk) MxPS=64 Ivl=0ms # 输出端点 ``` 关键参数: - `Bus`: USB 总线号 (如 `02`) - `Dev#`: 设备号 (如 `6`) - `Vendor/ProdID`: 设备标识 (如 `0400:c35a`)[^2][^3] 2. **查看可用捕获接口** ```bash $ ls /sys/kernel/debug/usb/usbmon u2c u2s u3c u3s # uXc=控制流,uXs=数据流 ``` ### 四、捕获 USB 日志 1. **实时监控总线数据** 监控总线 2 的所有端点: ```bash $ sudo cat /sys/kernel/debug/usb/usbmon/u2s ``` 输出示例: ```plaintext d118002d 3661788724 C Ii:1:001:1 0:2048 2 = 55534253 00000000 00000800 00000000 00000000 00000000 00000000 ``` 字段解析: - `d118002d`: 设备标识 (VID=0x18d1, PID=0x002d) - `Ii:1:001:1`: 端点类型(中断输入)/总线号/设备地址/端点号 - `0:2048`: 状态码/数据长度 - 十六进制数据: 实际传输内容[^3] 2. **保存日志到文件** ```bash $ sudo cat /sys/kernel/debug/usb/usbmon/u2s > usbmon.log ``` ### 五、高级捕获技巧 1. **过滤特定设备** 通过设备号过滤: ```bash $ grep "Dev#=6" /sys/kernel/debug/usb/usbmon/u2s ``` 2. **使用 wireshark 解析** 生成 pcap 格式: ```bash $ sudo tcpdump -i usbmon2 -w usb_traffic.pcap ``` 用 Wireshark 打开分析协议层次 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值