___2017

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

USB 描述符

所有 USB 设备都有一个层级式的描述符,这些描述符包含需要向主机提供的、描述设备的信息,例如它是什么设备,制造商信息,支持的 USB 版本,可以配置多少种方式,端点的数量及类型等等。
 
常见的 USB 描述符是:
  • 设备描述符(Device Descriptors)
  • 配置描述符(Configuration Descriptors)
  • 接口描述符(Interface Descriptors)
  • 端点描述符(Endpoint Descriptors)
  • 字符串描述符(String Descriptors)
 
USB 设备只能有一个设备描述符。设备描述符包含的信息有:设备符合的 USB 版本,产品 ID(Product ID)和厂商 ID(Vendor ID)—— 系统根据 PID 和 VID 加载适当的驱动程序,设备拥有的可能配置数量之类的信息。
 
对于自供电或总线供电的设备,配置描述符指定了此配置使用的功率,设备具有的接口数量。枚举设备时,主机将读取设备描述符,并可以决定启用哪种配置。一次只能启用一种配置(It can only enable one configuration at a time)。
 
例如,设备可以同时具有高功率总线供电的配置和自供电的配置,如果将设备插入具有电源的主机,则设备驱动程序可以选择启用高功率总线供电的配置,从而无需连接电源即可给设备供电;如果连接到便携式计算机,则可以启用第二种配置(自供电),要求用户将您的设备插入电源插座。

配置里的设置项不限制功率差异。每个配置可以以相同的方式供电并获取相同的电流,尽管使用不同的接口或端点组合。需要注意的是,更改配置需要停止每个端点上的所有活动。尽管 USB 提供了这种使用方式,但很少有设备具有多于1个的配置。
接口描述符可以看做是一个 header 或者是用于实现某一个功能的、一组端点的集合。例如,一个具有传真/扫描仪/打印等多功能的设备,一个接口描述符用来描述传真功能的端点,另一个接口描述符描述扫描功能,再一个接口描述符描述打印功能。与配置描述符不同,并不限制同一时刻启用的接口的数量。设备可以同时启用多个接口描述符。
 
接口描述符中的 bInterfaceNumber 字段用于指定接口编号,bAlternateSetting 允许接口动态更改设置。例如,现有一个带有两个接口的设备,1 号接口和 2 号接口。1 号接口的 bInterfaceNumber 字段为 0 表明其是第一个接口描述符,bAlternateSetting 字段设置为 0。1 号接口的 bInterfaceNumber 字段为 1 表明其是第二个接口描述符,AlternateSetting 字段为 0(默认值)。然后设备可以有另一个描述符,bInterfaceNumber 字段也为 1 表明其是第二个接口描述符,但是此时 bAlternateSetting 字段设置为 1 表明此接口描述符可以作为上一个接口描述符的替代描述符。
 
启用此配置后,将使用 bAlternativeSettings 等于零的前两个接口描述符。但是在工作过程中,主机可以通过向接口 1 发送 SetInterface 请求来启用另一个 bAlternateSetting 为 1 的接口描述符。
相比于具有两种配置的情况,这么做具有优势——因为我们可以通过接口 0 传输数据,同时能够更改与接口 1 关联的端点设置,而不会影响接口 0。
 
Each endpoint descriptor is used to specify the type of transfer, direction, polling interval and maximum packet size for each endpoint. Endpoint zero, the default control endpoint is always assumed to be a control endpoint and as such never has a descriptor.
 
每个端点描述符用于指定每个端点的传输的类型,方向,轮询间隔和最大包大小。 0 号端点为默认控制端点,始终为控制端点,因此永远不会包含描述符。

USB 描述符的构成

所有描述符均具有同样的格式。第一个字节指定描述符的长度,而第二个字节表示描述符的类型。如果描述符的长度小于规范定义的长度,则主机应忽略它。但是,如果大小大于规定值,则主机将忽略多余的字节,并在返回的实际长度的末尾开始寻找下一个描述符。通用结构格式如下:
Offset Field Size Value Description
0 bLength 1 Number

Size of Descriptor in Bytes

1 bDescriptionType 1 Constant

DescriptorType

2 ... n  

Start of parameters for descriptor

代码示例:
/* All standard descriptors have these 2 fields at the beginning */
struct usb_descriptor_header {
	__u8  bLength;
	__u8  bDescriptorType;
} __attribute__ ((packed));
 

设备描述符

USB 设备的设备描述符代表整个设备,所以 USB 设备只能有一个设备描述符。它指定了有关设备的一些基本但重要的信息,例如支持的 USB 版本,最大数据包大小,供应商 ID 和产品 ID,设备可以具有的配置数量。设备描述符的格式如下:
Offset Field Size Value Description
0 bLength 1 Number

Size of the Descriptor in Bytes (18 bytes)

1 bDescriptorType 1 Constant

Device Descriptor (0x01)

2 bcdUSB 2 BCD

USB Specification Number which device complies too.

4 bDeviceClass 1 Class

Class Code (Assigned by USB Org)

If equal to Zero, each interface specifies it’s own class code

If equal to 0xFF, the class code is vendor specified.

Otherwise field is valid Class Code.

5 bDeviceSubClass 1 SubClass

Subclass Code (Assigned by USB Org)

6 bDeviceProtocol 1 Protocol

Protocol Code (Assigned by USB Org)

7 bMaxPacketSize 1 Number

Maximum Packet Size for Zero Endpoint. Valid Sizes are 8, 16, 32, 64

8 idVendor 2 ID

Vendor ID (Assigned by USB Org)

10 idProduct 2 ID

Product ID (Assigned by Manufacturer)

12 bcdDevice 2 BCD

Device Release Number

14 iManufacturer 1 Index

Index of Manufacturer String Descriptor

15 iProduct 1 Index

Index of Product String Descriptor

16 iSerialNumber 1 Index

Index of Serial Number String Descriptor

17 bNumConfigurations 1 Integer

Number of Possible Configurations

  • bcdUSB 域:指明设备支持的 USB 的最高版本。该值采用二进制编码的十进制格式,格式为 0xJJMN,其中 JJ 是主要版本号(major),M 是次要版本号(minor),N是次子版本号(sub minor)。举例来说,USB 2.0 写作 0x0200,USB 1.1 写作 0x0110,USB 1.0 写作 0x0100
  • bDeviceClass/bDeviceSubClass/bDeviceProtocol 域:它们被操作系统使用,用于为你的设备加载对应的驱动程序。通常,仅在设备级别设置 bDeviceClass,大多数类规范(class specification)选择在接口级别(interface level)标识自身,因此将 bDeviceClass 设置为 0x00,这样一台设备即可支持多个类别(:意味着一个设备需要有多个驱动程序支持)。
  • bMaxPacketSize 域:指明端点 0 的最大数据包大小。所有设备必须支持零端 0。
  • idVendor/idProduct 域:被操作系统用来为你的设备加载对应的驱动程序。idVendor 由 USB 联盟组织分配。
  • bcdDevice 域:与 bcdUSB 具有相同的格式,用于提供设备版本号。此值由开发人员分配。
  • bNumConfigurations 域:定义设备以其当前速度支持的可能的配置数。
 
设备描述符代码示例:
/* USB_DT_DEVICE: Device descriptor */
struct usb_device_descriptor {
	__u8  bLength;
	__u8  bDescriptorType;

	__le16 bcdUSB;
	__u8  bDeviceClass;
	__u8  bDeviceSubClass;
	__u8  bDeviceProtocol;
	__u8  bMaxPacketSize0;
	__le16 idVendor;
	__le16 idProduct;
	__le16 bcdDevice;
	__u8  iManufacturer;
	__u8  iProduct;
	__u8  iSerialNumber;
	__u8  bNumConfigurations;
} __attribute__ ((packed));

#define USB_DT_DEVICE_SIZE		18
 

配置描述符

USB 设备可以具有几种不同的配置,不过大多数设备很简单,只有一个。描配置描述符指定设备的供电方式,最大功耗是多少,设备具有的接口数。因此,设备可以有两种配置,一种用于设备由总线供电时,另一种用于电源供电时。这么看来,配置描述符就像接口描述符的“描述头(header)”,因此可以在不同的配置中使用不同的传输模式。
 
主机检查完所有配置后,主机将发送 SetConfiguration 命令,命令是非 0 值,该值和其中一种配置的 bConfigurationValue 域的值一致,这样就选中了所需的配置。配置描述符的格式如下:
Offset Field Size Value Description
0 bLength 1 Number

Size of Descriptor in Bytes

1 bDescriptorType 1 Constant

Configuration Descriptor (0x02)

2 wTotalLength 2 Number

Total length in bytes of data returned

4 bNumInterfaces 1 Number

Number of Interfaces

5 bConfigurationValue 1 Number

Value to use as an argument to select this configuration

6 iConfiguration 1 Index

Index of String Descriptor describing this configuration

7 bmAttributes 1 Bitmap

D7 Reserved, set to 1. (USB 1.0 Bus Powered)

D6 Self Powered

D5 Remote Wakeup

D4..0 Reserved, set to 0.

8 bMaxPower 1 mA

Maximum Power Consumption in 2mA units

  • wTotalLength 域:读取配置描述符时,它将返回整个配置层次结构,其中包括所有相关的接口和端点描述符。wTotalLength 代表层次结构中的字节数。示例如下:
  • bNumInterfaces 域:指定此配置的接口数。
  • bConfigurationValue 域:SetConfiguration 请求通过该域值选中此配置。
  • iConfiguration 域:iConfiguration 是字符串描述符的索引,该字符串描述符以人类可读的形式描述了配置。
  • bmAttributes 域:指定此配置的电源参数。如果设备是自供电的,则会设置 D6。USB 1.0 中使用位 D7 表示总线供电的设备,但是现在由 bMaxPower 完成。如果设备使用总线上的任何电源,无论是总线供电的设备还是自供电设备,都必须在 bMaxPower 中报告其功耗。设备还可以支持远程唤醒,远程唤醒允许设备在主机处于挂起状态时唤醒主机。
  • bMaxPower 域:定义设备将从总线消耗的最大功率,以 2mA 为单位,因此可以指定最大约 500mA。该规范允许高功率总线供电的设备从 Vbus 汲取不超过 500mA 的电流。如果设备失去了外部电源,则其消耗的电量不得超过 bMaxPower 中指定的。如果没有外部电源,它将无法执行任何操作。
 
配置描述符代码示例:
/* USB_DT_CONFIG: Configuration descriptor information.
 *
 * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
 * descriptor type is different.  Highspeed-capable devices can look
 * different depending on what speed they're currently running.  Only
 * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG
 * descriptors.
 */
struct usb_config_descriptor {
	__u8  bLength;
	__u8  bDescriptorType;

	__le16 wTotalLength;
	__u8  bNumInterfaces;
	__u8  bConfigurationValue;
	__u8  iConfiguration;
	__u8  bmAttributes;
	__u8  bMaxPower;
} __attribute__ ((packed));

#define USB_DT_CONFIG_SIZE		9

 

接口描述符

接口描述符格式如下:
Offset Field Size Value Description
0 bLength 1 Number

Size of Descriptor in Bytes (9 Bytes)

1 bDescriptorType 1 Constant

Interface Descriptor (0x04)

2 bInterfaceNumber 1 Number

Number of Interface

3 bAlternateSetting 1 Number

Value used to select alternative setting

4 bNumEndpoints 1 Number

Number of Endpoints used for this interface

5 bInterfaceClass 1 Class

Class Code (Assigned by USB Org)

6 bInterfaceSubClass 1 SubClass

Subclass Code (Assigned by USB Org)

7 bInterfaceProtocol 1 Protocol

Protocol Code (Assigned by USB Org)

8 iInterface 1 Index

Index of String Descriptor Describing this interface

  • bInterfaceNumber 域:表示接口描述符的索引(index)。 它应该从零开始,并为每个新接口描述符增加一次。
  • bAlternativeSetting 域:用来指定备用接口(alternative interfaces),备用接口可由 SetInterface 请求选中。
  • bNumEndpoints 域:表示接口使用的端点数量,该值不包括端点 0,并用于指示要遵循的端点描述符的数量。
  • bInterfaceClass/bInterfaceSubClass/bInterfaceProtocol 域:用于指定支持的设备类别(例如 HID 设备,通信设备,大容量存储设备等),这使许多设备可以使用类驱动程序,从而无需为设备编写特定的驱动程序。
  • iInterface 域:描述该接口的字符串描述符的索引。
 
接口描述符代码示例:
/* USB_DT_INTERFACE: Interface descriptor */
struct usb_interface_descriptor {
	__u8  bLength;
	__u8  bDescriptorType;

	__u8  bInterfaceNumber;
	__u8  bAlternateSetting;
	__u8  bNumEndpoints;
	__u8  bInterfaceClass;
	__u8  bInterfaceSubClass;
	__u8  bInterfaceProtocol;
	__u8  iInterface;
} __attribute__ ((packed));

#define USB_DT_INTERFACE_SIZE		9

 

端点描述符

端点描述符用于描述端点,不包括端点 0,端点 0 始终为控制端点(control endpoint ),并且在请求任何描述符之前就已对其进行了配置。主机使用从这些描述符获取的信息来确定总线大的带宽要求。端点描述符格式如下:
 
Endpoint descriptors are used to describe endpoints other than endpoint zero. Endpoint zero is always assumed to be a control endpoint and is configured before any descriptors are even requested. The host will use the information returned from these descriptors to determine the bandwidth requirements of the bus.端点描述符用于描述端点零以外的端点。 始终将端点零假定为控制端点,并且在甚至请求任何描述符之前就已对其进行了配置。 主机将使用从这些描述符返回的信息来确定总线的带宽要求。端点描述符格式如下:
Offset Field Size Value Description
0 bLength 1 Number

Size of Descriptor in Bytes (7 bytes)

1 bDescriptorType 1 Constant

Endpoint Descriptor (0x05)

2 bEndpointAddress 1 Endpoint Endpoint Address
Bits 0..3b Endpoint Number.
Bits 4..6b Reserved. Set to Zero
Bits 7 Direction 0 = Out, 1 = In (Ignored for Control Endpoints)
3 bmAttributes 1 Bitmap Bits 0..1 Transfer Type
      00 = Control

      01 = Isochronous

      10 = Bulk

      11 = Interrupt

Bits 2..7 are reserved. If Isochronous endpoint,
Bits 3..2 = Synchronisation Type (Iso Mode)
      00 = No Synchonisation

      01 = Asynchronous

      10 = Adaptive

      11 = Synchronous

Bits 5..4 = Usage Type (Iso Mode)
      00 = Data Endpoint

      01 = Feedback Endpoint

      10 = Explicit Feedback Data Endpoint

      11 = Reserved
4 wMaxPacketSize 2 Number

Maximum Packet Size this endpoint is capable of sending or receiving

6 bInterval 1 Number

Interval for polling endpoint data transfers. Value in frame counts. Ignored for Bulk & Control Endpoints. Isochronous must equal 1 and field may range from 1 to 255 for interrupt endpoints.


  • bEndpointAddress 域:描述端点的基本信息,如端点地址,端点数据方向。
  • bmAttributes 域:指定传输类型,可以是控制,中断,同步或批量传输。如果指定了是同步传输端点,则可以指定其他熟悉,如 Synchronisation 类型,Usage 类型。
  • wMaxPacketSize 域:指定此端点的最大有效负载大小。
  • bInterval 域:用于指定某些传输的轮询间隔,单位以帧表示(The units are expressed in frames),因此对于低速/全速设备而言等于 1ms,对于高速设备而言等于 125us。
 
端点描述符代码示例:
/* USB_DT_ENDPOINT: Endpoint descriptor */
struct usb_endpoint_descriptor {
	__u8  bLength;
	__u8  bDescriptorType;

	__u8  bEndpointAddress;
	__u8  bmAttributes;
	__le16 wMaxPacketSize;
	__u8  bInterval;

	/* NOTE:  these two are _only_ in audio endpoints. */
	/* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
	__u8  bRefresh;
	__u8  bSynchAddress;
} __attribute__ ((packed));

#define USB_DT_ENDPOINT_SIZE		7
#define USB_DT_ENDPOINT_AUDIO_SIZE	9	/* Audio extension */

 

字符串描述符

字符串描述符提供人类可读的信息,是可选的。 如果不适用字符串描述符,则描述符的任何字符串索引字段都必须设置为零,以指示没有可用的字符串描述符。
 
字符串以 Unicode 格式编码,产品可以支持多种语言。0 号字符串描述符应该返回支持的语言列表,USB 语言的 ID 编码可在 LANGIDs(Universal Serial Bus Language Identifiers) 版本 1.0 中找到。0 号字符串描述符格式如下:
Offset Field Size Value Description
0 bLength 1 Number

Size of Descriptor in Bytes

1 bDescriptorType 1 Constant

String Descriptor (0x03)

2 wLANGID[0] 2 number

Supported Language Code Zero
(e.g. 0x0409 English - United States)

4 wLANGID[1] 2 number

Supported Language Code One
(e.g. 0x0c09 English - Australian)

n wLANGID[x] 2 number

Supported Language Code x
(e.g. 0x0407 German - Standard)

上面的字符串描述符展示了0 号字符串描述符的格式。主机应该读取该描述符,以确定可用的语言。如果支持某一种语言,则可以通过在 GetDescriptor(String)请求的 wIndex 字段中发送语言 ID 来使用用该语言。后续所有字符串采用以下格式:
Offset Field Size Value Description
0 bLength 1 Number

Size of Descriptor in Bytes

1 bDescriptorType 1 Constant

String Descriptor (0x03)

2 bString n Unicode

Unicode Encoded String

 

附录

posted on 2020-11-18 19:12  yin'xiang  阅读(921)  评论(0编辑  收藏  举报