3. Linux USB子系统架构:USB核心、HCD、usbcore、设备驱动模型
USB子系统是Linux内核中最为复杂的设备管理框架之一,它通过分层设计将主机控制器硬件、总线协议与设备驱动解耦。理解这一架构是编写正确、高效USB驱动的前提。本章将剖析USB子系统的四个核心层次:USB核心(USB Core)、主机控制器驱动(HCD)、usbcore以及设备驱动模型,并揭示它们之间的数据流与控制流关系。
架构要点: USB子系统采用“主机侧-总线-设备侧”三层模型。主机侧由HCD驱动具体硬件(如EHCI、xHCI),USB核心提供通用API与urb管理,usbcore负责设备枚举与配置,设备驱动模型则通过usb_driver与内核设备模型对接。
3.1 整体分层架构
下图展示了USB子系统在Linux内核中的完整层次结构,从最底层的硬件到最上层的设备驱动,每一层都有明确的职责边界。
关键理解: 设备驱动不直接操作HCD。所有通信都通过USB核心提供的urb接口进行。usbcore在设备枚举阶段负责将USB设备描述符解析为内核设备模型中的usb_device、usb_interface等结构体。
3.2 核心组件详解
3.2.1 USB核心(USB Core)
USB核心是USB子系统的中枢神经,它提供了一组与硬件无关的API,供上层驱动和usbcore调用。主要功能包括:
- urb生命周期管理:
usb_alloc_urb()、usb_submit_urb()、usb_kill_urb()、usb_free_urb() - 端点与管道抽象: 将端点地址映射为管道(pipe),提供
usb_sndintpipe()、usb_rcvintpipe()等宏 - DMA缓冲区管理:
usb_alloc_coherent()、usb_free_coherent() - 设备描述符访问:
usb_get_descriptor()系列函数
3.2.2 主机控制器驱动(HCD)
HCD是唯一直接操作硬件寄存器的层。Linux支持四种主机控制器标准:
| 标准 | 速度 | 典型硬件 | 内核驱动 |
|---|---|---|---|
| UHCI | USB 1.1 (全速/低速) | Intel/VIA南桥 | uhci-hcd |
| OHCI | USB 1.1 (全速/低速) | 非Intel平台(如S3C2440) | ohci-hcd |
| EHCI | USB 2.0 (高速) | 大多数PC主板 | ehci-hcd |
| xHCI | USB 3.0/3.1 (超高速) | 现代Intel/AMD平台 | xhci-hcd |
开发注意: 编写设备驱动时,不需要关心底层是哪种HCD。USB核心的urb提交机制会通过
struct hc_driver回调自动路由到正确的HCD实现。但理解HCD差异有助于调试DMA对齐、中断延迟等问题。
3.2.3 usbcore
usbcore是USB子系统的总线逻辑层,它实现了USB规范中的核心协议处理:
- 设备枚举: 检测设备插入/拔出,分配地址,读取设备/配置/接口/端点描述符
- 配置管理: 选择活动配置,激活接口与端点
- hub驱动: 管理USB hub,处理端口状态变化
- 设备模型集成: 创建
usb_device和usb_interface内核对象,触发uevent
3.2.4 设备驱动模型
USB设备驱动模型遵循Linux内核标准的总线-设备-驱动模型:
- 总线:
usb_bus_type— 注册所有USB设备与驱动 - 设备:
struct usb_device(代表物理设备)、struct usb_interface(代表功能接口) - 驱动:
struct usb_driver— 包含probe()、disconnect()、id_table
驱动与设备的匹配通过usb_device_id表完成,匹配字段包括idVendor、idProduct、bInterfaceClass等。
3.3 关键数据结构关系
以下SVG展示了USB子系统中核心数据结构之间的引用关系,这是驱动开发者必须掌握的内存模型。
3.4 中断端点与URB回调的架构位置
在USB子系统的分层架构中,中断端点和URB回调的协同工作涉及三个层次:
- 设备驱动层: 分配并初始化urb,设置
complete回调函数,指定中断端点管道 - USB核心层: 将urb提交到端点队列,管理DMA映射,调用HCD的
urb_enqueue方法 - HCD层: 将urb转换为硬件传输描述符(TD),在中断服务例程中检查传输完成,调用urb回调
回调执行上下文: URB回调函数在
softirq(软中断)上下文中执行,不能调用可能导致睡眠的函数(如kmalloc(GFP_KERNEL)、mutex_lock())。如果需要执行阻塞操作,必须通过workqueue或tasklet将工作推迟到进程上下文。
3.5 架构总结与对比
| 层次 | 核心文件 | 主要职责 | 与中断端点的关系 |
|---|---|---|---|
| 设备驱动 | drivers/usb/class/* |
实现具体设备功能,处理数据 | 分配urb,设置中断端点管道,实现回调 |
| usbcore | drivers/usb/core/hub.c |
设备枚举,配置管理,模型集成 | 枚举时读取中断端点描述符 |
| USB核心 | drivers/usb/core/urb.c |
urb分配/提交/取消,DMA管理 | 提供urb操作API,管理端点队列 |
| HCD | drivers/usb/host/ehci-hcd.c |
硬件寄存器操作,中断处理 | 将urb映射为硬件TD,触发中断回调 |
学习路径建议: 对于中断端点驱动的开发,重点掌握
drivers/usb/core/urb.c中的urb API和include/linux/usb.h中的数据结构定义。HCD层的细节可以在遇到性能问题时再深入。