gslx680触摸屏驱动源码码分析(gslX680.c)
Posted 正在起飞的蜗牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了gslx680触摸屏驱动源码码分析(gslX680.c)相关的知识,希望对你有一定的参考价值。
1、触摸屏代码整体分析
(1)gslx680触摸屏是I2C接口设备,所以驱动代码是利用I2C子系统提供的接口来编写,用I2C核心层提供的I2C驱动注册接口将构建好的I2C驱动结构体向I2C子系统注册;】
(2)注册的触摸屏I2C驱动会在I2C总线上和对应的I2C设备匹配上,从而调用I2C驱动的probe方法;
(3)I2C子系统在整个触摸屏驱动代码中,只是负责I2C设备和主控Soc的通信,整个触摸屏代码还涉及了input子系统用于向上层应用上报触摸时间,涉及中断子系统用于处理触摸屏的中断;
2、触摸屏驱动注册函数
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,
;
static int __init gsl_ts_init(void)
int ret;
print_info("==gsl_ts_init==\\n");
ret = i2c_add_driver(&gsl_ts_driver);
print_info("ret=%d\\n",ret);
return ret;
注册函数完成的功能就是向I2C子系统注册了名字是gsl_ts_driver的I2C驱动;
3、触摸屏驱动的probe函数
//在gslx680触摸屏驱动中用来描述I2C驱动的结构体
struct gsl_ts
struct i2c_client *client;
struct input_dev *input;
struct work_struct work;
struct workqueue_struct *wq;
struct gsl_ts_data *dd;
u8 *touch_data;
u8 device_id;
int irq;
#if defined(CONFIG_HAS_EARLYSUSPEND)
struct early_suspend early_suspend;
#endif
;
static int __devinit gsl_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id)
struct gsl_ts *ts;
int rc;
······
//检查适配器是否支持标准I2C通信协议
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
dev_err(&client->dev, "I2C functionality not supported\\n");
return -ENODEV;
ts = kzalloc(sizeof(*ts), GFP_KERNEL);
if (!ts)
return -ENOMEM;
print_info("==kzalloc success=\\n");
//将client保存到ts结构体中
ts->client = client;
//把ts保存到client->dev的私有数据
i2c_set_clientdata(client, ts);
ts->device_id = id->driver_data;
//注册input子系统,初始化工作队列,绑定触摸屏中断的下半部
rc = gslX680_ts_init(client, ts);
if (rc < 0)
dev_err(&client->dev, "GSLX680 init failed\\n");
goto error_mutex_destroy;
gsl_client = client;
//设置触摸屏相关GPIO引脚
gslX680_init();
//通过读写触摸屏芯片相关的寄存器完成初始化
init_chip(ts->client);
check_mem_data(ts->client);
//申请中断号并绑定中断处理程序
rc= request_irq(client->irq, gsl_ts_irq, IRQF_TRIGGER_RISING, client->name, ts);
if (rc < 0)
print_info( "gsl_probe: request irq failed\\n");
goto error_req_irq_fail;
······
(1)向I2C核心层注册的I2C触摸屏驱动最终会在I2C总线上匹配上I2C设备,也就是struct i2c_client结构体;
(2)I2C总线会调用I2C驱动的probe方法,把匹配上的struct i2c_client结构体传进去;
(3)probe函数中会完成初始化工作,其中包括input子系统的注册,中断程序的注册;
4、中断处理函数
static irqreturn_t gsl_ts_irq(int irq, void *dev_id)
struct gsl_ts *ts = dev_id;
print_info("========gslX680 Interrupt=========\\n");
//禁止中断
disable_irq_nosync(ts->irq);
//检测中断下半部所属的工作队列是否挂起,如果挂起则将中断的下半部添加到队列中进行调度
//调用中断下半部函数,也就是gslX680_ts_worker()
if (!work_pending(&ts->work))
queue_work(ts->wq, &ts->work);
return IRQ_HANDLED;
(1)gsl_ts_irq()函数只是中断处理函数的上半部,实际功能就是禁止中断,然后调用中断下半部;
(2)gslX680_ts_worker()是中断的下半部,在gslX680_ts_init()函数中指定;
补充:参考博客:《中断的顶半部和底半部介绍以及实现方式(tasklet 和 工作队列)》;
5、整个触摸屏驱动代码工作的逻辑
gsl_ts_irq() //中断上半部
gslX680_ts_worker() //中断下半部
gsl_ts_write() //触摸屏驱动的写数据
i2c_master_send() //实际调用I2C核心层的发数据接口
gsl_ts_read() //触摸屏驱动的读数据
i2c_master_recv() //实际调用I2C核心层的收数据接口
report_data() //上报数据
input_report_abs() //实际调用input子系统的上报接口
(1)当触摸屏发生触摸事件时,触发绑定的中断处理程序gsl_ts_irq();
(2)gsl_ts_irq()是中断上半部,禁止中断然后调用中断下半部gslX680_ts_worker();
(3)gslX680_ts_worker()函数会通过I2C子系统提供的I2C总线的收发数据接口函数,读写触摸屏芯片的相关寄存器;
(4)gslX680_ts_worker()函数将从触摸屏芯片读取到的数据进行计算和转换,然后填充成输入事件结构体,根据之前注册的input子系统,按input子系统的输入事件往应用层上报;
以上是关于gslx680触摸屏驱动源码码分析(gslX680.c)的主要内容,如果未能解决你的问题,请参考以下文章
Aurora R4显示器驱动以停止响应。GTX 680 双显卡。