module_init(egalax_i2c_ts_init)–>表示驱动加载时首先执行的函数是egalax_i2c_ts_init,下面看egalax_i2c_ts_init函数源码:
static int egalax_i2c_ts_init(void)
{
int result;
result = misc_register(&egalax_misc_dev);
if(result)
{
EGALAX_DBG(DBG_MODULE, " misc device register failed\n");
goto fail;
}
p_char_dev = setup_chardev(); // allocate the character device
if(!p_char_dev)
{
result = -ENOMEM;
goto fail;
}
dbgProcFile = proc_create(PROC_FS_NAME, S_IRUGO|S_IWUGO, NULL, &egalax_proc_fops);
if (dbgProcFile == NULL)
{
remove_proc_entry(PROC_FS_NAME, NULL);
EGALAX_DBG(DBG_MODULE, " Could not initialize /proc/%s\n", PROC_FS_NAME);
}
EGALAX_DBG(DBG_MODULE, " Driver init done!\n");
return i2c_add_driver(&egalax_i2c_driver);
//通过i2c_add_driver这个函数向内核添加驱动,从而调
用register_driver向内核注册驱动,如果驱动和设备匹配上以后,
会调用peobe函数(前面有文章专门分析这个匹配过程,这篇文章主要
分probe函数做的工作);
fail:
egalax_i2c_ts_exit();
return result;
}
这里的egalax_i2c_driver为:
static struct i2c_driver egalax_i2c_driver = {
.driver = {
.name = "egalax_i2c",
.owner = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = egalax_i2c_dt_ids,
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0)
.pm = &egalax_i2c_pm_ops,
#endif
},
.class = I2C_CLASS_HWMON,
.id_table = egalax_i2c_idtable,
.probe = egalax_i2c_probe,
.remove = __devexit_p(egalax_i2c_remove),
.suspend = egalax_i2c_pm_suspend,
.resume = egalax_i2c_pm_resume,
.detect = ctp_detect,
.address_list = normal_i2c,
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
#ifndef CONFIG_HAS_EARLYSUSPEND
.suspend = egalax_i2c_pm_suspend,
.resume = egalax_i2c_pm_resume,
#endif
#endif
};
看probe函数的源码:
static int __devinit egalax_i2c_probe(struct i2c_client *client, const struct i2c_device_id *idp)
{
int ret;
#ifdef CONFIG_OF//这里定义的CONFIG_OF是指是否使用了设备树,
这里对使用和没使用两种,都做了兼容;
struct device_node *devnode;
#endif //#ifdef CONFIG_OF
EGALAX_DBG(DBG_MODULE, " Start probe\n");
p_egalax_i2c_dev = (struct _egalax_i2c *)kzalloc(sizeof(struct _egalax_i2c), GFP_KERNEL);
//开辟结构体在和内核的内存空间
if (!p_egalax_i2c_dev)
{
EGALAX_DBG(DBG_MODULE, " Request memory failed\n");
ret = -ENOMEM;
goto fail1;
}
#ifdef CONFIG_OF
devnode = client->dev.of_node;
if(devnode) //if use the device tree config
{
//通过of_get_named_gpio函数来获取设备树的节点信息(获取设备树中名称为int-gpios的gpio number)
并将此gpio注册为中断,返回中断号
p_egalax_i2c_dev->interrupt_gpio = of_get_named_gpio(devnode, "int-gpios", 0);
client->irq = gpio_to_irq(p_egalax_i2c_dev->interrupt_gpio);
}
#else
//p_egalax_i2c_dev->interrupt_gpio = irq_to_gpio(client->irq);
p_egalax_i2c_dev->interrupt_gpio = 356;//未使用设备树时,可直接使用该gpio对应的gpio number
client->irq = gpio_to_irq(p_egalax_i2c_dev->interrupt_gpio);
#endif //#ifdef CONFIG_OF
if( !gpio_is_valid(p_egalax_i2c_dev->interrupt_gpio) )
//判断此gpio是否可用
{
ret = -ENODEV;
goto fail1;
}
ret = gpio_request(p_egalax_i2c_dev->interrupt_gpio, "Touch IRQ");
//如果可用,向内核说明该gpio此被占用
if(ret<0 && ret!=-EBUSY)
{
EGALAX_DBG(DBG_MODULE, " gpio_request[%d] failed: %d\n", p_egalax_i2c_dev->interrupt_gpio, ret);
goto fail1;
}
gpio_direction_input(p_egala