总线设备模型(二): USB总线

总线设备模型(二): USB总线

标签: linux系统

1. 数据结构

所有的USB设备都和一个东东关联,那就是bus,其类型定义在drivers/usb/core/driver.c

struct bus_type usb_bus_type = {
    .name =     "usb",
    .match =    usb_device_match,
    .uevent =   usb_event,
};

这里默认只实现了两个接口:匹配device和driver的match和检测add/remove事件的uevent。列一下match回调,马上就会用到。

static int usb_device_match(struct device *dev, struct device_driver *drv)
{
    /* devices and interfaces are handled separately */
    if (is_usb_device(dev)) {

        /* interface drivers never match devices */
        if (!is_usb_device_driver(drv))
            return 0;

        /* TODO: Add real matching code */
        return 1;

    } 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 */
        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;
}

2. 注册

在core/usb.c中通过
retval = bus_register(&usb_bus_type)把usb_bus_type注册进内核,并且初始化了一条bus_notifier chain。紧接着通过bus_register_notifier(&usb_bus_type, &usb_bus_nb)向usb bus_notifier chain添加了一个notifier_block(实际上是调用blocking_notifier_chain_register()),其定义为

static struct notifier_block usb_bus_nb = {
    .notifier_call = usb_bus_notify,
;

通过blocking_notifier_call_chain()就可以来处理usb bus_notifier chain上的block。
通过bus_unregister_notifier(&usb_bus_type, &usb_bus_nb)和bus_unregister(&usb_bus_type)来撤销usb bus。

3. usb_bus_type使用

3.1 device driver 如何使用bus type来匹配device

在USB子系统初始化的时候,利用usb_register()来注册接口驱动,最终会调用drivers/base/driver.c 中的driver_register,然后利用driver_find()根据名字匹配到bus上的driver。其原型如下:
static device_driver *driver_find(const char *name, struct bus_type *bus), 如果匹配到了,说明已经注册了该driver,因此返回EBUSY。否则,通过bus_add_driver将device_driver挂载到bus上。
int bus_add_driver(struct device_driver *drv)
紧接着就对bus上的device进行枚举,来匹配device和device driver(通过__driver_attach调用driver_match_device)。如果匹配上了则进行probe。相关代码如下:

static int __driver_attach(struct device *dev, void *data)
{
    struct device_driver *drv = data;
    if (!driver_match_device(drv, dev))
        return 0;
    ...
}

static inline int driver_match_device(struct device_driver *drv, struct device *dev)
{
    return drv->bus->match? drv->bus->match(dev, drv) : 1;
}

这里回调了bus的match成员,关于usb_bus_type就到这里了。

你可能感兴趣的:(linux,驱动,usb,总线)