gslx680电容触摸屏是一种目前Android嵌入式设备中比较常用的触摸屏类型。这里我们以Exynos4412为Android bsp平台,移植一款gslx680电容触摸屏。 关于电容触摸屏的原理,这里不进行讲解,不明白的,可以参照一下博客:http://blog.csdn.net/xubin341719/article/details/7820492 这里只从实际工程出发,讲解移植过程。谢谢~~
路径:xxx/kernel/drivers/input/touchscreen/Kconfig 
路径:xxx/kernel/drivers/input/touchscreen/Makefile 
gslx680.c gslx680.h gsl_point_id 查看附件
注意:gsl_point_id是一个linux库文件
这里的IIC地址一定要与程序上面一致,并且和设备的吻合
首先,在加载驱动后,Linux系统通过module_init(gsl_ts_init);进行设备的初始化
static int __init gsl_ts_init(void){ int ret; if(strcasecmp(tp_name, "gslx680") == 0) { printk("Initial gslx680 Touch Driver/n"); } else { return 0; } print_info("==gsl_ts_init==/n"); ret = i2c_add_driver(&gsl_ts_driver); print_info("ret=%d/n",ret); return ret;}主要是通过i2c_add_driver(&gsl_ts_driver)将
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,};挂载到IIC总线
设备的探测函数,退出函数、设备的ID等等都注册上去。 在设备工作时,首先是探测函数
static int __devinit gsl_ts_probe(struct i2c_client *client, const struct i2c_device_id *id){ struct gsl_ts *ts; int rc; print_info("GSLX680 Enter %s/n", __func__); 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"); ts->client = client; i2c_set_clientdata(client, ts); ts->device_id = id->driver_data; rc = gslX680_ts_init(client, ts); //初始化gls1680 if (rc < 0) { dev_err(&client->dev, "GSLX680 init failed/n"); goto error_mutex_destroy; } gsl_client = client; gslX680_init(); /初始化gls1680相关的IO端口 init_chip(ts->client); check_mem_data(ts->client); rc= request_irq(client->irq, gsl_ts_irq, IRQF_TRIGGER_RISING, client->name, ts); //中断请求 ,注册终端,上升沿触发 gsl_ts_irq 回调函数 if (rc < 0) { print_info( "gsl_probe: request irq failed/n"); goto error_req_irq_fail; } /* create debug attribute */ //rc = device_create_file(&ts->input->dev, &dev_attr_debug_enable);#ifdef CONFIG_HAS_EARLYSUSPEND ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; //ts->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 1; ts->early_suspend.suspend = gsl_ts_early_suspend; ts->early_suspend.resume = gsl_ts_late_resume; register_early_suspend(&ts->early_suspend);#endif#ifdef GSL_MONITOR print_info( "gsl_ts_probe () : queue gsl_monitor_workqueue/n"); INIT_DELAYED_WORK(&gsl_monitor_work, gsl_monitor_worker); gsl_monitor_workqueue = create_singlethread_workqueue("gsl_monitor_workqueue"); queue_delayed_work(gsl_monitor_workqueue, &gsl_monitor_work, 1000);#endif print_info("[GSLX680] End %s/n", __func__); return 0; //exit_set_irq_mode:error_req_irq_fail: free_irq(ts->irq, ts);error_mutex_destroy: input_free_device(ts->input); kfree(ts); return rc;}看看中断回调函数,中断回调函数相当于中断的上半部,主要是做一些简单工作,复制事情交给中断下半部实现,也就是开启的工作队列线程。
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);//关闭中断 if (!work_pending(&ts->work)) { queue_work(ts->wq, &ts->work);//将工作线程再次加入工作队列 } return IRQ_HANDLED;}这里我们看看中断下半部核心处理部分,包括数据采集与上报子系统等等
static void gslX680_ts_worker(struct work_struct *work){ int rc, i,j; u8 id, touches, read_buf[4] = {0}; u16 x, y; struct gsl_ts *ts = container_of(work, struct gsl_ts,work); print_info("=====gslX680_ts_worker=====/n");#ifdef GSL_MONITOR if(i2c_lock_flag != 0) goto i2c_lock_schedule; else i2c_lock_flag = 1;#endif#ifdef GSL_NOID_VERSION u32 tmp1; u8 buf[4] = {0}; struct gsl_touch_info cinfo = {0};#endif rc = gsl_ts_read(ts->client, 0x80, ts->touch_data, ts->dd->data_size);//读取触摸屏的信息 if (rc < 0) { dev_err(&ts->client->dev, "read failed/n"); goto schedule; } touches = ts->touch_data[ts->dd->touch_index];//触点数 print_info("-----touches: %d -----/n", touches);#ifdef GSL_NOID_VERSION cinfo.finger_num = touches; print_info("tp-gsl finger_num = %d/n",cinfo.finger_num); for(i = 0; i < (touches < MAX_CONTACTS ? touches : MAX_CONTACTS); i ++) { cinfo.x[i] = join_bytes( ( ts->touch_data[ts->dd->x_index + 4 * i + 1] & 0xf), ts->touch_data[ts->dd->x_index + 4 * i]); cinfo.y[i] = join_bytes(ts->touch_data[ts->dd->y_index + 4 * i + 1], ts->touch_data[ts->dd->y_index + 4 * i ]); cinfo.id[i] = ((ts->touch_data[ts->dd->x_index + 4 * i + 1] & 0xf0)>>4); print_info("tp-gsl before: x[%d] = %d, y[%d] = %d, id[%d] = %d /n",i,cinfo.x[i],i,cinfo.y[i],i,cinfo.id[i]); } cinfo.finger_num=(ts->touch_data[3]<<24)|(ts->touch_data[2]<<16) |(ts->touch_data[1]<<8)|(ts->touch_data[0]); gsl_alg_id_main(&cinfo); tmp1=gsl_mask_tiaoping(); print_info("[tp-gsl] tmp1=%x/n",tmp1); if(tmp1>0&&tmp1<0xffffffff) { buf[0]=0xa; buf[1]=0; buf[2]=0; buf[3]=0; gsl_ts_write(ts->client,0xf0,buf,4); buf[0]=(u8)(tmp1 & 0xff); buf[1]=(u8)((tmp1>>8) & 0xff); buf[2]=(u8)((tmp1>>16) & 0xff); buf[3]=(u8)((tmp1>>24) & 0xff); print_info("tmp1=%08x,buf[0]=%02x,buf[1]=%02x,buf[2]=%02x,buf[3]=%02x/n", tmp1,buf[0],buf[1],buf[2],buf[3]); gsl_ts_write(ts->client,0x8,buf,4); } touches = cinfo.finger_num;#endif for(i = 1; i <= MAX_CONTACTS; i ++) { if(touches == 0) id_sign[i] = 0; id_state_flag[i] = 0; } for(i= 0; i < (touches > MAX_FINGERS ? MAX_FINGERS : touches); i ++) {#ifdef GSL_NOID_VERSION id = cinfo.id[i]; x = cinfo.x[i]; y = cinfo.y[i];#else x = join_bytes( ( ts->touch_data[ts->dd->x_index + 4 * i + 1] & 0xf), ts->touch_data[ts->dd->x_index + 4 * i]); y = join_bytes(ts->touch_data[ts->dd->y_index + 4 * i + 1], ts->touch_data[ts->dd->y_index + 4 * i ]);//id = ts->touch_data[ts->dd->id_index + 4 * i] >> 4; id = ts->touch_data[ts->dd->id_index + 4 * i] >> 4;#endif print_info("-->x = %d, y = %d,id = %d, max = %d,ts->dd->x_index = %d/n",x,y,id,MAX_CONTACTS,ts->dd->id_index);//id = touches; if(1 <=id && id <= MAX_CONTACTS) {#ifdef FILTER_POINT filter_point(x, y ,id);//滤波#else record_point(x, y , id);//记录处理#endif print_info("-->x_new = %d, y_new = %d/n",x_new,y_new); report_data(ts, x_new, y_new, 10, id); //上报数据 id_state_flag[id] = 1; } } for(i = 1; i <= MAX_CONTACTS; i ++) { if( (0 == touches) || ((0 != id_state_old_flag[i]) && (0 == id_state_flag[i])) ) {#ifdef REPORT_DATA_ANDROID_4_0 input_mt_slot(ts->input, i); input_report_abs(ts->input, ABS_MT_TRACKING_ID, -1); input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, false);#endif id_sign[i]=0; } id_state_old_flag[i] = id_state_flag[i]; } if(0 == touches) {#ifndef REPORT_DATA_ANDROID_4_0 input_mt_sync(ts->input);#endif#ifdef HAVE_TOUCH_KEY if(key_state_flag) { input_report_key(ts->input, key, 0); input_sync(ts->input); key_state_flag = 0; }#endif } input_sync(ts->input);//同步更新schedule:#ifdef GSL_MONITOR i2c_lock_flag = 0;i2c_lock_schedule:#endif enable_irq(ts->irq);//再次开启中断}至此,glax680电容触摸屏的驱动移植与分析完毕,希望能给大家带来一点点的帮助… 参考资料下载地址:http://download.csdn.net/detail/zgkxzx/9763694
新闻热点
疑难解答