Edit online

USB Device Layer

24 Jan 2024
Read time: 7 minute(s)

Device (struct usb_device)

USB Device Device 对应的数据结构为 struct usb_device ,会在两种情况下被创建:

  • roothub device。在 HCD 驱动注册时创建:

/* (1) 首先创建和初始化 `usb_device` 结构: */
usb_add_hcd() → usb_alloc_dev():
struct usb_device *usb_alloc_dev(struct usb_device *parent,
                struct usb_bus *bus, unsigned port1)
{

    /* (1.1) dev 总线初始化为 usb_bus_type */
    dev->dev.bus = &usb_bus_type;
    /* (1.2) dev 类型初始化为 usb_device_type,标明自己是一个 usb device */
    dev->dev.type = &usb_device_type;
    dev->dev.groups = usb_device_groups;

}

/* (2) 然后注册  `usb_device` 结构: */
usb_add_hcd() → register_root_hub() → usb_new_device() → device_add()
  • 普通 usb device。在 Hub 检测到端口有设备 attach 时创建:

/* (1) 首先创建和初始化 `usb_device` 结构: */
hub_event() → port_event() → hub_port_connect_change() → hub_port_connect() → usb_alloc_dev()

/* (2) 然后注册  `usb_device` 结构: */
hub_event() → port_event() → hub_port_connect_change() → hub_port_connect() → usb_new_device() → device_add()

Driver (struct usb_device_driver)

USB Device Driver 对应的数据结构为 struct usb_device_driver,使用 usb_register_device_driver() 函数进行注册:

int usb_register_device_driver(struct usb_device_driver *new_udriver,
        struct module *owner)
{

    /* (1) 设置 devices 标志为 1,表面这个驱动时给 usb device 使用的 */
    new_udriver->drvwrap.for_devices = 1;
    new_udriver->drvwrap.driver.name = new_udriver->name;
    new_udriver->drvwrap.driver.bus = &usb_bus_type;
    new_udriver->drvwrap.driver.probe = usb_probe_device;
    new_udriver->drvwrap.driver.remove = usb_unbind_device;
    new_udriver->drvwrap.driver.owner = owner;
    new_udriver->drvwrap.driver.dev_groups = new_udriver->dev_groups;

    retval = driver_register(&new_udriver->drvwrap.driver);

}

注册的 USB Device Driver 驱动非常少,一般情况下所有的 USB Device Device 都会适配到 usb_generic_driver。因为这一层次驱动的目的很单纯,就是给 USB Device 下所有的 Interface 创建对应的 USB Interface Device。

usb_init() → usb_register_device_driver() :

static int __init usb_init(void)
{

    retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE);

}

struct usb_device_driver usb_generic_driver = {
    .name = "usb",
    .match = usb_generic_driver_match,
    .probe = usb_generic_driver_probe,
    .disconnect = usb_generic_driver_disconnect,
#ifdef      CONFIG_PM
    .suspend = usb_generic_driver_suspend,
    .resume = usb_generic_driver_resume,
#endif
    .supports_autosuspend = 1,
};

驱动 probe() 过程:

usb_probe_device() → usb_generic_driver_probe() → usb_set_configuration():

int usb_set_configuration(struct usb_device *dev, int configuration)
{

    /* (1) 创建和初始化 `struct usb_interface` */
    for (i = 0; i < nintf; ++i) {
        /* (1.1) dev 总线初始化为 usb_bus_type */
        intf->dev.bus = &usb_bus_type;
        /* (1.2) dev 类型初始化为 usb_if_device_type,标明自己是一个 usb interface */
        intf->dev.type = &usb_if_device_type;
        intf->dev.groups = usb_interface_groups;
    }

    /* (2) 注册 `struct usb_interface` */
    for (i = 0; i < nintf; ++i) {
        ret = device_add(&intf->dev);
    }

}

Bus (usb_bus_type)

可以看到 struct usb_devicestruct usb_interface 使用的总线都是 usb_bus_type。他们是通过字段 dev.type 来区分的:

/* (1) `struct usb_device` 的 `dev.type` 值为 `usb_device_type`: */
usb_add_hcd() → usb_alloc_dev():
struct usb_device *usb_alloc_dev(struct usb_device *parent,
                struct usb_bus *bus, unsigned port1)
{
    dev->dev.type = &usb_device_type;
}

/* (2) `struct usb_interface` 的 `dev.type` 值为 `usb_if_device_type` */
usb_probe_device() → usb_generic_driver_probe() → usb_set_configuration():
int usb_set_configuration(struct usb_device *dev, int configuration)
{
    for (i = 0; i < nintf; ++i) {
        intf->dev.type = &usb_if_device_type;
    }
}

static inline int is_usb_device(const struct device *dev)
{
    /* (3) 判断当前 Device 是否为 Usb Device */
    return dev->type == &usb_device_type;
}

static inline int is_usb_interface(const struct device *dev)
{
    /* (4) 判断当前 Device 是否为 Usb Interface */
    return dev->type == &usb_if_device_type;
}

另外 struct usb_device_driverstruct usb_driver 使用的总线都是 usb_bus_type。他们是通过字段 drvwrap.for_devices 来区分的:

/* (1) `struct usb_device_driver` 的 `drvwrap.for_devices` 值为 1: */
int usb_register_device_driver(struct usb_device_driver *new_udriver,
        struct module *owner)
{
    new_udriver->drvwrap.for_devices = 1;
}

/* (2) `struct usb_driver` 的 `drvwrap.for_devices` 值为 0: */
int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
            const char *mod_name)
{
    new_driver->drvwrap.for_devices = 0;
}

/* (3) 判断当前 Driver 是适配 Usb Device 还是 Usb Interface */
static inline int is_usb_device_driver(struct device_driver *drv)
{
    return container_of(drv, struct usbdrv_wrap, driver)->
            for_devices;
}

usb_bus_typematch() 函数中利用 dev.type 进行判别分开处理:

struct bus_type usb_bus_type = {
    .name =         "usb",
    .match =        usb_device_match,
    .uevent =       usb_uevent,
    .need_parent_lock =     true,
};

static int usb_device_match(struct device *dev, struct device_driver *drv)
{
    /* devices and interfaces are handled separately */
    /* (1) Device 是 `Usb Device` 的处理 */
    if (is_usb_device(dev)) {
        struct usb_device *udev;
        struct usb_device_driver *udrv;

        /* interface drivers never match devices */
        /* (1.1) 只查找 `Usb Device` 的 Driver */
        if (!is_usb_device_driver(drv))
            return 0;

        udev = to_usb_device(dev);
        udrv = to_usb_device_driver(drv);

        /* If the device driver under consideration does not have a
        * id_table or a match function, then let the driver's probe
        * function decide.
        */
        if (!udrv->id_table && !udrv->match)
            return 1;

        return usb_driver_applicable(udev, udrv);

    /* (2) Device 是 `Usb Interface` 的处理 */
    } else if (is_usb_interface(dev)) {
        struct usb_interface *intf;
        struct usb_driver *usb_drv;
        const struct usb_device_id *id;

        /* device drivers never match interfaces */
        /* (2.1) 只查找 `Usb Interface` 的 Driver */
        if (is_usb_device_driver(drv))
            return 0;

        intf = to_usb_interface(dev);
        usb_drv = to_usb_driver(drv);

        id = usb_match_id(intf, usb_drv->id_table);
        if (id)
            return 1;

        id = usb_match_dynamic_id(intf, usb_drv);
        if (id)
            return 1;
    }

    return 0;
}