请保留-> 【原文: https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】
在之前的博客中,曾经谈到制作USB HID需要掌握的背景知识。包括USB软件架构、USB描述符和USB命令。前两个已经讨论过了,本篇介绍USB命令。
1 USB命令(USB Device Request)
USB规范定义了设备请求(USB Device Request),以更好地完成USB主机对总线上所有USB设备的统一控制。此设备请求由USB主机发往USB设备,为方便理解USB主机和设备间的主从关系,后续行文中一律称为“USB命令”。
USB命令包括USB标准命令、类命令和厂商命令。这些命令的格式都是相同的,如表1所示。
表1 USB命令的结构
偏移 | 字段 | 长度 | 数值 | 描述 |
---|---|---|---|---|
0 | bmRequesType | 1 | 位图 | D7:数据的传输方向 0=主机->设备 1=设备->主机 D6…5:命令的类型 0=标准命令 1=类命令 2=厂商命令 3=保留 D4…0:接收对象 0=设备 1=接口 2=端点 3=其他 4…31=保留 |
1 | bRequest | 1 | 值 | 命令的序号 |
2 | wValue | 2 | 值 | 根据不同的命令,含义也不同 |
4 | wIndex | 2 | 索引或偏移 | 根据不同的命令,含义不同,主要用于传送索引或者偏移 |
6 | wLength | 2 | 如果有数据阶段,此字段为数据的字节数 |
标准命令是每种USB设备都要支持的,类命令则与USB设备所述类有关,比如USB HID设备有HID类特有的命令,如Get_Report、SetReport等。
2 USB标准命令
USB 1.1的规范中,规定了11种USB标准命令,用来完成各种目的。根据不同的命令,相应的字段含义也有所不同。表2列出了11个USB标准命令的功能。
表2 USB标准命令
命令 | 请求号 | 功能描述 |
---|---|---|
Get_Status | 0x00 | 读取USB设备、接口或者端口的状态 |
Clear_Feature | 0x01 | 清除或禁止USB设备、接口或端点的某些特征 |
Set_Feature | 0x03 | 设置或使能USB设备、接口或端点的某些特征 |
Set_Address | 0x05 | 分配USB设备地址 |
Get_Descriptor | 0x06 | 读取描述符 |
Set_Descriptor | 0x07 | 更新已有的描述符或添加新的描述符 |
Get_Configuration | 0x08 | 读取USB设备的当前配置值 |
Set_Configuration | 0x09 | 为USB设备选择一个合适的配置值 |
Get_Interface | 0x0A | 获得设备接口当前工作的选择设置值 |
Set_Interface | 0x0B | 激活USB设备的某个接口 |
Synch_Frame | 0x0C | 设置并报告端点的同步帧号 |
在USB规范中,对于这些标准的USB命令,所有的USB设备必须都支持,并能够对命令进行响应。如果不需要对命令进行操作,也必须准备一个空的响应。除了这些标准的USB命令,对于不同的类,也有类相关的USB命令。比如人机接口类设备有Set_Report、Get_Report等命令,集线器类设备有GetHubStatus、GetBusState等命令。在开发相应类设备的时候,也需要熟悉这些类本身特有的USB命令。
我所准备的嵌入式示例程序中,主要需要了解的USB标准命令是Get_Descriptor,其余的命令基本是由框架代码生成的,了解有这些处理过程就可以了。下面详细介绍Get_Descriptro命令,其余的命令可以参考USB规范中的描述。
如表3所示,给出了Get_Descriptor命令的结构。
表3 Get_Descriptor命令的结构
偏移 | 字段 | 内容 |
---|---|---|
0 | bmRequesType | 值为10000000B,设备到主机 |
1 | bRequest | GET_DESCRIPTOR,0x06 |
2 | wValue | 描述符的类型和描述符的索引值 |
4 | wIndex | 0或语言标识(LANGID) |
6 | wLength | 描述符的长度 |
Get_Descriptor命令用来获取USB设备的各种描述符,包括设备描述符、配置描述符、接口描述符、端点描述符和字符串描述符。需要获取的描述符类型,由wValue字段给出。wValue由两个字节组成,高字节表示描述符的类型,低字节表示描述符的索引值。
wIndex字段除去获取字符串描述符之外,其他情况下设置为0。获得字符串描述符的过程分为两步:第一次发送命令后获得语言标识;第二次发送命令时,将语言标识赋给wIndex字段,需要获取的字符串描述符的索引值赋给wValue字段,即可获得所需要的字符串。
Get_Descriptor命令中的字段wLength,表示描述符的字节长度,由USB主机指定。当指定wLength比实际的描述符长度小时,USB设备严格按照主机指定的字节长度返回描述符信息;当wLength比实际的描述符长度大时,USB设备值返回描述符长度的信息。比如在访问配置描述符时,USB主机不清楚配置信息的总长,可以将Get_Descriptor命令中的wLength设置为4,得到配置描述符中wTotalLength。然后,重新发送Get_Descriptor命令,此时将wLength设置为wTotalLength的值,从而获得整个配置描述符信息。
3 USB HID的类命令
HID设备除了支持标准的USB命令外,还支持6个HID特定的类命令,如表4所示。
表4 HID的类命令
命令 | 请求号 | 功能描述 |
---|---|---|
Get_Report | 0x01 | USB主机接收HID设备发来的报告 |
Get_Idle | 0x02 | 用于读取HID设备当前空闲速率 |
Get_Protocol | 0x03 | 用于读取HID设备的协议值 |
Set_Report | 0x09 | USB主机向HID设备发送报告 |
Set_Idle | 0x0A | 用于设置HID设备的空闲速率 |
Set_Protocol | 0x0B | 用于设置HID设备的协议值 |
HID的类命令,其数据结构与USB的标准命令类似,而且也是采用控制传输发送的。本章准备的HID示例中,主要用到了Get_Report和Set_Report两个命令,下面介绍这两个命令。
Get_Report命令用于获取HID设备发送来的报告,它主要在HID设备初始化和读取HID报告时使用。此命令是所有HID设备都必须支持的,其结构如表5所示。
表5 Get_Report命令的结构
偏移 | 字段 | 内容 |
---|---|---|
0 | bmRequesType | 值为10100001B,设备到主机 |
1 | bRequest | GET_REPORT,0x01 |
2 | wValue | 报告类型及报告ID |
4 | wIndex | 用于指明支持此命令的接口号码 |
6 | wLength | 报告长度 |
其中,wValue用来指明报告的类型。它由两个字节组成,低字节表示报告ID。高字节值为1时,表示Input报告;值为2时,表示Output报告;值为3时,表示Feature报告。
Set_Report命令用于USB主机向HID设备发送报告数据,它与Get_Report命令类似,只是数据传输的方向不同。Set_Report命令并不是所有HID设备都必须支持的,其结构如表6所示。
表6 Set_Report命令的结构
偏移 | 字段 | 内容 |
---|---|---|
0 | bmRequesType | 值为00100001B,主机到设备 |
1 | bRequest | SET_REPORT,0x09 |
2 | wValue | 报告类型及报告ID |
4 | wIndex | 用于指明支持此命令的接口号码 |
6 | wLength | 报告长度 |
从UEFI开发探索81到本篇,所有关于制作USB HID设备的背景知识,就全部介绍完了。熟练掌握这些知识后,可以在任何一款带USB功能的单片机上,实现我们所需要的HID设备。
下篇将以YIE002-STM32型开发板为例(也即主芯片为STM32F103C8T6的YIE002开发板),实现一个具三种通信方式的USB HID设备。
943 total views, 3 views today