Imx6使用的触摸屏控制芯片是ft5x06系列的,对应的文件为:ft5x06_ts.c。

Ft5x06_ts驱动涉及的内容如下:

1.  I2C驱动框架。

2.  中断子系统,中断分层思想。

3.  Workqueue机制。

4.  Input输入子系统。

如上图所示,是触摸板与cpu的连接图,触摸板没有使用cpu的AD转换装置,ft5x06内部自带AD转换,将x y坐标通过I2C传送出来。当用户手指接触触摸屏时,CAP_TCH_INT0产生中断,在中断处理函数中,将数据读取出来,并通过处理传输到上层。

引脚功能配置

1.  I2C2功能初始化:

查看原理图可知道,触摸板与cpu的I2C-2相连。

在board-mx6q_sarbresd.h中找到mx6q_sabresd_pads[]数组,在数组中添加:

/* I2C2, Camera, MIPI */

MX6Q_PAD_KEY_COL3__I2C2_SCL,

MX6Q_PAD_KEY_ROW3__I2C2_SDA,

2.将A16(NANDF_ALE)引脚设置为中断模式

仍然在mx6q_sabresd_pads[]数组中添加:

/* CAP_TCH_INT0*/

MX6Q_PAD_NANDF_ALE__GPIO_6_8,

板级文件添加

board-mx6q_sarbresd.c中找到mxc_i2c1_board_info2[]数组,这里很奇怪,为什么是mxc_i2c1?这是飞思卡尔的定义,在原理图中,I2C以1开头,而在驱动中,I2C又是以I2C0开头。在xc_i2c1_board_info2[]添加:

{

I2C_BOARD_INFO("ft5x0x_ts", 0x38),

.irq = gpio_to_irq(SABRESD_CAP_TCH_INT0),

},

通过查看原理图,和芯片手册,可以知道Ft5x06_ts的地址是0x38。将触摸板的设备名字取为“ft5x06_ts”,I2C通信的地址为0x38。

.irq = gpio_to_irq(SABRESD_CAP_TCH_INT0),设置A16引脚的中断号,gpio_to_irq是飞思卡尔提供的一个接口函数,宏SABRESD_CAP_TCH_INT0的定义为:

#define SABRESD_CAP_TCH_INT0    IMX_GPIO_NR(6, 8)

关于如何使用引脚,参考:

http://blog.csdn.net/sddsighhz/article/details/36653517

板级文件添加好了之后,接下来分析驱动,驱动对应的文件是:ft5x06_ts.c。

老方法,驱动的入口函数是module_init:

module_init(ft5x0x_ts_init);

static int __init ft5x0x_ts_init(void)

{

int ret;

//printk("ft5x0x_ts_init\n");

ret =i2c_add_driver(&ft5x0x_ts_driver);

//printk("ret=%d\n",ret);

return ret;

}

ft5x0x_ts_init函数中注册了一个i2c驱动,找到ft5x0x_ts_driver结构。

static struct i2c_driver ft5x0x_ts_driver = {

.probe        = ft5x0x_ts_probe,

.remove       = __devexit_p(ft5x0x_ts_remove),

.id_table = ft5x0x_ts_id,

.driver  = {

.name    = FT5X0X_NAME,

.owner   = THIS_MODULE,

},

};

I2C设备和驱动是通过.name匹配的,FT5X0X_NAME宏就是ft5x0x_ts。

#defineFT5X0X_NAME   "ft5x0x_ts"

前面板级文件中,有:I2C_BOARD_INFO("ft5x0x_ts",0x38)正好和驱动中的FT5X0X_NAME匹配,配备成功之后,就会运行.probe。

接下来分析ft5x0x_ts_probe函数

代码就不全部贴出来了,分析关键部分。

if (!i2c_check_functionality(client->adapter,I2C_FUNC_I2C)) {

err =-ENODEV;

goto exit_check_functionality_failed;

}

上面代码判断i2c适配器的所支持的通信方法,如果这个适配器不具有I2C功能,则失败。

ft5x0x_ts = kzalloc(sizeof(struct ft5x0x_ts_data),GFP_KERNEL);

//ft5x0x_ts= kmalloc(sizeof(struct ft5x0x_ts_data), GFP_KERNEL);

if(!ft5x0x_ts) {

err =-ENOMEM;

goto exit_alloc_data_failed;

}

上述代码分配一个structft5x0x_ts_data结构,这个结构是自己定义的,我们看看这个结构,并注释好结构中的内容:

structft5x0x_ts_data {

struct input_dev    *input_dev;//input输入设备结构

struct ts_event     event;//飞凌定义的触摸结构,包括x坐标,y坐标等。

struct work_struct pen_event_work;//工作结构体,用于中断分层

struct workqueue_struct *ts_workqueue;//工作队列结构体,用于处理中断下部分工作

struct early_suspend    early_suspend;//安卓的休眠机制。

struct mutex device_mode_mutex;   /* Ensures that only one function canspecify the Device Mode at a time. */

};

reqirq_id = client->irq;

这行代码是获取板级文件中的中断号。 .irq =gpio_to_irq(SABRESD_CAP_TCH_INT0)

i2c_set_clientdata(client, ft5x0x_ts);

将自定义的设备结构ft5x0x_ts赋给设备驱动client的私有指针.

mutex_init(&ft5x0x_ts->device_mode_mutex);

初始化互斥锁。

INIT_WORK(&ft5x0x_ts->pen_event_work,ft5x0x_ts_pen_irq_work);

初始化工作队列。待会儿需要关注ft5x0x_ts_pen_irq_work。

ft5x0x_ts->ts_workqueue =create_singlethread_workqueue(dev_name(&client->dev));

创建workqueue,只创建一个内核线程。它和create_workqueue区别:create_workqueue用于创建一个workqueue队列,为系统中的每个CPU都创建一个内核线程。

err =request_irq(reqirq_id, ft5x0x_ts_interrupt, IRQF_TRIGGER_FALLING,"ft5x0x_ts", ft5x0x_ts);

申请中断,采用的是下降沿的方式触发中断,当中断产生时,进入到ft5x0x_ts_interrupt函数中执行。

disable_irq(reqirq_id);

使中断失效。

input_dev = input_allocate_device();

分配输入型设备结构

ft5x0x_ts->input_dev = input_dev;

将输入型设备结构复制给struct ft5x0x_ts结构中的input_dev成员变量。

接下来的代码,将重点分析:

#ifdef CONFIG_ANDROID

set_bit(ABS_MT_TOUCH_MAJOR,input_dev->absbit);

set_bit(ABS_MT_POSITION_X,input_dev->absbit);

set_bit(ABS_MT_POSITION_Y,input_dev->absbit);

set_bit(ABS_MT_WIDTH_MAJOR,input_dev->absbit);

input_set_abs_params(input_dev,

ABS_MT_POSITION_X, 0, SCREEN_MAX_X, 0, 0);

input_set_abs_params(input_dev,

ABS_MT_POSITION_Y, 0, SCREEN_MAX_Y, 0, 0);

input_set_abs_params(input_dev,

ABS_MT_TOUCH_MAJOR, 0, PRESS_MAX, 0, 0);

input_set_abs_params(input_dev,

ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0);

input_set_abs_params(input_dev,

ABS_MT_TRACKING_ID, 0, 5, 0, 0);

set_bit(EV_KEY, input_dev->evbit);

set_bit(EV_ABS, input_dev->evbit);

#if CFG_SUPPORT_TOUCH_KEY

//setup keycode area

set_bit(EV_SYN, input_dev->evbit);

set_bit(BTN_TOUCH, input_dev->keybit);

input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); //new

input_dev->keycode = tsp_keycodes_forlinx;

for(i = 0;i < CFG_NUMOFKEYS; i++)

{

input_set_capability(input_dev, EV_KEY,((int*)input_dev->keycode)[i]);

tsp_keystatus_forlinx[i] = KEY_RELEASE;

}

#endif

#else

set_bit(EV_SYN, input_dev->evbit);

set_bit(EV_KEY, input_dev->evbit);

set_bit(EV_ABS,input_dev->evbit);

set_bit(BTN_TOUCH, input_dev->keybit);

input_set_abs_params(input_dev, ABS_X, TOUCHSCREEN_MINX,TOUCHSCREEN_MAXX, 0, 0);

input_set_abs_params(input_dev, ABS_Y, TOUCHSCREEN_MINY,TOUCHSCREEN_MAXY, 0, 0);

input_set_abs_params(input_dev,ABS_PRESSURE, 0, 255, 0, 0);

input_set_abs_params(input_dev, ABS_TOOL_WIDTH, 0, 15, 0, 0);

#endif

首先,上述这段代码用宏控制用于安卓还是linux,安卓设备中,一般支持多点触控,在上报input event的时候,需要设置多点触控的相关属性,以便于在中断中实现多点触控的协议。Linux+QT设备,一般不需要使用多点触控的功能。

set_bit(ABS_MT_TOUCH_MAJOR,input_dev->absbit);ABS_MT_TOUCH_MAJOR:接触区域的长轴的长度。该长度应该按接触表面的单位提供。如果表面的分辨率是X-Y,则ABS_MT_TOUCH_MAJOR可能的最大值是sqrt(X^2 + Y^2)。

set_bit(ABS_MT_POSITION_X,input_dev->absbit);ABS_MT_POSITION_X:接触中心的X坐标。

set_bit(ABS_MT_POSITION_Y, input_dev->absbit);ABS_MT_POSITION_Y:接触中心的Y坐标。

set_bit(ABS_MT_WIDTH_MAJOR, input_dev->absbit);ABS_MT_WIDTH_MAJOR:工具轮廓区域短轴的表面单位长度,圆形的话可以被忽略。

input_set_abs_params(input_dev,ABS_MT_POSITION_X, 0,SCREEN_MAX_X, 0, 0);设置x坐标取值范围。SCREEN_MAX_X为800

input_set_abs_params(input_dev,ABS_MT_POSITION_Y,0, SCREEN_MAX_Y, 0, 0);设置y坐标取值范围。SCREEN_MAX_X为480

input_set_abs_params(input_dev,ABS_MT_TOUCH_MAJOR,0, PRESS_MAX, 0, 0);将触摸点看成一个椭圆,这里是设置它的长轴长度。这个是可选项,并不影响正常使用。PRESS_MAX是255.

input_set_abs_params(input_dev,ABS_MT_WIDTH_MAJOR,0, 200, 0, 0); 如果设备支持ABS_MT_WIDTH_MAJOR这个事件,那么此事件可以提供手指触摸接触面积大小。

ABS_MT_TOUCH_MAJOR表示了手指接触TP的直径的近似。ABS_MT_WIDTH_MAJOR是手指的直径的近似。当手指和触摸屏接触的越紧密,则压力越大,手指和屏幕接触的面积(直径)也会越大。而手指的直径通常是一个常量。这样ABS_MT_TOUCH_MAJOR / ABS_MT_WIDTH_MAJOR就可以用来表示压力了。而且这个值在[0,1)间。对于某些提供了压力值的TP,可以使用ABS_MT_PRESSURE来替代ABS_MT_TOUCH_MAJOR.

input_set_abs_params(input_dev,ABS_MT_TRACKING_ID,0, 5, 0, 0);设置上报的id数目为5个。ABS_MT_TRACKING_ID,用来支持硬件跟踪多点信息,即该点属于哪一条线等。

对于触摸屏,必须支持的事件类型有以下这么三个

set_bit(EV_SYN, input_dev->evbit); //设备同步,每次触摸完成以后都要发送一个同步事件,来表明这次触摸已经完成

set_bit(EV_ABS, input_dev->evbit); //绝对坐标事件,触摸屏每次发送的坐标都是绝对坐标,不同于鼠标的相对坐标

set_bit(EV_KEY, input_dev->evbit); //按键事件,每次触摸都有一个

#if CFG_SUPPORT_TOUCH_KEY

//setup keycode area

set_bit(EV_SYN, input_dev->evbit);

set_bit(BTN_TOUCH, input_dev->keybit);

input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); //new

input_dev->keycode = tsp_keycodes_forlinx;

for(i = 0;i < CFG_NUMOFKEYS; i++)

{

input_set_capability(input_dev,EV_KEY, ((int*)input_dev->keycode)[i]);

tsp_keystatus_forlinx[i] = KEY_RELEASE;

}

#endif

这部分代码是支持屏幕之外的触摸按键的,就是我们安卓手机home键那一排的三个实体的按键(back home menu),这里要却别于安卓的虚拟按键,有很多厂商在显示屏内部也搞了三个虚拟按键(back home menu),虚拟按键是在framework层实现的,这里我们不管。

代码中的input_set_capability(input_dev, EV_KEY,((int*)input_dev->keycode)[i]); 用于记录本设备对于哪些事件感兴趣,这里把(back home menu)按键记录下来了。我们知道,实体按键是和触摸屏连在一起的,在LCD屏的显示区域外,当触摸屏发现x坐标>800,或者y坐标> 480的时候,我们就需要去处理本设备“感兴趣”事件。

Linux的部分先不分析,比较简单。

继续分析ft5x0x_ts_probe。

input_dev->name= FT5X0X_NAME;

设置input设备的名字为ft5x0x_ts。

err = input_register_device(input_dev);

注册input设备驱动,代码运行到这儿,linux内核中就可以在设备的/dev/input/目录下看到相应的eventX设备了,至于是event几,要看内核的分配。

#ifdef CONFIG_HAS_EARLYSUSPEND

//printk("==register_early_suspend=\n");

ft5x0x_ts->early_suspend.level= EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;

ft5x0x_ts->early_suspend.suspend= ft5x0x_ts_suspend;

ft5x0x_ts->early_suspend.resume = ft5x0x_ts_resume;

register_early_suspend(&ft5x0x_ts->early_suspend);

#endif

上面的这段代码是与安卓休眠机制有关的,early_suspend是Android休眠流程的第一阶段即浅度休眠,不会受到wake_lock的阻止,一般用于关闭lcd、tp等设备为运行的应用节约电能。Android的PowerManagerService会根据用户的操作情况调整电源状态,如果需要休眠则会调用到HAL层的set_screen_state()接口,在set_screen_state()中会向/sys/power/state节点写入"mem"值让驱动层开始进入休眠流程。

.level代表的是这个休眠的等级。这里设置的是51级

.suspend是休眠挂起的函数,我们进入到ft5x0x_ts_suspend函数中,其实只有一行代码:

disable_irq(this_client->irq);其实就是使中断失能能。当安卓设备休眠之后,我们再按屏幕是没有反应的,因为中断已经被我们关闭了。

. resume是唤醒函数,进入到ft5x0x_ts_resume函数中,其实就是使中断使能而已。enable_irq(this_client->irq);

register_early_suspend(&ft5x0x_ts->early_suspend);把early_suspend注册到内核。这样系统就可以统一调度休眠唤醒了。

关于安卓浅度休眠的详细介绍,参考博客http://blog.csdn.net/g_salamander/article/details/7982170

msleep(150);  //make sure CTPalready finish startup process

//get someregister information

uc_reg_value = ft5x0x_read_fw_ver();

//printk("[FTS] Firmware version = 0x%x\n", uc_reg_value);

ft5x0x_read_reg(FT5X0X_REG_PERIODACTIVE, &uc_reg_value);

//printk("[FTS] report rate is %dHz.\n", uc_reg_value * 10);

ft5x0x_read_reg(FT5X0X_REG_THGROUP, &uc_reg_value);

//printk("[FTS] touch threshold is %d.\n", uc_reg_value * 4);

//#ifdef CONFIG_ANDROID

//#else

printk("uc_reg_value=%d \n",uc_reg_value);

//uc_reg_value=128 while read iic error

if(uc_reg_value<128)

{

ts_proc_entry =create_proc_entry("driver/ft5x06_ts", 0, NULL);

//if (ts_proc_entry) {

//  ts_proc_entry->write_proc= 0;

//}

}

上面的这些代码就是去读取ft5x0x_ts相关寄存器的内容,其结果就起到调试的作用。

ts_proc_entry = create_proc_entry("driver/ft5x06_ts",0, NULL);会在开发板/proc/driver/目录创建一个ft5x0x_ts文件,这个文件不可用来操作ft5x0x_ts。

#if CFG_SUPPORT_AUTO_UPG

fts_ctpm_auto_upg();

#endif

#if CFG_SUPPORT_UPDATE_PROJECT_SETTING

fts_ctpm_update_project_setting();

#endif

上面的这些代码是不编译的。

enable_irq(reqirq_id);

probe函数退出之前,需要使能中断。

err = sysfs_create_group(&client->dev.kobj,&ft5x0x_attribute_group);

在kobj目录下创建一个属性集合,并显示集合中的属性文件。也就是这个input设备的属性集合。

分析probe函数中提交的工作

在ft5x0x_ts_probe函数中,我们分析到注册了一个中断函数。

err = request_irq(reqirq_id, ft5x0x_ts_interrupt,IRQF_TRIGGER_FALLING, "ft5x0x_ts", ft5x0x_ts);

中断来临时,会执行注册的ft5x0x_ts_interrupt函数,打开该函数:

static irqreturn_t ft5x0x_ts_interrupt(int irq, void*dev_id)

{

structft5x0x_ts_data *ft5x0x_ts = dev_id;

//disable_irq(IRQ_EINT(6));

disable_irq_nosync(reqirq_id);

//   printk("-------------------------INT______-\n");

//  enable_irq(reqirq_id);

if(!work_pending(&ft5x0x_ts->pen_event_work))

{

queue_work(ft5x0x_ts->ts_workqueue,&ft5x0x_ts->pen_event_work);

}

return IRQ_HANDLED;

}

进入中断后,先disable_irq_nosync(reqirq_id);关闭中断,防止触摸屏再次发送中断过来。为什么使用disable_irq_nosync呢?

因为disable_irq关闭中断并等待中断处理完后返回, 而disable_irq_nosync立即返回.在中断中是不允许使用disable_irq的,否则会导致cpu被synchronize_irq独占而发生系统崩溃.

接着work_pending(&ft5x0x_ts->pen_event_work)检查之前初始化的work队列是否被挂起,如果没有挂起,则提交工作(queue_work(ft5x0x_ts->ts_workqueue,&ft5x0x_ts->pen_event_work);)。

在ft5x0x_ts_probe函数中,我们也分析到初始化了一个工作:

INIT_WORK(&ft5x0x_ts->pen_event_work,ft5x0x_ts_pen_irq_work);

中断中提交了工作之后,中断就结束了,然后下半部分的中断就留给ft5x0x_ts_pen_irq_work函数处理。

static void ft5x0x_ts_pen_irq_work(struct work_struct*work)

{

int ret =-1;

ret =ft5x0x_read_data();

if (ret ==0)

{

ft5x0x_report_value();

}

enable_irq(reqirq_id);

}

下半部分中断中,先读取触摸芯片的数据,然后通过一系列的处理传送给上层,最后重新使能中断。

读取触摸芯片分析

static int ft5x0x_read_data(void)

{

structft5x0x_ts_data *data = i2c_get_clientdata(this_client);

structts_event *event = &data->event;

u8buf[CFG_POINT_READ_BUF] = {0};

int ret =-1;

int i;

//printk("start read_data i2c_rxdata\n");

ret = ft5x0x_i2c_rxdata(buf,CFG_POINT_READ_BUF);

if (ret< 0) {

//printk("%sread_data i2c_rxdata failed: %d\n", __func__, ret);

returnret;

}

memset(event,0, sizeof(struct ts_event));

event->touch_point= buf[2] & 0x07;

if(event->touch_point > CFG_MAX_TOUCH_POINTS)

{

event->touch_point = CFG_MAX_TOUCH_POINTS;

}

for (i = 0;i < event->touch_point; i++)

{

event->au16_x[i] = (s16)(buf[3 + 6*i] & 0x0F)<<8 |(s16)buf[4 + 6*i];

event->au16_y[i] = (s16)(buf[5 + 6*i] & 0x0F)<<8 |(s16)buf[6 + 6*i];

event->au8_touch_event[i] = buf[0x3 + 6*i] >> 6;

event->au8_finger_id[i] = (buf[5 + 6*i])>>4;

printk("\ntouch_point = %d event->au16_x[%d] = %u event->au16_y[%d] = %u \nau8_touch_event[%d] = %u au8_finger_id[%d] =%u\n",event->touch_point,i,event->au16_x[i],i,event->au16_y[i],i,event->au8_touch_event[i],event->au8_finger_id[i]);

}

if(event->touch_point==0)

{

printk("Touch up,it is end !\n");

}

event->pressure = 200;

//printk("start read_data i2c_rxdata OK\n");

return 0;

}

函数首先定义个buf数组,大小为3+6*5。这个数组格式正好是ft5x0x_ts芯片上报的数据格式。buf[0-2],包含的是一些基本信息,比如有多少个手指按下;每个6byte空间存放每个触控点的信息,这些信息包含接触点的x坐标(2byte)、y坐标(2byte)、按下还是弹起(1byte)、touch ID(1byte),加起来正好是6byte。这款触摸屏最多支持5点触控,所以buf设置也只能容下5个接触点的信息。

ret = ft5x0x_i2c_rxdata(buf, CFG_POINT_READ_BUF);

读取3+6*5长度的数据,读取不到这么多时,返回实际的读取长度,这个函数的实现,实际上是使用I2C core层提供的i2c_transfer函数。关于I2C驱动,这里不详细介绍了。

event->pressure = 200;这句说明这款新品不支持触摸压力检测,所以设置了一个常量。

读取之后,就是填充event结构了。下面是打印出来的event填充信息:

填充好event结构之后,就要上报event事件了,进入到ft5x0x_report_value函数中。我们简化一下代码,把宏去掉,把linux部分去掉:

static void ft5x0x_report_value(void)

{

structft5x0x_ts_data *data = i2c_get_clientdata(this_client);

structts_event *event = &data->event;

int i;

for (i  = 0; i < event->touch_point; i++)

{

if(event->au16_x[i] < SCREEN_MAX_X && event->au16_y[i] <SCREEN_MAX_Y) // LCD view area

{

input_report_abs(data->input_dev,ABS_MT_POSITION_X, event->au16_x[i]);

input_report_abs(data->input_dev,ABS_MT_POSITION_Y, event->au16_y[i]);

input_report_abs(data->input_dev,ABS_MT_WIDTH_MAJOR, 1);

input_report_abs(data->input_dev,ABS_MT_TRACKING_ID, event->au8_finger_id[i]);

if (event->au8_touch_event[i]== 0 ||event->au8_touch_event[i] == 2)

{

input_report_abs(data->input_dev,ABS_MT_TOUCH_MAJOR, event->pressure);

}

else

{

input_report_abs(data->input_dev,ABS_MT_TOUCH_MAJOR, 0);

}

}

else //maybe the touch key area

{

if(event->au16_x[i] >= SCREEN_MAX_X)

{

ft5x0x_touch_key_process_forlinx(data->input_dev,event->au16_x[i], event->au16_y[i], event->au8_touch_event[i]);

}

}

input_report_key(data->input_dev,BTN_TOUCH, 1); //new

input_mt_sync(data->input_dev);

}

if(event->touch_point==0)//touch up

{

intk=0;

for(k=0;k<CFG_NUMOFKEYS_FORLINX;k++)

{

if(tsp_keystatus_forlinx[k] == KEY_PRESS)

{

input_report_key(data->input_dev, tsp_keycodes_forlinx[k], 0);

tsp_keystatus_forlinx[k] = KEY_RELEASE;

printk( "[FTS] %s key is up. Keycode : %d\n",tsp_keyname_forlinx[k], tsp_keycodes_forlinx[k]);

}

}

input_report_key(data->input_dev, BTN_TOUCH, 0); //new

input_mt_sync(data->input_dev);//new

}

input_sync(data->input_dev);

if(event->touch_point == 0) {

ft5x0x_ts_release();

return;

}

}   /*endft5x0x_report_value*/

先简单介绍下多点触控的协议。

多点触摸协议有两种,A协议和B协议。

根具代码看,是使用A协议,协议上说了报点格式是这样的,以两点为例:

ABS_MT_POSITION_X x[0]

ABS_MT_POSITION_Yy[0]

SYN_MT_REPORT

ABS_MT_POSITION_X x[1]

ABS_MT_POSITION_Y y[1]

SYN_MT_REPORT

SYN_REPORT

如果第一个触点离开(抬起),这里的意思是说还有一个触点,需要继续上报这个触点。

ABS_MT_POSITION_X x[1]

ABS_MT_POSITION_Y y[1]

SYN_MT_REPORT

SYN_REPORT

如果两个触点都离开了,那么只需要报告一个同步事件就可以了。

SYN_MT_REPORT

SYN_REPORT

if(event->au16_x[i] >= SCREEN_MAX_X)

{

ft5x0x_touch_key_process_forlinx(data->input_dev,event->au16_x[i], event->au16_y[i], event->au8_touch_event[i]);

}

上述代码判断是否按下的是物理back、home、menu按键,SCREEN_MAX_X值是800,当x坐标值大于800时,ft5x0x_touch_key_process_forlinx函数将执行,然后将本设备记录的感兴趣事件上报给上层。

int ft5x0x_touch_key_process_forlinx(struct input_dev*dev, int x, int y, int touch_event)

{

int i;

int key_id;

if( y <120&&y > 90)

{

key_id= 0;

}

else if (y< 67&&y > 47)

{

key_id= 1;

}

elseif(y<20&&y>=0)

{

key_id =2;

}

else

{

key_id= 0xf;

}

for(i = 0;i <CFG_NUMOFKEYS_FORLINX; i++ )

{

if(key_id == i )

{

if(touch_event == 0)                                  // detect

{

input_report_key(dev, tsp_keycodes_forlinx[i], 1);

printk( "[FTS] %s key is pressed. Keycode : %d\n",tsp_keyname_forlinx[i], tsp_keycodes_forlinx[i]);

tsp_keystatus_forlinx[i] = KEY_PRESS;

}

}

}

return 0;

}

IMX6q ft5x0x_ts触摸芯片分析相关推荐

  1. 触摸芯片电路布局和走线设计注意事项

    触摸芯片模拟电路 随着科技的不断发展,我们生活中的机械开关,不断的被模拟IC芯片所替代,这就可以将我们生活中的各类开关,按键更加的便捷,美观,体积小,很大的程度上提高了人们的体验感.广泛应用于玩具.消 ...

  2. 你的fpga为什么不能正常工作——拆解第一款FPGA芯片分析原理

    你的fpga为什么不能正常工作--拆解第一款FPGA芯片分析原理 现场可编程门阵列(FPGA)可以实现任意数字逻辑,从微处理器到视频生成器或加密矿机,一应俱全.FPGA由许多逻辑模块组成,每个逻辑模块 ...

  3. 触摸芯片XPT2046的使用理解

    触摸芯片XPT2046的使用理解 以下只考虑SPI作为MASTER时的情况: SPI接口由于输入和输出两根线是用同一个时钟,所以发送命令时,同时能接收到数据,此时不去接收这些数据,因为这些数据是无效的 ...

  4. 番茄定时调光台灯触摸芯片-DLT8T10S-杰力科创

    方案基本组成 12V 恒流: 5个触摸按键,开关指示灯,延时指示灯,番茄模式指示灯,一路灯条: 方案产品功能 此款番茄定时调光台灯方案,主控芯片采用DLT8T10S系列触摸芯片,封装型号是16引脚SO ...

  5. 电源供电系列VKD104BC 4/四键感应触摸芯片提供4路输出自动校准功能

    型号:VKD104BC 品牌:VINKA/永嘉微电 封装形式:SOP16 年份:新年份 概 述: VKD104BC具有4个触摸按键,可用来检测外部触摸按键上人手的触摸动作.该芯片具有较高的集成度,仅需 ...

  6. 应用在洗衣机触摸屏中的触摸芯片

    由于洗衣机通常放置在污渍.灰尘.水污集中的位置,用户需要经常清洗洗衣机的表面,在清洗过程中发现,触摸按键容易损坏或进水,致使触摸按键失灵.触摸屏感应到手指的触摸是因为当手指触摸屏幕上的一个具体位置时, ...

  7. 红外遥控氛围灯触摸芯片-DLT8SA15A-杰力科创

    方案基本组成 5V输入,电池供电,恒压方案: 一个触摸按键,一个滑条,一个红外遥控,4路PWM口输出: 方案产品功能 此款红外遥控调光调色氛围灯方案,主控芯片采用DLT8SA15A系列触摸芯片,封装型 ...

  8. 触摸芯片按键触摸应用开发笔记

    触摸按键应用原理 当有人体手指靠近触摸按键时,人体手指与大地构成的感应电容并联焊盘与大地构成的感应电容,会使总感应电容值增加.电容式触摸按键IC在检测到某个按键的感应电容值发生改变后,将输出某个按键被 ...

  9. 自动光感大臂灯触摸芯片-DLT8SA15B-杰力科创

    方案基本组成 九个触摸按键,两个指示灯(一个定时,一个光感),一个光感,两路PWM口输出: 方案产品功能 此款九键五档调光三档色温带定时自动光感大臂灯方案,主控芯片采用DLT8SA15B系列触摸芯片, ...

最新文章

  1. AndroidManifest.xml文件详解
  2. python爬虫 小白轻松从0到1_如何从0到1,学习Python的流程【小白入门】
  3. Windows驱动开发要点总结一
  4. OpenCV行人检测
  5. 分表分库中间件 sharding-jdbc
  6. 山西省能源产业发展动向及投资风险分析报告2021版
  7. Spring框架—体系结构
  8. Android之Installation error: INSTALL_FAILED_UPDATE_INCOMPATIBLE问题解决
  9. 【渝粤题库】陕西师范大学700005 遗传学
  10. mvc html 生成图片,asp.net mvc5 cs代码中获取视图生成后的HTML
  11. 今天的成功的滋味 企业即时通讯
  12. PHP全栈学习笔记3
  13. Node.js、express、mongodb 实现分页查询、条件搜索
  14. Rust : 宏、重复、及向量与递归实例
  15. idea 中vim快捷键
  16. 数据结构 实验2——表达式求值
  17. python cad 二次开发bom_python处理BOM
  18. tk域名管理后台_Freenom免费域名.TK、.CF、.ML、.GA注册及使用方法
  19. word中怎么把脚注转换为尾注
  20. glassfish插件_在Eclipse JavaEE开发环境上集成GlassFish开发插件(截图多多)

热门文章

  1. 谷歌浏览器的小恐龙游戏
  2. Win10系统 Office2010程序打开PPT文档报错“此应用无法在你的电脑上运行
  3. About 不以物喜 不以己悲
  4. UISwitch - 开关按钮 的使用详解
  5. linux个人学习记录
  6. python opencv图片拼接、特征点匹配
  7. 关于手机唯一识别码的研究meid和imei
  8. 让图片和文字在一行中垂直居中对齐的方法
  9. 页码怎么设置从某一页位置开始,word文档如何设置开始页面
  10. Spring @Value读取配置文件