决定自己去分析下我工作中会经常涉及到的几个驱动,暂定的有TP(义隆2127),G-SENSOR(bma150),CAMERA(GC0308),CODEC(es8328)这几个驱动吧,因为现在的LCD不需要驱动,而USB-wifi方面,并没有去公开源代码,采用的是直接加载KO文件,所以在USB设备驱动方面,只能更多的参考usb-Skeleton.c这个标准文件。
第一节我们分析的是TP的驱动,TP驱动,在接口方面很简单,使用I2C来传递命令和数据,其中主要涉及到的内容有I2C设备,输入子系统,中断以及下半部机制,工作队列等内容吧。
从头开始分析代码:一切驱动的入口module_init(),在驱动的最后位置找了下,没看到module_init()函数,倒是看到这个late_initcall(elan_ktf2k_ts_init)和module_exit(elan_ktf2k_ts_exit)相对应,原来late_initcall(elan_ktf2k_ts_init)就是这个驱动的入口。有关late_initcall()和module_init()函数的区别可以参考此文章: http://blog.csdn.net/cstk502/article/details/6579231
我们接着看elan_ktf2k_ts_init()内部的主要内容:
首先定义了一个i2c_board_info结构体,以及i2c_adapter和i2c_client指针。紧接着就是对i2c_board_info结构体和i2c_adapter指针进行填充,这两个结构体的主要功能基本是为了收集资源,client = i2c_new_device(adapter, &info);这个函数利用i2c_board_info结构体和i2c_adapter指针生成了一个新的i2c_client,并且将这个i2c_clint注册到了i2c_device链表中。
err =i2c_add_driver(&ektf2k_ts_driver);这个函数的作用就是将ektf2k_ts_driver注册到i2c_driver链表中,在每次注册完i2c_device或者i2c_driver后,都会有个匹配过程,主要是通过名字匹配,如果匹配成功,则会调用i2c_driver的probe函数。接下来我们去看看ektf2k_ts_driver的probe函数elan_ktf2k_ts_probe。
elan_ktf2k_ts_probe函数开头有两个非常重要的参数定义:
struct elan_ktf2k_i2c_platform_data *pdata;主要是为了接受i2c_clint中i2c_board_info传来的资源,structelan_ktf2k_ts_data *ts;这个是为了综合整个TP驱动中使用的所有资源,包括中断,输入子系统,工作队列等,应该说,整个驱动最难的地方在于如何设计这个结构体。
开始会进行对adapter有效性的测试,ts的内存分配等。主要的工作在下面:
ts->elan_wq =create_singlethread_workqueue("elan_wq"); 创建一个工作队列
INIT_WORK(&ts->work, elan_ktf2k_ts_work_func); 设置ts中的任务,这个任务相当重要elan_ktf2k_ts_work_func
ts->client = client;
i2c_set_clientdata(client, ts); 将ts和i2c_clint进行相互绑定
fw_err = elan_ktf2k_ts_setup(client); 读取hello_packet,检查通信是否正常
ts->input_dev = input_allocate_device() 创建input_device
紧接着会对input_device进行一系列的设置,有关input_device的原理,可以参见这篇文章:
http://blog.csdn.net/wealoong/article/details/7580916
err =input_register_device(ts->input_dev); 设置之后自然是注册
现在仅仅最后一步,也是最重要的一步,注册中断,因为整个TP的数据传输都是采用中断方式实现的。
elan_ktf2k_ts_register_interrupt(ts->client); 这是整个中断注册函数的封装。
现在我们仔细对elan_ktf2k_ts_register_interrupt(ts->client);这个中断注册函数进行分析。
err = request_irq(_sui_irq_num,elan_ktf2k_ts_irq_handler,0/*IRQF_TRIGGER_FALLING*/, client->name, ts); 中断注册函数
中断处理函数elan_ktf2k_ts_irq_handler()中主要的内容为:
queue_work(ts->elan_wq,&ts->work); 将任务添加到队列
有关工作队列的使用,可以参考这篇文章:http://www.cnblogs.com/wwang/archive/2010/10/27/1862202.html
我们继续跟踪下工作队列中任务函数:elan_ktf2k_ts_work_func()
elan_ktf2k_ts_recv_data(ts->client,buf); 利用i2c接受数据
elan_ktf2k_ts_report_data(ts->client,buf); 数据分析,然后上报到输入子系统
其中有关数据分析,主要是和通信协议有关。
整个驱动中,最重要的是elan_ktf2k_ts_data这个结构体,这个结构体中,最重要的几个元素,i2c_clint,input_device,workqueue_struct,work_struct等,产生中断,中断处理函数将任务放到工作队列,任务是通过i2c接受数据,分析数据,上报到输入子系统
通过分析,发现惠鼎,敦泰的驱动在流程上都是一样的,主要区别有两点,一是ts_data结构体,二是在通信数据分析不一样。