3. Linux内核USB核心数据结构

USB子系统在Linux内核中通过四个核心数据结构来抽象物理设备、逻辑功能、传输端点和I/O请求。理解usb_device、usb_interface、usb_host_endpoint和urb是编写USB驱动的基础,也是分析枚举流程的关键。

学习提示: 这四个结构体分别对应USB规范中的设备层、配置/接口层、端点层和传输层。驱动开发中90%的USB操作都围绕它们展开。

3.1 usb_device —— USB设备的软件抽象

usb_device是内核中代表一个物理USB设备的核心结构体,定义在include/linux/usb.h中。每个连接到USB总线上的设备(包括Hub)都会对应一个usb_device实例。

struct usb_device {
    int devnum;                     // 设备地址(1-127)
    enum usb_device_state state;    // 设备状态:ATTACHED/POWERED/DEFAULT/ADDRESS/CONFIGURED/SUSPENDED
    enum usb_device_speed speed;    // 速度:USB_SPEED_LOW/FULL/HIGH/SUPER/SUPER_PLUS
    unsigned int route;             // 拓扑路径位图(USB 3.0+)
    struct usb_device *parent;      // 父设备(Hub)
    struct usb_device **children;   // 子设备数组(Hub端口)
    struct usb_device_descriptor descriptor; // 设备描述符
    struct usb_host_config *config; // 当前激活的配置
    struct usb_host_config *rawdescriptors; // 原始配置描述符
    unsigned short bus_mA;          // 总线供电电流(mA)
    u8 portnum;                     // 父Hub上的端口号
    u8 level;                       // 拓扑深度
    struct device dev;              // 内核通用设备结构
    struct usb_bus *bus;            // 所属USB总线
};
关键字段解读:
  • devnum:枚举过程中由内核分配,范围1~127,0表示未分配地址。
  • state:反映设备在枚举流程中的当前阶段,驱动可通过usb_get_device_state()查询。
  • speed:决定传输时序和带宽计算,直接影响端点最大包大小。
  • config:指向当前激活的usb_host_config,一个设备同一时刻只能有一个配置激活。
usb_device 结构体核心字段关系图 struct usb_device devnum / state / speed parent / children descriptor config 设备地址/状态/速度 USB拓扑树关系 设备描述符(18字节) 当前配置 usb_device 生命周期 1. 设备插入 → 2. Hub检测到端口状态变化 → 3. 内核分配usb_device 4. 枚举(获取描述符、分配地址) → 5. 选择配置 → 6. 驱动绑定

3.2 usb_interface —— 逻辑功能单元

usb_interface是USB设备中一个独立功能的抽象。一个USB配置(Configuration)可以包含多个接口(Interface),每个接口对应一个逻辑功能,例如一个复合设备可能包含键盘接口和音频接口。

struct usb_interface {
    struct usb_host_interface *altsetting;    // 当前激活的备用设置
    struct usb_host_interface *cur_altsetting; // 当前备用设置指针
    unsigned num_altsetting;                  // 备用设置数量
    struct usb_interface_descriptor desc;     // 接口描述符
    struct device dev;                        // 内核通用设备结构
    struct usb_device *usb_dev;               // 所属usb_device
    int minor;                                // USB major号(用于usbfs)
};
常见误区: 驱动绑定的是usb_interface而非usb_device。一个设备可以有多个接口,每个接口由不同的驱动管理。例如USB摄像头通常包含视频接口和音频接口,分别由uvcvideo和snd-usb-audio驱动处理。
usb_interface 与 usb_device 对比
对比维度 usb_device usb_interface
代表对象 物理USB设备 逻辑功能单元
驱动绑定 否(Hub驱动绑定) 是(功能驱动绑定)
数量关系 1个设备 1~多个接口
枚举时机 设备插入时创建 选择配置后创建
端点归属 设备级描述符 接口级端点集合
USB复合设备:usb_device → usb_interface 映射 usb_device Configuration Interface 0 (键盘) Interface 1 (音频) Interface 2 (HID) EP IN / EP OUT EP IN (isochronous) EP IN (interrupt)

3.3 usb_host_endpoint —— 传输端点描述

usb_host_endpoint封装了USB端点的硬件属性和内核管理信息。每个端点对应设备端的一个数据缓冲区,驱动通过端点进行数据收发。

struct usb_host_endpoint {
    struct usb_endpoint_descriptor desc;      // 端点描述符(地址、属性、最大包大小)
    struct list_head urb_list;                // 挂起的URB链表
    void *hcpriv;                             // Host Controller私有数据
    struct ep_device *ep_dev;                 // sysfs端点设备
    unsigned char *extra;                     // 额外描述符
    int enabled;                              // 端点使能标志
};
USB端点传输类型对比
传输类型 端点属性 典型应用 带宽保证 错误重传
控制传输 0x00 枚举、配置命令 10%保留 硬件自动重试
批量传输 0x02 U盘、打印机 无 硬件自动重试
中断传输 0x03 键盘、鼠标 保证延迟 硬件自动重试
等时传输 0x01 音频、视频 保证带宽 无重传
usb_host_endpoint 与端点描述符结构 usb_endpoint_descriptor bEndpointAddress bmAttributes wMaxPacketSize bInterval usb_host_endpoint urb_list (URB链表) hcpriv (HC私有数据) 端点地址编码规则 bEndpointAddress[7] = 方向(0: OUT, 1: IN) | bEndpointAddress[3:0] = 端点号(0~15)

3.4 urb —— USB请求块

urb(USB Request Block)是USB数据传输的基本载体,类似于网络协议栈中的sk_buff。驱动通过构造并提交URB来发起一次USB传输。

struct urb {
    struct list_head urb_list;           // 链表节点
    struct usb_device *dev;              // 目标设备
    unsigned int pipe;                   // 管道信息(端点+方向+类型)
    int status;                          // 传输状态
    unsigned int transfer_flags;         // 传输标志
    void *transfer_buffer;               // 数据缓冲区
    dma_addr_t transfer_dma;             // DMA地址
    int transfer_buffer_length;          // 缓冲区长度
    int actual_length;                   // 实际传输长度
    int interval;                        // 中断/等时传输间隔
    int error_count;                     // 等时传输错误计数
    void *context;                       // 完成回调上下文
    usb_complete_t complete;             // 完成回调函数
    int number_of_packets;               // 等时传输包数量
    struct usb_iso_packet_descriptor iso_frame_desc[]; // 等时帧描述符
};
URB生命周期:
  1. 创建:usb_alloc_urb() 分配URB结构体
  2. 填充:设置设备、管道、缓冲区、回调函数
  3. 提交:usb_submit_urb() 将URB加入端点队列
  4. 执行:Host Controller处理URB,进行DMA传输
  5. 完成:回调函数被调用,驱动处理结果
  6. 释放:usb_free_urb() 回收资源
URB生命周期与数据流 1. usb_alloc_urb 2. 填充URB 3. usb_submit_urb 4. HC处理 分配URB结构体 设置transfer_flags 初始化链表 设置dev/pipe 绑定缓冲区 注册complete回调 加入端点队列 检查带宽 返回0或错误码 DMA传输 硬件中断 更新actual_length 5. complete回调执行 6. usb_free_urb

3.5 四者关系总结

四个核心数据结构在USB驱动栈中的层次关系如下:

USB核心数据结构层次关系
层次 数据结构 对应USB规范 驱动操作
设备层 usb_device Device usb_alloc_dev() / usb_new_device()
接口层 usb_interface Interface usb_set_interface() / usb_find_interface()
端点层 usb_host_endpoint Endpoint usb_endpoint_dir_in() / usb_endpoint_maxp()
传输层 urb Transfer usb_submit_urb() / usb_kill_urb()
驱动开发实用技巧:
  • 通过interface_to_usbdev(interface)从usb_interface获取usb_device。
  • 使用usb_rcvbulkpipe()/usb_sndbulkpipe()等宏构造管道值(pipe)。
  • 批量传输推荐使用usb_bulk_msg()简化URB管理,但等时传输必须手动管理URB。
  • URB回调函数在中断上下文执行,不能调用可能导致睡眠的函数。
USB核心数据结构层次架构 usb_device — 物理设备抽象 ← 上一章 📖 返回目录 下一章 →