Linux-USB-检测枚举-1 lsusb输出内容详细解读

USB设备检测的一般过程
USB设备检测也是通过/proc目录下的USB文件系统进行的。为了使一个USB设备能够正常工作,必须要现在系统中插入USB桥接器模块。在检测开始时,一般要先检测是否存在/proc/bus/usb目录,若不存在则尝试插入USB桥接模块。

现在一般的USB桥接器模块有两种类型,UHCI和OHCI。在决定插入那一个桥接器模块时,可以察看/proc/pci文件来决定。

打开此文件,您若发现 USB节为 I/O at 0xHHHH格式(例如出现 I/O at 0xe000[0xe01f]),HHHH为16进制数,则桥接器类型为UHCI。

若是它为32 bit memory at 0xHH000000形式(例如出现32 bit memory at0xee000000),HH为16进制数,则桥接器类型为OHCI。

但是若您的桥接器类型不满足上述任何一种情况,唯一的解决办法就是您尝试插入这两种模块,直到成功为止。一般而言,UHCI类型的桥接器它的插入模块是uhci或usb-uhci(由内核版本决定);而对于OHCI类型的桥接器它的插入模块是ohci或usb-ohci。

您在正确的插入了桥接器模块之后,这时/proc文件系统下就会出现USB设备目录,不过这时这个目录是空的,没有任何文件。这时您就必须挂接usbdevfs文件系统,然后通过此文件系统检测连接的设备。

在成功挂接usb文件系统之后,就会生成文件/proc/bus/usb/devices,/proc/bus/usb/drivers和目录/proc/bus/usb/busNo。

挂接usbdevfs文件

您可以通过如下操作实现:
mount -t usbdevfs none /proc/bus/usb
或在/etc/fstab上加入
none /proc/bus/usb usbdevfs defaults 0 0
然后通过/proc/bus/usb/devices文件的内容,您就可以获得连接的设备信息,包括设备标识和制造商标是等信息。

usb设备类型描述:
---------------------
设备规范           设备类码           接口类码 
应用程序特定                          0xFE 
声音接口           0x00               0x01 
通信设备           0x02               
CDC控制接口                         0x02 
CDC数据接口                         0x0A 
HID                   0x00               0x03 
HUB                  0x09               0x09 
批量存储设备       0x00               0x08 
监视器             same asHID        same as HID 
电源设备           same asHID        same as HID 
物理设备                            0x05 
打印机                              0x07 
供应商特定                          0xFF 

5.2 usb文件系统简介
T = 总线拓扑结构(Lev, Prnt, Port, Cnt, 等),是指USB设备和主机之间的连接方式
B = 带宽 (仅用于USB主控制器)
D = 设备描述信息
P = 产品标识信息
S = 串描述符
C = 配置描述信息 (* 表示活动配置)
I = 接口描述信息
E = 终端点描述信息

一般格式:
d = 十进制数
x = 十六进制数
s = 字符串

拓扑信息

T:   Bus=dd Lev=dd Prnt=ddPort=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd
                                                    |__最大子设备
                                            |__设备速度(Mbps)
                                    |__设备编号
                             |__这层的设备数
                      |__此设备的父连接器/端口
              |__父设备号
        |__此总线在拓扑结构中的层次
  |__总线编号
|__拓扑信息标志

带宽信息

B:   Alloc=ddd/ddd us (xx%),#Int=ddd, #Iso=ddd
                                       |__同步请求编号
                             |__中断请求号
  |__分配给此总线的总带宽
|__带宽信息标志

设备描述信息和产品标识信息

D:   Ver=x.xx Cls=xx(s) Sub=xxProt=xx MxPS=dd #Cfgs=dd
P:   Vendor=xxxx ProdID=xxxxRev=xx.xx

D:   Ver=x.xx Cls=xx(sssss)Sub=xx Prot=xx MxPS=dd #Cfgs=dd
                                              |__配置编号
                                       |______缺省终端点的最大包尺寸 
                                                  
                                |__设备协议
                         |__设备子类型
           |__设备类型
  |__设备USB版本
|__设备信息标志编号#1

P:   Vendor=xxxx ProdID=xxxxRev=xx.xx
                           |__产品修订号
              |__产品标识编码
  |__制造商标识编码
|__设备信息标志编号#2

串描述信息

S:   Manufacturer=ssss
  |__设备上读出的制造商信息
|__串描述信息

S:   Product=ssss
  |__设备上读出的产品描述信息,对于USB主控制器此字段为"USB *HCI Root Hub"
|__串描述信息

S:   SerialNumber=ssss
  |__设备上读出的序列号,对于USB主控制器它是一个生成的字符串,表示设备标识
|__串描述信息

配置描述信息

C:   #Ifs=dd Cfg#=dd Atr=xxMPwr=dddmA
                       |__最大电流(mA)
                 |__属性
          |__配置编号
  |__接口数
|__配置信息标志

接口描述信息(可为多个)

I:   If#=dd Alt=dd #EPs=ddCls=xx(sssss) Sub=xx Prot=xx Driver=ssss
                                                  |__驱动名
                                           |__接口协议
                                     |__接口子类
                      |__接口类
               |__中断点数
        |__可变设置编号
  |__接口编号
|__接口信息标志

终端点描述信息

E:   Ad=xx(s) Atr=xx(ssss)MxPS=dddd Ivl=dddms
E:   Ad=xx(s) Atr=xx(ssss)MxPS=dddd Ivl=dddms
                                  |__间隔
                        |__终端点最大包尺寸
           |__属性(终端点类型)
  |__终端点地址(I=In,O=Out)
|__终端点信息标志

举个例子,这是在连接了一个USB键盘时的配置情况。
T: Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh=2
B: Alloc= 41/900 us ( 5%), #Int= 3, #Iso= 0

D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=0000 ProdID=0000 Rev= 0.00
S: Product=USB UHCI Root Hub
S: SerialNumber=e000
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms

T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh=3
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=07e4 ProdID=a961 Rev= 0.01
S: Manufacturer=ALCOR
S: Product=Movado USB Keyboard
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms

T: Bus=01 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=12 MxCh=0
D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8#Cfgs= 1
P: Vendor=07e4 ProdID=a961 Rev= 0.01
S: Manufacturer=ALCOR
S: Product=Movado USB Keyboard
C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr= 0mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=01Driver=hid
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl= 10ms
I: If#= 1 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=00 Prot=00Driver=hid
E: Ad=82(I) Atr=03(Int.) MxPS= 4 Ivl=255ms


它的物理拓扑可用下图来表示:

Linux-USB-检测枚举-1 <wbr> <wbr>lsusb输出内容详细解读


对于Linux下的usb设备而言,T:(总线拓扑)行用于生成连接在hub上的设备的描述信息,I:(接口信息)行可用于决定每个设备所用的驱动程序,C:(配置信息)可用于列出设备使用最大电流。

USB的枚举过程

所谓USB设备与主机是通过检测Vcc上拉电阻的变化来确定是否有设备连接的。在D12内部集成了1.5kΩ的上拉电阻,默认状态下不与Vcc相连,程序运行时可以向D12发送连接命令使1.5kΩ电阻连接到Vcc,这样主机便检测到有设备连接。

它的枚举过程分析如下。

设备连接到总线后,设备从总线获得5V电源,程序首先初始化,端口,然后向D12发出USB连接命令。

主机检测到设备连接

主机向设备发出第一个信号:总线复位。总线复位产生一个中断,并且D12器件在默认地址0处使能,以便在接下来的枚举过程中使用地址0传输命令和数据,同时中断寄存器的总线复位位被置为1。在程序中的表现是,D12向主循环请求中断,进入中断处理程序USB_int_handler(),读取中断寄存器,确定中断的类型,进行相应的处理。

主机使用默认地址0读取设备描述符。

具体过程是:主机向D12发送第一个Setup包,每个Setup包都是8个字节,第一个包Get Descriptor的内容为:8006 00 01 00 00 40 00,数据为16进制表示。其中的40表示返回的数据最大长度为40H字节。此Setup包存储在D12的端点0缓冲区中,并产生一个外部中断。(这时在D12的中断寄存器中保存了中断的类型:端点0的OUT中断,即中断寄存器字节1的值应为0x01)进入中断服务程序后,由于D12端点0的缓冲区只有16个字节,所以单片机就先发送16个字节的设备描述符。

当主机接收到这16个字节的字符后,就认为真正有设备连接了。

地址分配。

主机向D12发送第二个Setup包,这是一个含有指定地址的数据包,其内容一般为:00 05 02 00 00 00 00 00,其中的02就表示主机为设备分配的地址为0x02,在以后的通信里设备就只对0x02地址的信息作出应答。D12收到这个Setup包后同样产生一个中断(端点0的OUT中断),需要注意的是单片机处理这个中断时需要向主机返回一个长度为0的空数据包。

主机从新的地址获取设备描述符。

主机收到设备发来的空的应答数据包后,确认地址分配成功。然后主机向D12发送第三个Setup包,再次要求获取设备描述符。这个Setup包的内容一般是:8006 00 01 00 00 12 00。与上次不同的是,这次要求实际的描述符长度,其中的12(十六进制数)表示要求得到全部18字节的设备描述符。因为每次只能发送16字节,因此程序中要分两次完成此要求。第一次16字节,第二次2字节。

主机读取配置描述符。

成功得到18字节的设备描述符后,主机向D12发送第四个Setup包,要求得到设备的配置描述符。这个Setup包的数据为:8006 00 02 00 00 09 00 。其中的09指定设备返回9字节数据,这正是配置描述符的长度。

读取描述符集合。

成功得到9字节的配置描述符后,主机向D12发送第五个Setup包,要求得到设备的配置描述符、接口描述符、端点描述符的集合。这次Setup包的内容是:8006 00 02 00 00 FF 00 。由于不知道描述符集合的真实长度,因此它要求得到256字节。

到这一步,主机现在应该已经发现新硬件并为新设备安装好驱动程序。对于以上过程,主机是在总线驱动层处理,下面的一步,也是典型枚举过程的最后一步,就需要设备驱动程序来做了。

数值配置

主机得到各种描述符之后,认为设备的信息已经齐全,便对设备进行配置,使设备从地址状态进入配置状态。

主机向D12发送第六个Setup包,其数据为:00 09 01 00 00 00 00 00 。程序中需要调用SetConfiguration()函数处理此事件,允许所有端点进入工作状态。

至此,USB枚举过程结束,设备可以正常使用了。在这个过程中D12指示灯根据通信的状况间歇闪烁。

USB 最主要的的是要理解  USB主机发送命令给设备,设备要对主机的命令进行响应, USB通讯的基本单位为“包”   理解好“包”这个概念是学习USB的关键所在。

包有如下分类: 
分别是令牌包、数据包、握手包和特殊包(其实是由PID决定的)

令牌包:可分为输入包、输出包、设置包和帧起始包(注意这里的输入包是用于设置输入命令的,输出包是用来设置输出命令的,而不是放据数的)其中输入包、输出包和设置包的格式都是一样的:SYNC+PID+ADDR+ENDP+CRC5(五位的校验码) 
帧起始包:SYNC+PID+11位FRAM+CRC5(五位的校验码) 
数据包:分为DATA0包和DATA1包,当USB发送数据的时候,当一次发送的数据长度大于相应端点的容量时,就需要把数据包分为好几个包,分批发送,DATA0包和DATA1包交替发送,即如果第一个数据包是DATA0,那第二个数据包就是DATA1。但也有例外情况,在同步传输中(四类传输类型中之一),所有的数据包都是为DATA0,格式如下: 
SYNC+PID+0~1023字节+CRC16 
握手包:结构最为简单的包,格式如下 
SYNC+PID

下面举几个例子来说明USB的通讯过程: 
1:主机想要向设备传送一串数据。 过程如下: 
(1)   主机向从机发送“令牌包”,令牌包的类型为输出包,表示主机要向从机发送数据了。 
(2)  主机向从机发送完令牌以后,USB处理器件根据发送的令牌,会将中断状态寄存器标志置位,从机CPU通过查询USB处理器件的中断状态寄存器,对主机的令牌包进行响应 
(3)  从机判别出中断类型,于是,准备从主机接收数据。 
(4)   从机准备好了,于是主机开始发送“数据包”这时,USB处理器件会自动将从主发送过来的数据放如它的内部缓冲区内,接收完这个数据包后,从机向主机发送“应答包” 
这就是一个完整的通讯过程。 
由以上可以看出,USB若是想要传送数据,那么主机必须先发一个 IN或OUT的令牌包,然后发送DATA0,或DATA1数据包。 
简单的用现实生活中的事件进行描述: 老板想让员工去做一件事情,老板先会发出命令,告诉要做什么事情,员工准备好以后呢,老板再把做这件事情的经费发放给员工,当员工把发放的经费清点以后,发现数目正确,他会给老板一个回应信息,告诉老板,钱已经收到了,而且数目正确。 
老板想让员工做的事: 对应USB通讯里的令牌包。 
老板想要发放的经费: 对应USB通讯里的数据包。 
员工给老板的回应:   对应USB通讯里的握手包。 
这里尤其需要注意一个问题就是: 
USB主机向设备发送令牌包的时候,接收令牌是有USB器件来完成的,而不是有从机CPU来完成的,如主机发送一个如下的令牌: 
SYNC+PID+ADDR+ENDP+CRC5 
USB器件回根据PID的类型来判断是哪种类型的令牌根据ADDR的值来判断是否是和自己通讯,根据ENDP的值来判断是和哪个端点进行通讯,根据校验来判断,数据传送是否无误。根据以上的令牌包信息,USB器件会将其内部的中断状态寄存器相应的位置位,从机CPU可以查询这个中断状态寄存器来进行相应的操作。



lsusb输出内容详细解读

插入usb鼠标后执行lsusb的输出内容如下:
-----------------------------------------
Bus 005 Device 001: ID 0000:0000
Bus 001 Device 001: ID 0000:0000
Bus 004 Device 001: ID 0000:0000
Bus 003 Device 001: ID 0000:0000
Bus 002 Device 006: ID 15d9:0a37
Bus 002 Device 001: ID 0000:0000

内容解读:
-----------------------------------------
Bus 005
 
    表示第五个usb主控制器(机器上总共有5个usb主控制器 -- 可以通过命令lspci | grep USB查看)

Device 006
      表示系统给usb鼠标分配的设备号(devnum),同时也可以看到该鼠标是插入到了第二个usb主控制器
      006            usb_device.devnum
      /sys/devices/pci0000:00/0000:00:1d.1/usb2/2-2/devnum

ID 15d9:0a37
      表示usb设备的ID(这个ID由芯片制造商设置,可以唯一表示该设备)
      15d9      usb_device_descriptor.idVendor
      0a37      usb_device_descriptor.idProduct
      /sys/devices/pci0000:00/0000:00:1d.1/usb2/2-2/idVendor

Bus 002 Device 006: ID 15d9:0a37
Bus 002 Device 001: ID 0000:0000
      表示002号usb主控制器上接入了两个设备:
      一个是usb根Hub-- 001
      一个是usb鼠标    -- 006
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值