【转】MTK TP驱动移植

 

原文地址:https://blog.csdn.net/u010245383/article/details/50995919

对于MTK TP驱动移植一般分为六部分:

1、硬件IO口配置;

2、TP驱动移植;

3、I2C通信;

4、中断触发;

5、数据上报;

6、虚拟按键;

 

硬件电路:

 

1、GPIO配置

打开 mediatek\dct\DrvGen.exe 

选择 mediatek\custom\xiaoxi\kernel\dct\dct\codegen.dws 配置文件

配置EINT7_CTP引脚、CTP_RST复位引脚

 

2、TP驱动移植(以ft5x16为例)

在\mediatek\custom\common\kernel\touchpanel目录下创建ft5x16,将供应商提供的驱动驱动资料拷贝到该目录下;

修改配置文件:mediatek\config\prj\ProjectConfig.mk下的CUSTOM_KERNEL_TOUCHPANEL其值由改为ft5x16,表明对应ft5x16子目录;

打开ft5x16.c文件,修改一下:

 1 static struct i2c_board_info __initdata ft5x16_i2c_tpd={ I2C_BOARD_INFO("ft5x16", (0x70>>1))}; //"ft5x16"为设备名 ,设备地址为高7位
 2  
 3 static struct tpd_driver_t tpd_device_driver = {
 4     .tpd_device_name = "FT5x16",
 5     .tpd_local_init = tpd_local_init, 
 6     .suspend = tpd_suspend,
 7     .resume = tpd_resume,
 8 #ifdef TPD_HAVE_BUTTON  
 9     .tpd_have_button = 1,
10 #else
11     .tpd_have_button = 0,
12 #endif        
13 };
14  
15 /* called when loaded into kernel */
16 static int __init tpd_driver_init(void) {
17     printk("MediaTek FT5x16 touch panel driver init\n");
18     /* 注册板级设备信息 */
19     i2c_register_board_info(IIC_PORT, &ft5x16_i2c_tpd, 1);  //IIC_PORT表示i2c控制器号,由电路原理图可知TP设备连接到i2c控制器0,ft5x16_i2c_tpd为i2c设备结构,1表示该i2c_board_info个数
20     if(tpd_driver_add(&tpd_device_driver) < 0)
21         printk("add FT5x16 driver failed\n");
22     return 0;
23 }

 

重新编译:./mk n k && ./mk bootimage

 

3、I2C通信

新驱动编译进内核,启动内核后,我们怎样验证i2c接口能够正常通信呢?

系统启动后通过串口或adb shell进入系统命令行窗口,查询/sys/bus/i2c/devices目录下是否有0-0038信息,查询/sys/bus/i2c/drivers目录下是否存在‘ft5x16’设备名;先保证i2c能够正常通信;

 

4、中断触发

中断注册函数:mt_eint_registration(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_TYPE, tpd_eint_interrupt_handler, 1);

//tpd_eint_interrupt_handler函数为中断回调函数

 

5、数据上报

当触摸屏产生中断的时候就会调用到该接口;然后在中断处理函数中唤醒运行在子线程中的等待队列,再通过子线程获取TP数据并上报到系统;

 1 static DECLARE_WAIT_QUEUE_HEAD(waiter);  //初始化等待队列
 2  
 3 thread = kthread_run(touch_event_handler, 0, TPD_DEVICE);  //新建线程
 4  
 5 static int touch_event_handler(void *unused)
 6 { 
 7     ......
 8     do
 9     {
10         mt_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM); 
11         set_current_state(TASK_INTERRUPTIBLE); 
12         wait_event_interruptible(waiter,tpd_flag!=0);  //等待队列进入休眠,等待唤醒
13         tpd_flag = 0;
14         set_current_state(TASK_RUNNING);
15         ......
16         if (tpd_touchinfo(&cinfo, &pinfo))   //获取TP数据
17         {
18             //TPD_DEBUG("point_num = %d\n",point_num);
19             TPD_DEBUG_SET_TIME;
20             if(point_num >0) 
21             {
22                 for(i =0; i<point_num; i++)//only support 3 point
23                 {            
24                     cinfo.x[i] = cinfo.x[i];
25                     cinfo.y[i] = cinfo.y[i];
26                     
27                     tpd_down(cinfo.x[i], cinfo.y[i], cinfo.id[i]); //上报按下数据
28                     printk(KERN_DEBUG"----calibration----- X:%4d, Y:%4d, P:%4d \n", cinfo.x[i], cinfo.y[i], cinfo.id[i]);
29                 }
30                 input_sync(tpd->dev);
31             }
32             else  
33             {
34                 tpd_up(cinfo.x[0], cinfo.y[0]);      //上报弹起数据
35                 //TPD_DEBUG("release --->\n"); 
36                 //input_mt_sync(tpd->dev);
37                 input_sync(tpd->dev);
38             }
39         }
40     ......
41  
42     }while(!kthread_should_stop());
43  
44     return 0;
45 }

 

TP数据可以通过打印的方式进行查看,也可以激活‘系统设置’中‘开发者选项’的‘指针位置’,现在触摸操作在LCD的轨迹,也可以在packages\apps\Launcher2\src\com\android\launcher2\Launcher.java的onCreate方法最后添加Settings.System.putInt(this.getContentResolver(),Settings.System.POINTER_LOCATION, 1); 在Launcher中开启‘指针位置’功能(需要mm Launcher模块并重新打包和烧录system.img文件);

注:如果TP获取到的数据比较乱的时候建议通过打开‘指针位置’功能进行查看,排除TP固件分辨与LCD没对应等问题;

 

6、虚拟按键

 1 static struct tpd_driver_t tpd_device_driver = {
 2     .tpd_device_name = "FT5x16",
 3     .tpd_local_init = tpd_local_init, 
 4     .suspend = tpd_suspend,
 5     .resume = tpd_resume,
 6 #ifdef TPD_HAVE_BUTTON  
 7     .tpd_have_button = 1,
 8 #else
 9     .tpd_have_button = 0,
10 #endif        
11 };

 

从tpd_driver_t结构可知tpd_have_button成员为虚拟按键标志位;由宏TPD_HAVA_BUTTON开关决定的,宏定义在tpd_custom_fts.h中;

在tpd_custom_fts.h中定义了一系列关于虚拟按键的宏:

#define TPD_HAVE_BUTTON  //虚拟按键开关
#define TPD_BUTTON_WIDTH    (200)  //按键宽度
#define TPD_BUTTON_HEIGH    (100)  //按键高度
#define TPD_KEY_COUNT             3       //按键个数
#define TPD_KEYS                        {KEY_MENU, KEY_HOMEPAGE, KEY_BACK}  //按键对应的功能
#define TPD_KEYS_DIM              {{80,900,TPD_BUTTON_WIDTH,TPD_BUTTON_HEIGH}, {240,900,TPD_BUTTON_WIDTH,TPD_BUTTON_HEIGH}, {400,900,TPD_BUTTON_WIDTH,TPD_BUTTON_HEIGH}}  //按键对应位置

TPD_KEYS_DIM中的坐标是该按键区域的中心点:

 

TP驱动简要分析

 1 static struct tpd_driver_t tpd_device_driver = {
 2     .tpd_device_name = FT5x16,
 3     .tpd_local_init = tpd_local_init,  //初始化函数
 4     .suspend = tpd_suspend,
 5     .resume = tpd_resume,
 6 #ifdef TPD_HAVE_BUTTON
 7     .tpd_have_button = 1,
 8 #else
 9     .tpd_have_button = 0,
10 #endif        
11 };
12  
13 /* called when loaded into kernel */
14 static int __init tpd_driver_init(void) {
15     printk("MediaTek FT5x16 touch panel driver init\n");
16     i2c_register_board_info(0, &ft5x16_i2c_tpd, 1);  //注册板级设备信息
17     if(tpd_driver_add(&tpd_device_driver) < 0)  //添加驱动
18         printk("add FT5x16 driver failed\n");
19     return 0;
20 }

 

MTK自己编写了一套TP框架,通过该框架管理TP设备,tpd_driver_add为框架的接口之一;系统通过tpd_driver_add添加驱动后会回调tpd_local_init函数;

 

 1 #ifdef TPD_HAVE_BUTTON
 2 static int tpd_keys_local[TPD_KEY_COUNT] = TPD_KEYS;   //存放按键功能信息
 3 static int tpd_keys_dim_local[TPD_KEY_COUNT][4] = TPD_KEYS_DIM;   //存放虚拟按键信息
 4 #endif
 5  
 6 static int tpd_local_init(void)
 7 {
 8     TPD_DMESG("FTS I2C Touchscreen Driver (Built %s @ %s)\n", __DATE__, __TIME__);
 9  
10     if(i2c_add_driver(&tpd_i2c_driver)!=0)  //注册i2c驱动
11     {
12         TPD_DMESG("FTS unable to add i2c driver.\n");
13         return -1;
14     }
15     if(tpd_load_status == 0) 
16     {
17         TPD_DMESG("FTS add error touch panel driver.\n");
18         i2c_del_driver(&tpd_i2c_driver);
19         return -1;
20     }
21  
22 #ifdef TPD_HAVE_BUTTON      //如果定义虚拟按键,则初始化按键信息
23     tpd_button_setting(TPD_KEY_COUNT, tpd_keys_local, tpd_keys_dim_local);// initialize tpd button data
24 #endif   
25  
26 #if (defined(TPD_WARP_START) && defined(TPD_WARP_END))    
27     TPD_DO_WARP = 1;
28     memcpy(tpd_wb_start, tpd_wb_start_local, TPD_WARP_CNT*4);
29     memcpy(tpd_wb_end, tpd_wb_start_local, TPD_WARP_CNT*4);
30 #endif 
31  
32 #if (defined(TPD_HAVE_CALIBRATION) && !defined(TPD_CUSTOM_CALIBRATION))
33     memcpy(tpd_calmat, tpd_def_calmat_local, 8*4);
34     memcpy(tpd_def_calmat, tpd_def_calmat_local, 8*4);    
35 #endif  
36     TPD_DMESG("end %s, %d\n", __FUNCTION__, __LINE__);  
37     tpd_type_cap = 1;
38     return 0; 
39 }

 

向系统注册i2c驱动后,如果找到对应的设备就会调用tpd_probe函数;

  1 static const struct i2c_device_id ft5x16_tpd_id[] = {{TPD_NAME,0},{}};
  2  
  3 static struct i2c_driver tpd_i2c_driver = {
  4     .driver = {
  5         .name     = TPD_NAME,
  6     },
  7     .probe         = tpd_prob,
  8     .remove     = __devexit_p(tpd_remove),
  9     .id_table     = ft5x16_tpd_id,
 10     .detect     = tpd_detect,
 11 };
 12  
 13 static int __devinit tpd_probe(struct i2c_client *client, const struct i2c_device_id *id)
 14 {     
 15     int retval = TPD_OK;
 16     char data;
 17     u8 report_rate=0;
 18     int err=0;
 19     int reset_count = 0;
 20     u8 chip_id,i;
 21  
 22 reset_proc:   
 23     i2c_client = client;
 24 #ifdef MAIERXUN_TP_COM
 25     if(touchpanel_flag){
 26         return 0;
 27     }
 28 #endif
 29     //复位  
 30     //power on, need confirm with SA
 31     mt_set_gpio_mode(GPIO_CTP_RST_PIN, GPIO_CTP_RST_PIN_M_GPIO);
 32     mt_set_gpio_dir(GPIO_CTP_RST_PIN, GPIO_DIR_OUT);
 33     mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ZERO);  
 34     msleep(5);
 35     TPD_DMESG(" fts ic reset\n");
 36  
 37     //打开TP电源
 38 #ifdef TPD_POWER_SOURCE_CUSTOM
 39     hwPowerOn(TPD_POWER_SOURCE_CUSTOM, VOL_3300, "TP");
 40 #else
 41     hwPowerOn(MT65XX_POWER_LDO_VGP2, VOL_3300, "TP");
 42 #endif
 43  
 44     mt_set_gpio_mode(GPIO_CTP_RST_PIN, GPIO_CTP_RST_PIN_M_GPIO);
 45     mt_set_gpio_dir(GPIO_CTP_RST_PIN, GPIO_DIR_OUT);
 46     mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ONE);
 47  
 48 #ifdef TPD_CLOSE_POWER_IN_SLEEP     
 49     hwPowerDown(TPD_POWER_SOURCE,"TP");
 50     hwPowerOn(TPD_POWER_SOURCE,VOL_3300,"TP");
 51     msleep(100);
 52  
 53 #else  /* 结束复位 */
 54     mt_set_gpio_mode(GPIO_CTP_RST_PIN, GPIO_CTP_RST_PIN_M_GPIO);
 55     mt_set_gpio_dir(GPIO_CTP_RST_PIN, GPIO_DIR_OUT);
 56     mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ZERO);  
 57     msleep(5);
 58     TPD_DMESG(" fts ic reset\n");
 59     mt_set_gpio_mode(GPIO_CTP_RST_PIN, GPIO_CTP_RST_PIN_M_GPIO);
 60     mt_set_gpio_dir(GPIO_CTP_RST_PIN, GPIO_DIR_OUT);
 61     mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ONE);
 62 #endif
 63  
 64     /* 初始化中断引脚 */
 65     mt_set_gpio_mode(GPIO_CTP_EINT_PIN, GPIO_CTP_EINT_PIN_M_EINT);
 66     mt_set_gpio_dir(GPIO_CTP_EINT_PIN, GPIO_DIR_IN);
 67     mt_set_gpio_pull_enable(GPIO_CTP_EINT_PIN, GPIO_PULL_ENABLE);
 68     mt_set_gpio_pull_select(GPIO_CTP_EINT_PIN, GPIO_PULL_UP);
 69  
 70     /* 中断配置和注册 */
 71     mt_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN);
 72     mt_eint_registration(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_TYPE, tpd_eint_interrupt_handler, 1);  //注册中断处理函数,TP产生中断时就会回调tpd_eint_interrupt函数
 73     mt_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);  
 74  
 75     msleep(400);
 76  
 77     err=i2c_smbus_read_i2c_block_data(i2c_client, 0x00, 1, &data);
 78  
 79     TPD_DMESG("gao_i2c:err %d,data:%d\n", err,data);
 80     if(err< 0 || data!=0)// reg0 data running state is 0; other state is not 0
 81     {
 82         TPD_DMESG("I2C transfer error, line: %d\n", __LINE__);
 83 #ifdef TPD_RESET_ISSUE_WORKAROUND
 84         if ( reset_count < TPD_MAX_RESET_COUNT )
 85         {
 86             reset_count++;
 87             goto reset_proc;
 88         }
 89 #endif
 90         //add at 20150330 by zhu
 91 #ifdef MAIERXUN_TP_COM
 92         touchpanel_flag=false;
 93 #endif
 94         return -1; 
 95     }
 96  
 97     ......
 98  
 99 #ifdef VELOCITY_CUSTOM_FT5206
100     if((err = misc_register(&tpd_misc_device)))  //注册混杂设备驱动
101     {
102         printk("mtk_tpd: tpd_misc_device register failed\n");
103  
104     }
105 #endif
106  
107 #ifdef TPD_AUTO_UPGRADE
108     printk("********************Enter CTP Auto Upgrade********************\n");
109     fts_ctpm_auto_upgrade(i2c_client);
110 #endif
111     thread = kthread_run(touch_event_handler, 0, TPD_DEVICE);  //创建子线程,通过该子线程获取和上报数据
112     if (IS_ERR(thread))
113     { 
114         retval = PTR_ERR(thread);
115         TPD_DMESG(TPD_DEVICE " failed to create kernel thread: %d\n", retval);
116     }
117  
118     TPD_DMESG("FTS Touch Panel Device Probe %s\n", (retval < TPD_OK) ? "FAIL" : "PASS");
119  
120     /* 初始化TP的P-sensor功能,暂不分析 */
121 #ifdef TPD_PROXIMITY
122     struct hwmsen_object obj_ps;
123  
124     obj_ps.polling = 0;//interrupt mode
125     obj_ps.sensor_operate = tpd_ps_operate;
126     if((err = hwmsen_attach(ID_PROXIMITY, &obj_ps)))
127     {
128         APS_ERR("proxi_fts attach fail = %d\n", err);
129     }
130     else
131     {
132         APS_ERR("proxi_fts attach ok = %d\n", err);
133     }        
134 #endif
135     
136 #ifdef MAIERXUN_TP_COM
137     touchpanel_flag=true;
138 #endif
139     
140     return 0;
141  
142 }

 

/* 中断处理函数 */

 

1 static void tpd_eint_interrupt_handler(void)
2 {
3     //TPD_DEBUG("TPD interrupt has been triggered\n");
4     TPD_DEBUG_PRINT_INT;
5     tpd_flag = 1; 
6     wake_up_interruptible(&waiter);  //唤醒等待队列
7 }

 

中断处理遵循中断上下文的设计原则,使得中断子程序只是简单唤醒等待队列就可以了,没有多余的操作;

/* 子线程处理函数 */

 1 static int touch_event_handler(void *unused)
 2 { 
 3     struct touch_info cinfo, pinfo;
 4     int i=0;
 5  
 6     struct sched_param param = { .sched_priority = RTPM_PRIO_TPD };
 7     sched_setscheduler(current, SCHED_RR, ¶m);
 8  
 9 #ifdef TPD_PROXIMITY
10     int err;
11     hwm_sensor_data sensor_data;
12     u8 proximity_status;
13  
14 #endif
15     u8 state;
16  
17     do  //进入while循环进行睡眠-等待唤醒的操作
18     {
19         mt_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);  //中断使能(解除屏蔽)
20         set_current_state(TASK_INTERRUPTIBLE); 
21         wait_event_interruptible(waiter,tpd_flag!=0);  //进入睡眠等待唤醒
22  
23         tpd_flag = 0;
24  
25         set_current_state(TASK_RUNNING);
26         ......
27  
28 #ifdef TPD_PROXIMITY  //TP的P-sensor功能,暂不分析
29         if (tpd_proximity_flag == 1)
30         {
31             i2c_smbus_read_i2c_block_data(i2c_client, 0xB0, 1, &state);
32             TPD_PROXIMITY_DEBUG("proxi_5206 0xB0 state value is 1131 0x%02X\n", state);
33  
34             if(!(state&0x01))
35             {
36                 tpd_enable_ps(1);
37             }
38  
39             i2c_smbus_read_i2c_block_data(i2c_client, 0x01, 1, &proximity_status);
40             TPD_PROXIMITY_DEBUG("proxi_5206 0x01 value is 1139 0x%02X\n", proximity_status);
41  
42             if (proximity_status == 0xC0)
43             {
44                 tpd_proximity_detect = 0;    
45             }
46             else if(proximity_status == 0xE0)
47             {
48                 tpd_proximity_detect = 1;
49             }
50  
51             TPD_PROXIMITY_DEBUG("tpd_proximity_detect 1149 = %d\n", tpd_proximity_detect);
52  
53             if ((err = tpd_read_ps()))
54             {
55                 TPD_PROXIMITY_DMESG("proxi_5206 read ps data 1156: %d\n", err);    
56             }
57             sensor_data.values[0] = tpd_get_ps_value();
58             sensor_data.value_divide = 1;
59             sensor_data.status = SENSOR_STATUS_ACCURACY_MEDIUM;
60             if ((err = hwmsen_get_interrupt_data(ID_PROXIMITY, &sensor_data)))
61             {
62                 TPD_PROXIMITY_DMESG(" proxi_5206 call hwmsen_get_interrupt_data failed= %d\n", err);    
63             }
64         }  
65 #endif
66  
67         if (tpd_touchinfo(&cinfo, &pinfo))   //获取TP设备数据,并把数据保存在cinfob buf中
68         {
69             //TPD_DEBUG("point_num = %d\n",point_num);
70             TPD_DEBUG_SET_TIME;
71             if(point_num >0) 
72             {
73                 for(i =0; i<point_num; i++)//only support 3 point
74                 {
75                     printk(KERN_DEBUG"X:%4d, Y:%4d, P:%4d \n", cinfo.x[i], cinfo.y[i], cinfo.id[i]);
76                     
77                     cinfo.x[i] = cinfo.x[i];
78                     cinfo.y[i] = cinfo.y[i];
79                     
80                     tpd_down(cinfo.x[i], cinfo.y[i], cinfo.id[i]);  //按下数据处理
81                     printk(KERN_DEBUG"----calibration----- X:%4d, Y:%4d, P:%4d \n", cinfo.x[i], cinfo.y[i], cinfo.id[i]);
82                 }
83                 input_sync(tpd->dev);
84             }
85             else  
86             {
87                 tpd_up(cinfo.x[0], cinfo.y[0]);    //弹起数据处理
88                 //TPD_DEBUG("release --->\n"); 
89                 //input_mt_sync(tpd->dev);
90                 input_sync(tpd->dev);
91             }
92         }
93         ......
94         
95     }while(!kthread_should_stop());
96  
97     return 0;
98 }

 

/* 获取TP数据 */

 1 static int tpd_touchinfo(struct touch_info *cinfo, struct touch_info *pinfo)
 2 {
 3     int i = 0;
 4     char data[128] = {0};
 5     u16 high_byte,low_byte,reg;
 6     u8 report_rate =0;
 7  
 8     p_point_num = point_num;
 9     if (tpd_halt)
10     {
11         TPD_DMESG( "tpd_touchinfo return ..\n");
12         return false;
13     }
14     mutex_lock(&i2c_access);
15  
16  
17     reg = 0x00;
18     fts_i2c_Read(i2c_client, &reg, 1, data, 64);  //获取TP数据,一些TP是支持多点触控的,所以有可能就产生多个触点的数据
19     mutex_unlock(&i2c_access);
20  
21     /*get the number of the touch points*/
22     point_num= data[2] & 0x0f;
23  
24     TPD_DEBUG("point_num =%d\n",point_num);
25  
26     /* 根据芯片协议解析数据并存放在cinfo buf中 */
27     for(i = 0; i < point_num; i++)  
28     {
29         cinfo->p[i] = data[3+6*i] >> 6; //event flag 
30         cinfo->id[i] = data[3+6*i+2]>>4; //touch id
31         /*get the X coordinate, 2 bytes*/
32         high_byte = data[3+6*i];
33         high_byte <<= 8;
34         high_byte &= 0x0f00;
35         low_byte = data[3+6*i + 1];
36         cinfo->x[i] = high_byte |low_byte;
37  
38  
39         /*get the Y coordinate, 2 bytes*/
40         high_byte = data[3+6*i+2];
41         high_byte <<= 8;
42         high_byte &= 0x0f00;
43         low_byte = data[3+6*i+3];
44         cinfo->y[i] = high_byte |low_byte;
45         }
46  
47     }
48     TPD_DEBUG(" cinfo->x[0] = %d, cinfo->y[0] = %d, cinfo->p[0] = %d\n", cinfo->x[0], cinfo->y[0], cinfo->p[0]);    
49  
50     return true;
51 }
 1 static  void tpd_down(int x, int y, int p) {
 2   static int tpd_x = 0;
 3   static int tpd_y = 0;
 4   
 5   tpd_x = x;
 6   tpd_y = y;    
 7   
 8         /* 通过输入子系统上报数据 */
 9     input_report_key(tpd->dev, BTN_TOUCH, 1);
10     input_report_abs(tpd->dev, ABS_MT_TOUCH_MAJOR, 20);
11     input_report_abs(tpd->dev, ABS_MT_POSITION_X, x);
12     input_report_abs(tpd->dev, ABS_MT_POSITION_Y, y);
13  
14     printk(KERN_ERR, "D[%4d %4d %4d] ", x, y, p);
15     /* track id Start 0 */
16     input_report_abs(tpd->dev, ABS_MT_TRACKING_ID, p); 
17     input_mt_sync(tpd->dev);
18 #ifndef MT6572
19     if (FACTORY_BOOT == get_boot_mode()|| RECOVERY_BOOT == get_boot_mode())
20 #endif    
21     {   
22         tpd_button(x, y, 1); //虚拟按键的处理
23     }
24     TPD_EM_PRINT(x, y, x, y, p-1, 1);
25 }
26  
27 static  void tpd_up(int x, int y) {
28  
29     input_report_key(tpd->dev, BTN_TOUCH, 0);
30     input_mt_sync(tpd->dev);
31     TPD_EM_PRINT(x, y, x, y, 0, 0);
32  
33 #ifndef MT6572
34     if (FACTORY_BOOT == get_boot_mode()|| RECOVERY_BOOT == get_boot_mode())
35 #endif
36     {   
37         tpd_button(x, y, 0); 
38     }            
39 }

 

/* 虚拟按键判断和处理函数 */

 1 void tpd_button(unsigned int x, unsigned int y, unsigned int down) {
 2     int i;
 3     if(down) {
 4         for(i=0;i<tpd_keycnt;i++) 
 5         {
 6         /* 判断数据是否落在虚拟按键的范围内,数据处理算法实现了以坐标点为中心的虚拟按键 */
 7             if(x>=tpd_keys_dim[i][0]-(tpd_keys_dim[i][2]/2) &&
 8                x<=tpd_keys_dim[i][0]+(tpd_keys_dim[i][2]/2) &&
 9                y>=tpd_keys_dim[i][1]-(tpd_keys_dim[i][3]/2) &&
10                y<=tpd_keys_dim[i][1]+(tpd_keys_dim[i][3]/2) &&
11                !(tpd->btn_state&(1<<i)))    
12             {
13                 input_report_key(tpd->kpd, tpd_keys[i], 1);  //上报按键
14                 input_sync(tpd->kpd);
15                 tpd->btn_state|=(1<<i);
16                 TPD_DEBUG("[mtk-tpd] press key %d (%d)\n",i, tpd_keys[i]);
17                 printk("[mtk-tpd] press key %d (%d)\n",i, tpd_keys[i]);
18             }
19         }
20     } else {
21         for(i=0;i<tpd_keycnt;i++) {
22             if(tpd->btn_state&(1<<i)) {
23                 input_report_key(tpd->kpd, tpd_keys[i], 0);
24                 input_sync(tpd->kpd);
25                 TPD_DEBUG("[mtk-tpd] release key %d (%d)\n",i, tpd_keys[i]);
26                 printk("[mtk-tpd] release key %d (%d)\n",i, tpd_keys[i]);
27             }
28         }
29         tpd->btn_state=0;
30     }
31 }
32 tpd_keys_dim和tpd_keys的数据是通过tpd_button_setting初始化的,可以去看tpd_button_setting()的实现;

 

通过简单分析,由此可知MTK的TP驱动的整体框架跟普通TP驱动框架也是大致差不多;

 

posted @ 2018-10-08 20:27  葫芦baby  阅读(1810)  评论(0编辑  收藏  举报