(请保留-> 作者: 罗冰 https://blog.csdn.net/luobing4365)

YIE002USB开发板之制作HID设备-USB标准描述符

  • 1 USB描述符概述
  • 2 USB标准描述符
    • 2.1 设备描述符
    • 2.2 配置描述符
    • 2.3 接口描述符
    • 2.4 端点描述符
    • 2.5 字符串描述符

从软件的角度,制作USB HID设备,需要理解的知识包括几大块:
1) USB协议的基本架构和软件架构;
2) USB描述符,包括标准描述符和类描述符;
3) USB命令,包括标准命令和类命令。

当然,如果能从字节序上(比如USB包的构成)了解USB通信的过程,对理解整个USB协议的构成也很有好处。但在编程中,不需要理解到这个地步。大部分介绍USB协议的书籍,以及USB规范中,都很详细地描述了这些过程,非常建议读一读。

在前一篇中,已经简要地概述了USB协议的基本架构和软件架构。本篇主要介绍USB描述符中的标准描述符,这是所有USB设备都要支持的描述符。

1 USB描述符概述

为了方便USB主机对USB设备进行管理,USB-IF对USB设备的功能采用了分层结构,包括设备层、配置层、接口层和端点层。图1给出了一个复合设备的例子,展示了USB设备的分层结构。

图1 USB设备的功能分层结构

这四层的作用分别为:

  1. 设备层。说明USB设备的主要类型特征(如设备类别、接口、端点等属性),保障设备枚举过程的正常进行。
  2. 配置层。选择不同的失败配置满足USB主机对设备功能的选择,可选择复式的设备接口功能,如图1展示的选择鼠标、键盘和游戏杆的复合功能。
  3. 接口层。将具体功能分类,不同的功能对用不同的操作方式。
  4. 端点层。针对特定的设备功能,选择不同的端点,提供不同的数据管道,与USB主机进行数据通讯。

为了描述USB设备的这些特征,USB规范定义了相应结构的描述符,包括设备描述符、配置描述符、接口描述符、端点描述符和字符串描述符等。表1给出了USB1.1下各种USB描述符的类型值。

表1 USB1.1的描述符类型值

类型 描述符 描述符值
标准描述符 设备描述符(Device Descriptor) 0x01
配置描述符(Configuration Descriptor) 0x02
字符串描述符(String Descriptor) 0x03
接口描述符(Interface Descriptor) 0x04
端点描述符(Endpoint Descriptor) 0x05
类描述符 集线器类描述符(hub descriptor) 0x29
人机接口类描述符(HID) 0x21
厂商自定义 0xFF

其他版本的USB规范,还定义了其他类型的描述符,比如USB 2.0中的设备限定描述符(Device_Qualifier)、USB 3.2中的二进制设备对象存储描述符(Binary Device Object Store,简称BOS)等。这些内容在博客中不会涉及,可在USB-IF的官网下载相关的USB规范文档了解。

下面对标准描述符进行详细介绍。

2 USB标准描述符

不管哪种USB设备,都必须提供标准描述符,用于告知主机设备本身的属性。以下介绍的内容,会比较枯燥,建议使用Bus Hound或USB逻辑分析仪等工具,去抓取USB设备的识别和通信包,实际体会这些描述符的用法。

如图2,抓取的是自制的USB HID设备信息。设备描述符中,含有自定义的厂商ID和产品ID,分别为0x8765和0x4321。

图2 BUS Hound抓取USB包

USB主机会发送USB命令给USB设备,图2中的GET_DESCRIPTOR是常用的获取描述符命令。USB设备根据命令所要求的,给出对应的描述符。本篇主要讲述描述符的结构,USB命令将在后续的博客中讲述。

2.1 设备描述符

USB的设备描述符用于表示USB设备的一般信息,如制造商ID、产品序列号等。一个USB设备有且只有一个设备描述符,它是USB主机所读取的第一个描述符,其结构如表2所示。

表2 设备描述符的结构

偏移 大小 描述
0 bLength 1 数字 描述符字节数长度(0x12)
1 bDescriptor 1 常量 描述符的类型(0x01)
2 bcdUSB 2 BCD码 USB设备支持的协议版本号
4 bDeviceClass 1 设备类代码
5 bDeviceSubClass 1 子类 子类代码,更加bDeviceClass来定
6 bDevicePortocol 1 协议 协议码
7 bMaxPacketSize0 1 数字 端点0的最大包长度
8 idVendor 2 ID 厂商ID(由USB-IF赋值)
10 idProduct 2 ID 产品ID(由厂商赋值)
12 bcdDevice 2 BCD码 设备发行号(BCD码)
14 iManufacturer 1 索引 厂商信息的字符串描述符索引值
15 iProduct 1 索引 产品信息的字符串描述符索引值
16 iSerialNumber 1 索引 设备序列号信息的字符串描述符索引值
17 bNumConfigurations 1 数字 配置描述符数目

设备描述符结构中的bMaxPacketSize0,它用来告知USB主机设备所支持的最大数据长度。

bDeviceClass表示设备所述的类别,如果此值为0,则表示每一个配置中的每个接口来指明它所属的类别(即在接口描述符中给出设备类),并且各接口独立工作。如果此值为0xFF,则由供应商自定义该设备类。介于两者之间的值0x1~0xFE,表示USB规范中定义的某个设备类,比如0x03表示HID设备类。它和bDeviceSubClass、bDeviceProtocol共同规定了设备的类别和采用的协议,更具体的分类定义,可以参考USB-IF官网。

设备描述符中的iManufacturer、iProduct和iSerialNumber,使用字符串描述符的索引值来进行描述,索引值为0表示没有字符串描述符对其进行描述。通过此索引值和USB命令Get_Descriptor,可以得到对应的字符串描述符。

2.2 配置描述符

USB规范中,USB设备可以有一个或者多个配置描述符,每个配置描述符提供了设备特定的配置。在设备描述符中的bNumConfigurations提供了配置描述符的个数,任何时刻只有一种配置处于工作状态。

配置描述符中提供了在该配置下设备的接口数目,一个设备的不同配置描述符可能包含不同数目和特性的设备接口。图1中的设备配置1,就包含了鼠标功能接口和键盘功能接口两种接口。此外,配置描述符中还会描述设备的供电方式(自供电/总线供电)、最大耗电量等信息。其结构如表3所示。

表3 配置描述符的结构

偏移 大小 描述
0 bLength 1 数字 描述符的字节数长度(0x09)
1 bDescriptorType 1 常量 配置描述符的类型(0x02)
2 wTotalLength 2 BCD码 配置信息的总长(包括配置、接口、端点和设备类及厂商定义的描述符)
4 BnumInterfaces 1 该设备所支持的接口数目
5 bConfigurationValue 1 子类 配置值
6 iConfiguration 1 协议 描述该配置的字符串描述符索引值
7 bmAttributes 1 数字 配置特性:D7:保留 D6:自供电 D5:远程唤醒 D4…0:保留
8 MaxPower 1 数字 该配置下所需最大总线电流(2mA为单位)

2.3 接口描述符

USB设备的接口是端点的集合,负责完成该设备的特定功能,比如数据的输入和输出。接口描述符用来表示在USB设备中,各个接口的特性,包括接口的端点个数、所述的设备类和子类等。

拥有多个接口的USB设备,如果设备描述符中描述的bDeviceClass不为0,则表示接口之间是互斥关系,否则接口相互独立,每个接口有自己的类号、子类号和协议号。类号、子类号和协议号的定义,与设备描述符中的定义是一致的。接口描述符的结构如表4所示。

表4 接口描述符的结构

偏移 大小 描述
0 bLength 1 数字 描述符的字节数长度(0x09)
1 bDescriptorType 1 常量 接口描述符的类型(0x04)
2 bInterfaceNumber 1 数字 接口号(从0开始)
3 bAlternateSetting 1 数字 可选设置的索引值
4 bNumEndpoint 1 数字 此接口的端点数量(不计默认端点0)
5 bInterfaceClass 1 接口所属的类值
6 bInterfaceSubClass 1 子类 接口所属子类的值
7 bInterfaceProtocol 1 协议 协议码,根据上面的两个值而定
8 iInterface 1 索引 表示此接口的字符串描述符的索引值

2.4 端点描述符

USB规范中,端点描述符用于指出USB设备端点的特性,包括其所支持的传输类型、传输方向等。端点0没有端点描述符,其他端点必须包含端点描述符。

端点是设备与主机之间进行数据传输的逻辑接口,除配置使用的端点0为双向外,其他均为单向。端点描述符描述了数据的传输类型、传输方向、数据包大小,以及端点地址,其结构如表5所示。

表5 端点描述符的结构

偏移 大小 描述
0 bLength 1 数字 描述符的字节数长度(0x07)
1 bDescriptorType 1 常量 端点描述符的类型(0x05)
2 bEndPointAddress 1 端点 描述了端点的地址、方向 Bit3…0:端点号 Bit6…4:保留,为0 Bit7:传输方向,如果是控制端点则忽略 0:输出端点(主机到设备) 1:输入端点(设备到主机)
3 bmAttributes 1 位图 端点传输类型 Bit1…0:传送类型 00B=控制传送 01B=实时传送 10B=批量传送 11B=中断传送
4 wMaxPacketSize 2 数字 接收/发送的最大数据包长度
6 bInterval 1 数字 周期数据传输端点的时间间隙

2.5 字符串描述符

字符串描述符是可选的,它描述了制造商、设备名称或序列号等信息。它使用的是Unicode编码,并支持多语言。USB主机要求获得字符串描述符时,需要用一个16位的语言标识出语言类别。比如,常用的语言标识1033表示美国英语,而2052表示中文。其他的语言标识,可以在微软的网站上找到 。

USB主机请求得到某个字符串描述符时分为两步,首先向USB设备发送USB命令Get_Descriptor,命令的wIndex字段设置为0,设备将返回描述语言标识的字符串描述符;然后,USB主机根据需要的语言,向USB设备发送命令Get_Descriptor,在命令对应的字段中设置字符串的索引值和语言标识,得到需要的字符串描述符。

字符串描述符有两种格式。第一种用来指明所用的语言标识,如表6所示。

表6 指明语言标识的字符串描述符

偏移 大小 描述
0 bLength 1 N+2 描述符的字节数长度(N+2字节)
1 bDescriptorType 1 常量 字符串描述符的类型(0x03)
2 wLANGID[0] 2 数字 语言标识(LANGID),码0
N wLANGID[x] 2 数字 语言标识(LANGID),码x

第二种为Unicode字符串描述符,包含了非NULL结尾的Unicode字符串,如表7所示。

表7 Unicode字符串描述符

偏移 大小 描述
0 bLength 1 N+2 描述符的字节数长度(N+2字节)
1 bDescriptorType 1 常量 字符串描述符的类型(0x03)
2 bString N 数字 Unicode编码的字符串

在实际编写代码中,接口描述符、端点描述符一般是和配置描述符在同一数组中的。后续代码编写时,我们再来看实际的情况。

本篇篇幅较长,也许是目前写的最长的博客了。主要是为了后续查询方便,将标准描述符相关的细节都包含了。

下一篇讨论USB的HID类描述符。


UEFI开发探索82- YIE002USB开发板(05 制作HID设备)相关推荐

  1. UEFI开发探索85- YIE002USB开发板(08 制作HID设备)

    (请保留-> 作者: 罗冰 https://blog.csdn.net/luobing4365) YIE002USB开发板之制作HID设备-编程 1 YIE002-STM32的USB编程 2 调 ...

  2. UEFI开发探索81- YIE002USB开发板(04 制作HID设备)

    (请保留-> 作者: 罗冰 https://blog.csdn.net/luobing4365) YIE002USB开发板之制作HID设备-USB系统概述 1 USB规范简介 2 软件工程师眼中 ...

  3. UEFI开发探索72- YIE002USB开发板(01 开篇)

    (请保留-> 作者: 罗冰   https://blog.csdn.net/luobing4365) 最近把USB的各个方面都研究了一遍,也在UEFI下实现了USB设备的访问.趁着这热乎劲,我计 ...

  4. UEFI开发探索74- YIE002USB开发板(03 Windows编程)

    (请保留-> 作者: 罗冰 https://blog.csdn.net/luobing4365) YIE002USB开发板之Windows编程 1 添加库文件 2 枚举HID设备 2.1 Set ...

  5. UEFI开发探索02 – 环境搭建1

    (请保留->作者:罗冰 ) 开发初期的目的就是做出可以在pci rom上跑的Oprom,当然是在uefi bios下.我的计划大致如下: 1 搭建完整的编译环境,了解使用哪些库进行编译: 2 我 ...

  6. UEFI开发探索97 – EDK2模拟器搭建网络环境

    (请保留-> 作者: 罗冰 https://blog.csdn.net/luobing4365) EDK2模拟器搭建网络环境 1 搭建EDK2开发环境 1)工具安装 2)下载代码库 3)更新子模 ...

  7. UEFI开发探索94 – 迷宫小游戏

    (请保留-> 作者: 罗冰 https://blog.csdn.net/luobing4365) UEFI下的迷宫小游戏 1 Maze程序结构分析 1)定义全局变量 2)设置迷宫 3) 游戏控制 ...

  8. UEFI开发探索98 – 硬盘访问Diskdump

    (请保留-> 作者: 罗冰 https://blog.csdn.net/luobing4365) 硬盘访问Diskdump 1 UEFI的存储介质访问栈 2 编写Diskdump程序 2.1 B ...

  9. UEFI开发探索100 – 《UEFI编程实践》发布啦

    (请保留-> 作者: 罗冰 https://blog.csdn.net/luobing4365) <UEFI编程实践>发布 1 内容简介 第一部分 UEFI环境搭建及UEFI应用构建 ...

最新文章

  1. 用SQL命令查看Mysql数据库大小
  2. 002_Spring Data JPA CRUD
  3. Docker入门-简介
  4. ARIMA模型之疏系数模型
  5. linux 同步北京时间_linux 同步北京时间
  6. 大三学生前端实习经验分享
  7. 如何使用小米手机对文档进行扫描
  8. 不知道为什么想起以前的事总是那么的心痛
  9. 灰色预测模型及其代码
  10. Java Web 开发实战经典 基础篇(1)
  11. js截取特定字符后面的字符串
  12. 重庆大学计算机学院导师郭平,重庆大学计算机学院召开首届学科研究宣讲会
  13. 神经网络时间序列分析,神经网络模型可解释性
  14. tensorflow报AttributeError: __enter__错误解决
  15. 大数据时代的隐私保护
  16. 如何配置Maven镜像?
  17. leetcode 126. 单词接龙 II
  18. excel快速入门-学习笔记
  19. python 获取uuid
  20. 自动转flash为html5,Adobe演示将Flash转换成HTML5

热门文章

  1. linux 删除乱码文件名的文件
  2. 流量威胁检测工具开发之路(7)
  3. c# DGV导出excel 使用object类型数组,解决string类型需双击后或分列才可运算的异常
  4. Linux命令之ll
  5. mysql 连续打卡_MySQL查询连续打卡信息?
  6. SharePoint 内容编辑器部件介绍
  7. PDF怎么编辑修改内容的免费方法
  8. python中对象的赋值、浅拷贝和深拷贝
  9. 威斯康星麦迪逊计算机专业排名,威斯康星大学麦迪逊分校计算机排名2020年
  10. error: cannot lock ref 'refs/remotes/origin/master': unable to resolve reference 'refs/remotes/origi