触摸屏驱动分析(eeti源码为例)

本文详细解析了触摸屏驱动的加载流程,从`module_init(egalax_i2c_ts_init)`开始,深入探究了`probe`函数、`allocate_Input_Dev`(input子系统注册)、中断注册及触摸数据上报处理。文章以eeti源码为实例,阐述了驱动执行的关键步骤,并预告将探讨input_dev和handler的匹配过程。
摘要由CSDN通过智能技术生成

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值