Lazy loaded image
USB专题04 - USB描述符和设备枚举过程
Words 2957Read Time 8 min
2025-4-29
USB描述符的设计解决了USB通信中设备识别的问题。通过多个层次的描述符,系统能够在不同的层面上获取设备信息,确保设备能与主机正常工作。
设计模式一般采用层次结构,每个描述符包含指向下一个描述符的指针,从而形成一个链表结构,便于主机快速遍历和解析。
 

1. 标准设备请求

1.1 SETUP事务的数据格式

Host 使用控制传输来识别设备、设置设备地址、启动设备的某些特性,对于控制传输,它首先发出"setup事务"(参考2.5.6 控制传输
在"setup事务"中:
  • SETUP令牌包:用来通知设备,"要开始传输了"
  • DATA0数据包:Host通过DATA0数据包发送8字节数据给设备,用来告诉设备"是读还是写"、"读什么"、"写什么"。它含有固定的格式,格式如下图所示:
    • notion image
      字段作用和含义
      字段按字节偏移量(Offset)从 0 开始排序,总共 8 个字节,字段的作用与组成如下:

      1. bmRequestType (偏移量 0)
      • 大小: 1 字节
      • 类型: 位图 (Bitmap)
      • 描述:
        • bmRequestType 描述请求的特性,包括数据传输方向、请求类型和目标设备。
        • 位定义:
          • D7 (数据传输方向):
            • 0: 从主机到设备 (Host-to-device)
            • 1: 从设备到主机 (Device-to-host)
          • D6...5 (请求类型):
            • 0: 标准请求 (Standard)
            • 1: 类请求 (Class-specific)
            • 2: 厂商自定义请求 (Vendor-specific)
            • 3: 保留 (Reserved)
          • D4...0 (目标类型):
            • 0: 设备 (Device)
            • 1: 接口 (Interface)
            • 2: 端点 (Endpoint)
            • 3: 其它 (Other)
            • 4~31: 保留 (Reserved)

      2. bRequest (偏移量 1)
      • 大小: 1 字节
      • 类型: 值 (Value)
      • 描述:
        • bRequest 指定具体的请求类型,标识主机想对设备执行的操作。
        • 这部分字段的值依赖于请求类型,标准请求的值在 USB 规范 表 9-3 中有定义,例如:
          • 0x06: 获取描述符 (Get Descriptor)
          • 0x09: 设置配置 (Set Configuration)

      3. wValue (偏移量 2)
      • 大小: 2 字节
      • 类型: 值 (Value)
      • 描述:
        • wValue 是一个 16 位(2 字节)的字段,其意义取决于具体请求,通常用来提供请求所需的参数。例如:
          • 在获取描述符请求时(Get Descriptor),wValue 的高字节表示描述符类型(如设备、配置、字符串描述符等),低字节表示描述符索引。
          • 在设置地址请求时(Set Address),wValue 的值表示分配给设备的地址。

      4. wIndex (偏移量 4)
      • 大小: 2 字节
      • 类型: 索引或偏移量 (Index or Offset)
      • 描述:
        • wIndex 的值根据请求而变化,通常用来传递一个接口或者端点的索引。例如:
          • 如果目标是某个接点(Endpoint),wIndex 表示端点号。
          • 如果目标是某个接口(Interface),wIndex 表示接口编号。

      5. wLength (偏移量 6)
      • 大小: 2 字节
      • 类型: 计数器 (Count)
      • 描述:
        • wLength 表示数据阶段 (Data Stage) 中要传输的数据字节数。
        • 当 wLength 为 0 时,这次传输没有数据阶段(仅包含 Setup 阶段)。
        • 通常由主机和设备协商具体的传输长度。

1.2 标准设备请求

控制传输的建立事务中,可以使用下列格式的数据:
notion image
上表中各个"宏"取值如下:
notion image

1.3 设备/配置/接口/端点

SETUP事务的数据里,表示了要访问的是什么:Device?Interface?Endpoint?
对于一个USB设备,它可以多种配置(Configuration)。比如4G上网卡就有2种配置:U盘、上网卡。第1次把4G上网卡插入电脑时,它是一个U盘,可以按照里面的程序。装好程序后,把它再次插入电脑,它就是一个上网卡。
  1. 驱动程序可以选择让它工作于哪种配置,同一时间只能有一种配置。大多数的USB设备只有一种配置。
  1. 一个配置下,可以有多个接口(Interface),接口等同于功能(Function)。比如USB耳机有两个接口(功能):声音收发、按键控制。
  1. 一个接口,可能有多个设置(Setting),比如默认设置下它使用较低的带宽,可以选择其他设置以使用更高带宽。
  1. 一个接口,由一个或多个端点(Endpoint)组成。端点0属于整个设备的,端点0是双向的。接口还可以有其他端点,这些端点是单向的,要么是批量(Bulk)端点、要么是中断(Interrupt)端点、要么是同步(Isochronous)端点。

2. 描述符

怎么描述设备、配置、接口、端点?
USB描述符分为几种类型,主要包括:设备描述符、配置描述符、接口描述符、端点描述符。所谓描述符,就是一些格式化的数据,用来描述信息。
还有一些字符串描述符(String descriptors),它用可读的文字来描述设备,是可选的。
notion image

2.1 设备描述符(Device Descriptor)

每个 USB 设备有且仅有一个设备描述符,用于提供设备的基本信息,包括:
notion image
  • 厂商 ID(VID)和产品 ID(PID)
  • USB 协议版本支持
  • 设备类型、子类和协议
  • 端点 0 的最大数据包大小
  • 设备拥有的配置数量

2.2 配置描述符(Configuration Descriptor)

一个设备可以有多个配置描述符,同一时间只能有一种配置,但通常只有一个。配置描述符定义:
notion image
  • 该配置下的接口数量
  • 供电方式(总线供电或自供电)
  • 最大电流需求
  • 配置属性(如是否支持远程唤醒)

2.3 接口描述符(Interface Descriptor)

每个配置下可以有多个接口描述符,代表设备的不同功能。接口描述符指定:
notion image
  • 接口编号
  • 接口的备用设置(Alternate Settings)数量
  • 接口类型、子类和协议
  • 该接口使用的端点数量
  • 接口的功能说明

2.4 端点描述符(Endpoint Descriptor)

每个接口可以有多个端点描述符(不包括端点 0,它是默认的控制端点)。端点描述符定义:
notion image
  • 端点地址和方向(IN 或 OUT)
  • 传输类型(控制、批量、中断或等时)
  • 端点的最大数据包大小
  • 轮询间隔(对于中断和等时传输)

2.5 描述符示例

在Ubuntu中可以执行lsusb -v查看USB设备的描述符信息:

3. 设备枚举示例

使用"usbprotocolsuite"打开,可以看到设备的枚举过程:
  • 使用控制传输,读取设备信息(设备描述符):第一次读取时,它只需要得到8字节数据,因为第8个数据表示端点0能传输的最大数据长度。
    • notion image
      第四行中,8个字节data数据格式见上文
      数据包结构及通信流程图
      setup stage 要求64个字节,但是data stage 只返回了18字节,这是因为设备描述符只有18个字节。
  • Host分配地址给设备,然后把新地址发给设备:
    • 没有data stage,涉及setup stage 和 status stage。
      notion image
  • 使用新地址,重新读取设备描述符,设备描述符长度是18:
    • notion image
  • 通过设备描述符配置,获取配置描述符
  • 设置配置 configuration
 
上一篇
模板设计模式:让你的代码结构更清晰
下一篇
Guide to Linux System

Comments
Loading...