触摸屏驱动通常会用input子系统的方式实现。x4412开发板对应的电容触摸屏驱动源码路径: - kernel/drivers/input/touchscreen/ft5x06_touch.c
- kernel/drivers/input/touchscreen/ft5x06_firmware_1024_600.h
- kernel/drivers/input/touchscreen/ft5x06_firmware_800_480.h
复制代码针对1024*600的LCD屏,使用ft5x06_firmware_1024_600.h头文件,针对800*480的LCD屏,使用ft5x06_firmware_800_480.h头文件。不同的LCD屏,驱动IC的firmware不一样,在驱动中通过__setup函数从内核的启动参数中将tp的值读到字符串数组tp_name中,程序再根据tp_name的内容确定LCD屏,进而确定firmware对应的头文件。 在驱动初始化文件ft5x06_ts_init中,同时调用了platform_device_register和platform_driver_register,对应的平台设备和平台驱动名称都为ft5x06-ts,在系统总线上完成device和driver的绑定,探测函数ft5x06_ts_probe得以运行。 在ft5x06_ts_probe函数中添加了一个I2C设备,真正触摸屏的一些初始化函数在I2C对应的探测函数ft5x06_iic_probe中。 程序中定义了一个全局结构体变量ft5x06_ts: - struct ft5x06_ts {
- struct workqueue_struct * wq;
- struct work_struct work;
- struct i2c_client * client;
- struct input_dev * input_dev;
-
- struct point_node node[5];
- };
复制代码 结构体中声明了一个工作队列wq,一个工作结构体work,wq和work用于实现一套完整的工作队列机制。client为一个i2c_client结构体,input_dev为输入子系统结构体,point_node用于记录多指触摸的数据。 探测函数ft5x06_iic_probe中定义了一个指向ft5x06_ts的结构体指针,并通过kzalloc函数为结构体申请内存,同时将结构体成员清零。使用create_singlethread_workqueue函数创建了一个私有的工作队列,用于实现中断底半部机制,因为多指触摸的中断函数中会有大量的数据处理,使用底半部机制是最佳选择。紧接着通过input_allocate_device函数给触摸屏分配一个输入子系统,并给ts->input_dev填充了name,phys,id号等。接着调用set_bit函数用于支持触摸屏的一系列事件,如事件分割事件,按键事件,绝对坐标,触摸事件等。input_set_abs_params函数用于初始化ts->input_dev结构体,input_register_device函数用于注册触摸屏输入子系统。随后请求中断,每当有触摸事件产生,将会触发中断产生,中断服务函数ft5x06_ts_irq_handler得以执行。 在ft5x06_ts_irq_handler函数中,work_pending函数用于判断当前任务是否仍在进行,如果是,则忽略此次中断事件,否则引用queue_work函数触发工作队列,进入中断底半部函数ft5x06_ts_work_func中。 ft5x06_ts_work_func函数通过ft5x06_read_coordinates函数从I2C接口上读取触摸数据,并保存到buf数组中。在buf数组中最大可同时保存5组触摸数据,通过里面的数据分析可以得到具体的触摸事件,最后通过如下函数组给上层提交触摸数据: - input_report_abs(); //上报坐标植数据
- input_report_key(); //上报按键数据
- input_mt_sync(); //上报一个点的信息,标记一个点的结束
- input_sync(); //上报多指信息,告知接收方开始接收下一点数据
复制代码 整个触摸屏输入子系统的驱动框架到这里就完成了。
|