linux那些事儿之我是i2c -- Gsenser(三)
来源:互联网 发布:vip域名后缀可以备案 编辑:程序博客网 时间:2024/04/30 18:02
3.是谁掀起了你的盖头来?
对linux驱动模型有一点了解的兄弟知道,一个驱动,特别是挂上总线的驱动,
真正开始执行都是始于probe函数。我们这里的lis3lv02d_i2c驱动,是挂在系统的i2c总线上的,
因而也就会从probe开始执行。那么是谁来调用这个probe内?就好像驱动通过总线介绍,嫁给了设备,
那到底是哪个设备去掀起驱动的红盖头呢?我们从i2c_register_driver看开去。
代码在kernel/driver/i2c/i2c-core.c中:
872 /*
873 * An i2c_driver is used with one or more i2c_client (device) nodes to access
874 * i2c slave chips, on a bus instance associated with some i2c_adapter.
875 */
876
877 int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
878 {
879 int res;
880
881 /* Can't register until after driver model init */
882 if (unlikely(WARN_ON(!i2c_bus_type.p)))
883 return -EAGAIN;
884
885 /* add the driver to the list of i2c drivers in the driver core */
886 driver->driver.owner = owner;
887 driver->driver.bus = &i2c_bus_type;
888
889 /* When registration returns, the driver core
890 * will have called probe() for all matching-but-unbound devices.
891 */
892 res = driver_register(&driver->driver);
893 if (res)
894 return res;
895
896 pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
897
898 INIT_LIST_HEAD(&driver->clients);
899 /* Walk the adapters that are already present */
900 mutex_lock(&core_lock);
901 bus_for_each_dev(&i2c_bus_type, NULL, driver, __attach_adapter);
902 mutex_unlock(&core_lock);
903 ///WTT DEBUG
904 printk("***** WTT DEBUG i2c_register_driver to return 0\n");
905 ///WTT DEBUG
906 return 0;
907 }
908 EXPORT_SYMBOL(i2c_register_driver);
此函数中第887行,driver->driver.bus = &i2c_bus_type;
将i2c_driver->device_driver.bus 赋值为&i2c_bus_type
那么这个&i2c_bus_type是在哪里定义的呢?
代码在kernel/driver/i2c/i2c-core.c中:
233 struct bus_type i2c_bus_type = {
234 .name = "i2c",
235 .match = i2c_device_match,
236 .probe = i2c_device_probe,
237 .remove = i2c_device_remove,
238 .shutdown = i2c_device_shutdown,
239 .suspend = i2c_device_suspend,
240 .resume = i2c_device_resume,
241 };
242 EXPORT_SYMBOL_GPL(i2c_bus_type);
struct bus_type 是linux中定义的总线类型,所有的总线都需要定义这么一个结构体,
用来储存总线的名称以及一些相关的API。
从字面上看,可以看到相关的API有:
设备匹配,主要是将驱动和设备进行匹配。
设备移除、关闭、挂起、恢复。
还有设备挂载(探测),是设备驱动probe的调用者,
也就是这节寻寻觅觅的掀起盖头的那位了。
那么这些函数都是怎么执行的呢?这个就跟伟大的Linux设备模型息息相关了。
具体的代码实现细节我没有跟读过,知识了解一些操作的结果和过程。
大致是这样的, 892 res = driver_register(&driver->driver);,我们把这个驱动,
注册到了i2c_bus_type总线上。当该总线上有新的设备添加i2c_add_device,
又或者有新的驱动注册i2c_add_driver,那么i2c_device_match就会被执行,我们来看这个函数:
也在i2c-core中
66 static int i2c_device_match(struct device *dev, struct device_driver *drv)
67 {
68 struct i2c_client *client = i2c_verify_client(dev);
69 struct i2c_driver *driver;
70
71 if (!client)
72 return 0;
73
74 driver = to_i2c_driver(drv);
75 ///WTT DEBUG
76 printk("***** WTT DEBUG i2c_device_match : driver name=%s\n",driver->id_table->name);
77 ///WTT DEBUG
78 /* match on an id table if there is one */
79 if (driver->id_table)
80 return i2c_match_id(driver->id_table, client) != NULL;
81
82 return 0;
83 }
我们看到,这个函数所要match的是驱动和设备的id—table。
我们跟着第80行,进入i2c_match_id:
55 static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
56 const struct i2c_client *client)
57 {
58 while (id->name[0]) {
59 if (strcmp(client->name, id->name) == 0)
60 return id;
61 id++;
62 }
63 return NULL;
64 }
这个函数应该没什么问题,大致意思就是比较从driver来的id中的name和client中的name。
client哪里来?这里先留个悬念,下节再细说,我们先往下看。
刚刚我们说完了i2c_device_match,接着来说说掀起盖头来的那位i2c_device_probe,
他是在什么时候被调用的呢?是在i2c_device_match调用完成后被调用的。
i2c-bus在检测到有新的设备和驱动后,会主动去调用i2c_device_match,将两者做匹配,
一旦匹配成功,就会去调用i2c_device_probe。
就好比男孩(device)和女孩(driver),去bus相亲,相中了(match),就步入婚姻殿堂,
而一般,掀盖头都是要用装备的,不是徒手去掀,用什么?用秤杆,所谓称心如意!
而这里的i2c_device_probe就好比是秤杆,去解开驱动的probe面纱。
把上述的match和probe加上调试语句,就可以看出相对关系:
[ 3.416687] ***** WTT DEBUG i2c_device_match : dismatch drv:lis3lv02d client:tpo_touch
[ 3.424652] ***** WTT DEBUG i2c_device_match : driver name=lis3lv02d
[ 3.431030] ***** WTT DEBUG i2c_device_match : dismatch drv:lis3lv02d client:elan_touch
[ 3.439056] ***** WTT DEBUG i2c_device_match : driver name=lis3lv02d
[ 3.445434] ***** WTT DEBUG i2c_device_match : dismatch drv:lis3lv02d client:lis3lv02d
[ 3.453369] ***** WTT DEBUG i2c_device_probe : driver name=lis3lv02d
[ 3.445434]王八绿豆对上眼了,那就去掀盖头吧,[ 3.453369] ***** WTT DEBUG i2c_device_probe : driver name=lis3lv02d。
他们都是总线上的API,都是由总线去调用的,
When i2c_bus_type was registered in linux kernel,in kernel/driver/base/bus.c
__device_attach and __driver_attach
///these functions will be called when one driver want to bind with device .
And function driver_match_device will call bus_type.match
And driver_probe_device will call bus_type.probe
话说秤杆有了,去挑起盖头咯,挑起前,还有些事情需要做,
比如,夫妻双方做个婚前体检,再次核实身份,诸如此类。
见i2c_device_probe代码,也在i2c-core中:
102 static int i2c_device_probe_count = 0;
103 static int i2c_device_probe(struct device *dev)
104 {
105 struct i2c_client *client = i2c_verify_client(dev);
106 struct i2c_driver *driver;
107 int status;
108
109 if (!client)
110 return 0;
111
112 driver = to_i2c_driver(dev->driver);
113 ///WTT DEBUG
114 printk("***** WTT DEBUG i2c_device_probe : driver name=%s\n",driver->id_table->name);
115 ///WTT DEBUG
116 if (!driver->probe || !driver->id_table)
117 return -ENODEV;
118 client->driver = driver;
119 if (!device_can_wakeup(&client->dev))
120 device_init_wakeup(&client->dev,
121 client->flags & I2C_CLIENT_WAKE);
122 dev_dbg(dev, "probe\n");
123 ///WTT DEBUG
124 printk("***** WTT DEBUG i2c_device_probe_count = %d\n",i2c_device_probe_count);
125 i2c_device_probe_count++;
126 printk("***** WTT DEBUG device to probe is %s\n",client->name);
127 ///WTT DEBUG
128 status = driver->probe(client, i2c_match_id(driver->id_table, client));
129
130 if (status)
131 client->driver = NULL;
132 return status;
133 }
先看i2c_verify_client,
251 /**
252 * i2c_verify_client - return parameter as i2c_client, or NULL
253 * @dev: device, probably from some driver model iterator
254 *
255 * When traversing the driver model tree, perhaps using driver model
256 * iterators like @device_for_each_child(), you can't assume very much
257 * about the nodes you find. Use this function to avoid oopses caused
258 * by wrongly treating some non-I2C device as an i2c_client.
259 */
260 struct i2c_client *i2c_verify_client(struct device *dev)
261 {
262 return (dev->type == &i2c_client_type)
263 ? to_i2c_client(dev)
264 : NULL;
265 }
266 EXPORT_SYMBOL(i2c_verify_client);
就是想检查一下,client是不是真的i2c_client_type类型。
就好比男孩(device)想找个女孩(driver),但是相亲时没注意,找了个人妖,
所以就要婚前检查一下,i2c_verify_client就是起这个作用的,核实一下是不是真的i2c_client_type。
中间部分都是一些简单的初始化。
再看128行,status = driver->probe(client, i2c_match_id(driver->id_table, client));
终于要先去驱动的盖头了,掀起前,还是再检查一下吧,看看我们到你配不配,乙方万一以后后悔,
linux里走到这一步,要是不匹配,顶多返回而已。现实中一旦选择,那就要一辈子不离不弃,相濡以沫。
走到这里,终于走到驱动的probe了,也就是第2节中的300行:lis3lv02d_i2c_probe
probe函数,在一般情况下,是一个驱动在挂上总线并被调用后最先执行的函数,旨在做一些初始化工作,比如申请中断,map内存地址,申请结构体等等。
到此为止,我们算是走完了这个驱动的挂载和启动,不过先不急着往下看,我们还有点小尾巴尚未解决:
他的参数是什么?一个是struct i2c_client *client,另一个是 const struct i2c_device_id *id。
对linux驱动模型有一点了解的兄弟知道,一个驱动,特别是挂上总线的驱动,
真正开始执行都是始于probe函数。我们这里的lis3lv02d_i2c驱动,是挂在系统的i2c总线上的,
因而也就会从probe开始执行。那么是谁来调用这个probe内?就好像驱动通过总线介绍,嫁给了设备,
那到底是哪个设备去掀起驱动的红盖头呢?我们从i2c_register_driver看开去。
代码在kernel/driver/i2c/i2c-core.c中:
872 /*
873 * An i2c_driver is used with one or more i2c_client (device) nodes to access
874 * i2c slave chips, on a bus instance associated with some i2c_adapter.
875 */
876
877 int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
878 {
879 int res;
880
881 /* Can't register until after driver model init */
882 if (unlikely(WARN_ON(!i2c_bus_type.p)))
883 return -EAGAIN;
884
885 /* add the driver to the list of i2c drivers in the driver core */
886 driver->driver.owner = owner;
887 driver->driver.bus = &i2c_bus_type;
888
889 /* When registration returns, the driver core
890 * will have called probe() for all matching-but-unbound devices.
891 */
892 res = driver_register(&driver->driver);
893 if (res)
894 return res;
895
896 pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
897
898 INIT_LIST_HEAD(&driver->clients);
899 /* Walk the adapters that are already present */
900 mutex_lock(&core_lock);
901 bus_for_each_dev(&i2c_bus_type, NULL, driver, __attach_adapter);
902 mutex_unlock(&core_lock);
903 ///WTT DEBUG
904 printk("***** WTT DEBUG i2c_register_driver to return 0\n");
905 ///WTT DEBUG
906 return 0;
907 }
908 EXPORT_SYMBOL(i2c_register_driver);
此函数中第887行,driver->driver.bus = &i2c_bus_type;
将i2c_driver->device_driver.bus 赋值为&i2c_bus_type
那么这个&i2c_bus_type是在哪里定义的呢?
代码在kernel/driver/i2c/i2c-core.c中:
233 struct bus_type i2c_bus_type = {
234 .name = "i2c",
235 .match = i2c_device_match,
236 .probe = i2c_device_probe,
237 .remove = i2c_device_remove,
238 .shutdown = i2c_device_shutdown,
239 .suspend = i2c_device_suspend,
240 .resume = i2c_device_resume,
241 };
242 EXPORT_SYMBOL_GPL(i2c_bus_type);
struct bus_type 是linux中定义的总线类型,所有的总线都需要定义这么一个结构体,
用来储存总线的名称以及一些相关的API。
从字面上看,可以看到相关的API有:
设备匹配,主要是将驱动和设备进行匹配。
设备移除、关闭、挂起、恢复。
还有设备挂载(探测),是设备驱动probe的调用者,
也就是这节寻寻觅觅的掀起盖头的那位了。
那么这些函数都是怎么执行的呢?这个就跟伟大的Linux设备模型息息相关了。
具体的代码实现细节我没有跟读过,知识了解一些操作的结果和过程。
大致是这样的, 892 res = driver_register(&driver->driver);,我们把这个驱动,
注册到了i2c_bus_type总线上。当该总线上有新的设备添加i2c_add_device,
又或者有新的驱动注册i2c_add_driver,那么i2c_device_match就会被执行,我们来看这个函数:
也在i2c-core中
66 static int i2c_device_match(struct device *dev, struct device_driver *drv)
67 {
68 struct i2c_client *client = i2c_verify_client(dev);
69 struct i2c_driver *driver;
70
71 if (!client)
72 return 0;
73
74 driver = to_i2c_driver(drv);
75 ///WTT DEBUG
76 printk("***** WTT DEBUG i2c_device_match : driver name=%s\n",driver->id_table->name);
77 ///WTT DEBUG
78 /* match on an id table if there is one */
79 if (driver->id_table)
80 return i2c_match_id(driver->id_table, client) != NULL;
81
82 return 0;
83 }
我们看到,这个函数所要match的是驱动和设备的id—table。
我们跟着第80行,进入i2c_match_id:
55 static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
56 const struct i2c_client *client)
57 {
58 while (id->name[0]) {
59 if (strcmp(client->name, id->name) == 0)
60 return id;
61 id++;
62 }
63 return NULL;
64 }
这个函数应该没什么问题,大致意思就是比较从driver来的id中的name和client中的name。
client哪里来?这里先留个悬念,下节再细说,我们先往下看。
刚刚我们说完了i2c_device_match,接着来说说掀起盖头来的那位i2c_device_probe,
他是在什么时候被调用的呢?是在i2c_device_match调用完成后被调用的。
i2c-bus在检测到有新的设备和驱动后,会主动去调用i2c_device_match,将两者做匹配,
一旦匹配成功,就会去调用i2c_device_probe。
就好比男孩(device)和女孩(driver),去bus相亲,相中了(match),就步入婚姻殿堂,
而一般,掀盖头都是要用装备的,不是徒手去掀,用什么?用秤杆,所谓称心如意!
而这里的i2c_device_probe就好比是秤杆,去解开驱动的probe面纱。
把上述的match和probe加上调试语句,就可以看出相对关系:
[ 3.416687] ***** WTT DEBUG i2c_device_match : dismatch drv:lis3lv02d client:tpo_touch
[ 3.424652] ***** WTT DEBUG i2c_device_match : driver name=lis3lv02d
[ 3.431030] ***** WTT DEBUG i2c_device_match : dismatch drv:lis3lv02d client:elan_touch
[ 3.439056] ***** WTT DEBUG i2c_device_match : driver name=lis3lv02d
[ 3.445434] ***** WTT DEBUG i2c_device_match : dismatch drv:lis3lv02d client:lis3lv02d
[ 3.453369] ***** WTT DEBUG i2c_device_probe : driver name=lis3lv02d
[ 3.445434]王八绿豆对上眼了,那就去掀盖头吧,[ 3.453369] ***** WTT DEBUG i2c_device_probe : driver name=lis3lv02d。
他们都是总线上的API,都是由总线去调用的,
When i2c_bus_type was registered in linux kernel,in kernel/driver/base/bus.c
__device_attach and __driver_attach
///these functions will be called when one driver want to bind with device .
And function driver_match_device will call bus_type.match
And driver_probe_device will call bus_type.probe
话说秤杆有了,去挑起盖头咯,挑起前,还有些事情需要做,
比如,夫妻双方做个婚前体检,再次核实身份,诸如此类。
见i2c_device_probe代码,也在i2c-core中:
102 static int i2c_device_probe_count = 0;
103 static int i2c_device_probe(struct device *dev)
104 {
105 struct i2c_client *client = i2c_verify_client(dev);
106 struct i2c_driver *driver;
107 int status;
108
109 if (!client)
110 return 0;
111
112 driver = to_i2c_driver(dev->driver);
113 ///WTT DEBUG
114 printk("***** WTT DEBUG i2c_device_probe : driver name=%s\n",driver->id_table->name);
115 ///WTT DEBUG
116 if (!driver->probe || !driver->id_table)
117 return -ENODEV;
118 client->driver = driver;
119 if (!device_can_wakeup(&client->dev))
120 device_init_wakeup(&client->dev,
121 client->flags & I2C_CLIENT_WAKE);
122 dev_dbg(dev, "probe\n");
123 ///WTT DEBUG
124 printk("***** WTT DEBUG i2c_device_probe_count = %d\n",i2c_device_probe_count);
125 i2c_device_probe_count++;
126 printk("***** WTT DEBUG device to probe is %s\n",client->name);
127 ///WTT DEBUG
128 status = driver->probe(client, i2c_match_id(driver->id_table, client));
129
130 if (status)
131 client->driver = NULL;
132 return status;
133 }
先看i2c_verify_client,
251 /**
252 * i2c_verify_client - return parameter as i2c_client, or NULL
253 * @dev: device, probably from some driver model iterator
254 *
255 * When traversing the driver model tree, perhaps using driver model
256 * iterators like @device_for_each_child(), you can't assume very much
257 * about the nodes you find. Use this function to avoid oopses caused
258 * by wrongly treating some non-I2C device as an i2c_client.
259 */
260 struct i2c_client *i2c_verify_client(struct device *dev)
261 {
262 return (dev->type == &i2c_client_type)
263 ? to_i2c_client(dev)
264 : NULL;
265 }
266 EXPORT_SYMBOL(i2c_verify_client);
就是想检查一下,client是不是真的i2c_client_type类型。
就好比男孩(device)想找个女孩(driver),但是相亲时没注意,找了个人妖,
所以就要婚前检查一下,i2c_verify_client就是起这个作用的,核实一下是不是真的i2c_client_type。
中间部分都是一些简单的初始化。
再看128行,status = driver->probe(client, i2c_match_id(driver->id_table, client));
终于要先去驱动的盖头了,掀起前,还是再检查一下吧,看看我们到你配不配,乙方万一以后后悔,
linux里走到这一步,要是不匹配,顶多返回而已。现实中一旦选择,那就要一辈子不离不弃,相濡以沫。
走到这里,终于走到驱动的probe了,也就是第2节中的300行:lis3lv02d_i2c_probe
probe函数,在一般情况下,是一个驱动在挂上总线并被调用后最先执行的函数,旨在做一些初始化工作,比如申请中断,map内存地址,申请结构体等等。
到此为止,我们算是走完了这个驱动的挂载和启动,不过先不急着往下看,我们还有点小尾巴尚未解决:
他的参数是什么?一个是struct i2c_client *client,另一个是 const struct i2c_device_id *id。
- linux那些事儿之我是i2c -- Gsenser(三)
- linux那些事儿之我是i2c -- Gsenser(一)
- linux那些事儿之我是i2c -- Gsenser(二)
- linux那些事儿之我是i2c -- Gsenser(四)
- Linux 驱动i2c -- Gsenser(三)
- Linux那些事儿之我是SCSI硬盘(6)三座大山(三)
- Linux那些事儿之我是Hub(引子)
- Linux那些事儿之我是Sysfs--引子
- Linux那些事儿之我是UHCI-引子
- Linux那些事儿之我是EHCI 引子
- Linux那些事儿之我是U盘
- 《Linux那些事儿之我是USB》前言
- 《Linux那些事儿之我是USB》语录
- 《Linux那些事儿之我是USB》前言
- 《Linux那些事儿之我是USB》语录
- Linux那些事儿之我是EHCI 引子
- Linux那些事儿之我是Hub(引子)
- Linux那些事儿之我是Sysfs
- 多点触控参数
- Winform 无标题栏可以移动窗体
- 流年轻弹、离殇一曲
- git命令
- BLOG
- linux那些事儿之我是i2c -- Gsenser(三)
- 线程中使用Timer
- 奋斗黑马程序员----Java内部类讲解
- maven构建appfuse常用命令
- 初始化多选下拉款并判断是否换行
- linux那些事儿之我是i2c -- Gsenser(四)
- android开发-使用Dialog AlertDialog
- 又一次来到合肥
- ActiveX(一)