一个驱动支持多个设备再usb子系统、input子系统、platform、iic子系统 中的实现

来源:互联网 发布:日语教材 知乎 编辑:程序博客网 时间:2024/05/02 01:45

platform

这里写图片描述

你写的驱动你应该知道它适用与哪些设备吧,如果你想支持一个设备,那么你就构造一个
usb_device_id (USB)、i2c_device_id (IIC)、platform_device_id(Platform)放到对应驱动的id_table中

/**    先看平台总线。*/struct bus_type platform_bus_type = {    .name       = "platform",    .dev_attrs  = platform_dev_attrs,    /**        匹配驱动与设备    */    .match      = platform_match,      .uevent     = platform_uevent,    .pm     = &platform_dev_pm_ops,};    /**        匹配的方法有两种 :                     1 : 是利用了platform_driver中定义的id_table,(一个驱动可能支持多个设备)                        如果定义了id_table,那么,就会逐一遍历id_table表中的每一项                        否则,使用name来匹配                    2 : 使用name来匹配 (一个驱动只能支持一个设备)        */    static int platform_match(struct device * dev,struct device_driver * drv)    {        /**            底层调用container_of宏来获取平台设备、平台设备驱动        */        struct platform_device = to_platform_device(dev);        struct platform_driver = to_platform_driver(drv);        /**            这个函数,如果drv->of_match_table不存在,或者dev->of_node不存在            就会返回NULL,实际中用的不多            最终还是比较 drv->of_match_table 和 dev->of_node的name、type等是不是一样            if ((!matches) || (!dev->of_node))                return NULL;            return of_match_node(matches, dev->of_node);        */        if(of_driver_match_device(dev,drv))        {            return 1;        }        /**            如果平台驱动提供了id_table,那么就会platform_match_id函数            id_table的出现,让一个驱动支持多个设备成为可能。            platform_match_id()这个函数会在下面说        */        if(pdrv->id_table)        {            return platform_match_id(pdrv->id_table,pdev) != NULL;        }        /**          如果平台驱动没有提供id_table,那么就会利用名字来比较了          如果是这样,一个驱动只能支持一个设备了        */          return (strcmp(pdev->name,drv->name) == 0);    }    /**        这个函数 会在驱动的id_table表里面 查找和platform_device的name字段相同的一项        如果相同,那么就返回true,否则返回false,        所以 :            这样就可以一个驱动支持多个设备,            如果只是简单的比较name的话,那么一个驱动只能支持一个设备      */    static const struct platform_device_id *platform_match_id(            const struct platform_device_id *id,            struct platform_device *pdev)    {        while (id->name[0])         {            /**                还是比较每一项的名字            */            if (strcmp(pdev->name, id->name) == 0) {                pdev->id_entry = id;                return id;            }            id++;        }        return NULL;    }

iic子系统

在前面的博文中已经详细的分析过,这里简单的说一下,方便对比

struct bus_type i2c_bus_type = {    .name       = "i2c",    /**        匹配函数,下面看这个函数。    */    .match      = i2c_device_match,    /**        iic总线提供了probe,匹配成功后会调用这个probe,        然后再这个probe中调用驱动的probe    */    .probe      = i2c_device_probe,    .....};static int i2c_device_match(struct device *dev, struct device_driver *drv){    /**        根据type类型来检查是不是iic_client类型,    */    struct i2c_client   *client = i2c_verify_client(dev);    struct i2c_driver   *driver;    /**        不是iic_client类型,就直接返回,因为这里要匹配是iic_client和对应的驱动    */    if (!client)     {        return 0;    }       /**        获取iic_driver,是为了在下面取出来它的id_table    */    driver = to_i2c_driver(drv);    /**        如果提供了id_table就调用i2c_match_id()来比较    */    if (driver->id_table)    {        /**            这个函数就是遍历id_table,取出每一个表项来与iic_client的name比较            其实还是利用了name比较,        */        return i2c_match_id(driver->id_table, client) != NULL;    }       return 0;}/**    看最终还是和上面的platform调用的是同一个函数。*/static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,                        const struct i2c_client *client){    while (id->name[0]) {        if (strcmp(client->name, id->name) == 0)            return id;        id++;    }    return NULL;}

usb子系统

struct bus_type usb_bus_type = {    .name =     "usb",    /**        当调用usb_register()注册一个usb_driver的时候        __driver_attach()            ....               driver_match_device()                     调用总线提供的match函数          如果这个match函数匹配不成功的话,那么就不会调用驱动提供的probe函数(这里总线没有提供probe)        具体match函数怎么做的,下面有分析              */    .match =    usb_device_match,    .uevent =   usb_uevent,};static struct usb_driver usb_mouse_driver = {    .name       = "usbmouse",    .probe      = usb_mouse_probe,    /**        usb设备拔出后调用的函数        主要做一些销毁、释放、杀死urb的工作    */    .disconnect = usb_mouse_disconnect,    /**        前面说过,要想你写的驱动支持某一个设备的话,        可以构造一个usb_device_id放到usb_mouse_id_table这个数组中        怎么构造,以前的博文已经说过,可以使用内核提供了一些宏来构造。    */    .id_table   = usb_mouse_id_table,};
0 0
原创粉丝点击