本文以触摸屏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 matchin