[Hardware翻译]坚果壳中的USB第五章:USB描述符

291 阅读13分钟

原文地址:www.beyondlogic.org/usbnutshell…

原文作者:

发布时间:

USB描述符

所有的USB设备都有一个描述符的层次结构,它向主机描述了一些信息,如设备是什么,谁制造的,它支持什么版本的USB,它可以有多少种配置方式,端点的数量及其类型等。

比较常见的USB描述符有

USB设备只能有一个设备描述符。设备描述符包括诸如设备符合的USB修订版、用于加载适当驱动程序的产品和供应商ID,以及设备可以拥有的配置数量等信息。配置数量表示有多少个配置描述符分支要遵循。

配置描述符指定了一些值,例如这个特定配置使用的功率,设备是自供电还是总线供电,以及它拥有的接口数量。当一个设备被枚举时,主机读取设备描述符,可以决定启用哪个配置。它一次只能启用一个配置。

例如,可以有一个大功率总线供电配置和一个自供电配置。如果设备被插入带有主电源的主机,设备驱动程序可能会选择启用高功率总线供电配置,使设备无需连接到主电源即可供电,但如果它被连接到笔记本电脑或个人整理器,它可以启用第二种配置(自供电),要求用户将设备插入电源点。

配置设置并不限于电源的差异。每种配置都可以以相同的方式供电,消耗相同的电流,但却有不同的接口或端点组合。不过需要注意的是,改变配置需要停止每个端点的所有活动。虽然USB提供了这种灵活性,但很少有设备有1种以上的配置。

接口描述符可以被看作是一个头或将端点分组成一个功能组,执行设备的单一功能。例如你可以有一个多功能的传真/扫描/打印机设备。接口描述符一可以描述传真功能的端点,接口描述符二描述扫描仪功能,接口描述符三描述打印机功能。与配置描述符不同,一次只启用一个接口没有限制。一个设备可以同时启用一个或多个接口描述符。

接口描述符有一个bInterfaceNumber字段,指定接口号,还有一个bAlternateSetting字段,允许接口在运行中改变设置。例如我们可以有一个设备有两个接口,接口一和接口二。接口一的bInterfaceNumber设置为0,表示它是第一个接口描述符,bAlternativeSetting为0。

接口二的bInterfaceNumber设置为1,表示它是第二个接口,bAlternativeSetting为0(默认)。然后我们可以抛出另一个描述符,也是bInterfaceNumber设为1,表示它是第二个接口,但这次将bAlternativeSetting设为1,表示这个接口描述符可以是另一个接口描述符二的替代设置。

启用此配置后,使用bAlternativeSettings等于0的前两个接口描述符。但是在操作过程中,主机可以发送一个SetInterface请求,直接指向接口一的替代设置,以启用另一个接口描述符。

这样做的好处是比有两个配置更有优势,因为我们在改变与接口一相关的端点设置时,可以通过接口零传输数据,而不影响接口零。

每个端点描述符用于指定每个端点的传输类型、方向、轮询间隔和最大数据包大小。端点零,即默认的控制端点总是被假定为控制端点,因此从来没有描述符。

USB描述符的组成

所有的描述符都由一个共同的格式组成。第一个字节指定描述符的长度,第二个字节表示描述符的类型。如果一个描述符的长度小于规范定义的长度,那么主机将忽略它。但是,如果描述符的大小大于预期,则主机将忽略多余的字节,并在返回的实际长度的最后开始寻找下一个描述符。

偏移字段大小说明
0bLength1Number描述符的大小(字节)
1bDescriptionType1常数DescriptorType
2...n描述符参数的开始

设备描述符

一个USB设备的设备描述符代表了整个设备。因此,一个USB设备只能有一个设备描述符。它指定了有关设备的一些基本但重要的信息,如支持的USB版本、最大数据包大小、供应商和产品ID以及设备可以拥有的配置数量。设备描述符的格式如下所示。

偏移字段大小说明
0bLength1Number描述符的大小,以字节为单位(18字节)。
1bDescriptorType1常量设备描述符 (0x01)
2bcdUSB2BCD裝置符合的 USB 規格編號。
4bDeviceClass1Class类别代码(由USB组织指定)。如果等于零,每个接口都会指定自己的类代码。如果等于0xFF,则类代码是供应商指定的。否则,该字段为有效的类代码。
5bDeviceSubClass1子类子类代码(由USB组织分配)
6bDeviceProtocol1Protocol协议代码(由USB组织指定)
7bMaxPacketSize1Number零端点的最大数据包大小,有效大小为8、16、32、64。有效大小为8、16、32、64。
8idVendor2ID供应商ID(由USB组织指定)
10id产品2ID产品ID(由制造商指定)
12bcdDevice2BCD设备发布号
14iManufacturer1Index制造商索引字符串描述符
15iProduct1Index产品字符串描述符的索引
16iSerialNumber1索引序列号的索引 字符串描述符
17bNumConfigurations1整数可能的配置数量
  • bcdUSB字段报告设备支持的USB最高版本。该值以二进制编码的十进制为单位,格式为0xJJMN,其中JJ是主要版本号,M是次要版本号,N是次要版本号。例如,USB 2.0报告为0x0200,USB 1.1报告为0x0110,USB 1.0报告为0x0100。

  • bDeviceClass、bDeviceSubClass和bDeviceProtocol被操作系统用来为你的设备找到一个类驱动程序。通常只有bDeviceClass是在设备级设置的。大多数类规范选择在接口级别上标识自己,因此将bDeviceClass设置为0x00。这样,一个设备就可以支持多个类。

  • bMaxPacketSize字段报告端点零的最大数据包大小。所有设备都必须支持端点零。

  • idVendor和idProduct被操作系统用来为你的设备寻找驱动程序。Vendor ID是由USB-IF分配的。

  • bcdDevice的格式与bcdUSB相同,用于提供设备版本号。这个值是由开发者分配的。

  • 存在三个字符串描述符,以提供制造商、产品和序列号的细节。对字符串描述符没有要求。如果没有字符串描述符,应使用零的索引。

  • bNumConfigurations 定义了设备在其当前速度下支持的配置数量。

配置描述符

一个USB设备可以有几种不同的配置,尽管大多数设备都很简单,只有一种配置。配置描述符指定了设备的供电方式,最大功耗是多少,它有多少个接口。因此,可以有两种配置,一种是设备总线供电时的配置,另一种是主电源供电时的配置。由于这是接口描述符的 "头",因此也可以让一个配置与另一个配置使用不同的传输模式。

一旦主机检查了所有配置,主机将发送一个SetConfiguration命令,该命令的值与其中一个配置的bConfigurationValue相匹配的非零值。这将用于选择所需的配置。

偏移字段大小说明
0bLength1Number描述符的大小(字节)
1bDescriptorType1常量配置描述符 (0x02)
2w总长度2数量返回的数据总长度(字节)
4bNumInterfaces1数量接口数量
5bConfigurationValue1Number选择此配置时作为参数使用的值。
6iConfiguration1索引描述此配置的字符串描述符的索引。
7bmAttributes1BitmapD7 保留,设置为 1。(USB 1.0总线供电)。D6自供电。D5远程唤醒。D4..0 保留,设置为 0。
8bMaxPower1mA最大功耗(2mA单位)
  • 读取配置描述符时,会返回整个配置层次结构,其中包括所有相关的接口和端点描述符。wTotalLength字段反映的是层次结构中的字节数。

  • bNumInterfaces指定该配置存在的接口数量。

  • bConfigurationValue被SetConfiguration请求用来选择这个配置。

  • iConfiguration是指向以人类可读形式描述配置的字符串描述符的索引。

  • bmAttributes指定配置的电源参数。如果设备是自供电,则设置D6。在USB 1.0中,D7位用来表示总线供电设备,但现在由bMaxPower完成。如果设备使用总线供电,无论是作为总线供电设备还是作为自供电设备,都必须在bMaxPower中报告其功耗。设备还可以支持远程唤醒,当主机处于暂停状态时,设备可以唤醒主机。

  • bMaxPower定义了设备将从总线上消耗的最大功率。这是以2mA为单位,因此可以指定最大约500mA的功率。该规范允许一个高功率总线供电的设备从Vbus中消耗的功率不超过500mA。如果一个器件失去了外部电源,那么它的耗电量不能超过bMaxPower中所指示的数值。在没有外部电源的情况下,它不能执行的任何操作都应该失败。

接口描述符

接口描述符可以被看作是一个头或将端点分组为一个功能组,执行设备的单一功能。接口描述符符合以下格式:

偏移字段大小说明
0bLength1Number描述符的大小,以字节为单位(9字节)
1bDescriptorType1常量接口描述符 (0x04)
2bInterfaceNumber1Number接口数量
3bAlternateSetting1Number用于选择替代设置的值
4bNumEndpoints1Number该接口使用的端点数量
5bInterfaceClass1类别代码(由USB组织指定
6bInterfaceSubClass1子类子类代码(由USB组织分配)
7bInterfaceProtocol1协议协议代码(由USB组织指定)
8iInterface1索引描述该接口的字符串描述符的索引。
  • bInterfaceNumber表示接口描述符的索引。这应该以零为基础,每增加一个新的接口描述符就递增一次。

  • bAlternativeSetting可以用来指定替代接口。这些替代接口可以通过设置接口请求来选择。

  • bNumEndpoints表示接口使用的端点数量。这个值应该不包括端点零,用于指示后续的端点描述符的数量。

  • bInterfaceClass、bInterfaceSubClass和bInterfaceProtocol可以用来指定支持的类(如HID、通信、大容量存储等),这允许许多设备使用类驱动程序,防止需要为您的设备编写特定的驱动程序。

  • iInterface允许对接口进行字符串描述。

端点描述符

端点描述符用于描述端点零以外的端点。端点零总是被假定为控制端点,并且在请求任何描述符之前就已经配置好了。主机将使用这些描述符返回的信息来确定总线的带宽需求。

偏移字段大小说明
0bLength1Number描述符的大小,以字节为单位(7字节)
1bDescriptorType1常量端点描述符 (0x05)
2bEndpointAddress1端点注2
3bmAttributes1位图注3
4wMaxPacketSize2Number此端点能够发送或接收的最大数据包大小。
6bInterval1Number轮询端点数据传输的时间间隔。以帧数为单位的值。对于批量和控制端点,忽略。对于中断端点,异步必须等于1,该字段的范围为1至255。
注2:
端点地址
Bits 0...3b Endpoint Number.
Bits 4..6b 保留。设置为零
Bits 7 方向 0 = 出,1 = 入(控制端点忽略)。
注3:
Bits 0...1 = 传输类型
  00 = 控制
  01 = 异步法
  10 = 散装
  11 = 中断
Bits 2..7为保留位。如果是异步端点。
Bits 3..2 = 同步类型(Iso模式)
  00 = 无同步化
  01 = 异步
  10 = 自适应
  11 = 同步
Bits 5..4 = 使用类型(Iso模式)。
  00 = 数据端点
  01 = 反馈端点
  10 = 显式反馈数据端点
  11 = 保留
  • bEndpointAddress表示这个描述符描述的是什么端点。

  • bmAttributes指定传输类型。这可以是控制、中断、异步或批量传输。如果指定了Isochronous端点,可以选择其他属性,如同步和使用类型。

  • wMaxPacketSize表示该端点的最大有效载荷大小。

  • bInterval用于指定某些传输的轮询间隔。单位以帧为单位,因此对于低速/全速设备来说相当于1ms,对于高速设备来说相当于125us。

字符串描述符

字符串描述符提供人可读的信息,是可选的。如果不使用它们,描述符的任何字符串索引字段必须设置为零,表示没有可用的字符串描述符。

字符串以Unicode格式编码,产品可以支持多种语言。字符串索引0应返回支持的语言列表。通用串行总线语言标识符(LANGIDs)1.0版本中可以找到USB语言ID的列表。

偏移字段大小说明
0bLength1Number描述符的大小(字节)
1bDescriptorType1常量字符串描述符 (0x03)
2wLANGID[0]2数字支持的语言代码为零(例如:0x0409 英文 - 美国)
4wLANGID[1]2数字支持的语言代码一(例如:0x0c09英语-澳大利亚语)
nwLANGID[x]2数字支持的语言代码 x(例如 0x0407 德语 - 标准)

上面的字符串描述符显示了零号字符串描述符的格式。主机应该阅读这个描述符来确定哪些语言是可用的。如果支持某种语言,那么可以通过在Get Descriptor(String)请求的wIndex字段中发送语言ID来引用它。

所有后续字符串的格式如下。

偏移字段大小说明
0bLength1Number描述符的大小(字节)
1bDescriptorType1常量字符串描述符 (0x03)
2bStringnUnicode统一码编码字符串

www.deepl.com 翻译