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

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,
};

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值