USB的描述符详解总结剖析.pdf

上传人:tbuqq 文档编号:4701682 上传时间:2019-11-27 格式:PDF 页数:24 大小:376.37KB
返回 下载 相关 举报
USB的描述符详解总结剖析.pdf_第1页
第1页 / 共24页
亲,该文档总共24页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《USB的描述符详解总结剖析.pdf》由会员分享,可在线阅读,更多相关《USB的描述符详解总结剖析.pdf(24页珍藏版)》请在三一文库上搜索。

1、USB 的描述符与命令请求详解 一、 描述符 1.什么是描述符 所谓描述符,就是用于描述设备特性的具有特定格式排列的一种数据组织结构。 2.描述符的作用 描述符的作用在于设备向主机汇报自己的信息、特征,主机根据这些信息从而加载相应 的驱动程序。 3.描述符的分类 描述符分为三大类:标准描述符、设备类描述符、厂商描述符。 除字符串描述符可选外,任何设备都必须包含剩下的几种标准描述符。 在 USB1.0 中规定了 5 种标准的描述符: 设备描述符 配置描述符 接口描述符 端点描述符 字符串描述符 规定的设备类描述符有:集线器类描述符、人机接口类描述符。 下表是三种描述符的类型值: 表 1 . US

2、B 描述符的类型值 类型描述符描述符值 标准描述符 设备描述符( Device Descriptor) 0x01 配置描述符( Configuration Descriptor)0x02 字符串描述符(String Descriptor)0x03 接口描述符( Interface Descriptor)0x04 端点描述符( EndPoint Descriptor)0x05 (Device Qualifier descriptor) 0x06 (BOS descriptor) 0x0F (Device Capability descriptor) 0x10 端点伴随描述符(Endpoint c

3、ompanion descriptor) 0x30 类描述符 集线器类描述符(Hub Descriptor)0x29 人机接口类描述符(HID )0x21 厂商定义的描述符0xFF 4.使用的几种类 设备类 DeviceClass 下表是设备类值的含义。 表 2. 设备的类别( bDeviceClass) 值(十进制)值(十六进制)说明 0 0x00 使用接口描述符中提供的类 2 0x02 通信类( CDC ) 9 0x09 集线器类 220 0xDC 用于诊断用途的设备类 224 0xEF 混杂类型设备类 255 0xFF 厂商定义的设备类 接口类 InterfaceClass 下表是接口类

4、值的含义。 表 3. USB 协议定义的接口类别(bInterfaceClass) 值(十六进制)类别 0x01 音频类 0x02 通信类( CDC ) 0x03 人机接口类( HID ) 0x05 物理类 0x06 图像类 0x07 打印机类 0x08 大数据存储类 0x09 集线器类 0x0A CDC 数据类 0x0B 智能卡类 0x0D 安全类 0x0E Video 视频设备(摄像头,Class_0e / 接口描述符的字节数大小 BYTE bDescriptorType; / 接口描述符的类型编号 BYTE bInterfaceNumber; / 接口的编号 BYTE bAlternat

5、eSetting; / 可替换的接口描述符编号。实际就是接口的描述符的编号。 BYTE bNumEndpoints; / 该接口使用的端点数,不包括端点0 BYTE bInterfaceClass; / 接口类 BYTE bInterfaceSubClass; / 接口子类 BYTE bInterfaceProtocol; / 接口遵循的协议 BYTE iInterface; / 描述该接口的字符串索引值 INTERFACE_DESCRIPTOR_STRUCT, * pINTERFACE_DESCRIPTOR_STRUCT; 【说明 1:】接口描述符中用到接口编号bInterfaceNumbe

6、r,以区分在同一配置下的不同的接口。同 时还有该接口描述符的索引iInterface,这意味着将为其准备准备一个字符串描述符。 【说明 2:】接口描述符中有一项:可替换的接口描述符编号bAlternateSetting,表示对某一接口 进行描述的描述符编号。虽然,USB设备的配置与配置描述符是一一对应的,即一个配置只能由一个配置 描述来描述它,但一个接口却允许有多种描述符来描述它,尽管接口描述符的编号还是唯一一个。说白了 就是:一个接口有唯一的一个接口编号,但一个接口却可以有多个不同的描述符编号,而这些不同的接口 描述符的编号值就是bAlternateSetting。所以,通过bInterfa

7、ceNumber可以选定一个唯一的接口,然后 再通过 bAlternateSetting选择想要的对该接口的描述。主机通过GetInterface可以获取当前正在使用的 接口及接口描述,通过SetInerface可以选定某接口及其使用的描述符。 端点描述符 端点是设备与主机之间进行数据传输的逻辑接口,除配置使用的端点0 (控制端点,一般一个设备只 有一个控制端点)为双向端口外,其它均为单向。端点描述符描述了数据的传输类型、传输方向、数据包 大小和端点号(也可称为端点地址)等。 每个设备必须要有一个默认的控制型端点,地址为 0 ,它的数据传输为双向,而且没有专门的描述符, 只是在设备描述符中定义

8、了它的最大包长度。主机通过此端点向设备发送命令,获得设备的各种描述符的 信息,并通过它来配置设备。 / 定义标准的端点描述符结构 typedef struct _ENDPOINT_DESCRIPTOR_STRUCT BYTE bLegth; / 端点描述符字节数大小 BYTE bDescriptorType; / 端点描述符类型编号 BYTE bEndpointAddress; / 端点地址及输入输出属性 BYTE bmAttributes; / 端点的传输类型属性 WORD wMaxPacketSize; / 端点收、发的最大包大小 BYTE bInterval; / 对周期性端点的访问间隔

9、 ENDPOINT_DESCRIPTOR_STRUCT, * pENDPOINT_DESCRIPTOR_STRUCT; 【说明 1:】端点的传输类型字节bmAttributes,描述了该端点的传输特性:01bit定义了传输类 型-00=控制传输、 01=同步传输、 10=批量传输、 11=中断传输。 【说明 2:】周期端点的访问周期字节bInterval,定义了该端点被主机的访问周期,此域值对于批 量传输和控制传输毫无意义。对于同步传输,其值必须为1,即 1ms为标准的同步帧周期。对于中断传输, 该值为 1255,即 1ms255ms 。 字符串描述符 字符串描述符是一种可选的USB 标准描述

10、符,描述了如制商、设备名称或序列号等信息。如果一个 设备无字符串描述符, 则其它描述符中与字符串有关的索引值都必须为0。 字符串使用的是Unicode编码。 字符串描述符是用字符的形式描述设备、配置、接口、端点等信息。 字符串描述符以一种格式2 类符值的方式存在: 1. 显示语言的字符串描述符-该字符串描述符表明了设备支持哪几种语言。 2. 显示信息的字符串描述符-用于描述具体的信息。 标准的字符串描述符的格式为: 表 9. 字符串描述符 偏移量域大小值描述 0 bLength 1 数字此描述表的字节数(bString 域的数值 N2) 1 bDescriptorType 1 常量描述符类型

11、(此处应为0x03 ) 2N Strings N 数字字符串 显示语言的字符串描述符与显示信息的字符串描述符的区别在于Strings项的不同, 对于显示语言的 字符串描述符来说Strings项由多个 wLANGIDn数组元素组成,每个wLANGIDn是一个双字节的代 表语言的 ID 值。而对于显示信息的字符串描述符而言,Strings则是描述信息后的一组UNICODE编码。 为什么会出现这两种情况,原因在于访问字符串描述符的过程,主机请求访问某个字符串描述符的步 骤分成两步: 第一步:获取语言信息-首先主机向设备发送标准请求命令Get_Descriptor,其参数 为:描述符类型 = 字符串描

12、述符,字符串的索引值=0 ,语言 =0 ,这样设备将返回显示语言的字符串描述 符,从而主机知道了设备能支持哪些语言。 第二步:主机根据自已需要的语言,再次向设备发出标准请求命令Get_Descriptor,其参数为:描 述符类型 = 字符串描述符,字符串索引值= 目标字符串索引值,语言= 目标语言。这次设备将返回目标已经 明确的显示信息的字符串描述符。 【说明 1:】只有字符串描述符的长度不是固定的,其长度为N+2 ,其中 N 代表 Strings项的字节 数, 2 代表字符串描述符的bLength、bDescritorType所占的两个字节。 设备类描述符之HID 描述符 在 USB 协议中

13、, HID 设备的描述符没有划作为标准的描述符,而是作为一类设备单独划分出来进行 描述,以设备类的方式来描述它。所以,描述它的格式用设备类描述符。 HID 设备的信息在设备描述符和配置描述符中都不包含,而是包含在接口描述符中,所以在使用HID 设备时,其设备描述符中的相关项应定义如下: bDeviceClass=0; bDeviceSubClass=0; bDeviceProtocol=0; 其接口描述符应该: bInterfaceClass=0x03 另外,对无引导的HID 设备,其接口描述符中子类代码bInterfaceSubClass 应置 0,此时 bInterfaceProtocol

14、 无效,置零即可。即为: bInterfaceClass=0x03 bInterfaceSubClass=0 bInterfaceProtocol=0 对支持引导的USB 设备,其接口描述符中子类代码bInterfaceSubClass 应置 1,此时 bInterfaceProtocol 可以 为 1 或 2,1 表示键盘接口, 3 表示鼠标接口。其参考设置如下: bInterfaceClass=0x03 bInterfaceSubClass=1 bInterfaceProtocol=1 或 2 下面是 HID 设备类描述符: 【说明 1: 】HID 设备类描述符并不是说仅用这一个描述符就可

15、描述清楚这类设备,而是指HID 设备 除包含所有的标准描述符外,还需这个HID 设备来补充描述。也就是说,在使用一般的设备时,只需使用 标准的描述符就可描述清楚,而若使用 HID 设备时, 除了要使用全部的标准的描述符外还需HID 描述符来 补充描述。同时,从HID 描述符中看出,它还将引出HID 的报告描述符,在此不讲述。可以这么说,设备 类描述符是作为一个对标准描述进行补充描述的描述符。 6.描述符的编号及索引 1. 一个 USB 设备只能拥有一个设备描述符,故设备描述符不需要编号。但设备描述符通常会提供设 备最基本的文字描述信息,通常包含厂商、设备、产品的信息,故它拥有3 个字符串描述符

16、的索引,这3 个索引将指向3 个字符串描述,分别描述厂商信息、产品信息、设备序列号信息。简言之,设备描述符指 示了设备有几种配置,及厂商、产品、设备序列号的字符串描述符索引。 2. 配置描述符提供了相应的配置参数和查找参数:配置描述符编号bCongfigurationValue、配置 描述符的字符串描述符的索引。 3. 接口描述提供了该接口的应用参数和查找参数:接口编号bInterfaceNumber、接口描述符编号 bAlternateSetting、该接口描述符对应的字符串描述符的索引。 4. 字符串描述符是对各描述符所需的字符信息描述的实现,每个描述符所需的字符信息描述的索 引都将对应一

17、个字符串描述符。但通常都不那么做,而是把所有的字符描述的实现都写在一个总的字符串 描述符中,即字符串描述符的bStrings 项,它们之间用索引来区分。 7.描述符的获取 获取描述符的命令格式 命令码 CmdCode = GetDescriptor , 格式如下: bmRequestType bRequest wValue wIndex wLength 0x80 0x60 类型和索引0 或语言 ID 描述符长度 wValue- 其高字节 wValue_H 指明要获取的描述符类型(实际只有3 种类型:设备描述符类型、配置 描述符类型、 字符串描述符类型) , 低字节 wValue_L 指明目标描

18、述符的索引,然而 wValue_L 的值只对配置描述符和字符串描述符有效,而对设备描述符无效。 wIndex- 只对字符串描述符有意义,对其它描述符时该值为0.。当然对于字符串描述符时,其值也 可为 0,表示要获取“显示语言的字符串描述符”,若为其它值则代表了确定的语言ID, 即表明要获取指定了语言的“显示信息的字符串描述符”。 wLength- 主机要求的返回的描述符长度。如果wLength 大于实际的描述符长度,则以实际描述符长度 为准;如果wLength 小于实际描述符长度,则以wLength 值为准。 获取描述符的过程 获取描述符属于枚举的过程,其整个过程当然必经Setup 传输的 3

19、 大过程: Setup 过程、数据过程、 状 态信息过程。 首先,在 Setup过程中,主机发送GetDescriptor 命令。若成功,设备就开始准备数据,通信将继续向 前推进,进入数据过程。 然后,在数据过程中,主机启动IN 事件,设备就把准备好的数据(描述符)发送出去。若成功,则 通信继续向前推进,进入状态信息过程。 最后,在状态信息过程,主机发送通信过程的信息状态,祝贺并告知通信完美结束。 获取配置描述符 对于主机来说,配置是广义的,包括狭义的配置、接口配置、端点配置等,而接口配置、端点配置等 都隶属于标准配置描述符,故主机若要求获取配置描述符时,实际上是要求获取除设备描述符和字符串描

20、 述符以外的所有描述符。 对于只有标准描述符的设备而言,当主机要求或者配置描述符时,需设备按照顺序把标准配置描述符、 标准接口描述符、标准端点描述符一次性发给主机。 所以,通常在写程序时,会将广义上的“配置”打成一个包,在包中,由标准配置描述符引领,按照 发送顺序依次实现标准接口描述符、标准端点描述符等。这样做的理由是,在标准配置描述符中有一项 wTotalLength,它代表广义上的配置包描述符总长度,根据这个参数就可把广义的配置包描述符一起发 给主机,以避免多个描述符时的多次传输。 bmRequestType bRequest wValue wIndex wLength 0x80 0x60

21、 类型和索引0 或语言 ID 描述符长度 wValue _H = 配置描述符类型。 wValue _L = 配置描述符编号(索引 ),实际为 bCongfigurationValue值。 wIndex = 0 。 wLength ,其值由主机自己规定。 因为,是按确定的顺序发送的,故主机解析的结果也将一一对应。 下面是一个广义配置包描述符的结构模板: uint8_t USB_ConfigDescriptor = 标准配置描述符的实现; 标准接口描述符的实现; 标准设备类描述符的实现; 标准端点描述符的实现; ; 获取字符串描述符 从设备描述符到端点描述符,需要许多的信息描述,即需要许多字符串描

22、述符来描述它们的信息。然 而,标准字符串中没有总长度显示项wTotalLength,且每个字符串描述符的格式都一样,所以不可能向 获取配置描述符那样,用广义的配置包描述符一起发给主机,况且有些字符串描述符不是必须的,所以很 难做到统一的格式。 不过,为了方便管理,在编程时通常还是把所有的字符串描述符组织在一起,不过主机在访问它们时 只能一个一个的访问,而不能打包访问,它们之间的选取是依赖各个字符串描述符的长度进行跳过操作来 实现的。所以这种组织在一起,只是为了方便管理或好看,而没有其它任何作用,组织的形式通常以“显 示语言的字符串描述符”领头,模板如下: uint8_t USB_StringD

23、escriptor = 显示语言的标准字符串描述符; 显示信息的标准字符串描述符1 ; 显示信息的标准字符串描述符n ; ; 在字符串描述符组织中,各个字符串是怎么区分的?是应用程序,因为这个组织是编写应用程序时自 己规定内部秩序的,故组织中各个字符串描述符对应的索引,程序员当然知道。 bmRequestType bRequest wValue wIndex wLength 0x80 0x60 类型和索引0 或语言 ID 描述符长度 wValue _H = 字符串描述符类型。 wValue _L = 字符串描述符对应的编号(索引)。 wIndex = 0 或 ID 。 wLength ,其值由

24、主机自己规定。 在获取字符串描述符的第一步:获取设备所支持的语言中,wValue _L = 0 ,wIndex = 0 ,设备将把显示 语言的标准字符串描述符发给主机,主机会从中挑选一种语言。 在获取字符串描述符的第二步:获取显示信息的字符串描述符中,wValue _L = 目标字符串对应的编号, wIndex=语言 ID,设备则把确定的字符串描述符发给主机。 二、 标准命令 usb 协议分析 - 设备描述符配置包 -描述 符 /* usb 协议分析仅供大家参考 - 设备描述符配置包,设备描述符,地址设置, 配置描述符,字符串描述符 */ /* -1- usb设备描述符配置包 */ typed

25、ef struct _USB_SETUP_PACKET REQUEST_TYPE bmRequestType; BYTE bRequest; WORD_BYTE wValue; WORD_BYTE wIndex; WORD wLength; USB_SETUP_PACKET; 1.bmRequestType 是包含有下面几方面的内容: D7 D6 D5 D4 D3 D2 D1 D0 在这一个字节里,又按位分为: D7位是表示后面传送数据的方向位。 当 D7等于 0 时,表示后面的数据是从主控器发送到USB 设备。在 PC里,就是从 PC机发送到 USB 的设备。 当 D7等于 1 时,表示后面

26、的数据是从USB 设备发送到主控器。 在 PC里,就是从 USB设备发送到 USB 设备。 在上次里,我收到并显示出来的数据是80,就表示从 USB设备里发送数据给PC 。 在这里再次给出上一次的包数据: 80 06 00 01 00 00 40 00 这里的 80,就是 D7位为 1。 D6-D5位是请求主分类型 0 是表示标准的请求。 1 是表示类别的请求。 2 是表示厂商的请求。 3 是保留。 D4-D0位是表求接收这个包的接口。 0 是表示 USB设备接收。 1 是表示接口接收。 2 是表示端点接收。 3 是表示其它接收,不知道的。 4-31 是保留。 2.bRequest 是本描述符

27、的请求类型,也就是后面发送的数据是什么样的东西。 由于 USB里有很多配置信息, 比如获取设备描述符, 又有设置 USB地址等等, 就 是通过这个字节来区分的。 从 USB协议里查找表 9- 4,就可看到如下的编码: GET_STATUS 0 CLEAR_FEATURE 1 Reserved for future use 2 SET_FEATURE 3 Reserved for future use 4 SET_ADDRESS 5 GET_DESCRIPTOR 6 SET_DESCRIPTOR 7 GET_CONFIGURATION 8 SET_CONFIGURATION 9 GET_INTE

28、RFACE 10 SET_INTERFACE 11 SYNCH_FRAME 12 在上面的数据包里,看到它的内容是06,那么它就是 GET_DESCRIPTOR类型。也 就是主控器想读取USB设备的描述符, 到这里就已经分析出来的意思, 就是主控器想读取USB 描述符,但还不知道是什 么描述符的内容。 3.wValue 是根据不同的请求而设置不同的值。一般就是传送参数给设备标明这 是什么请求。在上面GET_DESCRIPTOR获取设备描述符里,它的值是00 01。 在 GET_DESCRIPTOR里这个字段的低字节表示描述符的索引,高字节表示描述符 的类型。高字节的类型如下: DEVICE 1

29、 CONFIGURATION 2 STRING 3 INTERFACE 4 ENDPOINT 5 DEVICE_QUALIFIER 6 OTHER_SPEED_CONFIGURATION 7 INTERFACE_POWER1 8 wValue 值在这里的高字节是01,那么它就是设备描述符了。低字节是00,那么 它就是表示从偏移地址0 开始读取设备描述符。 由于在配置描述符里有很多配置, 所以低字节在那里就可以用来识别获取同样类 型的描述符不同的配置。 4.wIndex 是根据不同的请求而设置不同的值。一般用来说明端点号或者说明接 口标识。在获取描述符里,设置为0,或者是语言 ID。 在这个发送

30、的描述符里,它是设置为00 00。 5.wLength 是根据请求来决定下一阶段发送数据的长度。前面请求第一个字节 里,已经说明下一阶段数据传送的方向, 这里说明了传送数据的长度。 不管是发送数据, 还是接收数据, 都不要超过这个 数据长度,否则主机会出问题,或者设备有问题。 在这个获取设备描述里,它的长度是40 00,按小端格式去解释,就是64 个字 节。 到这里,就把主控器发下来的数据解释完成了,知道去做什么的事情和回应。下 一次就去分析怎么样返回设备描述符。 /* - - */ /* -2- 回应设备描述符 */ 上一次已经介绍怎么样收到主控器的获取设备描述符的数据,这里就解释怎么样 发

31、送回应数据给主控器。 先从 USB协议里找到标准设备的定义,我把它用C语言定义如下: typedef struct _USB_DEVICE_DESCRIPTOR BYTE bLength; BYTE bDescriptorType; WORD bcdUSB; BYTE bDeviceClass; BYTE bDeviceSubClass; BYTE bDeviceProtocol; BYTE bMaxPacketSize0; WORD idVendor; WORD idProduct; WORD bcdDevice; BYTE iManufacturer; BYTE iProduct; BYT

32、E iSerialNumber; BYTE bNumConfigurations; USB_DEVICE_DESCRIPTOR; 返回给主控器的数据结构就是上面的内容,只要把上面的结构填写合适的内容, 就可以发送回去给主控器。 在我的 USB设备里,我把它填写如下的数据: 12 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 01 看到这串数据是不明白是什么东西的,现在就来仔细地分析它的具体定义。下面 就按着一个字段一个字段地分析它。 bLength 是本结构的数据长度,这样可以方便以后兼容不同的版本协议。因为不 同的结构是不同的长度,这样就可以

33、区分不同的协议了。 比如有一天想添加一个字段, 那么它的长度就会改变, 这时就可以根据不同的长 度进行解释不同的协议了。 这次返回的结构长度是0x12,也就是 18 个字节,它的长度是从bLength 长度开 始,也就是说是完全整个结构的长度。 bDescriptorType是描述符的类型。 它的定义跟主控器发下来描述符的类型是一 样的,如下: DEVICE 1 CONFIGURATION 2 STRING 3 INTERFACE 4 ENDPOINT 5 DEVICE_QUALIFIER 6 OTHER_SPEED_CONFIGURATION 7 INTERFACE_POWER1 8 由于返

34、回的是设备描述符,所以就选择了1,也就是包里显示的第二个字节01。 用这个类型来区分不同的描述符。 bcdUSB是 USB 发布的协议版本。也就是本设备能适用于那种协议,目前USB 主 要有两个版本,一个是1. 10,一个是 2.10 版本。 在本设备里,采用了 1.10 的协议版本。由于这个字段是采用BCD编码, 所以 1.10 的表示为 0x0110 的格式,按小端格式输出来,就变成10 01 的显示了。 bDeviceClass 是设备分类。当它的值是0 时,表示所有接口在配置描述符里, 并且所有接口是独立的。 当它的值是 1 到 FEH时,表示不同的接口关联的。 当它的值是 FFH时,

35、它是厂商 自己定义的。在这个设备里,是定义为0。 bDeviceSubClass 是设备子分类码。当前面的bDeviceClass 值是 0 时,这里一 定要设置为 0。其它就跟据 USB-IF组织定义的编码。 bDeviceProtocol是设备使用的协议。如果使用USB-IF组织定义的协议,就需 要设置这里的值。如果不使用,就直接设置为0。 如果厂商自己定义的可以设置为FFH 。 以上三个值,在本设备里全部设置为0。 bMaxPacketSize0 是端点 0 收发最大的包大小。仅允许设置8,16,32,64 中的 任何一个大小。在本设备里是设置为64 个字节大小。所以看到这个字段是40

36、的 大小。 12 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 01 idVendor 是厂商标识。由 USB-IF 分配的编码。在这里使用0x8000。 idProduct是厂商定义的产品标识。由厂家和产品标识,就可以让操作系统加载 不同的驱动程序。如下: 12 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 01 bcdDevice 是用 BCD 表示的设备发布的版本号。这里是1. 00。 12 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 0

37、1 iManufacturer是厂商字符串的偏移值。 这值主要说明了它在字符串描述符里的 偏移位置。如果它设置为0,表示没有厂商字符串。在 这里是 0x04,就是从字符串描述符开始位置算起第4 个字节位置读取字符串。 iProduct是产品字符串的偏移值。这值主要说明了它在字符串描述符里的偏移 位置。如果它设置为0,表示没有产品字符串。 在这里是 0x2C , 就是从字符串描述符开始位置算起第2C个字节位置读取字符串。 iSerialNumber是序列号字符串的偏移值。 这值主要说明了它在字符串描述符里 的偏移位置。如果它设置为0,表示没有序列号字符串。 在这里是 0x4A, 就是从字符串描述

38、符开始位置算起第4A个字节位置读取字符串。 所有字符串,都是采有UNICODE 编码。 bNumConfigurations 是配置描述符的个数。在这里只使用了一个配置,所以设 置为 1。 /* - - */ /* -3- 设置 USB地址 */ 前面已经解释主控器怎么样发送设备描述符下来,然后设备返回相应的设备描述 符。下一步主控器的动作是做什么呢? 由于在 USB总线上的设备有很多, 为了区分不同的设备通讯, 就需要给每个设备 分配一个地址,这跟网络中的IP 地址是一样的,或者跟MAC 地址也是一样的。 因而,接着下来就是主控器分配地址给设备,USB的设备地址是从 1 开始到 127。 下

39、面就是接收到主控器发下来的数据包: 00 05 01 00 00 00 00 00 由 USB_SETUP_PACKET定义具体地分析这个数据,就可以知道应做什么样的响应 了。下面就来解释这个操作。 先取得 bmRequestType的类型,也就是第一个字节,它是00。从 USB 协议里查 看,它的方向位是主控器发送给设备, 由 D6D5位就知道它是 USB协议里定义的标准请求,由D4-D0位知道它是 USB设 备接收这个包数据。 bRequest 是 05,从前面已经介绍的类型,就知道它是设置地址,如下: SET_ADDRESS 5 所以这个包需要按设置地址的格式去解释后面的数据。 由于 U

40、SB协议可以知道,USB的设备地址放在字段wValue里,因它的值是 01 00, 按小端格式解释就是0x0001 了。 其它相应的字段 wIndex 和 wLength 应都是 0,如果是其它非 0 的数据,是没有 定义的。 USB的串行引擎通过这个地址来判断是否接收总线上的数据,如果发送的地址跟 它一致,就会接收主控器发过来的数据, 当然从这个设备发送出去的数据也带有这个地址,因此就可以让主控器识别不同 的 USB设备数据了。 /* - - */ /* -4- 配置描述符 */ 前面已经介绍设置USB的设备地址,接着下来是做什么呢?其实有了设备地址 后,主控器还会再次发送获取上面已经读取的

41、设备描述符下来,如下: 80 06 00 01 00 00 12 00 然后 USB设备也再次回应它,但这次发送的长度是0x0012 了,不再是第一次 64 个字节长度了。 接着 USB设备就返回下面的描述符给主控器, 也就是第一次已经发送的设备描述 符,如下: 12 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 01 这样分配地址之后, 再次获取设备描述符成功了, 接着下来就是主控器获取配置 描述符。下面就是收到的配置描述符数据: 80 06 00 02 00 00 09 00 分析上面的数据如下: bmRequestType是 80,表示方

42、向 USB设备发送给主控器,接收设备是USB设备。 bRequest 是 06,表示这是获取描述符。 GET_DESCRIPTOR 6 wValue 是 00 02。低字节表示偏移地址00,高字节表示描述符的类型。如下: CONFIGURATION 2 所以这里的返回的设备描述符是配置描述符。 wIndex 是 00 00。 wLength 是 09 00。它表示返回描述符的长度。这里是9 个字节。 接着下来,就是设备返回配置描述符给主控器,发送的数据如下: 09 02 22 00 01 01 00 01 32 发送的数据是按下面的结构来定义,这也是在USB协议里定义的格式。如下: typed

43、ef struct _USB_CONFIGURATION_DESCRIPTOR BYTE bLength; BYTE bDescriptorType; WORD wTotalLength; BYTE bNumInterfaces; BYTE bConfigurationValue; BYTE iConfiguration; BYTE bmAttributes; BYTE MaxPower; USB_CONFIGURATION_DESCRIPTOR; bLength 是配置的长度,也就是配置结构的整个长度。在这里9 个字节。 bDescriptorType是描述符的类型,这里配置描述符,所以设置

44、为02。 wTotalLength 是所有配置设置的结构长度。包括配置描述符、接口描述符、HID 或者其它描述符和端点描述符的长度。这里是22 00,也就是 0x0022个字节。 bNumInterfaces 是接口个数,这里一个。 bConfigurationValue是配置的个数,当设置配置时发送的值。这时设置为1 个 配置。 iConfiguration是说明配置的字符的偏移值。这里是0。 bmAttributes是配置特性, D7位保留。D6位是说明是否自供电。 D5位是否支持 远程唤醒。 D4 D0是保留,设置为0。 MaxPower是使用的功率,它采用电流来表示。每2mA 为单位,

45、比如它的值是50 时就表示是 100mA的电流消耗。 通过这样说明,主控器就知道这个设备是什么样的设备,有多少功能。 /* - - */ /* -5- 字符串描述符 */ 上一次说到把配置描述符返回给主控器那里了,现在接着下来, 就会收到主控器 发来字符串描述符。如果在设备描述符那里指定没有字符串描述的话, 在这里是不会收到字符串描述符的。 由于我在设备描述符里指定有字符串描述符 的偏移地址,因此,就收到主控器发出请求字符串描述符。收到的数据如下: 80 06 00 03 00 00 FF 00 bmRequestType是 80,表示方向 USB设备发送给主控器,接收设备是USB设备。 bR

46、equest 是 06,表示这是获取描述符。 GET_DESCRIPTOR 6 wValue 是 00 03。低字节表示偏移地址00,高字节表示描述符的类型,如下: STRING 3 wIndex 是 00 00。 wLength 是 FF 00。它表示返回描述符的长度。这里是256 个字节。 因此,这个获取字符串描述符,就是从字符串描述内存里,0 偏移地址开始的位 置读取第一个字符串描述符返回给主控器。接着就返回下面的数据给主控器: 04 03 09 04 上面的数据是按字符串描述符来组织的,它的结构,我定义结构如下: typedef struct _USB_STRING_DESCRIPTO

47、R BYTE bLength; BYTE bDescriptorType; WORD bString/*/; USB_STRING_DESCRIPTOR; bLength 是所有数据的长度。在这里是4。 bDescriptorType是描述类型,这里字符串描述符,所以它是3。 bString是可变的字符数组。不超过254 个应都可以的,并且它是使用UNICODE 编码的字符串。 在这里是 09 04,这是美国英语的标识, 0x0409。如果想输入中文的标识,只要 改为 0x0804 就可以了。 通过这个字符串描述符,主控器就知道字符串描述符是使用什么语言说明的了, 这样就可以支持全世界的语言标识。 USB 描述符【整理】 USB 描述符 USB 描述符信息存储在USB 设备中,在枚举过程中,USB 主机会向 USB 设备发送 GetDescriptor 请 求, USB 设备在收到这个请求之后,会将USB 描述符信息返回给USB 主机, USB 主机分析返回来的数据,判 断出该设备是哪一种USB 设备,建立

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1