2. UDC 驱动核心数据结构详解

在 USB Gadget 框架中,UDC(USB Device Controller)驱动层通过三个核心数据结构完成对底层硬件、设备控制器以及上层功能的抽象。理解 struct usb_gadget、struct usb_udc 和 struct usb_gadget_driver 的成员与作用,是进行 UDC 驱动移植和枚举流程分析的基础。

核心关系提示: 一个 usb_udc 管理一个物理 UDC 控制器实例;该控制器实例通过 usb_gadget 暴露给 Gadget 功能层;usb_gadget_driver 则代表一个具体的 Gadget 功能(如 ECM、ACM、Mass Storage),三者通过注册与绑定机制协同工作。

2.1 struct usb_gadget:设备控制器抽象

struct usb_gadget 是 UDC 硬件控制器的软件抽象,它代表一个 USB 设备端控制器实例。该结构体包含了控制器的状态、能力、操作接口以及与系统其他部分的连接信息。

关键作用: 作为 UDC 驱动与 Gadget 功能驱动之间的桥梁,提供对底层硬件控制器的统一访问接口。

2.1.1 主要成员与作用

成员名 类型 作用描述
ops struct usb_gadget_ops * 指向控制器操作函数集,包括 get_frame、wakeup、set_selfpowered、vbus_session、pullup 等硬件级操作。
ep0 struct usb_ep * 指向端点 0(控制端点)的实例,用于枚举过程中的控制传输。
eps struct list_head 链表头,挂载该控制器所有可用的端点(struct usb_ep),供 Gadget 功能驱动遍历和申请。
speed enum usb_device_speed 记录当前协商的 USB 总线速度(USB_SPEED_HIGH/LOW/FULL/SUPER)。
max_speed enum usb_device_speed 控制器硬件支持的最高速度能力。
state enum usb_device_state USB 设备状态机当前状态(如 USB_STATE_NOTATTACHED、USB_STATE_POWERED、USB_STATE_DEFAULT、USB_STATE_ADDRESS、USB_STATE_CONFIGURED)。
name const char * 控制器名称,通常与设备树中匹配的 compatible 字符串或平台设备名一致。
dev struct device 内嵌的通用设备结构体,用于设备模型管理、sysfs 属性导出等。
udc struct usb_udc * 反向指针,指向管理该 gadget 的 UDC 核心层实例。
sg_supported unsigned 标志位,指示控制器是否支持 scatter-gather DMA 传输。
is_otg unsigned 标志位,指示控制器是否支持 OTG(On-The-Go)规范。

2.1.2 struct usb_gadget 与控制器操作集关系

下图展示了 struct usb_gadget 与 struct usb_gadget_ops 之间的引用关系,以及 ops 中关键回调函数的作用。

struct usb_gadget 与 usb_gadget_ops 关系图 struct usb_gadget ops → usb_gadget_ops * ep0 → usb_ep * speed / max_speed state / name / dev struct usb_gadget_ops int (*get_frame)(struct usb_gadget *); int (*wakeup)(struct usb_gadget *); int (*set_selfpowered)(struct usb_gadget *, int); int (*vbus_session)(struct usb_gadget *, int); int (*pullup)(struct usb_gadget *, int); int (*udc_start)(struct usb_gadget *, ...); int (*udc_stop)(struct usb_gadget *); int (*set_config)(struct usb_gadget *, unsigned); ops 指针 说明: UDC 驱动在 probe 阶段分配并初始化 usb_gadget,同时填充 usb_gadget_ops。 Gadget 功能驱动通过 ops 回调间接控制硬件行为,无需直接操作寄存器。

2.2 struct usb_udc:UDC 核心管理层

struct usb_udc 是 UDC 核心层(drivers/usb/gadget/udc/core.c)用于管理所有已注册 UDC 控制器的数据结构。它封装了 struct usb_gadget,并增加了与 Gadget 功能驱动绑定、sysfs 属性管理、电源管理等高层逻辑。

移植注意: UDC 驱动开发者通常只需要分配和初始化 struct usb_gadget,然后调用 usb_add_gadget_udc() 将其注册到核心层。核心层会自动创建对应的 struct usb_udc 实例并加入全局链表。

2.2.1 主要成员与作用

成员名 类型 作用描述
gadget struct usb_gadget * 指向该 UDC 实例所管理的底层 gadget 控制器。
driver struct usb_gadget_driver * 指向当前绑定到该 UDC 的 Gadget 功能驱动。为 NULL 时表示未绑定。
dev struct device 内嵌设备结构体,用于在 sysfs 中创建 /sys/bus/udc/devices/ 下的设备节点。
list struct list_head 全局链表节点,用于将本 UDC 实例加入 udc_list 全局链表。
vbus bool VBUS 状态标志,表示 USB 总线是否提供电源。
connected bool 连接状态标志,表示设备是否已连接到主机。
allow_connect bool 控制是否允许物理连接。用于软件可控的 D+ 上拉电阻管理。

2.2.2 UDC 注册与全局管理流程

下图展示了 UDC 驱动从 probe 到注册完成,以及 Gadget 功能驱动绑定过程中,struct usb_udc 所扮演的核心角色。

struct usb_udc 注册与绑定流程 UDC 驱动 probe 分配 usb_gadget 初始化 ops / ep0 / eps usb_add_gadget_udc() 创建 usb_udc 实例 加入 udc_list 全局链表 等待绑定 driver = NULL allow_connect = false Gadget 驱动注册 usb_gadget_probe_driver() udc_bind_to_driver() 设置 udc->driver 调用 gadget->ops->udc_start() 枚举就绪 allow_connect = true 等待主机复位 关键点: • usb_add_gadget_udc() 是 UDC 驱动注册的入口,内部自动创建 usb_udc 并加入全局链表。 • 绑定后 udc->driver 非空,核心层通过该指针将主机请求转发给 Gadget 功能驱动。

2.3 struct usb_gadget_driver:Gadget 功能驱动抽象

struct usb_gadget_driver 代表一个具体的 USB Gadget 功能实现,例如 ECM(以太网控制模型)、ACM(抽象控制模型)、Mass Storage、HID 等。它定义了功能驱动的生命周期回调、描述符管理以及事件处理接口。

核心作用: 提供标准化的回调函数集,使 UDC 核心层能够在枚举过程的不同阶段(如设置地址、获取描述符、设置配置)通知功能驱动,并获取相应的响应数据。

2.3.1 主要成员与作用

成员名 类型 作用描述
function char * 功能名称字符串,如 "g_ether"、"g_serial"、"g_mass_storage"。
max_speed enum usb_device_speed 该功能驱动支持的最高 USB 速度。
setup int (*)(struct usb_gadget *, const struct usb_ctrlrequest *) 处理主机发来的标准/类/厂商请求。这是枚举过程中最核心的回调,负责解析 Setup 包并返回响应。
disconnect void (*)(struct usb_gadget *) 当主机断开连接或 VBUS 掉电时调用,用于清理资源。
bind int (*)(struct usb_gadget *, struct usb_gadget_driver *) 绑定回调,在功能驱动与 UDC 绑定时调用。功能驱动在此函数中分配端点、注册回调、初始化功能状态。
unbind void (*)(struct usb_gadget *, struct usb_gadget_driver *) 解绑回调,在功能驱动与 UDC 解绑时调用,用于释放资源。
suspend void (*)(struct usb_gadget *) 挂起回调,当总线进入挂起状态时调用。
resume void (*)(struct usb_gadget *) 恢复回调,当总线从挂起状态恢复时调用。
reset void (*)(struct usb_gadget *) 复位回调,当主机发出总线复位信号时调用。
driver struct device_driver 内嵌的通用设备驱动结构体,用于驱动模型注册和 sysfs 属性管理。

2.3.2 Gadget 功能驱动注册与绑定代码示例

以下代码展示了典型的 Gadget 功能驱动注册过程,重点突出 struct usb_gadget_driver 各回调的赋值与注册函数调用。

/* 定义 Gadget 功能驱动实例 */
static struct usb_gadget_driver my_gadget_driver = {
    .function   = "g_my_function",
    .max_speed  = USB_SPEED_HIGH,
    .bind       = my_gadget_bind,
    .unbind     = my_gadget_unbind,
    .setup      = my_gadget_setup,
    .disconnect = my_gadget_disconnect,
    .suspend    = my_gadget_suspend,
    .resume     = my_gadget_resume,
    .reset      = my_gadget_reset,
    .driver     = {
        .name   = "g_my_function",
        .owner  = THIS_MODULE,
    },
};

/* 模块初始化函数 */
static int __init my_gadget_init(void)
{
    int ret;

    /* 注册 Gadget 功能驱动到 UDC 核心层 */
    ret = usb_gadget_register_driver(&my_gadget_driver);
    if (ret)
        pr_err("Failed to register gadget driver: %d\n", ret);

    return ret;
}
module_init(my_gadget_init);

/* 模块退出函数 */
static void __exit my_gadget_exit(void)
{
    usb_gadget_unregister_driver(&my_gadget_driver);
}
module_exit(my_gadget_exit);

2.4 三大核心数据结构关系总结

下表从层次、职责、生命周期三个维度对比 struct usb_gadget、struct usb_udc 和 struct usb_gadget_driver 的差异与联系。

对比维度 struct usb_gadget struct usb_udc struct usb_gadget_driver
所属层次 UDC 硬件抽象层 UDC 核心管理层 Gadget 功能驱动层
主要职责 封装硬件控制器状态与操作 管理 UDC 注册、绑定、sysfs 实现具体 USB 功能逻辑
生命周期 由 UDC 驱动 probe/release 管理 由 usb_add/remove_gadget_udc 管理 由 usb_gadget_register/unregister_driver 管理
与硬件关系 直接对应一个物理控制器 间接管理,通过 gadget 指针 与硬件无关,纯软件功能
关键关联 udc 指针指向 usb_udc gadget 指针指向 usb_gadget 通过 udc_bind_to_driver 绑定到 usb_udc

2.5 枚举过程中的数据结构协作

在 USB 设备枚举过程中,三个核心数据结构协同工作,完成从主机复位到配置完成的完整流程。下图展示了枚举关键阶段的数据流与回调关系。

枚举过程中三大数据结构协作关系 USB 主机 Setup 包 struct usb_gadget 接收硬件中断,解析 Setup 包 转发 struct usb_udc 通过 driver 指针分发请求 struct usb_gadget_driver setup() 回调处理请求 枚举阶段数据流 1. 总线复位 gadget->reset() 回调 重置端点状态 2. 获取描述符 setup() 处理 GET_DESCRIPTOR 返回设备/配置描述符 3. 设置地址 setup() 处理 SET_ADDRESS gadget->state 更新 4. 设置配置 setup() 处理 SET_CONFIGURATION 激活功能端点 协作要点: ← 上一章 📖 返回目录 下一章 →