Linux USB驱动移植 从芯片选型到设备树适配 - 第1节
1. USB协议基础
USB(Universal Serial Bus)采用主从式星形拓扑,由一个主机控制器(Host Controller)管理总线上所有设备。与PCIe、Ethernet等对等总线不同,USB总线上的所有通信必须由主机发起,设备不能主动发送数据。
1.1.1 拓扑层次结构
USB总线在物理上分为四层:
- 主机(Host):包含USB主机控制器(如EHCI、XHCI)和根集线器(Root Hub)。
- 集线器(Hub):负责端口扩展和信号中继,每个集线器可向下连接最多7个设备(包括下级集线器)。
- 功能设备(Function Device):实现具体功能的终端设备,如U盘、鼠标、摄像头。
- 复合设备(Composite Device):一个物理设备包含多个功能(如带麦克风的摄像头),通过内部集线器或接口描述符实现。
1.1.2 物理连接与电气特性
| 信号线 | 颜色 | 功能 | 备注 |
|---|---|---|---|
| VBUS | 红色 | 电源(+5V) | 低功耗设备最大 100mA,高功耗设备最大 500mA(USB 2.0) |
| D- | 白色 | 差分数据负端 | 与 D+ 配合传输差分信号 |
| D+ | 绿色 | 差分数据正端 | USB 2.0 高速模式下 D+ 上拉 1.5kΩ 电阻 |
| GND | 黑色 | 地线 | 公共参考地 |
vbus-supply 和 disable-over-current 属性。
1.2 USB传输类型
USB总线定义了四种传输类型,分别对应不同的带宽、延迟和可靠性需求。驱动开发者在选择端点(Endpoint)时必须明确传输类型,因为这会直接影响数据吞吐量和CPU占用率。
1.2.1 控制传输(Control Transfer)
控制传输是USB中最基础的传输类型,用于设备枚举、配置查询和命令发送。每个USB设备必须实现端点0(默认控制端点),主机通过端点0读取设备描述符、设置地址和配置。
控制传输包含两个或三个阶段:
- 建立阶段(Setup):主机发送8字节的Setup包,包含请求类型、请求码、参数。
- 数据阶段(Data)(可选):主机或设备发送数据,方向由Setup包中的方向位决定。
- 状态阶段(Status):接收方返回握手包,确认传输完成。
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)。它不保证数据送达(无重传),但保证带宽和固定时间间隔。
usb-phy 和 dma-ranges 配置是否正确。
1.3 USB描述符体系
USB描述符是设备向主机报告自身能力的结构化数据。主机通过枚举过程读取描述符,从而识别设备类型、分配驱动、配置端点。描述符采用层级树状结构,从设备描述符向下逐级展开。
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 表示一个接口,驱动匹配时比较接口的
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)编码。
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