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. 生命周期
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)链:
- URB 分解:USB Core 将 URB 拆分为多个 TD(根据端点最大包大小)
- 硬件调度:主机控制器按 ED(Endpoint Descriptor)组织 TD 链
- 中断反馈:传输完成后通过
HcInterruptStatus
通知内核
8. 错误处理
错误码 | 含义 | 处理建议 |
---|---|---|
-ENOMEM |
内存不足 | 减少请求大小或重试 |
-ENODEV |
设备已断开 | 停止后续URB提交 |
-EPIPE |
端点暂停(Stall) | 调用usb_clear_halt() |
9. 性能优化
- URB 池化:预分配多个 URB 避免动态分配开销
- 异步提交:在完成回调中提交下一个 URB 保持管道饱和
- 批量化:对大数据传输使用 scatter-gather DMA
10. 与用户空间的交互
通过 ioctl
或 usbfs
可将 URB 暴露给用户程序,实现自定义设备控制(如 libusb
库的核心机制)。
状态:未修正