i2c_adapter->dev与i2c_driver->driver并没有匹配关系,而是
i2c_adapter->class与i2c_driver->class的匹配,它们支持的设备类型的匹配。
二、两类i2c_driver的区别
"new style" driver:
is_newstyle_driver(d) ((d)->probe || (d)->remove || (d)->detect)
"legacy"driver:
driver->detach_adapter || driver->detach_client
这两类驱动的区别就是他们所拥有的函数不一样。
不能出现这两类驱动的混合体,即兼有这两类驱动的标志函数的驱动。
"new style" driver是携带地址信息,并将这些地址转换成具体的设备client注册
到内核,这些设备client的name在该驱动的id_table中。
函数driver->detect便是填充结构体i2c_board_info,用i2c_board_info去初始化
client,驱动id_table中的name就是i2c_board_info->type带入client的。
该驱动与设备就是根据这个name相匹配的,匹配后调用函数probe执行一些初始化或是设备探测。
当然该驱动也是可以不携带地址信息的,而是注册后与内核中已存在的client匹配执行probe()。
"legacy"driver是不携带地址信息的,它的主要任务是调用函数driver->detach_adapter为新加入
的适配器,或是与之匹配的适配器创建一个可依附的设备节点,或者是做其他初始化工作。
三、两个重要函数的区别
当一个新的驱动加入内核时,会在类型为i2c_adapter_class的适配器中找与之匹配的,
并将驱动支持的设备插入适配器。
class_for_each_device(&i2c_adapter_class, NULL, driver,
__attach_adapter);
当一个新的适配器加入内核时,会在总线类型为i2c_bus_type的驱动中找与之匹配的,
并将驱动支持的设备插入新加入的这个适配器。
bus_for_each_drv(&i2c_bus_type, NULL, adap,
i2c_do_add_adapter);
函数class_for_each_device和bus_for_each_drv调用了两个相似的函数,
__attach_adapter和i2c_do_add_adapter。
这两函数的对比如下:
前者是在新的驱动加入内核时调用函数class_for_each_device时调用的函数。
函数class_for_each_device是在类i2c_adapter_class中找一个适配器设备
与新驱动匹配。该函数变化的是设备不变的是加入的新的驱动(void *data)
后者是在新的适配器加入内核时调用函数 bus_for_each_drv时调用的函数。
函数bus_for_each_drv是在总线类型为i2c_bus_type的驱动中找到一个驱动
与新加入的适配器匹配。该函数变化的是驱动,不变的是新加入的适配器(void *data)。
相同点都是执行函数i2c_detect和函数driver->attach_adapter。
其实在bus_for_each_drv和class_for_each_device并不执行匹配的操作。
只是简单的取出所有的驱动或是适配器,执行函数i2c_detect和attach_adapter。
真正的匹配是在函数i2c_detect和attach_adapter中进行的。
函数i2c_detect中会去判断驱动支持的设备类和适配器所支持的设备类是否匹配。
函数driver->attach_adapter中会判断adapter->nr是不是自己需要处理的
适配器,或者是是不是该适配器已被处理过了。
当然函数i2c_detect和函数driver->attach_adapter是绝不会同时执行的。
因为函数i2c_detect的执行需要用到函数driver->detect而该函数是"new style" drivers
的标志函数。而函数driver->attach_adapter是 "legacy" drivers的标志函数。i2c_driver中是
没有兼有这两种驱动的混合体驱动的。
四、 不同驱动一般不会对同一个适配器两次执行函数attach_adapter
每一个函数driver->attach_adapter的操作都跟adapter->nr有关,在这些函数
中都会对adapter->nr进行判断,所以driver->attach_adapter并不是,一个驱动
的函数attach_adapter对每一个适配器都会成功执行。
比如在驱动i2cdev_driver中函数attach_adapter的执行会创建一个设备节点,
但是对同一个适配器两次执行函数attach_adapter就不会产生两个设备节点,
因为产生设备节点的次设备号是由adapter->nr来决定的。内核是不会允许
对同一个设备号注册两次的。
五、关于地址管理结构体i2c_client_address_data
i2c.h中初始化了一个默认的结构体addr_data :
static const struct i2c_client_address_data addr_data = { \
.normal_i2c = normal_i2c, \
.probe = probe, \
.ignore = ignore, \
.forces = forces, \
}
这个结构体与地址探测函数
static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)
紧密相关。
forces:
它存储的地址有如下特点:
跳过适配器支持的设备类和驱动支持的设备类匹配判断
if (!(adapter->class & driver->class))
goto exit_free;
也就是说即使不匹配,这些设备地址只要满足某些条件也要将其插入适配器。
probe:
probe支持的设备地址不受ignore(忽略某些地址)的影响.
normal_i2c:
normal_i2c[i]中的地址就要受到ignore的影响.
驱动中所支持的地址一般都存于address_data->normal_i2c中。