平时在处理客户问题时,经常需要分析出现问题时抓取的usbmon log,这个log中有一个字段非常重要:URB Status word,这个字段就是struct urb结构体中的status成员变量。
通过这个status的值,可以分析出模块端和HOST端usb的一些状态,有利于定位到问题点。
Linux内核中对该成员变量的注释如下:
表明该字段仅仅表示批量传输、控制传输和中断传输的URB状态,等时传输不在其中,不过我们的模组也没有等时传输的端点。
在讲解URB的status之前先看下linux中URB的处理流程,如下图所示:

① 使用usb_alloc_urb()创建一个URB结构体
② 对于不同的传输方式,分别使用相应的函数初始化URB,中断传输使用usb_fill_int_urb(),批量传输使用usb_fill_bulk_urb(),控制传输使用usb_fill_control_urb(),等时传输比较特殊需要手动初始化URB。
③ 使用usb_submit_urb()向usb控制器提交上一步初始化完成的URB,提交成功函数返回0,提交失败函数返回一个负数。当提交失败时,usbmon log中的Event Type字段就为 E(submission error)。

④ URB被提交到了usb控制器中,这个URB将来会有三种命运,而这三种URB的结束方式就对应到URB的status。
第一种:成功完成传输
第二种:传输发生了错误
第三种:URB从usb控制器中"unlinked"
⑤ 当URB结束时,会调用之前注册的complete回调函数
在这种情况下,URB被成功发送给设备,并且设备返回正确的确认。对于一个输出URB,表示数据被成功发送;对于一个输入URB,成功获取请求的数据。此时,urb->status = 0;
下面是一条qmi消息成功交互的过程:
ffff8800b7d91740 S Ii:3:008:9 -115:256 8 < // 这里的-115(EINPROGRESS)仅仅表示URB被提交给usb控制器去处理了
ffff8800b7d90600 S Co:3:008:0 s 21 00 0000 0004 000c 12 = 010b0000 00000001
ffff8800b7d90600 C Co:3:008:0 0 12 > // 这里urb status为0,表示qmi request消息成功发送给模块了
ffff8800b7d91740 C Ii:3:008:9 0:256 8 = a 0 // 这里Ti的urb status为0,表明可以读取qmi的response信息了
ffff8800b7d915c0 S Ci:3:008:0 s a1 01 0000 0004 1000 4096 <
ffff8800b7d91740 S Ii:3:008:9 -115:256 8 <
ffff8800b7d915c0 C Ci:3:008:0 0 19 = 0 00000101 0 000000 // 这里返回0,表示HOST端成功的读取了模块的qmi response
再看一下AT指令的交互过程:
ffff8800b1480f00 S Bo:3:008:3 -115 1 = 61
ffff8800b1480f00 C Bo:3:008:3 0 1 > // 成功向模块发送了 A
ffff8800b1480f00 S Bo:3:008:3 -115 1 = 74
ffff8800b1480f00 C Bo:3:008:3 0 1 > // 成功向模块发送了T
ffff8800b1480f00 S Bo:3:008:3 -115 1 = 0d
ffff8800b1480f00 C Bo:3:008:3 0 1 > // 成功向模块发送了换行
ffff8800b1481e00 C Bi:3:008:4 0 6 = 0d0a4f4b 0d0a
ffff8800b1481e00 S Bi:3:008:4 -115 4096 <
ffff8800b1481b00 C Ii:3:008:5 0:256 10 = a 0 0000 // 成功读取模块的AT Response ==> OK
urb传输异常就有很多种了,下面列举一下常见的错误对应的status:
注:下面的usb status状态码在 linux-x.x.x/Documentation/usb/error-codes.txt 这个文件中有详细的说明,可以参考一下。
-EINPROGRESS (-115)
这个字段前面已经说过了,它出现在URB submission的时候,表示这个URB的控制权交给了usb控制器,将由usb控制器处理,这个并不是真正的错误。
-EPROTO (-71)
有两种原因会导致这个错误:
-
- A bitstuff error happened during the transfer
- No response packet was received in time by the hardware
这个错误经常发生在usb设备枚举失败时,下图就是EC25模块在客户树莓派上枚举失败对应的log,URB的status字段为-71

-EILSEQ (-84)
这个错误不太常见,具体可以参考error-codes.txt
-ECOMM (-70)
对于IN URB,在数据传输中,接收USB设备数据的速度 > 将数据写入内存中的速度
-ENOSR (-63)
在OUT URB数据传输中,数据不能从系统内存中获取的足够快,以便可以跟上请求的usb的数据速率
-EPIPE (-32)
这个表明usb管道"不通",批量端点可能会设置了halt条件,设置了这种条件的端点必然会堵塞管道,可以使用usb_clear_halt()清除halt
-EOVERFLOW (-75)
当发送给端点的数据包长度大于端点特定的数据包长度时会出现这个错误,从错误码也能看出来,数据“溢出了“
ENODEV (-19)
usb设备已经从系统中移除,但是hub没有及时检测到usb设备的断开,驱动仍然提交URB,就会导致这个错误发生。
Note: -EPROTO、-EILSEQ、-EOVERFLOW一般是由于usb设备、设备固件或usb数据线出问题导致的。
"unlinked"发生下下面的场景下:
(1)驱动中调用 usb_unlink_urb( ) 或 usb_kill_urb( ) 主动取消一个已经提交给usb控制器的URB
调用 usb_unlink_urb( ) 之后,URB的status值为-104(ECONNRESET)
调用 usb_kill_urb( ) 之后,URB的status值为-2(ENOENT)
(2)当URB已经提交给某个usb设备,但该设备被remove了,硬件断开了,比如将模块从主机上拔掉,这种情况下URB的status字段就为-108(ESHUTDOWN)

使用 busybox microcom /dev/ttyUSB2 命令打开模块的AT口(open /dev/ttyUSB2),什么都不输入,然后 ctrl+x 退出 microcom(close /dev/ttyUSB2),相应的usbmon log如下:

可以看到,当主动退出microcom时,相应的URB的status字段值为-2,对应到串口驱动中就是调用了usb_wwan_close()中的usb_kill_urb()

对应的E(submission error)是在回调函数重新提交URB产生的,此时串口已经close,再去提交就产生了错误。
后面URB的status字段为-1(EPERM),这里分析 usb_submit_urb() 的代码,可以看到-1是 usb_submit_urb() 的返回值
usb_submit_urb
return usb_hcd_submit_urb;

同样使用 busybox microcom /dev/ttyUSB2 命令打开模块的AT口,然后此时拔掉EVB板,断开usb设备,对应的usbmon log如下,可以比较和前面的区别:
-108(ESHUTDOWN)是usb物理层断开URB对应的status

下面再看一下模块autosuspend过程中的usbmon log:
echo auto > /sys/bus/usb/devices/3-2.1/power/control 使用模块的autosuspend
ffff8800ba S Ci:3:009:0 s 80 00 0000 0000 0002 2 <
ffff8800ba C Ci:3:009:0 0 2 = 0000
ffff8800b7da3a40 S Ii:3:009:5 -115:256 10 <
ffff8800b7da2180 S Bi:3:009:4 -115 4096 <
ffff8800b7da2240 S Bi:3:009:4 -115 4096 <
ffff8800b7da2f00 S Bi:3:009:4 -115 4096 <
ffff8800b7da2d80 S Bi:3:009:4 -115 4096 <
ffff8800ba S Co:3:009:0 s 21 22 0003 0002 0000 0
ffff8800ba C Co:3:009:0 0 0
ffff8800b7da3a40 C Ii:3:009:5 0:256 10 = a 0 0000
ffff8800b7da3a40 S Ii:3:009:5 -115:256 10 <
ffff8800b7da2180 C Bi:3:009:4 -2 0 // ① 这里等待了2s(2223, - 2220, ),然后进入了autosuspend ② -2是这个URB在suspend函数中被usb_kill_urb()取消了
ffff8800b7da2180 S Bi:3:009:4 -115 4096 <
ffff8800b7da2180 E Bi:3:009:4 -1 0 // 这里和前面出现的原因相同,模块已经进入autosuspend,回调函数中又去提交这个URB
ffff8800b7da2240 C Bi:3:009:4 -2 0
ffff8800b7da2240 S Bi:3:009:4 -115 4096 <
ffff8800b7da2240 E Bi:3:009:4 -1 0
ffff8800b7da2f00 C Bi:3:009:4 -2 0
ffff8800b7da2f00 S Bi:3:009:4 -115 4096 <
ffff8800b7da2f00 E Bi:3:009:4 -1 0
ffff8800b7da2d80 C Bi:3:009:4 -2 0
ffff8800b7da2d80 S Bi:3:009:4 -115 4096 <
ffff8800b7da2d80 E Bi:3:009:4 -1 0
ffff8800b7da3a40 C Ii:3:009:5 -2:256 0
ffff8800ba S Co:3:009:0 s 00 03 0001 0000 0000 0
ffff8800ba C Co:3:009:0 0 0
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.mushiming.com/mjsbk/1401.html