4. Linux USB核心架构:USB核心层(usbcore)、主机控制器驱动层(HCD)、设备驱动层(usb_driver)

Linux USB子系统采用经典的分层架构设计,从上到下依次为:设备驱动层、USB核心层(usbcore)和主机控制器驱动层(HCD)。这种分层结构实现了硬件无关性与驱动可复用性,是理解USB驱动开发的基础。

核心认知:USB核心层是上下两层之间的“交通枢纽”,它向上为设备驱动提供统一的接口,向下通过HCD抽象不同主机控制器的硬件差异。设备驱动无需关心底层是OHCI、UHCI还是EHCI。

4.1 三层架构总览

下图展示了Linux USB子系统的完整分层结构及各层之间的交互关系:

Linux USB核心架构分层图 Linux USB 子系统三层架构 设备驱动层(usb_driver) USB鼠标驱动 | USB键盘驱动 | USB存储驱动 | USB HID驱动 struct usb_driver → probe() / disconnect() / id_table 注册/回调 USB核心层(usbcore) 设备枚举 | 配置管理 | 端点分配 | 数据传输调度 struct usb_device | struct usb_interface | urb usb_submit_urb() | usb_control_msg() | usb_bulk_msg() HCD接口层 主机控制器驱动层(HCD) OHCI(USB 1.1) | UHCI(USB 1.1) | EHCI(USB 2.0) | XHCI(USB 3.0) struct hc_driver → 硬件寄存器操作 / DMA / 中断处理 USB主机控制器硬件(PCI / Platform)

4.2 各层职责与核心数据结构

每一层都有明确的职责边界和核心数据结构,理解这些是编写USB驱动的第一步。

层次 核心职责 关键数据结构 主要接口/函数
设备驱动层 实现具体设备功能(鼠标、键盘、存储等) struct usb_driver
struct usb_class_driver
probe() / disconnect()
usb_register()
USB核心层 设备枚举、配置管理、URB调度、电源管理 struct usb_device
struct usb_interface
struct urb
usb_submit_urb()
usb_control_msg()
主机控制器驱动层 直接操作硬件寄存器、处理中断、DMA传输 struct hc_driver
struct usb_hcd
hcd->driver->start()
urb_enqueue()

4.3 设备驱动层(usb_driver)

设备驱动层是开发者最常接触的层次。每个USB设备驱动通过注册一个struct usb_driver实例来声明自己支持的设备。

/* USB驱动结构体核心成员 */
struct usb_driver {
    const char *name;                    /* 驱动名称 */
    int (*probe) (struct usb_interface *intf,
                  const struct usb_device_id *id);  /* 设备匹配后调用 */
    void (*disconnect) (struct usb_interface *intf); /* 设备拔出时调用 */
    const struct usb_device_id *id_table; /* 支持的设备ID列表 */
    int (*suspend) (struct usb_interface *intf,
                    pm_message_t message); /* 电源管理 */
    int (*resume) (struct usb_interface *intf);
};
开发要点:设备驱动层不直接操作USB总线事务。当需要与设备通信时,驱动调用usbcore提供的API(如usb_control_msg())来构造并提交URB,由核心层和HCD层完成实际传输。

4.4 USB核心层(usbcore)

usbcore是USB子系统的中枢,它实现了以下关键功能:

  • 设备枚举:检测设备插入/拔出,读取设备描述符、配置描述符、接口描述符和端点描述符。
  • 配置管理:为设备选择配置(struct usb_host_config),分配接口和端点资源。
  • URB管理:提供URB(USB Request Block)的创建、提交、取消和完成回调机制。
  • 总线调度:管理USB帧/微帧的传输时间片,确保实时性要求。
  • 电源管理:处理挂起/唤醒、远程唤醒等电源事件。

usbcore对外暴露的核心API包括:

/* 控制传输(常用于枚举和配置) */
int usb_control_msg(struct usb_device *dev, unsigned int pipe,
                    __u8 request, __u8 requesttype,
                    __u16 value, __u16 index,
                    void *data, __u16 size, int timeout);

/* 批量传输(常用于存储、网络设备) */
int usb_bulk_msg(struct usb_device *dev, unsigned int pipe,
                 void *data, int len, int *actual_length,
                 int timeout);

/* 中断传输(常用于HID设备) */
int usb_interrupt_msg(struct usb_device *dev, unsigned int pipe,
                      void *data, int len, int *actual_length,
                      int timeout);

/* 异步URB提交(高性能场景) */
int usb_submit_urb(struct urb *urb, gfp_t mem_flags);

4.5 主机控制器驱动层(HCD)

HCD层直接与硬件打交道,是USB子系统中唯一与具体主机控制器硬件相关的部分。Linux支持四种主流HCD标准:

HCD类型 USB版本 传输速率 典型硬件 驱动文件
OHCI USB 1.1 1.5 Mbps / 12 Mbps 嵌入式平台、旧式PC ohci-hcd.c
UHCI USB 1.1 1.5 Mbps / 12 Mbps Intel/VIA芯片组 uhci-hcd.c
EHCI USB 2.0 480 Mbps 大多数现代PC ehci-hcd.c
XHCI USB 3.0/3.1 5 Gbps / 10 Gbps 现代PC、服务器 xhci-hcd.c
兼容性注意:XHCI控制器可以向下兼容USB 2.0和USB 1.1设备,但需要usbcore在枚举时通过“端口握手”机制将低速/全速/高速设备路由到对应的配套控制器(Companion Controller)。嵌入式开发中,如果使用USB 3.0控制器连接低速HID设备,务必确认XHCI驱动对低速设备的支持情况。

4.6 三层协作流程:以HID设备枚举为例

当一个USB鼠标插入系统时,三层架构的协作流程如下:

  1. HCD层检测到端口状态变化(中断或轮询),通知usbcore。
  2. usbcore启动枚举流程:复位设备 → 获取设备描述符 → 分配地址 → 获取配置描述符 → 解析接口和端点。
  3. usbcore根据id_table匹配已注册的usb_driver(如usbhid驱动)。
  4. 设备驱动层的probe()被调用,驱动解析HID报告描述符,注册输入设备。
  5. 驱动通过usb_submit_urb()提交中断URB,usbcore将其传递给HCD层。
  6. HCD层将URB转换为硬件事务,通过DMA或PIO与设备交换数据。
USB三层协作枚举流程 USB三层协作:HID设备枚举流程 HCD层 检测到端口状态变化 → 通知usbcore usbcore 复位设备 → 获取设备描述符 → 分配地址 usbcore 获取配置描述符 → 解析接口/端点 → 匹配驱动 设备驱动层 probe()被调用 → 解析HID报告 → 注册输入设备 设备驱动层 提交中断URB → usbcore转发 → HCD层执行硬件传输 ① ② ③ ④ ⑤

4.7 关键设计原则

分层隔离原则:
  • 设备驱动层 不直接访问 主机控制器寄存器。
  • HCD层 不关心 设备的具体功能(鼠标、键盘还是存储)。
  • usbcore层 不感知 设备驱动内部状态,只负责传输调度和资源管理。
这种设计使得添加一个新的USB设备驱动时,无需修改HCD代码;更换主机控制器硬件时,也无需改动上层驱动。