本文以触摸屏GSL3680为例详细分析驱动从注册到调用的整个流程。程序详见GSL3680目录下的gslX680.c文件。
谨以本文记录当时分析思路为之后回顾保留资料,同时纪念那在力源思创昏天黑的的加班日子。
该TP驱动调用module_init(gsl_ts_init);对整个tp模块驱动进行初始化。函数gsl_ts_init()中先初始化电源;接着分配gpio口;之后获取adapter总线上的主设备;又读取配置文件;然后初始化了一个设备;最后注册该tp所用的相关驱动函数。
这里主要分析最后一步,tp所用的相关驱动函数注册。
例程中所调用的驱动注册函数代码为:ret = i2c_add_driver(&gsl_ts_driver);
第一步:分析该行代码
i2c_add_driver()是一个宏,其原型是:
#define i2c_add_driver(driver) \
i2c_register_driver(THIS_MODULE, driver)
它封装了函数i2c_register_driver()。
它的参数&gsl_ts_driver是一个结构体指针,原型为:struct i2c_driver {
unsigned int class;
int (*attach_adapter)(struct i2c_adapter *) __deprecated;
int (*detach_adapter)(struct i2c_adapter *) __deprecated;
int (*probe)(struct i2c_client *, const struct i2c_device_id *);
int (*remove)(struct i2c_client *);
void (*shutdown)(struct i2c_client *);
int (*suspend)(struct i2c_client *, pm_message_t mesg);
int (*resume)(struct i2c_client *);
void (*alert)(struct i2c_client *, unsigned int data);
int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
struct device_driver driver;
const struct i2c_device_id *id_table;
int (*detect)(struct i2c_client *, struct i2c_board_info *);
const unsigned short *address_list;
struct list_head clients;
}
初始化后的gsl_ts_driver结构体:
static struct i2c_driver gsl_ts_driver = {
.driver = {
.name = GSLX680_I2C_NAME,
.owner = THIS_MODULE,
},
#ifndef CONFIG_HAS_EARLYSUSPEND
.suspend = gsl_ts_suspend,
.resume = gsl_ts_resume,
#endif
.probe = gsl_ts_probe,
.remove = __devexit_p(gsl_ts_remove),
.id_table = gsl_ts_id,
.address_list = gsl_addresses,
};
该结构体初始化了相关的操作函数和设备驱动对应设备的名字和所属模块。
第二步:分析驱动注册函数i2c_register_driver(),原型如下:
int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{
int res;
/* Can't register until after driver model init */
if (unlikely(WARN_ON(!i2c_bus_type.p)))
return -EAGAIN;
/* add the driver to the list of i2c drivers in the driver core */
driver->driver.owner = owner;/*设置它的所属模块*/
driver->driver.bus = &i2c_bus_type;/*设置它的总线类型*/
/* When registration returns, the driver core
* will have called probe() for all matching-but-unbound devices.
*/
res = driver_register(&driver->driver);/*注册驱动*/
if (res)
return res;
/* Drivers should switch to dev_pm_ops instead. */
if (driver->suspend)
pr_warn("i2c-core: driver [%s] using legacy suspend method\n",
driver->driver.name);
if (driver->resume)
pr_warn("i2c-core: driver [%s] using legacy resume method\n",
driver->driver.name);
pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
INIT_LIST_HEAD(&driver->clients);
/* Walk the adapters that are already present */
i2c_for_each_dev(driver, __process_new_driver);
return 0;
}
其中主要关注第10行,11行,16行。
10行,11行设置了gsl_ts_driver里设备驱动(即driver成员)的所属模块为:THIS_MODULE和总线类型是i2c_bus_type。
.driver成员的原型为:struct device_driver {
const char *name;
struct bus_type *bus;
struct module *owner;
const char *mod_name; /* used for built-in modules */
bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
const struct of_device_id *of_match_table;
int (*probe) (struct device *dev);
int (*remove) (struct device *dev);
void (*shutdown) (struct device *dev);
int (*suspend) (struct device *dev, pm_message_t state);
int (*resume) (struct device *dev);
const struct attribute_group **groups;
const struct dev_pm_ops *pm;
struct driver_private *p;
};
而其成员.bus原型struct bus_type为:
struct bus_type {
const char *name;
struct bus_attribute *bus_attrs;
struct device_attribute *dev_attrs;
struct driver_attribute *drv_attrs;
int (*match)(struct device *dev, struct device_driver *drv);
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
int (*probe)(struct device *dev);
int (*remove)(struct device *dev);
void (*shutdown)(struct device *dev);
int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev);
const struct dev_pm_ops *pm;
struct iommu_ops *iommu_ops;
struct subsys_private *p;
};
而总线类型i2c_bus_type结构体具体初始化为:
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
.pm = &i2c_device_pm_ops,
};
第三步:分析19行res = driver_register(&driver->driver);其原型如下:
int driver_register(struct device_driver *drv)
{
int ret;
struct device_driver *other;
BUG_ON(!drv->bus->p);
if ((drv->bus->probe && drv->probe) ||//见分析
(drv->bus->remove && drv->remove) ||
(drv->bus->shutdown && drv->shutdown))
printk(KERN_WARNING "Driver '%s' needs updating - please use "
"bus_type methods\n", drv->name);
other = driver_find(drv->name, drv->bus);
if (other) {
put_driver(other);
printk(KERN_ERR "Error: Driver '%s' is already registered, "
"aborting...\n", drv->name);
return -EBUSY;
}
ret = bus_add_driver(drv);
if (ret)
return ret;
ret = driver_add_groups(drv, drv->groups);
if (ret)
bus_remove_driver(drv);
return ret;
}
分析第8行:
传入的drv参数就是&gsl_ts_driver->driver,而之前只初始化了&gsl_ts_driver->driver.bus并没有赋值相应的操作函数,而i2c_bus_type初始化了相关的操作函数,所以这里drv->bus的操作函数有,但是drv的操作函数就没有初始化。
分析第14行other =driver_find(drv->name, drv->bus);:
第一个参数就是之前定义的GSLX680_I2C_NAME,让其与bus的driver链表每个驱动内嵌的kobj名字比较,如果找到同名的,说明驱动注册过返回退出,如果没有找到,说明驱动没有注册,之后添加驱动到总线即调用22行的ret =bus_add_driver(drv);。
第四步:分析bus_add_driver()将驱动注册到总线,该函数中最主要的就是driver_attach(),该驱动关联函数又调用bus_for_each_dev(drv->bus,NULL, drv, __driver_attach);,它的意思是遍历总线上的每一设备,并对每个设备调用函数__driver_attach(),当要驱动的设备被找到__driver_attach()调用成功,返回0。函数__driver_attach()原型如下:
static int __driver_attach(struct device *dev, void *data)
{
struct device_driver *drv = data;
/*
* Lock device and try to bind to it. We drop the error
* here and always return 0, because we need to keep trying
* to bind to devices and some drivers will return an error
* simply if it didn't support the device.
*
* driver_probe_device() will spit a warning if there
* is an error.
*/
if (!driver_match_device(drv, dev))//driver和device尝试匹配
return 0;
if (dev->parent) /* Needed for USB */
device_lock(dev->parent);
device_lock(dev);
if (!dev->driver)//如果设备没有指定driver,那么需要初始化匹配到这个设备
driver_probe_device(drv, dev);
device_unlock(dev);
if (dev->parent)
device_unlock(dev->parent);
return 0;
}
第15行driver_match_device(),如果总线的match函数没有被注册就返回1,如果注册了,则调用注册匹配函数。GSL3680tp总线类型是i2c_bus_type,它调用的是i2c_device_match(),原型如下:
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
struct i2c_client *client = i2c_verify_client(dev);
struct i2c_driver *driver;
if (!client)
return 0;
/* Attempt an OF style match */
if (of_driver_match_device(dev, drv))
return 1;
driver = to_i2c_driver(drv);
/* match on an id table if there is one */
if (driver->id_table)
return i2c_match_id(driver->id_table, client) != NULL; //只匹配id的名字和client的名字,跟驱动的名字没有关系,注意这里的client是设备转换过来,而不是设备的本身
return 0;
}
转而调用i2c_match_id(),其函数原型如下:
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) //匹配设备client名字和id_table中的名字
return id;
id++;
}
return NULL;
}
所以i2c总线根据设备client名字和id_table中的名字进行匹配的。如果匹配了,则返回id值,在i2c_device_match中则返回真。也就是bus的match函数将会返回真。那将会进入driver_probe_device(),其原型如下:
int driver_probe_device(struct device_driver *drv, struct device *dev)
{
int ret = 0;
if (!device_is_registered(dev)) //判断这个设备是否已经注册
return -ENODEV;
pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name);
pm_runtime_get_noresume(dev);
pm_runtime_barrier(dev);
ret = really_probe(dev, drv); //这里真正开始调用用户在device_driver中注册的probe()例程,GSL3680中即是:gsl_ts_probe()
pm_runtime_put_sync(dev);
return ret;
}
真正调用用户的probe()例程的函数really_probe()原型:
static int really_probe(struct device *dev, struct device_driver *drv)
{
int ret = 0;
//static atomic_t probe_count = ATOMIC_INIT(0);记录probe数目
atomic_inc(&probe_count);//原则增加计数
pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
drv->bus->name, __func__, drv->name, dev_name(dev));
WARN_ON(!list_empty(&dev->devres_head));
dev->driver = drv;
if (driver_sysfs_add(dev)) {//主要是添加driver和dev之间的连接文件
printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
__func__, dev_name(dev));
goto probe_failed;
}
if (dev->bus->probe) {//如果bus的probe存在就执行,否则执行driver的probe,这也是函数开始时检测的原因
ret = dev->bus->probe(dev);//此处调用i2c总线的probe函数
if (ret)
goto probe_failed;
} else if (drv->probe) {
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}
driver_bound(dev);//driver绑定dev
ret = 1;
pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name);
goto done;
probe_failed:
devres_release_all(dev);
driver_sysfs_remove(dev);
dev->driver = NULL;
if (ret != -ENODEV && ret != -ENXIO) {
/* driver matched but the probe failed */
printk(KERN_WARNING
"%s: probe of %s failed with error %d\n",
drv->name, dev_name(dev), ret);
} else {
pr_debug("%s: probe of %s rejects match %d\n",
drv->name, dev_name(dev), ret);
}
/*
* Ignore errors returned by ->probe so that the next driver can try
* its luck.
*/
ret = 0;
done:
atomic_dec(&probe_count);
wake_up(&probe_waitqueue);
return ret;
}
通过之前的bus类型传入,确定为i2c_bus_type,所以在19行确定调用的是i2c总线的probe函数即:i2c_device_probe(),其原型如下:
static int i2c_device_probe(struct device *dev)
{
struct i2c_client *client = i2c_verify_client(dev);
struct i2c_driver *driver;
int status;
if (!client)
return 0;
driver = to_i2c_driver(dev->driver);
if (!driver->probe || !driver->id_table)
return -ENODEV;
client->driver = driver;
if (!device_can_wakeup(&client->dev))
device_init_wakeup(&client->dev,
client->flags & I2C_CLIENT_WAKE);
dev_dbg(dev, "probe\n");
status = driver->probe(client, i2c_match_id(driver->id_table, client));//执行我们写的probe()函数。
if (status) {
client->driver = NULL;
i2c_set_clientdata(client, NULL);
}
return status;
}
第10行的driver=to_i2c_driver(dev->driver);获取i2c驱动,也就是我们编写的具体的i2c设备驱动的结构体i2c_driver,在GSL3680中即:
static struct i2c_driver gsl_ts_driver = {
.driver = {
.name = GSLX680_I2C_NAME,
.owner = THIS_MODULE,
},
#ifndef CONFIG_HAS_EARLYSUSPEND
.suspend = gsl_ts_suspend,
.resume = gsl_ts_resume,
#endif
//attach_adapter
.probe = gsl_ts_probe,
//detach_client
.remove = __devexit_p(gsl_ts_remove),
.id_table = gsl_ts_id,
.address_list = gsl_addresses,
};
这样就调用了我们驱动的probe()了,这就是我们在驱动里调用i2c_add_driver(),通过driver_register()的一系列调用,最后执行我们所写的probe()。在19行status = driver->probe(client, i2c_match_id(driver->id_table, client)); 行我们所写的probe()。
参考文献:
http://blog.csdn.net/snowwupl/article/details/9117733