linux下的ehci控制器调试

1 调试方法

linux下的usb ehci控制器的调试方法:
  1. mount -t debugfs debugfs /sys/kernel/debug
  2. cat /sys/kernel/debug/usb/devices
  3. cat /sys/kernel/debug/usb/usbmon/$(bus_num)u
  4. ehci控制器下的async、periodic、registers等字段的解析
步骤1:目的是mount上调试文件系统,这个调试文件系统功能强大,譬如gpio,audio,usb,binder等模块,在这下面都提供了丰富的信息。
步骤2:查看目前usb host controller下,设备的链接情况及usb设备的信息
步骤3:抓特定usb controller下的usb传输包,该部分的详细解析,请查看我的另一篇blog:linux下的usb抓包方法
步骤4: 查看ehci控制器的驱动工作情况,这里重点讨论这条

2 解读


2.1 usbfs

        usbfs文件系统提供当前链接的usb设备的设备信息,usbfs的代码实现,请参考:linux/drivers/usb/core/inode.c。 另外通过usbfs,可以在用户空间实现usb的驱动,即在用户空间发起usb的控制、块传输。接口代码在如下位置:linux/drivers/usb/core/devio.c 下面我将解析下usbfs中的/sys/kernel/debug/usb/devices文件的格式和含义:

2.1.1 Topology Tag

linux下的ehci控制器调试_第1张图片

    通过tag为T的条目,可以知道目前系统的usb设备的链接情况,即设备的拓扑结构图。
Selecting only the "T:" and "I:" lines from output of devices file(for example, by using
"procusb ti"), we have:
T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12   MxCh= 2
T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12   MxCh= 4
I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5  MxCh= 0
I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=mouse
T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12   MxCh= 0
I:  If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial

Physically this looks like (or could be converted to):
linux下的ehci控制器调试_第2张图片

Or, in a more tree-like structure (ports [Connectors] without
connections could be omitted):

PC:  Dev# 1, root hub, 2 ports, 12 Mbps
|_ CN.0:  Dev# 2, hub, 4 ports, 12 Mbps
     |_ CN.0:  Dev #3, mouse, 1.5 Mbps
     |_ CN.1:
     |_ CN.2:  Dev #4, serial, 12 Mbps
     |_ CN.3:
|_ CN.1:

2.1.2 Bandwidth Tag

Bandwidth info:
linux下的ehci控制器调试_第3张图片

    Bandwidth allocation is an approximation of how much of one frame
    (millisecond) is in use.  It reflects only periodic transfers, which
    are the only transfers that reserve bandwidth.  Control and bulk
    transfers use all other bandwidth, including reserved bandwidth that
    is not used for transfers (such as for short packets).

    The percentage is how much of the "reserved" bandwidth is scheduled by
    those transfers.  For a low or full speed bus (loosely, "USB 1.1"),
    90% of the bus bandwidth is reserved.  For a high speed bus (loosely,
    "USB 2.0") 80% is reserved.

2.1.3 Device descriptor andProduct ID Tag

Device descriptor info & Product ID info:
D:  Ver=x.xx Cls=xx(s) Sub=xx Prot=xx MxPS=dd #Cfgs=dd
P:  Vendor=xxxx ProdID=xxxx Rev=xx.xx
linux下的ehci控制器调试_第4张图片
MaxPacketSize of Default Endpoint:即是控制端点的最大包大小

2.1.4 Configuration Tag

Configuration descriptor info:


    USB devices may have multiple configurations, each of which act
    rather differently.  For example, a bus-powered configuration
    might be much less capable than one that is self-powered.  Only
    one device configuration can be active at a time; most devices
    have only one configuration.

    Each configuration consists of one or more interfaces.  Each
    interface serves a distinct "function", which is typically bound
    to a different USB device driver.  One common example is a USB
    speaker with an audio interface for playback, and a HID interface
    for use with software volume control.
    一个设备可能有多个配置,一个配置可能有多个接口,但同一时间,只能有一个配置生效;但同一时间则可以有多个接口生效,对于有多个配置的情况,C后面的*号,标记当前生效的配置

2.1.5 Interface Tag

Interface descriptor info (can be multiple per Config):
linux下的ehci控制器调试_第5张图片

    A given interface may have one or more "alternate" settings.
    For example, default settings may not use more than a small
    amount of periodic bandwidth.  To use significant fractions
    of bus bandwidth, drivers must select a non-default altsetting.

    Only one setting for an interface may be active at a time, and
    only one driver may bind to an interface at a time.  Most devices
    have only one alternate setting per interface.
    一个配置可能包含多个接口,而一个接口则可以包含多个可选的设置,这些可选设置的差异就是占用的同步带宽是不一样的。多个接口可以同时有效,但同一个接口中的多个可选设置中,同一时间只能有一个可选设置有效;I后面的*号表示当前那个设置是生效的。一个接口如果有包含多个设置,默认的设置通常不占用同步带宽,即function不使能时的状态;如果function使能后,则会选择一个非默认设置,根据所需同步带宽的不同。

2.1.6 Endpoint Tag

Endpoint descriptor info (can be multiple per Interface):
linux下的ehci控制器调试_第6张图片

    The interval is nonzero for all periodic (interrupt or isochronous)
    endpoints.  For high speed endpoints the transfer interval may be
    measured in microseconds rather than milliseconds.

    For high speed periodic endpoints, the "MaxPacketSize" reflects
    the per-microframe data transfer size.  For "high bandwidth"
    endpoints, that can reflect two or three packets (for up to
    3KBytes every 125 usec) per endpoint.

    With the Linux-USB stack, periodic bandwidth reservations use the
    transfer intervals and sizes provided by URBs, which can be less
    than those found in endpoint descriptor.

2.1.7 实例分析

    下面以Sonix的usb2.0的camera链接到我们的ehci host controller上为列,来说明这些调试信息的含义。Sonix的camera在linux使用标准的uvc驱动,并且他同时支持两路视频,一路是yuv的,一路是h264的,每一路对应一个接口(interface),每个接口生成一个设备节点,即会有两个设备节点:/dev/video0(输出yuv数据), /dev/video1(输出h264编码数据).
执行步骤2,得到如下信息:

T:  Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=480  MxCh= 0 // Topology,roothub的lev为0,Dev为1。所以这里显示应该是接在roothub的端口0上的设备
D:  Ver= 2.00 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs=  1 //该设备属于复合设置(misc),包含一个配置( #Cfgs=  1),控制端点的最大包长度为64(MxPS=64
P:  Vendor=0c45 ProdID=6366 Rev= 1.00 // VID,PID
S:  Manufacturer=Sonix Technology Co., Ltd.   //String descriptor info
S:  Product=USB 2.0 Camera
S:  SerialNumber=SN0001
C:* #Ifs= 5 Cfg#= 1 Atr=80 MxPwr=500mA              //  “ * ”表示这个是当前生效的配置,且配置标号是1(Cfg#= 1
A:  FirstIf#= 0 IfCount= 3 Cls=0e(video) Sub=03 Prot=00
A:  FirstIf#= 3 IfCount= 2 Cls=01(audio) Sub=00 Prot=00
I:* If#= 0 Alt= 0 #EPs= 1 Cls=0e(video) Sub=01 Prot=00 Driver=uvcvideo  //I后面的*号,表示当前是活跃的接口,接口编号是0,且包含一个端点( #EPs= 1),是视频类接口(Cls=0e),该接口绑定的驱动为:uvcvideo  
E:  Ad=83(I) Atr=03(Int.) MxPS=  16 Ivl=4ms                                                         //这个是interface0下面的中断端点(Atr=03),且是地址为0x3的输入端点Ad=83),该中断端点的最大包长度为16(MxPS=  16),间隔为4ms
I:  If#= 1 Alt= 0 #EPs= 0 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo  //对应接口编号为1的可选设置0( If#= 1 Alt= 0),该设置是默认设置,不包含任何端点
I:  If#= 1 Alt= 1 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo //对应接口编号为1的可选设置1,该设置包含一个端点

E:  Ad=81(I) Atr=05(Isoc) MxPS= 128 Ivl=125us//接口1的设置1包含的一个地址为1的输入端点( Ad=81(I)),且是同步端点(Atr=05),最大包长度为128,间隔为125us,即一个微帧的时间
I:  If#= 1 Alt= 2 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo   //对应接口编号为1的可选设置2
E:  Ad=81(I) Atr=05(Isoc) MxPS= 256 Ivl=125us//各个不同设置之间的差别是同步带宽的不同
I:  If#= 1 Alt= 3 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo    //对应接口编号为1的可选设置3
E:  Ad=81(I) Atr=05(Isoc) MxPS= 800 Ivl=125us
I:* If#= 1 Alt= 4 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo    //对应接口编号为1的可选设置4
E:  Ad=81(I) Atr=05(Isoc) MxPS=1600 Ivl=125us
I:  If#= 1 Alt= 5 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo      //对应接口编号为1的可选设置5
E:  Ad=81(I) Atr=05(Isoc) MxPS=2400 Ivl=125us
I:  If#= 1 Alt= 6 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo       //对应接口编号为1的可选设置6
E:  Ad=81(I) Atr=05(Isoc) MxPS=3072 Ivl=125us    //对于高速同步端点,端点的最大包长度为:3KBytes,即3072Byte(80%的同步带宽)
I:* If#= 2 Alt= 0 #EPs= 0 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo   //对应接口2的设置0( If#= 2 Alt= 0),I后面的*表示,当前设置是生效的设置,不包含任何端点,是默认设置。对应视频类接口(Cls=0e
I:  If#= 2 Alt= 1 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo     //对应接口2的设置1,包含一个端点
E:  Ad=82(I) Atr=05(Isoc) MxPS= 128 Ivl=125us   //接口2的设置1包含一个地址为2的输入端点(Ad=82(I) ),且是同步端点( Atr=05),最大包长度为128,间隔为125us,即每个微帧一次同步传输
I:  If#= 2 Alt= 2 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo    //对应接口2的设置2,包含一个端点
E:  Ad=82(I) Atr=05(Isoc) MxPS= 256 Ivl=125us
I:  If#= 2 Alt= 3 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo    //对应接口2的设置3,包含一个端点
E:  Ad=82(I) Atr=05(Isoc) MxPS= 800 Ivl=125us
I:  If#= 2 Alt= 4 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo    //对应接口2的设置4,包含一个端点
E:  Ad=82(I) Atr=05(Isoc) MxPS=1600 Ivl=125us
I:  If#= 2 Alt= 5 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo    //对应接口2的设置5,包含一个端点
E:  Ad=82(I) Atr=05(Isoc) MxPS=2400 Ivl=125us
I:  If#= 2 Alt= 6 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo    //对应接口2的设置6,包含一个端点
E:  Ad=82(I) Atr=05(Isoc) MxPS=3072 Ivl=125us                                                    //接口2的不同设置之间的唯一不同就是,传输视频帧所占用的同步带宽不同。
I:* If#= 3 Alt= 0 #EPs= 0 Cls=01(audio) Sub=01 Prot=00 Driver=snd-usb-audio
I:* If#= 4 Alt= 0 #EPs= 0 Cls=01(audio) Sub=02 Prot=00 Driver=snd-usb-audio
I:  If#= 4 Alt= 1 #EPs= 1 Cls=01(audio) Sub=02 Prot=00 Driver=snd-usb-audio

E:  Ad=84(I) Atr=05(Isoc) MxPS= 402 Ivl=1ms

    由于这个摄像头能够同时输出两路视频,一个路是yuv,一路是h264,所以可以两个接口同时生效,并且每个接口还都包含了多个可选设置,那为什么需要这么多的可选设置呢?因为我们知道摄像头他可以设置不同的帧率(5fps,30fps等)和分辨率(640*480,1080*1920等),这样不同的帧率和分别率的组合,就会产生不同的带宽需求,所以就会对应不同的可选设置,道理就在这里。

2.2 snapshot of async and periodic shedule

    该部分在usb ehci运行的过程中,提供了对异步调度循环列表和同步调度列表的一个快照(snapshot)的扑捉功能,用以观察ehci的运行状况。该功能不仅可用于调试ehci driver,也可用于理解ehci驱动,和形象的观察它的运行机制。该部分用于调试的代码位置为:drivers\usb\host\ehci-dbg.c文件

2.2.1 periodic schedule snapshot

    我们知道周期调度的数据组织结构是一个循环列表,而表项中链接的都是周期传输,先是分裂同步传输sitd,然后是同步传输(tid),再然后是中断传输(qh,包括分裂中断传输),而对于中断传输,则按他们的poll rate降序排列。
下面先贴sonix camera在实际使用过程中周期列表的快照图,然后再分析格式和字段含义:

/sys/kernel/debug/usb/ehci/0000:00:04.0 # cat periodic 
size = 512  //即为周期调度列表的长度,有如下合法的值(1024,512,256),该周期列表连接了一个间隔为1uframe的同步传输(itd),和一个pollrate为4的中断IN传输
   0:  itd/ffc791e0    // 表项0,只有同步传输,没有安排中断传输
   1:  itd/ffc79140 qh4-0001/c61ccb80 (h2 ep3in [1/0] q1 p16)
   2:  itd/ffc5e960
   3:  itd/ffc5e6e0
   4:  itd/ffc79500
   5:  itd/ffc79460 qh4-0001/c61ccb80
   6:  itd/ffc793c0
   7:  itd/ffc79280
   8:  itd/ffc79780
   9:  itd/ffc796e0 qh4-0001/c61ccb80
  10:  itd/ffc79640
  11:  itd/ffc790a0
  12:  itd/ffc79a00
  13:  itd/ffc79960 qh4-0001/c61ccb80
  14:  itd/ffc798c0
  15:  itd/ffc79320
  16:  itd/ffc79c80
  17:  itd/ffc79be0 qh4-0001/c61ccb80
  18:  itd/ffc79b40
  19:  itd/ffc795a0
  20:  itd/ffc79f00
  21:  itd/ffc79e60 qh4-0001/c61ccb80
  22:  itd/ffc79dc0
  23:  itd/ffc79820
  24:  itd/ffc5f1e0
  25:  itd/ffc5f140 qh4-0001/c61ccb80
  26:  itd/ffc5f0a0
  27:  itd/ffc79aa0
  28:  itd/ffc5f460
  29:  itd/ffc5f3c0 qh4-0001/c61ccb80
  30:  itd/ffc5f320
  31:  itd/ffc79d20
  32:  itd/ffc5f6e0
  33:  itd/ffc5f640 qh4-0001/c61ccb80
  34:  itd/ffc5f5a0
  35:  itd/ffc5f000
  36:  itd/ffc5f960
  37:  itd/ffc5f8c0 qh4-0001/c61ccb80
  38:  itd/ffc5f820
  39:  itd/ffc5f280
  41:  qh4-0001/c61ccb80
  45:  qh4-0001/c61ccb80
...     ... 
469:  qh4-0001/c61ccb80
 473:  qh4-0001/c61ccb80
 477:  qh4-0001/c61ccb80
 481:  qh4-0001/c61ccb80
 485:  qh4-0001/c61ccb80
 488:  itd/ffc5faa0
 489:  itd/ffc5fb40 qh4-0001/c61ccb80 // 在周期表项为第489个frame的时候,连接了一个同步itd传输,一个pollrate 为4的中断IN传输
 490:  itd/ffc5fbe0
 491:  itd/ffc5f780
 492:  itd/ffc5fd20
 493:  itd/ffc5fdc0 qh4-0001/c61ccb80
 494:  itd/ffc5fe60
 495:  itd/ffc5fa00
 496:  itd/ffc5e000
 497:  itd/ffc5e0a0 qh4-0001/c61ccb80
 498:  itd/ffc5e140
 499:  itd/ffc5fc80
 500:  itd/ffc5e280
 501:  itd/ffc5e320 qh4-0001/c61ccb80
 502:  itd/ffc5e3c0
 503:  itd/ffc5ff00
 504:  itd/ffc5e500
 505:  itd/ffc5e5a0 qh4-0001/c61ccb80
 506:  itd/ffc5e640
 507:  itd/ffc5e1e0
 508:  itd/ffc5e780
 509:  itd/ffc5e820 qh4-0001/c61ccb80
 510:  itd/ffc5e8c0
 511:  itd/ffc5e460           // 达到511时,会翻转到周期列表的0表项


    我们从devices文件的输出知道,itd的间隔是一个微帧,即125us,而中断传输是每3个大帧连接一个中断传输。并且同步传输的itd是随客户端的驱动提交urb(submit_urb)到usbcore时,连接到周期列表中的,一个urb可能对应多个itd,一个可能对应一个itd,此列中是对应一个itd(从itd后面跟的urb的地址可以看出),而每次连接itd时,都是从当前周期列表中正在被ehci controller读取的表项的位置往后添加到对应的时隙中去的,所以随着controller读取的当前表项的移动,itd的链接也会被相应的移动,所以是动态的变化的。
    另外需要注意的是,一个itd表示一个同步端点在一个大帧中的传输情况, 所以他包含了8个微帧的传输情况,而对于这个列子,由于同步端点的间隔是125us,所以一个itd中将包含8个transcation,
每个transation对应个一个微帧,即125us内,同步端点需要发起的传输。

    而中断传输的qh则是第一次在submit_int_urb时,就将中断端点对应的qh结构连接到了所有的对应时隙中,此实例中就是会在0到511总计512个表项中,每个3个表项,就连入qh结构。但需要注意的是,尽管第一个中断urb提交时,就将qh连入了所有的对应的时隙中,但如果后面不继续提交中断urb,则就不会有对应的qtd链入到qh的qtd列表中,如果qh中的qtd列表都被controller消耗完了,即使qh还链接在周期列表中,但也不会被执行,也就不会有中断数据会被填冲到urb中,并回传到客户端驱动。

qh4-0001/c61ccb80  的格式为:  qh中断查询间隔 -  uframe-cmask smask / qh结构的地址
(h2ep3in [1/0]q1 p16) 格式: 
 端点速度(h) 设备地址(2) ep端点地址(3) 端点方向(in)[usecs/c_usecs] q编号(1) p最大包长度(16) 
    以上选项针对每个中断端点,只会打印出一次,列如如果qh 1后面还有连接qh 2,并且qh2已经打印过一次了,则后续在qh1后面再出现qh2时,直接打印“...”
    一个qh对应的一个中断端点,同一个表项中的,一个itd表示一个同步端点

2.2.2 async schedule snapshot

    异步调度的数据组织结构是一个qh循环队列,而每个qh下面又有qtd成员连接起来的qtd列表,一个qh表示一个端点 (控制端点或是bulk端点),qh之间通过水平指针连接,组成一个单向循环列表, 而同一个qh下的qtd,通过next qtd pointer
指针连接成列表。 同上,先贴上异步调度列表的快照图,然后再分析格式和字段含义:

/sys/kernel/debug/usb/ehci/0000:00:04.0 # cat async 
qh/c5e5f280 dev4 hs ep2 42002204 40000000 (08000d80* data0 nak0)  //qh结构,对应设备地址4的端点2,“*”表示当前qh是活跃的。
        ffdcb960 in len=0 00001d00 urb da10e300  //qtd结构
        ffdcb5a0 in len=0 00001d00 urb da10e300
        ffdcb2a0 in len=0 00001d00 urb da10e300
        ffdcb900 in len=0 00001d00 urb da10e300
        ffdcb360 in len=0 00001d00 urb da10e300
        ffdcb600 in len=0 00001d00 urb da10e300
        ffdcb720 in len=0 00001d00 urb da10e300
        ffdcba80 in len=0 00001d00 urb da10e300
        ffdcbb40 in len=0 00001d00 urb da10e300  //qtd的数据长度为0,表示controller已经传输完这个qtd包含的数据
        ffdcb4e0 in len=0 00001d00 urb da10e300
        ffdcb1e0 in len=0 00001d00 urb da10e300
        ffdcbc00 in len=0 00001d00 urb da10e300
        ffdcb780 in len=0 00001d00 urb da10e300
        ffdcbc60 in len=0 00001d00 urb da10e300
        ffdcb0c0 in len=0 00001d00 urb da10e300
        ffdcb9c0 in len=0 00001d00 urb da10e300
        ffdcb420 in len=0 00001d00 urb da10e300
        ffdcb6c0 in len=0 00001d00 urb da10e300
        ffdcb3c0 in len=0 00001d00 urb da10e300
        ffdcb300 in len=0 00001d00 urb da10e300
        ffdcba20 in len=0 00001d00 urb da10e300
        ffdcb7e0 in len=0 00001d00 urb da10e300
        ffdcbae0*in len=409610000d80 urb da10e300  //“ * ”当前正在被controller执行的qtd结构
        ffdcb540+in len=409690000d80 urb da10e300 // " + "表示当前qtd的下一个将被执行的qtd
        ffdcb840#in len=4096 10000d80 urb da10e300
        ffdcb180#in len=4096 90000d80 urb da10e300
        ffdcb660#in len=4096 10000d80 urb da10e300  //长度为4096,表该qtd的传输还为被controller处理
        ffdcb240#in len=4096 90000d80 urb da10e300
        ffdcb8a0#in len=4096 10000d80 urb da10e300
        ffdcb480#in len=4096 90008d80 urb da10e300 //8对应hw_token的IOC位,说明qtd完成后,会产生中断。
qh/c5e5fe00 dev4 hs ep1 42002104 40000000 (00008c01  data0 nak4)  //另一个qh结构,对应设备地址4的端点1,方向是输入;

ffdcbae0*inlen=409610000d80urb da10e300  格式含义:  
qtd地址mask(*、+、#、space)令牌包(in,out,setup)传输长度  td->hw_tokenurb urb地址
    qtd的长度不为0,说是待处理的qtd,如果长度为0说明controller已经处理过了,通过td->hw_token的IOC位,我们可以知道在那个qtd传输完成后,会产生中断。以上可以看出,一个urb可以对应多个qtd,
并且只有当一个urb的数据传输完成后,才会产生中断。另外通过td->hw_token的dt位,我们可以看见data toggle位不停的在翻转(1,9,1,9... ... 1,9

qh/c5e5f280    dev4    hs        ep2    42002204     40000000   ( 08000d80  *  data0    nak0 )  格式含义:
qh/qh地址   dev地址  端点速度  ep地址qh->hw->hw_info1 hw_info2  (hw_token  mark(*,#,-,) data0/1表示nak数)

2.2.3 ehci运行状态统计和寄存器现场

/sys/kernel/debug/usb/ehci/0000:00:04.0 # cat registers 
bus pci, device 0000:00:04.0
EHCI Host Controller
EHCI 1.00, rh state suspended
structural params 0x00102203
capability params 0x00006872
status 1008 Halt FLR
command 0010004 (park)=0 ithresh=1 period=512 HALT
intrenable 37 IAA FATAL PCD ERR INT
uframe 1b7d
port:1 status 401885 0  ACK POWER sig=j SUSPEND PE CONNECT
port:2 status 401000 0  ACK POWER sig=se0
port:3 status 401000 0  ACK POWER sig=se0
irq normal 211390 err 49 reclaim 13 (lost 3)
complete 211398 unlink 17

3 参考资料

1  kernel\trunk\Documentation\usb\proc_usb_info.txt
2  kernel3.4.5 source code
3  ehci spec

你可能感兴趣的:(linux,Controlle,EHCI)