1. 基本定义

URB 是 USB 请求块(USB Request Block)的缩写,为 Linux USB 子系统中的核心数据结构,用于描述一个完整的 USB 传输请求(如控制传输、批量传输等)。

USB充当主机控制器驱动(如 OHCI/UHCI)与 USB 设备驱动之间的通信媒介。


2. 数据结构(简化版)

struct urb {
    struct usb_device *dev;          // 目标USB设备
    unsigned int pipe;               // 管道信息(设备地址+端点号+传输类型)
    void *transfer_buffer;          // 数据缓冲区
    int transfer_buffer_length;     // 数据长度
    usb_complete_t complete;        // 回调函数
    void *context;                  // 回调上下文
    int status;                     // 传输状态(成功/错误码)
    int actual_length;              // 实际传输的字节数
    // ...其他控制字段(ISO帧描述、间隔时间等)
};

3. 生命周期

sequenceDiagram participant Driver participant USB Core participant HC(Host Controller) Driver->>USB Core: usb_alloc_urb() Driver->>USB Core: usb_fill_bulk_urb() Driver->>USB Core: usb_submit_urb() USB Core->>HC: 将URB加入调度队列 HC->>USB Core: 传输完成中断 USB Core->>Driver: 调用complete回调 Driver->>USB Core: usb_free_urb()

4. 关键字段解析

字段 作用
pipe 编码目标端点、传输类型和方向(详见usb_sndctrlpipe()等宏)
transfer_buffer DMA映射后的物理地址(由主机控制器直接访问)
status 传输结果(如-EPIPE表示端点错误,0表示成功)
actual_length 实际传输的数据长度(可能小于transfer_buffer_length

5. 传输类型支持

URB 可处理所有 USB 传输类型:

类型 初始化函数 典型应用
控制传输 usb_fill_control_urb() 设备配置/命令
批量传输 usb_fill_bulk_urb() 大文件传输(U盘等)
中断传输 usb_fill_int_urb() 键盘/鼠标事件
等时传输 usb_fill_iso_urb() 音频/视频流

6. 驱动开发示例

批量传输URB提交

struct urb *urb;
void *buf = kmalloc(BUF_SIZE, GFP_KERNEL);

// 1. 分配URB
urb = usb_alloc_urb(0, GFP_KERNEL);

// 2. 填充批量URB参数
usb_fill_bulk_urb(urb, dev, usb_sndbulkpipe(dev, ep_num), 
                 buf, BUF_SIZE, complete_cb, dev);

// 3. 提交URB
ret = usb_submit_urb(urb, GFP_KERNEL);
if (ret) {
    err("提交失败: %d", ret);
    usb_free_urb(urb);
}

完成回调函数

void complete_cb(struct urb *urb) {
    if (urb->status) {
        printk("传输错误: %d\n", urb->status);
    } else {
        printk("成功传输%d字节\n", urb->actual_length);
    }
    usb_free_urb(urb);  // 释放URB
}

7. 内核实现机制

URB 的底层处理依赖主机控制器驱动(如 OHCI)的 TD(Transfer Descriptor)链

  1. URB 分解:USB Core 将 URB 拆分为多个 TD(根据端点最大包大小)
  2. 硬件调度:主机控制器按 ED(Endpoint Descriptor)组织 TD 链
  3. 中断反馈:传输完成后通过 HcInterruptStatus 通知内核

8. 错误处理

错误码 含义 处理建议
-ENOMEM 内存不足 减少请求大小或重试
-ENODEV 设备已断开 停止后续URB提交
-EPIPE 端点暂停(Stall) 调用usb_clear_halt()

9. 性能优化

  1. URB 池化:预分配多个 URB 避免动态分配开销
  2. 异步提交:在完成回调中提交下一个 URB 保持管道饱和
  3. 批量化:对大数据传输使用 scatter-gather DMA

10. 与用户空间的交互

通过 ioctlusbfs 可将 URB 暴露给用户程序,实现自定义设备控制(如 libusb 库的核心机制)。


状态:未修正