Edit online

Gadget Driver Legacy

31 Jan 2024
Read time: 2 minute(s)

对于 Legacy Gadget Driver 驱动来说,相当于 Configfs Gadget Driver 的一个简化版。

Gadget Driver

Legacy 风格的 gadget driver 的定义:

drivers\usb\gadget\composite.c:staticconststructusb_gadget_drivercomposite_driver_template={.bind=composite_bind,.unbind=composite_unbind,.setup=composite_setup,.reset=composite_disconnect,.disconnect=composite_disconnect,.suspend=composite_suspend,.resume=composite_resume,.driver={.owner=THIS_MODULE,},};

驱动提供了一个注册函数 usb_composite_probe(),以供 composite device 来进行调用:

int usb_composite_probe(struct usb_composite_driver *driver)
{
    struct usb_gadget_driver *gadget_driver;

    if (!driver || !driver->dev || !driver->bind)
        return -EINVAL;

    if (!driver->name)
        driver->name = "composite";

    /* (1) 把传递过来的 `usb_composite_driver` 包装成 `usb_gadget_driver` */
    driver->gadget_driver = composite_driver_template;
    gadget_driver = &driver->gadget_driver;

    gadget_driver->function =  (char *) driver->name;
    gadget_driver->driver.name = driver->name;
    gadget_driver->max_speed = driver->max_speed;

    /* (2) 注册 gadget driver,让其和 gadget device 适配 */
    return usb_gadget_probe_driver(gadget_driver);
}
EXPORT_SYMBOL_GPL(usb_composite_probe);

Composite Device

没有了 configfs 由用户来创建 composite device ,只能使用一个文件来创建 composite device 定义其使用哪些 function 和一系列配置。例如:
drivers\usb\gadget\legacy\acm_ms.c

static struct usb_composite_driver acm_ms_driver = {
    .name           = "g_acm_ms",
    .dev            = &device_desc,
    .max_speed      = USB_SPEED_SUPER,
    .strings        = dev_strings,
    .bind           = acm_ms_bind,
    .unbind         = acm_ms_unbind,
};

/* (1) 驱动一开始就调用 usb_composite_probe() 来注册 acm_ms_driver
        因为 acm_ms_driver 没有指定 udc_name 所以只能适配第一个 udc
*/
module_usb_composite_driver(acm_ms_driver);

#define module_usb_composite_driver(__usb_composite_driver) \
    module_driver(__usb_composite_driver, usb_composite_probe, \
            usb_composite_unregister)
在 gadget driver 驱动适配后,调用 bind() 函数:
usb_gadget_probe_driver() → udc_bind_to_driver() → composite_bind() → acm_ms_bind()

在 acm_ms_bind() 函数中创建 composite deviceConfigurationFunction/Interface ,并且和 Gadget Device / UDC 进行绑定。

其他操作和 Configfs Gadget Driver 类似。