Linux USB驱动移植 从芯片选型到设备树适配 - 第1节

1. USB协议基础

USB(Universal Serial Bus)采用主从式星形拓扑,由一个主机控制器(Host Controller)管理总线上所有设备。与PCIe、Ethernet等对等总线不同,USB总线上的所有通信必须由主机发起,设备不能主动发送数据。

核心概念: USB拓扑是非对称的——主机是唯一的通信调度者,设备只能被动响应。这一特性决定了USB驱动模型中主机端(Host Side)和设备端(Device Side)的代码结构完全不同。

1.1.1 拓扑层次结构

USB总线在物理上分为四层:

  • 主机(Host):包含USB主机控制器(如EHCI、XHCI)和根集线器(Root Hub)。
  • 集线器(Hub):负责端口扩展和信号中继,每个集线器可向下连接最多7个设备(包括下级集线器)。
  • 功能设备(Function Device):实现具体功能的终端设备,如U盘、鼠标、摄像头。
  • 复合设备(Composite Device):一个物理设备包含多个功能(如带麦克风的摄像头),通过内部集线器或接口描述符实现。
USB总线拓扑结构 USB主机控制器 (Host) 根集线器 (Root Hub) 集线器 (Hub) 1 集线器 (Hub) 2 功能设备 A 功能设备 B 复合设备 功能设备 C 拓扑规则 • 最多支持 127 个设备(含集线器) • 最大级联深度为 7 层(含根集线器) • 所有通信必须由主机发起

1.1.2 物理连接与电气特性

信号线 颜色 功能 备注
VBUS 红色 电源(+5V) 低功耗设备最大 100mA,高功耗设备最大 500mA(USB 2.0)
D- 白色 差分数据负端 与 D+ 配合传输差分信号
D+ 绿色 差分数据正端 USB 2.0 高速模式下 D+ 上拉 1.5kΩ 电阻
GND 黑色 地线 公共参考地
驱动移植提示: 在嵌入式平台(如i.MX6ULL、STM32MP1)上移植USB驱动时,必须确认VBUS电源控制GPIO和D+/D-的PCB走线阻抗(90Ω差分)。设备树中通常需要配置 vbus-supply 和 disable-over-current 属性。

1.2 USB传输类型

USB总线定义了四种传输类型,分别对应不同的带宽、延迟和可靠性需求。驱动开发者在选择端点(Endpoint)时必须明确传输类型,因为这会直接影响数据吞吐量和CPU占用率。

USB四种传输类型对比 控制传输 Control Transfer 配置/命令/状态 保证送达,带宽小 批量传输 Bulk Transfer 大块数据/U盘/打印机 利用空闲带宽,CRC校验 中断传输 Interrupt Transfer 鼠标/键盘/游戏手柄 保证轮询间隔,低延迟 同步传输 Isochronous Transfer 音频/视频/实时数据 无重传,带宽保证 传输类型选择策略 • 控制传输:枚举阶段必须使用,端点0固定为控制端点 • 批量传输:大数据量、非实时场景(存储、网络) • 中断传输:小数据量、周期性查询(HID设备) • 同步传输:实时流媒体,允许少量丢包(UAC、UVC)

1.2.1 控制传输(Control Transfer)

控制传输是USB中最基础的传输类型,用于设备枚举、配置查询和命令发送。每个USB设备必须实现端点0(默认控制端点),主机通过端点0读取设备描述符、设置地址和配置。

控制传输包含两个或三个阶段:

  1. 建立阶段(Setup):主机发送8字节的Setup包,包含请求类型、请求码、参数。
  2. 数据阶段(Data)(可选):主机或设备发送数据,方向由Setup包中的方向位决定。
  3. 状态阶段(Status):接收方返回握手包,确认传输完成。
驱动开发关键点: 在Linux USB子系统中,控制传输通过 usb_control_msg() 函数实现。设备驱动中常见的 usb_get_descriptor()、usb_set_configuration() 底层都使用控制传输。移植时需确保端点0的最大包大小(bMaxPacketSize0)与硬件匹配。

1.2.2 批量传输(Bulk Transfer)

批量传输用于大数据量、非实时的数据传输,如U盘读写、USB以太网卡。它利用总线空闲带宽,当总线繁忙时会被延迟,但通过CRC16/CRC32校验和重传机制保证数据完整性。

USB版本 批量传输最大包大小 典型吞吐量
USB 1.1 64 字节 ~1.2 MB/s
USB 2.0 512 字节 ~40 MB/s(理论)
USB 3.0 1024 字节 ~400 MB/s(理论)

1.2.3 中断传输(Interrupt Transfer)

中断传输并非硬件中断,而是主机保证以固定间隔轮询设备,获取小量数据。适用于人机交互设备(HID),如鼠标、键盘、游戏手柄。

  • 轮询间隔(bInterval):在端点描述符中定义,USB 2.0高速模式下最小间隔为125μs(微帧)。
  • 最大包大小:USB 2.0低速模式最大8字节,全速64字节,高速1024字节。
  • 可靠性:支持重传,保证数据送达。

1.2.4 同步传输(Isochronous Transfer)

同步传输用于实时数据流,如USB音频(UAC)和USB视频(UVC)。它不保证数据送达(无重传),但保证带宽和固定时间间隔。

移植注意事项: 同步传输对硬件DMA和内存带宽要求较高。在嵌入式平台上,如果USB控制器不支持同步传输(如某些低端MCU),则无法实现UAC/UVC设备。设备树中需确认 usb-phy 和 dma-ranges 配置是否正确。

1.3 USB描述符体系

USB描述符是设备向主机报告自身能力的结构化数据。主机通过枚举过程读取描述符,从而识别设备类型、分配驱动、配置端点。描述符采用层级树状结构,从设备描述符向下逐级展开。

USB描述符层级结构 设备描述符 (Device Descriptor) 配置描述符 (Configuration Descriptor) 接口描述符 (Interface Descriptor) 接口描述符 (Interface Descriptor) 端点描述符 (EP Desc) 端点描述符 (EP Desc) 端点描述符 (EP Desc) ... 其他可选描述符 字符串描述符 (String Descriptor) — 提供可读的厂商/产品名称 设备限定描述符 (Device Qualifier Descriptor) — USB 2.0高速/全速切换信息 其他速度配置描述符 (Other Speed Configuration Descriptor)

1.3.1 设备描述符(Device Descriptor)

设备描述符是USB设备的根描述符,主机通过端点0读取的第一个描述符就是它。它包含设备的基本标识和全局信息。

字段 偏移 大小 说明 驱动移植关注点
bLength 0 1 描述符长度(固定18字节) —
bDescriptorType 1 1 描述符类型(设备描述符=1) —
bcdUSB 2 2 USB规范版本号(BCD码,如0x0200=USB 2.0) 决定控制器驱动(EHCI/XHCI)
bDeviceClass 4 1 设备类代码(0x00=接口定义,0xFF=厂商自定义) 影响驱动匹配优先级
bDeviceSubClass 5 1 设备子类代码 —
bDeviceProtocol 6 1 设备协议代码 —
bMaxPacketSize0 7 1 端点0最大包大小(8/16/32/64) 必须与硬件FIFO匹配
idVendor 8 2 厂商ID(USB-IF分配) 驱动匹配的关键标识
idProduct 10 2 产品ID 驱动匹配的关键标识
bcdDevice 12 2 设备版本号(BCD码) —
iManufacturer 14 1 厂商字符串描述符索引 —
iProduct 15 1 产品字符串描述符索引 —
iSerialNumber 16 1 序列号字符串描述符索引 —
bNumConfigurations 17 1 支持的配置数量 通常为1

1.3.2 配置描述符(Configuration Descriptor)

配置描述符描述设备的电源管理和接口数量。一个设备可以有多个配置(如USB 2.0和USB 3.0模式),但同一时刻只能激活一个配置。

  • bConfigurationValue:配置编号,驱动通过 usb_set_configuration() 选择。
  • bNumInterfaces:该配置下的接口数量。
  • bMaxPower:设备从VBUS获取的最大电流(单位2mA),如50表示100mA。
  • bmAttributes:配置特性,bit6=自供电,bit5=远程唤醒。

1.3.3 接口描述符(Interface Descriptor)

接口描述符是驱动绑定的核心单元。Linux USB驱动通过 struct usb_interface 表示一个接口,驱动匹配时比较接口的、、。

驱动移植实战: 在设备树中,USB设备通常不需要显式描述接口——接口信息由设备自身的固件描述符提供。但复合设备(Composite Device)可能需要在内核配置中启用 CONFIG_USB_GADGET 和对应的功能驱动(如 CONFIG_USB_ETH、CONFIG_USB_MASS_STORAGE)。

1.3.4 端点描述符(Endpoint Descriptor)

端点描述符定义数据传输的通道属性。每个端点(除端点0外)必须有一个端点描述符。

字段 说明 驱动移植关键点
bEndpointAddress 端点号(bit7=方向,0 OUT/1 IN) 驱动中通过 usb_rcvbulkpipe() / usb_sndbulkpipe() 构造管道
bmAttributes 传输类型(0=控制,1=同步,2=批量,3=中断) 决定使用哪个URB函数族
wMaxPacketSize 最大包大小(bit10-0=大小,bit12-11=附加事务数) 必须与控制器FIFO深度匹配
bInterval 轮询间隔(中断/同步传输使用) 影响中断URB的调度频率

1.3.5 字符串描述符(String Descriptor)

字符串描述符提供人类可读的文本信息,如厂商名称、产品名称、序列号。它是可选的,但大多数设备至少包含一个产品字符串。字符串使用Unicode(UTF-16LE)编码。

调试技巧: 在Linux下使用 lsusb -v 可以查看所有描述符的原始内容。例如:
# lsusb -d 046d:c077 -v | grep -A 10 "Device Descriptor"
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0
  idVendor           0x046d (Logitech)
  idProduct          0xc077
  bcdDevice           72.00
  iManufacturer           1
  iProduct                2
  iSerial                 0
  bNumConfigurations      1

1.4 本章小结