static int touch_event_handler(void *para)
 {
 	int i;
	tinno_ts_point touch_point[TINNO_TOUCH_TRACK_IDS];
	struct sched_param param = { .sched_priority = RTPM_PRIO_TPD };
	tinno_ts_data *ts = (tinno_ts_data *)para;
	sched_setscheduler(current, SCHED_RR, &param);
	
	do {
		set_current_state(TASK_INTERRUPTIBLE); 
		wait_event_interruptible(waiter, tpd_flag!=0);
		tpd_flag = 0;
		memset(touch_point, FTS_INVALID_DATA, sizeof(touch_point));
		set_current_state(TASK_RUNNING);

            
            //LINE<JIRA_ID><DATE20130320><BUG_INFO>zenghaihui
            if(g_tp_charger_flag != g_pre_tp_charger_flag)
            {
                g_pre_tp_charger_flag = g_tp_charger_flag;
                g_need_refresh_tp_flag = 1;
            }

            if(g_need_refresh_tp_flag)
            {
                g_need_refresh_tp_flag = 0;
                fts_ft5316_switch_charger_status(g_tp_charger_flag);
            }
        
        
		if (!tpd_touchinfo(ts, &touch_point)) {

			if(ts->pcount > 0)
			{
				for ( i=0; i < ts->pcount; i++ )
				{
					tpd_down(ts, touch_point[i].x, touch_point[i].y, touch_point[i].pressure, touch_point[i].touch_id);//<20120714><for multi-touch id>wangyanhui
				}
				input_sync(tpd->dev);
			}
			else
			{
				tpd_up(ts, touch_point[0].x, touch_point[0].y, touch_point[0].pressure, touch_point[0].touch_id);
				input_sync(tpd->dev);
			}
            
            
		}
		
		mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM); 
	}while(!kthread_should_stop());
	mt65xx_eint_mask(CUST_EINT_TOUCH_PANEL_NUM); 
	return 0;
 }
예제 #2
0
//Clear the unfinished touch event, simulate a up event if there this a pen down or move event.
void ft6x06_complete_unfinished_event( void )
{
	int i = 0;
	for ( i=0; i < TINNO_TOUCH_TRACK_IDS; i++ ){
		if (  test_bit(i, &g_pts->fingers_flag) ){
			tpd_up(g_pts, g_pts->touch_point_pre[i].x, g_pts->touch_point_pre[i].y, 
				g_pts->touch_point_pre[i].pressure, i);
		}
	}
	input_sync(tpd->dev);
}
static int touch_event_handler(void *unused) {
    struct sched_param param = { .sched_priority = RTPM_PRIO_TPD };
    struct touch_info cinfo, sinfo;
    int pending = 0;
    struct i2c_client * i2c_client  =  ft5316_i2c_client ;
    TPD_DEBUG("touch_event_handler\n");
	
    cinfo.pending=0;
    sched_setscheduler(current, SCHED_RR, &param);
    do {
//Ivan added for testing
		if (tpd_status == 1){
		    mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM); // possibly to lose event?
         	 }
	        set_current_state(TASK_INTERRUPTIBLE);
	        if (!kthread_should_stop()) 
		{
	        //    TPD_DEBUG_CHECK_NO_RESPONSE;
	            do {
	                if(pending) wait_event_interruptible_timeout(waiter, tpd_flag!=0, HZ/10);
	                else wait_event_interruptible_timeout(waiter,tpd_flag!=0, HZ*2);
	            } while(0);
	            if(tpd_flag==0 && !pending) continue; // if timeout for no touch, then re-wait.
	            if(tpd_flag!=0 && pending>0)  pending=0;
	            tpd_flag=0;
	            TPD_DEBUG_SET_TIME;
	        }
	        set_current_state(TASK_RUNNING);
	        
	        if(!pending) if(tpd_gettouchinfo(&cinfo, &sinfo)) continue; 
	        if(pending>1) { pending--; continue; }
		//Ivan ++
		if (tpd_init_skip) {tpd_init_skip = 0; continue; }
		TPD_DEBUG("cinfo->count == %d!\n", cinfo.count);
		if(cinfo.count > 0)
		{
			int i;
			for ( i=0; i < cinfo.count; i++ )
			{
				TPD_DEBUG("cinfo->count == %d!\n", cinfo.count);
				TPD_DEBUG("Point ID == %d, x == %d , y == %d ,z ==%d\n!",cinfo.pt[i].id,cinfo.pt[i].x,cinfo.pt[i].y,cinfo.pt[i].z );
				tpd_down(cinfo.pt[i].x, cinfo.pt[i].y, cinfo.pt[i].id);
			}
			input_sync(tpd->dev);
		}
		else
		{
			TPD_DEBUG("TPD up x == %d , y == %d\n!",x_history[cinfo.count], y_history[cinfo.count]);
			tpd_up(x_history[cinfo.count], y_history[cinfo.count], 0);		
			input_sync(tpd->dev);
		}    
    } while (!kthread_should_stop());
    return 0;
}
/* platform device functions */
void tpd_suspend(struct early_suspend *h)
{
	TPD_DEBUG("[mtk-tpd] Suspend++.\n");
	if(isUpgrade ==1)
	{
	    TPD_DEBUG("Magnum tp is Upgrading.....\r\n");
		return;
	}
	mt65xx_eint_mask(CUST_EINT_TOUCH_PANEL_NUM);
	if(tpd_down_state){
	    tpd_up(down_x,down_y,NULL);
	//Ivan        input_report_abs(tpd->dev, ABS_MT_TRACKING_ID, 0);
	    input_sync(tpd->dev);
	    msleep(200);
	}
	tpd_status = 0;
	tinno_tp_power_off();
	TPD_DEBUG("[mtk-tpd] Suspend--.tpd_down_state=%d\n",tpd_down_state);
	if (ft5316_i2c_client == NULL)
		return;
}
예제 #5
0
static int touch_event_handler(void *unused)
{
    struct sched_param param = { .sched_priority = RTPM_PRIO_TPD }; 
    static int x1, y1, x2, y2, raw_x1, raw_y1, raw_x2, raw_y2;
    int temp_x1 = x1, temp_y1 = y1, temp_raw_x1 = raw_x1, temp_raw_y1 = raw_y1;
    int lastUp_x = 0, lastUp_y = 0;
    char buffer[10];
    int ret = -1, touching, oldtouching;//int pending = 0
    unsigned char Wrbuf[1] = {0};
    
    sched_setscheduler(current, SCHED_RR, &param); 
    do{
        set_current_state(TASK_INTERRUPTIBLE);
        while (tpd_halt) {tpd_flag = 0; msleep(20);}
        wait_event_interruptible(waiter, tpd_flag != 0);
        tpd_flag = 0;
        TPD_DEBUG_SET_TIME;
        set_current_state(TASK_RUNNING); 

        i2c_client->addr = ( i2c_client->addr & I2C_MASK_FLAG ) | I2C_ENEXT_FLAG;
        ret = i2c_master_send(i2c_client, Wrbuf, 1);
        if(ret != sizeof(Wrbuf))
        {
            TPD_DEBUG("[mtk-tpd] i2c write communcate error: 0x%x\n", ret);
            continue;
        }
        i2c_client->addr = ( ( i2c_client->addr & I2C_MASK_FLAG ) | I2C_DMA_FLAG ) | I2C_ENEXT_FLAG;
        ret = tpd_i2c_read(i2c_client, buffer, 7);
        buffer[7] = buffer[8] = buffer[9] = 0;
        if (ret != 7)//sizeof(buffer)
        {
            TPD_DEBUG("[mtk-tpd] i2c read communcate error: 0x%x\n", ret);
            continue;
        }
        i2c_client->addr = i2c_client->addr & I2C_MASK_FLAG;

        touching = buffer[0];
        if(touching > 0) 
        {
            raw_x1 = x1 = ((buffer[3] << 8) | buffer[2]);
            raw_y1 = y1 = ((buffer[5] << 8) | buffer[4]);
        }
        if(touching > 1)
        {
            raw_x2 = x2 = ((buffer[7] << 8) | buffer[6]);
            raw_y2 = y2 = ((buffer[9] << 8) | buffer[8]);
        }
        oldtouching = buffer[1]; 
        TPD_DEBUG("[mtk-tpd]:raw_x1:%d, raw_y1:%d, raw_x2:%d, raw_y2:%d\n", raw_x1, raw_y1, raw_x2, raw_y2);
        TPD_DEBUG("[mtk-tpd]:touch:%d, old_touch:%d\n", touching, oldtouching);
        switch(touching)
        {
        case 0:
            /* touching=0, oldtouching 0 is invalid */
            if(oldtouching > 0)
            {
                //tpd_up(raw_y1, raw_x1, y1, x1, 0);	
                //tpd_up(raw_x1, raw_y1, x1, y1, 0);
                lastUp_x = x1;
                lastUp_y = y1;
            }
            if(oldtouching > 1)
            {
                //tpd_up(raw_y2, raw_x2, y2, x2, 0);	
                //tpd_up(raw_x2, raw_y2, x2, y2, 0);
                //lastUp_x = x1;
                //lastUp_y = y1;
            }
            tpd_up(lastUp_x, lastUp_y, lastUp_x, lastUp_y, 0);
            break;
        case 1:
            tpd_calibrate(&x1, &y1);
            //tpd_down(raw_y1, raw_x1, y1, x1, 1);
            tpd_down(raw_x1, raw_y1, x1, y1, 1);
            if(oldtouching == 2)
            {
                if(abs(x1 - x2) < 2 && abs(y1 - y2) < 2) // need to adjust.
                {
                    //tpd_up(temp_raw_y1, temp_raw_x1, temp_y1, temp_x1, 0);
                    
                    //For ICS
                    //tpd_up(temp_raw_x1, temp_raw_y1, temp_x1, temp_y1, 0);
                }
                else
                {
                    //tpd_up(raw_y2, raw_x2, y2, x2, 0);
                    
                    //For ICS
                    //tpd_up(raw_x2, raw_y2, x2, y2, 0);
                }
            }
            break;
        case 2:
            tpd_calibrate(&x1, &y1);
            //tpd_down(raw_y1, raw_x1, y1, x1, 1);
            tpd_down(raw_x1, raw_y1, x1, y1, 1);
            //tpd_calibrate(&x2, &y2);
            //tpd_down(raw_y2, raw_x2, y2, x2, 1);
            //tpd_down(raw_x2, raw_y2, x2, y2, 1);
            break;
        default:
            TPD_DEBUG("[mtk-tpd] invalid touch num: 0x%x\n", touching);
            continue;
        }
        temp_x1 = x1;
        temp_y1 = y1;      
        temp_raw_x1 = raw_x1;
        temp_raw_y1 = raw_y1;
        input_sync(tpd->dev);
        
    } while (!kthread_should_stop()); 
    return 0;
}
예제 #6
0
 static int touch_event_handler(void *para)
 {	 
 	int i;
	tinno_ts_point touch_point[TINNO_TOUCH_TRACK_IDS];
	struct sched_param param = { .sched_priority = RTPM_PRIO_TPD };
	tinno_ts_data *ts = (tinno_ts_data *)para;
	sched_setscheduler(current, SCHED_RR, &param);
	
	//BEGIN <touch panel> <DATE20130831> <tp proximity> zhangxiaofei
	#if defined TPD_PROXIMITY
	int err;
	hwm_sensor_data sensor_data;
	u8 proximity_status;
	u8 state;
    #endif
    //END <touch panel> <DATE20130831> <tp proximity> zhangxiaofei
	do {
		set_current_state(TASK_INTERRUPTIBLE); 
		wait_event_interruptible(waiter, tpd_flag!=0);
		tpd_flag = 0;
		memset(touch_point, FTS_INVALID_DATA, sizeof(touch_point));
		set_current_state(TASK_RUNNING); 
		
		//BEGIN <touch panel> <DATE20130831> <tp proximity> zhangxiaofei
		#if defined TPD_PROXIMITY
		if (tpd_proximity_flag == 1)
		{
			i2c_smbus_read_i2c_block_data(g_pts->client, TPD_PROXIMITY_ENABLE_REG, 1, &state);
			TPD_PROXIMITY_DBG("proxi_5206 0xB0 state value is 1131 0x%02X\n", state);

			if(!(state&0x01))
			{
				tpd_enable_ps(1);
			}

			i2c_smbus_read_i2c_block_data(g_pts->client, 0x01, 1, &proximity_status);
			TPD_PROXIMITY_DBG("proxi_5206 0x01 value is 1139 0x%02X\n", proximity_status);
			
			if (proximity_status == TPD_PROXIMITY_CLOSE_VALUE)
			{
				tpd_proximity_detect = 0;	
			}
			else if(proximity_status == TPD_PROXIMITY_FARAWAY_VALUE)
			{
				tpd_proximity_detect = 1;
			}

			TPD_PROXIMITY_DBG("tpd_proximity_detect 1149 = %d\n", tpd_proximity_detect);

			if ((err = tpd_read_ps()))
			{
				TPD_PROXIMITY_DBG("proxi_5206 read ps data 1156: %d\n", err);	
			}
			sensor_data.values[0] = tpd_get_ps_value();
			sensor_data.value_divide = 1;
			sensor_data.status = SENSOR_STATUS_ACCURACY_MEDIUM;
			if ((err = hwmsen_get_interrupt_data(ID_PROXIMITY, &sensor_data)))
			{
				TPD_PROXIMITY_DBG(" proxi_5206 call hwmsen_get_interrupt_data failed= %d\n", err);	
			}
		}  
#endif
//END <touch panel> <DATE20130831> <tp proximity> zhangxiaofei	 
        //BEGIN <add changing flag> <DATE20130330> <add changing flag> zhangxiaofei
        if(g_tp_charger_flag != g_pre_tp_charger_flag){
			g_pre_tp_charger_flag = g_tp_charger_flag;
			fts_ft6x06_switch_charger_status(g_tp_charger_flag);
		}
        //END <add changing flag> <DATE20130330> <add changing flag> zhangxiaofei
        
		if (!tpd_touchinfo(ts, &touch_point)) {
			//report muti point then
			for ( i=0; i < TINNO_TOUCH_TRACK_IDS; i++ ){
				if ( FTS_INVALID_DATA != touch_point[i].x ){
					if ( FTS_EF_UP == touch_point[i].flag ){
						if( test_bit(i, &ts->fingers_flag) ){
							tpd_up(ts, ts->touch_point_pre[i].x, ts->touch_point_pre[i].y, 
								touch_point[i].pressure, i);
					}else{
							CTP_DBG("This is a invalid up event.(%d)", i);
						}
					}else{//FTS_EF_CONTACT or FTS_EF_DOWN
						if ( test_bit(i, &ts->fingers_flag) 
							&& (FTS_EF_DOWN == touch_point[i].flag) ){
							CTP_DBG("Ignore a invalid down event.(%d)", i);
							continue;
						}
						tpd_down(ts, touch_point[i].x, touch_point[i].y, 
							touch_point[i].pressure, i);
					}
				}else if (  test_bit(i, &ts->fingers_flag) ){
					CTP_DBG("Complete a invalid down or move event.(%d)", i);
					tpd_up(ts, ts->touch_point_pre[i].x, ts->touch_point_pre[i].y, 
						touch_point[i].pressure, i);
				}
			}
			input_sync(tpd->dev);
		}	
		mt_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM); 
	}while(!kthread_should_stop());
	mt_eint_mask(CUST_EINT_TOUCH_PANEL_NUM); 
	return 0;
 }
static int touch_event_handler(void *unused) {
    struct sched_param param = { .sched_priority = RTPM_PRIO_TPD }; 
    int x1=0, y1=0, x2=0, y2=0, x3=0, y3=0, x4=0, y4=0, p1=0, p2=0, p3=0, p4=0, id1=0xf, id2=0xf, id3=0xf, id4 = 0xf, pre_id1 = 0xf, pre_id2 = 0xf, pre_id3 = 0xf, pre_id4 = 0xf, pre_tt_mode = 0, finger_num = 0, pre_num = 0;
    int raw_x1=0, raw_y1=0, raw_x2=0, raw_y2=0, raw_x3=0, raw_y3=0, raw_x4=0, raw_y4=0;
    static char toggle;
    static char buffer[32];//[16];
//    int pending = 0;
	u32 temp;
    sched_setscheduler(current, SCHED_RR, &param); 
    g_temptimerdiff=get_jiffies_64();//jiffies;
    do {
		if(tpd_debuglog==1) {
			TPD_DMESG("[mtk-tpd] %s\n", __FUNCTION__); 
		}	    	
        set_current_state(TASK_INTERRUPTIBLE);
	if(tpd_debuglog==1)
		TPD_DMESG("[mtk-tpd], %s, tpd_halt=%d\n", __FUNCTION__, tpd_halt);
        while (tpd_halt) {tpd_flag = 0; msleep(20);}
        #ifndef POLL_MODE
        wait_event_interruptible(waiter, tpd_flag != 0);
        tpd_flag = 0;
        #endif
        TPD_DEBUG_SET_TIME;
        set_current_state(TASK_RUNNING); 
	//	#ifndef CY8CTMA300_CHARGE
		#if 0			
		temp =  *(volatile u32 *)CHR_CON0;	
		temp &= (1<<13);
		if(temp!=0)
		{
			   if(tpd_debuglog==1)	
			   	TPD_DMESG("[mtk-tpd], write 0x01 to 0x1D register!!\n");
			   buffer[0] = 0x01;
			   buffer[0] = 0x01;
			   i2c_smbus_write_i2c_block_data(i2c_client, 0x1D, 1, &(buffer[0]));    		
		}
		else
		{
			   if(tpd_debuglog==1)			
			   	TPD_DMESG("[mtk-tpd], write 0x00 to 0x1D register!!\n");
			   buffer[0] = 0x00;
			   i2c_smbus_write_i2c_block_data(i2c_client, 0x1D, 1, &(buffer[0])); 			
		} 
		#endif	
		#ifndef TPD_NO_GPIO 	    // for mt6575T fpga early porting    
        if (tpd_show_version) {
            tpd_show_version = 0;
                        
            mt_set_gpio_mode(GPIO1, 0x00);
            mt_set_gpio_dir(GPIO1, GPIO_DIR_OUT);
            mt_set_gpio_pull_enable(GPIO1, GPIO_PULL_ENABLE);
            mt_set_gpio_pull_select(GPIO1, GPIO_PULL_UP);
            
            mt_set_gpio_out(GPIO1, GPIO_OUT_ZERO);
            msleep(100);            
                        
            buffer[0] = 0x01; // reset touch panel mode
            i2c_smbus_write_i2c_block_data(i2c_client, 0x00, 1, &(buffer[0]));
            msleep(200);
            
            buffer[0] = 0x10; // swith to system information mode
            i2c_smbus_write_i2c_block_data(i2c_client, 0x00, 1, &(buffer[0]));
            msleep(200);
            
            i2c_smbus_read_i2c_block_data(i2c_client, 0x00, 8, &(buffer[0x0]));
            i2c_smbus_read_i2c_block_data(i2c_client, 0x08, 8, &(buffer[0x8]));
            i2c_smbus_read_i2c_block_data(i2c_client, 0x10, 8, &(buffer[0x10]));
            i2c_smbus_read_i2c_block_data(i2c_client, 0x18, 8, &(buffer[0x18]));
            printk("[mtk-tpd] Cypress Touch Panel ID %x.%x\n", buffer[0x07], buffer[0x08]);            
            printk("[mtk-tpd] Cypress Touch Panel Firmware Version %x.%x\n", buffer[0x15], buffer[0x16]); 
            buffer[0] = 0x04; // switch to operation mode
            i2c_smbus_write_i2c_block_data(i2c_client, 0x00, 1, &(buffer[0]));
            msleep(200);
                      
            mt_set_gpio_out(GPIO1, GPIO_OUT_ONE);            
            mt_set_gpio_mode(GPIO1, 0x01);
            mt_set_gpio_pull_enable(GPIO1, GPIO_PULL_ENABLE);
            mt_set_gpio_pull_select(GPIO1, GPIO_PULL_UP);           
            continue;
        }        
      #endif  
        i2c_smbus_read_i2c_block_data(i2c_client, 0x00, 8, &(buffer[0]));
        i2c_smbus_read_i2c_block_data(i2c_client, 0x08, 8, &(buffer[8]));
        i2c_smbus_read_i2c_block_data(i2c_client, 0x10, 8, &(buffer[16]));
        i2c_smbus_read_i2c_block_data(i2c_client, 0x18, 8, &(buffer[24]));		
	if(tpd_debuglog==1)
	{
        TPD_DMESG("[mtk-tpd]HST_MODE  : %x\n", buffer[0]); 
        TPD_DMESG("[mtk-tpd]TT_MODE   : %x\n", buffer[1]); 
        TPD_DMESG("[mtk-tpd]TT_STAT   : %x\n", buffer[2]);
       // TPD_DEBUG("[mtk-tpd]TOUCH_ID  : %x\n", buffer[8]);
		TPD_DMESG("[mtk-tpd]TOUCH_12ID  : %x\n", buffer[8]);
		TPD_DMESG("[mtk-tpd]TOUCH_34ID  : %x\n", buffer[21]);
	}	
        
        finger_num = buffer[2] & 0x0f;
        
        if (finger_num == 0 && pre_num ==0) {
            msleep(10);
            tpd_flag = 0;
            pre_tt_mode = buffer[1];
            continue;   
        }
        
        if (pre_tt_mode == buffer[1]) {
            msleep(5);
            tpd_flag = 0;
            pre_tt_mode = buffer[1];
            continue;  
        }
        
        if (buffer[1] & 0x20) {
            TPD_DEBUG("buffer not ready\n");
            tpd_flag = 0;
            pre_tt_mode = buffer[1];
            continue; // buffer is not ready for use
        }
        
        id1 = (buffer[8] & 0xf0) >> 4;
        id2 = (buffer[8] & 0x0f);
		id3 = (buffer[21] & 0xf0) >> 4;
		id4 = (buffer[21] & 0x0f);
                
//        if (id1 != 0xf) { 
	   if(finger_num>=1) {
            x1 = (((int)buffer[3]) << 8) + buffer[4]; 
            y1 = (((int)buffer[5]) << 8) + buffer[6]; 
            if(x1>2048 || y1>2048) {
	            tpd_flag = 0;
	            pre_tt_mode = buffer[1];  
	            continue;          		
            	}
            p1 = buffer[7];
            raw_x1 = x1; raw_y1 = y1;
            tpd_calibrate(&x1, &y1);
            tpd_down(raw_x1, raw_y1, x1, y1, p1);
            if(counter_pointer==0)
            	g_temptimerdiff=get_jiffies_64();//jiffies;
            if(x_min==0&&y_min==0&&x_max==0&&y_max==0) {
            		x_min = x1;
            		y_min = y1;
            		x_max = x1;
            		y_max = y1;
            	}
            if(x1<x_min)
            	x_min = x1;
            if(x1>x_max)
            	x_max = x1;
            if(y1<y_min)
            	y_min = y1;
            if(y1>y_max)
            	y_max = y1;
            counter_pointer++;
            if (time_after(jiffies, g_temptimerdiff + 100)){	//1s
            	TPD_DMESG("[mtk-tpd], x_min=%d, y_min=%d, x_max=%d, y_max=%d, counter_pointer=%d!!\n", x_min, y_min, x_max, y_max, counter_pointer);
            	x_min=0;
            	y_min=0;
            	x_max=0;
            	y_max=0;
            	counter_pointer=0;
            }
        }
        
//        if (id2 != 0xf || finger_num==2) {
	    if(finger_num>=2) {
            x2 = (((int)buffer[9]) << 8) + buffer[10]; 
            y2 = (((int)buffer[11]) << 8) + buffer[12]; 
            p2 = buffer[13];
            raw_x2 = x2; raw_y2 = y2;
            tpd_calibrate(&x2, &y2);
            tpd_down(raw_x2, raw_y2, x2, y2, p2);
        }
//	if(id3 != 0xf || finger_num==3) {
	    if(finger_num>=3) {
            x3 = (((int)buffer[16]) << 8) + buffer[17]; 
            y3= (((int)buffer[18]) << 8) + buffer[19]; 
            p3= buffer[20];
            raw_x3 = x3; raw_y3 = y3;
            tpd_calibrate(&x3, &y3);
            tpd_down(raw_x3, raw_y3, x3, y3, p3); 
		}

//	if(id4 != 0xf || finger_num==4) {
	    if(finger_num>=4) {
            x4 = (((int)buffer[22]) << 8) + buffer[23]; 
            y4= (((int)buffer[24]) << 8) + buffer[25]; 
            p4= buffer[26];
            raw_x4 = x4; raw_y4 = y4;
            tpd_calibrate(&x4, &y4);
            tpd_down(raw_x4, raw_y4, x4, y4, p4); 
		}	
        
	if(pre_num>=1 && pre_id1==0xf) {
		if(finger_num>=1 && id1==0xf) {
			if(tpd_debuglog==1)
				TPD_DMESG("finger1 is still down!\n");
		} else {
			if(tpd_debuglog==1)
				TPD_DMESG("finger1 is up!!\n");
			tpd_up(raw_x1, raw_y1, x1, y1, p1);
		}		
		
	} else if(pre_num>=1 && pre_id1 !=0xf) {
		if(id1==pre_id1) {
			if(tpd_debuglog==1)
				TPD_DMESG("finger1 is still down!!\n");
		} else {
			if(tpd_debuglog==1)
				TPD_DMESG("finger1 is up!\n");
			tpd_up(raw_x1, raw_y1, x1, y1, p1);
		}
	}
	
	if(pre_num>=2 && pre_id2==0xf) {
		if((finger_num>=2 && id2==0xf) || (finger_num==1 && id1==0xf)) {
			if(tpd_debuglog==1)
				TPD_DMESG("finger2 is still down!\n");
		} else {
			if(tpd_debuglog==1)
				TPD_DMESG("finger2 is up!!\n");
			tpd_up(raw_x2, raw_y2, x2, y2, p2);
		}		
		
	} else if(pre_num>=2 && pre_id2 !=0xf) {
		if(id2==pre_id2 || id1==pre_id2) {
			if(tpd_debuglog==1)
				TPD_DMESG("finger2 is still down!!\n");
		} else {
			if(tpd_debuglog==1)
				TPD_DMESG("finger2 is up!\n");
			tpd_up(raw_x2, raw_y2, x2, y2, p2);
		}
	}

	
	if(pre_num>=3 && pre_id3==0xf) {
		if((finger_num>=3 && id3==0xf) || (finger_num==2 && id2==0xf) || (finger_num==1 && id1==0xf)) {
			if(tpd_debuglog==1)
				TPD_DMESG("finger3 is still down!\n");
		} else {
			if(tpd_debuglog==1)
				TPD_DMESG("finger3 is up!!\n");
			tpd_up(raw_x3, raw_y3, x3, y3, p3);
		}		
		
	} else if(pre_num>=3 && pre_id3 !=0xf) {
		if(id3==pre_id3 || id2==pre_id3 || id1==pre_id3) {
			if(tpd_debuglog==1)
				TPD_DMESG("finger3 is still down!!\n");
		} else {
			if(tpd_debuglog==1)
				TPD_DMESG("finger3 is up!\n");
			tpd_up(raw_x3, raw_y3, x3, y3, p3);
		}
	}

	if(pre_num==4 && pre_id4==0xf) {
		if((finger_num>=4 && id4==0xf) || (finger_num==3 && id3==0xf) || (finger_num==2 && id2==0xf) || (finger_num==1 && id1==0xf)) {
			if(tpd_debuglog==1)
				TPD_DMESG("finger4 is still down!\n");
		} else {
			if(tpd_debuglog==1)
				TPD_DMESG("finger4 is up!!\n");
			tpd_up(raw_x4, raw_y4, x4, y4, p4);
		}		
		
	} else if(pre_num==4 && pre_id4 !=0xf) {
		if(id4==pre_id4 || id3==pre_id4 || id2==pre_id4 || id1==pre_id4) {
			if(tpd_debuglog==1)
				TPD_DMESG("finger4 is still down!!\n");
		} else {
			if(tpd_debuglog==1)
				TPD_DMESG("finger4 is up!\n");
			tpd_up(raw_x4, raw_y4, x4, y4, p4);
		}
	}
		if(tpd_debuglog==1)	
			TPD_DMESG("pre_id1=%d, pre_id2=%d, pre_id3=%d, pre_id4=%d, id1=%d, id2=%d, id3=%d, id4=%d\n", pre_id1, pre_id2, pre_id3, pre_id4, id1, id2, id3, id4);				
        pre_id1 = id1; pre_id2 = id2; pre_id3 = id3; pre_id4 = id4; pre_tt_mode = buffer[1];
	pre_num = finger_num;
       
	if(tpd && tpd->dev && tpd_register_flag==1) {      
	        input_sync(tpd->dev);
	}
        
        i2c_smbus_read_i2c_block_data(i2c_client, 0x00, 1, &toggle);
        if((toggle & 0x80) == 0) 
            toggle = toggle | 0x80;
        else 
            toggle = toggle & (~0x80);
        i2c_smbus_write_i2c_block_data(i2c_client, 0x00, 1, &toggle); // switch the read toggle bit to do next sampling 
        tpd_flag = 0;
    #ifndef POLL_MODE
    } while (!kthread_should_stop());
    #else 
    }while(1);
예제 #8
0
 static int tpd_touchinfo(tinno_ts_data *ts, tinno_ts_point *touch_point)
 {
	int i = 0;
	int iInvalidTrackIDs = 0;
	int iTouchID, iSearchDeep;
	fts_report_data_t *pReportData = (fts_report_data_t *)ts->buffer;
    
    int ret;
    uint8_t start_reg = 0x00;

#if 1
	if ( tpd_read_touchinfo(ts) ){
		CTP_DBG("Read touch information error. \n");
		return -EAGAIN; 
	}
#else
	memset((void *)ts->buffer, FTS_INVALID_DATA, FTS_PROTOCOL_LEN);

	mutex_lock(&g_pts->mutex);

	start_reg = 0x02;
	ret = i2c_master_send(ts->client, &start_reg,1);
	ret = i2c_master_recv(ts->client, &ts->buffer[2], 5);
	
	if (ts->buffer[2] > 1)
	{
	    start_reg = 9;
	    ret = i2c_master_send(ts->client,&start_reg,1);
	    ret = i2c_master_recv(ts->client, &ts->buffer[9], 4);
	} 
	//edit by Magnum 2012-8-6
	if (ts->buffer[9] > 1)
	{
	    start_reg = 0x0f;
	    ret = i2c_master_send(ts->client,&start_reg,1);
	    ret = i2c_master_recv(ts->client, &ts->buffer[15], 4);
	} 
	if (ts->buffer[15] > 1)
	{
	    start_reg = 0x15;
	    ret = i2c_master_send(ts->client,&start_reg,1);
	    ret = i2c_master_recv(ts->client, &ts->buffer[21], 4);
	} 
	if (ts->buffer[21] > 1)
	{
	    start_reg = 0x1b;
	    ret = i2c_master_send(ts->client,&start_reg,1);
	    ret = i2c_master_recv(ts->client, &ts->buffer[27], 4);
	} 
//	ret = i2c_master_recv(i2c_client, &buffer[0],8 );
	//ret = i2c_master_recv(i2c_client, &buffer[8],8 );	
	//ret = i2c_master_recv(i2c_client, &buffer[16],8 );	
	//ret = i2c_master_recv(i2c_client, &buffer[24],8 );	
	//ret = i2c_master_recv(i2c_client, &buffer[32],1 );	
	

	mutex_unlock(&g_pts->mutex);

	if (ret < 0) {
	    TPD_DEBUG("i2c_transfer failed");
		return 1;							//Error
	}

#endif
	
//	tpd_dump_touchinfo( ts );
	
	if ( 0 != pReportData->device_mode ){
		CTP_DBG("device mode is %d\n", pReportData->device_mode);
		return -EPERM; 
	}
	
	//We need only valid points...
	if ( pReportData->fingers > TINNO_TOUCH_TRACK_IDS ){
		CTP_DBG("fingers is %d\n", pReportData->fingers);
		return -EAGAIN; 
	}

	// For processing gestures.
	if (pReportData->gesture >= 0xF0 && pReportData->gesture <= 0xF3) {
		//fts_5x06_parase_keys(ts, pReportData);
	}
	
	iSearchDeep = 0;
#ifdef FTS_SUPPORT_TRACK_ID
	for ( i = 0; i < TINNO_TOUCH_TRACK_IDS; i++ ){
		iSearchDeep += ((pReportData->xy_data[i].event_flag != FTS_EF_RESERVED)?1:0);
	}
#else
	if (pReportData->fingers >= ts->last_fingers ){
		iSearchDeep = pReportData->fingers;
	}else{
		iSearchDeep = ts->last_fingers;
	}
	ts->last_fingers = pReportData->fingers;
#endif

	if ( iSearchDeep ) {
#ifdef FTS_SUPPORT_TRACK_ID
		for ( i=0; i < TINNO_TOUCH_TRACK_IDS; i++ ){
#else
		for ( i=0; i < iSearchDeep; i++ ){
#endif
			if (pReportData->xy_data[i].event_flag != FTS_EF_RESERVED) {
#ifdef FTS_SUPPORT_TRACK_ID
				iTouchID = pReportData->xy_data[i].touch_id;
				if ( iTouchID >= TINNO_TOUCH_TRACK_IDS )
				{
					CTP_DBG("i: Invalied Track ID(%d)\n!", i, iTouchID);
					iInvalidTrackIDs++;
					continue;
				}
#else
				iTouchID = i;
#endif
				touch_point[iTouchID].flag = pReportData->xy_data[i].event_flag;
				touch_point[iTouchID].x = pReportData->xy_data[i].x_h << 8 | pReportData->xy_data[i].x_l;
				touch_point[iTouchID].y = pReportData->xy_data[i].y_h << 8 | pReportData->xy_data[i].y_l;
				touch_point[iTouchID].pressure = pReportData->xy_data[i].pressure;
#ifdef TPD_FIRST_FIRWARE
				ft_map_coordinate(&(touch_point[iTouchID].x), &(touch_point[iTouchID].y));
#endif
			}else{
				//CTP_DBG("We got a invalied point, we take it the same as a up event!");
				//CTP_DBG("As it has no valid track ID, we assume it's order is the same as it's layout in the memory!");
				//touch_point[i].flag = FTS_EF_RESERVED;
			}
		}
		if ( TINNO_TOUCH_TRACK_IDS == iInvalidTrackIDs ){
			CTP_DBG("All points are Invalied, Ignore the interrupt!\n");
			return -EAGAIN; 
		}
	}
	CTP_DBG("p0_flag=0x%x x0=0x%03x y0=0x%03x pressure0=0x%03x "
	              "p1_flag=0x%x x1=0x%03x y1=0x%03x pressure1=0x%03x "
	              "gesture = 0x%x fingers=0x%x", 
	       touch_point[0].flag, touch_point[0].x, touch_point[0].y, touch_point[0].pressure,
	       touch_point[1].flag, touch_point[1].x, touch_point[1].y, touch_point[1].pressure,
	       pReportData->gesture, pReportData->fingers); 
	 return 0;

 };

 static int touch_event_handler(void *para)
 {
 	int i;
	tinno_ts_point touch_point[TINNO_TOUCH_TRACK_IDS];
	struct sched_param param = { .sched_priority = RTPM_PRIO_TPD };
	tinno_ts_data *ts = (tinno_ts_data *)para;
	sched_setscheduler(current, SCHED_RR, &param);
	
	do {
		set_current_state(TASK_INTERRUPTIBLE); 
		wait_event_interruptible(waiter, tpd_flag!=0);
		tpd_flag = 0;
		memset(touch_point, FTS_INVALID_DATA, sizeof(touch_point));
		set_current_state(TASK_RUNNING);
		if (!tpd_touchinfo(ts, &touch_point)) {
			//report muti point then
			for ( i=0; i < TINNO_TOUCH_TRACK_IDS; i++ ){
				if ( FTS_INVALID_DATA != touch_point[i].x ){
					if ( FTS_EF_UP == touch_point[i].flag ){
						if( test_bit(i, &ts->fingers_flag) ){
							tpd_up(ts, ts->touch_point_pre[i].x, ts->touch_point_pre[i].y, 
								touch_point[i].pressure, i);
					}else{
							CTP_DBG("This is a invalid up event.(%d)", i);
						}
					}else{//FTS_EF_CONTACT or FTS_EF_DOWN
						if ( test_bit(i, &ts->fingers_flag) 
							&& (FTS_EF_DOWN == touch_point[i].flag) ){
							CTP_DBG("Ignore a invalid down event.(%d)", i);
							continue;
						}
						tpd_down(ts, touch_point[i].x, touch_point[i].y, 
							touch_point[i].pressure, i);
					}
				}else if (  test_bit(i, &ts->fingers_flag) ){
					CTP_DBG("Complete a invalid down or move event.(%d)", i);
					tpd_up(ts, ts->touch_point_pre[i].x, ts->touch_point_pre[i].y, 
						touch_point[i].pressure, i);
				}
			}
			input_sync(tpd->dev);
		}
		
		mt_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM); 
	}while(!kthread_should_stop());
	mt_eint_mask(CUST_EINT_TOUCH_PANEL_NUM); 
	return 0;
 }
예제 #9
0
static int touch_event_handler(void *unused) {
    struct sched_param param = { .sched_priority = RTPM_PRIO_TPD };
    char index;
    char buffer[14];
    int i, pre_touch1 = 0, pre_touch2 = 0, touch = 0, finger_num = 0;
    int x1, y1, p1, x2, y2, p2, raw_x1, raw_y1, raw_x2, raw_y2;
    struct i2c_msg msg[2];
    
    sched_setscheduler(current, SCHED_RR, &param);
    
    do {
        MT6516_EINTIRQUnmask(CUST_EINT_TOUCH_PANEL_NUM); // possibly to lose event?
        set_current_state(TASK_INTERRUPTIBLE);
        if (!kthread_should_stop()) {
            while (tpd_halt) {tpd_flag=0; msleep(20);}
            if (pre_touch1 || pre_touch2)
                wait_event_interruptible_timeout(waiter, tpd_flag!=0, HZ/8);
            else
                wait_event_interruptible_timeout(waiter, tpd_flag!=0, HZ*2);
            TPD_DEBUG_SET_TIME;
        }
        set_current_state(TASK_RUNNING);
        
        if (tpd_calibrate_en | tpd_show_version) {
            mt_set_gpio_mode(GPIO61, 0x00);
            mt_set_gpio_pull_enable(GPIO61, GPIO_PULL_ENABLE);
            mt_set_gpio_pull_select(GPIO61,GPIO_PULL_UP);
            mt_set_gpio_dir(GPIO61, GPIO_DIR_OUT);
            mt_set_gpio_out(GPIO61, GPIO_OUT_ZERO);
            
            hwPowerDown(TPD_POWER_SOURCE,"TP");
            hwPowerOn(TPD_POWER_SOURCE,VOL_3300,"TP");
            msleep(20);
    
            if (tpd_calibrate_en) {
                tpd_do_calibrate();
                tpd_calibrate_en = 0;
            } else {
                tpd_print_version();
                tpd_show_version = 0;
            }
                
            /* added in android 2.2, for configuring EINT2 to EINT mode */
            mt_set_gpio_mode(GPIO61, 0x01);
            mt_set_gpio_pull_enable(GPIO61, GPIO_PULL_ENABLE);
            mt_set_gpio_pull_select(GPIO61,GPIO_PULL_UP);
            continue;
        } 
        
        if (!tpd_flag) {
            if (pre_touch1==1) {
                tpd_up(raw_x1, raw_y1, x1,y1,p1); pre_touch1 = 0;
            }
            if (pre_touch2==1) {
                tpd_up(raw_x2, raw_y2, x2,y2,p2); pre_touch2 = 0;
            }
            input_sync(tpd->dev);
            continue;
        } else {
            tpd_flag = 0;
        }
        
        buffer[0] = 0x80;
        i2c_master_send(i2c_rs_client, &buffer[0], (1 << 8 | 1));
    
        touch = (buffer[0] & 0x08) >> 3; // finger up or finger down
        //printk("buffer[0] = %d\n", buffer[0]);
        
        if (buffer[0]&0x80) {
           
            buffer[6] = 0xc0;
            i2c_master_send(i2c_rs_client, &buffer[6], (8 << 8 | 1));
              
            buffer[0] = 0xe0;
            i2c_master_send(i2c_rs_client, &buffer[0], (6 << 8 | 1));
            
            if (finger_num == 0x03 && buffer[0] == 0x00) {
                TPD_DEBUG("[mtk-tpd] firmware bug. hold one finger, hold another finger, and then tap the first finger, it will happen.\n");
                continue;
            }
            
            if ((buffer[0] & 0xF0)) {
                TPD_DEBUG("[mtk-tpd] this is not a position information\n");
                continue;
            }
            
            if (buffer[1] == 0x01) {
                TPD_DEBUG("[mtk-tpd] fat touch detect\n");
                continue;
            }
            
            finger_num = buffer[0]&0x07;
            if (finger_num&1) {
                x1 = buffer[2]+((buffer[3]&0x0f)<<8);
                y1 = buffer[4]+((buffer[3]&0xf0)<<4);
                p1 = buffer[5]&0x0f;
                raw_x1 = x1; raw_y1 = y1;
                tpd_calibrate(&x1, &y1);
                tpd_down(raw_x1, raw_y1, x1, y1, p1);
                pre_touch1=1;
            } else {
                if (pre_touch1!=0) {
                    tpd_up(raw_x1, raw_y1, x1, y1, p1); 
                    pre_touch1 = 0;
                }
            }
                
            if (finger_num&2) {
                x2 = buffer[6]+((buffer[7]&0x0f)<<8);
                y2 = buffer[8]+((buffer[7]&0xf0)<<4);
                p2 = buffer[9]&0x0f;
                raw_x2 = x2; raw_y2 = y2;
                tpd_calibrate(&x2, &y2);
                tpd_down(raw_x2, raw_y2, x2, y2, p2);
                pre_touch2=1;
            } else {
                if (pre_touch2!=0) {
                    tpd_up(raw_x2, raw_y2, x2, y2, p2); 
                    pre_touch2 = 0;
                }
            }
            
            input_sync(tpd->dev);
        } else {
            msleep(10);
        }       
    } while (!kthread_should_stop());
    return 0;
}
static int touch_event_handler(void *unused) {
    struct sched_param param = { .sched_priority = RTPM_PRIO_TPD }; 
    static int x1, y1, raw_x1, raw_y1;
    int temp_x1, temp_y1, temp_raw_x1, temp_raw_y1, temp_touch_dir, temp_contact_id;
    int report_id, touch_valid, contact_id, touch_dir, touch_need_sync;
    char buffer[10];
    int ret = -1;
    
    sched_setscheduler(current, SCHED_RR, &param); 
    do {
        set_current_state(TASK_INTERRUPTIBLE);
        while (tpd_halt) {tpd_flag = 0; msleep(20);}
        wait_event_interruptible(waiter, tpd_flag != 0);
        tpd_flag = 0;
        TPD_DEBUG_SET_TIME;
        set_current_state(TASK_RUNNING); 
        TPD_DEBUG("[mtk-tpd] touch interrupt\n");
        touch_need_sync = 0;
        temp_x1 = 0xFFFFFFFF;
        temp_y1 = 0xFFFFFFFF;
        temp_raw_x1 = 0xFFFFFFFF;
        temp_raw_y1 = 0xFFFFFFFF;
        temp_touch_dir = 0xFFFFFFFF;
        temp_contact_id = 0xFFFFFFFF;
        do
        {
            i2c_client->addr = i2c_client->addr & I2C_MASK_FLAG | I2C_DMA_FLAG | I2C_ENEXT_FLAG;
            ret = tpd_i2c_read(i2c_client, buffer, 10);
            if (ret != sizeof(buffer))
            {
                TPD_DEBUG("[mtk-tpd] i2c read communcate error: 0x%x\n", ret);
                continue;
            }
            i2c_client->addr = i2c_client->addr & I2C_MASK_FLAG;
            report_id = buffer[0];
            if (0x4 == report_id)
            {
            	touch_valid = buffer[1]>>7;
            	if (touch_valid)
            	{
            	    contact_id = (buffer[1]&0x7C)>>2;
            	    touch_dir = buffer[1]&0x1;
            	    raw_x1 = x1 = ((buffer[3] << 8) | buffer[2]);
                    raw_y1 = y1 = ((buffer[5] << 8) | buffer[4]);
                    TPD_DEBUG("[mtk-tpd]:id:%d, raw_x1:%d, raw_y1:%d\n", contact_id, raw_x1, raw_y1);
                    tpd_calibrate(&x1, &y1);
                    
                    if (((temp_x1 != x1) || (temp_y1 != y1) || (temp_contact_id != contact_id))
                        && (0xFFFFFFFF != temp_x1) && (0xFFFFFFFF != temp_y1))
                    {
                    	touch_need_sync = 1;
                        if (temp_touch_dir)
                        {
                    	    tpd_down(temp_raw_y1, temp_raw_x1, temp_y1, temp_x1, 1);
                        }
                        else
                        {
                    	    tpd_up(temp_raw_y1, temp_raw_x1, temp_y1, temp_x1, 0);
                        }
                    }
                    temp_x1 = x1;
                    temp_y1 = y1;
                    temp_raw_x1 = raw_x1;
                    temp_raw_y1 = raw_y1;
                    temp_touch_dir = touch_dir;
                    temp_contact_id = contact_id;
            	}
            	else
            	{
            	    TPD_DEBUG("[mtk-tpd]:Touch Invalid\n");
            	}
            }
            else
            {
                TPD_DEBUG("[mtk-tpd]:Invalid report ID:%d\n", buffer);
            }
        }while(!mt_get_gpio_in(GPIO_CTP_EINT_PIN));
예제 #11
0
static int touch_event_handler(void *unused) {
    struct sched_param param = { .sched_priority = RTPM_PRIO_TPD }; 
    int i = 0,x1=0, y1=0, finger_num = 0;
    char buffer[32];//[16];
	u32 temp;
    
    sched_setscheduler(current, SCHED_RR, &param); 
    g_temptimerdiff=get_jiffies_64();//jiffies;
    do {
		if(tpd_debuglog==1) {
			TPD_DMESG("[mtk-tpd] %s\n", __FUNCTION__); 
		}	    	
        set_current_state(TASK_INTERRUPTIBLE);
	if(tpd_debuglog==1)
		TPD_DMESG("[mtk-tpd], %s, tpd_halt=%d\n", __FUNCTION__, tpd_halt);
        while (tpd_halt) {tpd_flag = 0; msleep(20);}
        wait_event_interruptible(waiter, tpd_flag != 0);
        //tpd_flag = 0;
        TPD_DEBUG_SET_TIME;
        set_current_state(TASK_RUNNING); 
        i2c_smbus_read_i2c_block_data(i2c_client, 0x00, 8, &(buffer[0]));
        i2c_smbus_read_i2c_block_data(i2c_client, 0x08, 8, &(buffer[8]));
        i2c_smbus_read_i2c_block_data(i2c_client, 0x10, 8, &(buffer[16]));
        i2c_smbus_read_i2c_block_data(i2c_client, 0x18, 8, &(buffer[24]));		
        if((buffer[1]&0x01) != (buffer[30]&0x01))
        {        
            i2c_smbus_read_i2c_block_data(i2c_client, 0x00, 8, &(buffer[0]));
            i2c_smbus_read_i2c_block_data(i2c_client, 0x08, 8, &(buffer[8]));
            i2c_smbus_read_i2c_block_data(i2c_client, 0x10, 8, &(buffer[16]));
            i2c_smbus_read_i2c_block_data(i2c_client, 0x18, 8, &(buffer[24]));		
        }
        if((buffer[1]&0xf0) != 0x10)
        {
            buffer[0] =  0x00;
            buffer[1] =  0x03;
            i2c_master_send(i2c_client,buffer,2);
            msleep(50);
            buffer[0] =  0x00;
            buffer[1] =  0x05;
            i2c_master_send(i2c_client,buffer,2);
            //status = i2c_master_recv(i2c_client, buffer, 3);
            msleep(50);
            buffer[0] =  0x00;
            buffer[1] =  0x21;
            buffer[2] =  0x07;
            buffer[3] =  0x01;
            buffer[4] =  0x00;
            i2c_master_send(i2c_client,buffer,5);
            msleep(50);
            continue; 
        }
	if(tpd_debuglog==1)
	{
        TPD_DMESG("[mtk-tpd]HST_MODE  : %x\n", buffer[0]); 
        TPD_DMESG("[mtk-tpd]TT_MODE   : %x\n", buffer[1]); 
        TPD_DMESG("[mtk-tpd]TT_STAT   : %x\n", buffer[2]);
       // TPD_DEBUG("[mtk-tpd]TOUCH_ID  : %x\n", buffer[8]);
		TPD_DMESG("[mtk-tpd]TOUCH_12ID  : %x\n", buffer[8]);
		TPD_DMESG("[mtk-tpd]TOUCH_34ID  : %x\n", buffer[21]);
	}	
                finger_num = 0;
        for(i = 0; i < 7;i++)
        { 
            x1 = buffer[4*i + 2] | ((buffer[4*i+4]&0x0f) << 8) ;
            y1 = buffer[4*i + 3] | ((buffer[4*i+4]&0xf0) << 4) ;
            if(x1 != 0xfff){
                tpd_down(x1, y1, x1, y1, 100);
                finger_num++;
                //printk("-----x:%d,y:%d-------down\n",x1,y1);            
            }
        }
           //printk("-----finger_num = %d-------\n",finger_num);            
        if(finger_num > 0)
            input_sync(tpd->dev);
        else
        {
           //printk("-----x:%d,y:%d-------up\n",x1,y1);            
            tpd_up(x1, y1, x1, y1, 0);
            //input_mt_sync(tpd->dev);
            input_sync(tpd->dev);
        }
       tpd_flag = 0;
   
    } while (!kthread_should_stop()); 
    return 0;
}
예제 #12
0
/* handle touch panel interrupt for down / up event */
void tpd_tasklet(unsigned long unused) {
    static int x1,y1,p1;//,d1,round=0;
    int cx=0, cy=0, cp=0, cd=0;               /* current point */
    int fx=0, fy=0, fp=0, fd=0;               /* foresee point */
    int ni=0, i =0;                           /* index         */
    static int lx=0, ly=0;                    /* latest  point */
    static int px=0, py=0;
    static struct touch_info buf_kp[3];
    static int buf_p=1, buf_c=2, buf_f=0, down = 0;
    int dx;

    TPD_DEBUG_SET_TIME;

    if (tpd_em_debounce_time != 0) {
        tpd_set_debounce_time(tpd_em_debounce_time);
        tpd_em_debounce_time = 0;
    }
    
    //struct timeval tv;
    //long t1, t2;
    //do_gettimeofday(&tv);
    //t1 = tv.tv_sec*1000000l+tv.tv_usec;

    //tpd_sampling(&cx, &cy, &cp, &cd);
    //tpd_calibrate(&cx, &cy);
    //printk("c [%5d %5d %5d %5d]\n", cx, cy, cp, cd);
    //mod_timer(&(tpd->timer),jiffies+TPD_DELAY);
    //return;
    tpd_sampling(&cx, &cy, &cp, &cd);
    tpd_calibrate(&cx, &cy);

    /* ============= boundary condition ============*/
    if(cx<0) cx=0;
    if(cy<0) cy=0;
    if(cx>TPD_RES_X) cx=TPD_RES_X;
    #if defined(TPD_HAVE_BUTTON) || defined(TPD_HAVE_VIRTUAL_KEY)
    if(cy>TPD_RES_Y && cy<TPD_BUTTON_HEIGHT) cp=TPD_PRESSURE_MAX+1,cd=0;
    #else
    if(cy>TPD_RES_Y) cy=TPD_RES_Y;
    #endif

    if(tpd_mode==TPD_MODE_KEYPAD &&
        ((cd==0 && down==1) || (tpd_mode_axis==0 && cy>=tpd_mode_min && cy<=tpd_mode_max) ||
         (tpd_mode_axis==1 && cx>=tpd_mode_min && cx<=tpd_mode_max))) {
        /* this segment of code should be refactorized with following drift elimination */
        #ifdef TPD_HAVE_DRIFT_ELIMINATION
        /* drift elimination */
        if(buf.count==0 || (cp>=TPD_PRESSURE_NICE && cd)) {
          TPD_DEBUG("drift eliminated (0) or Pressure filtering\n");
        #ifdef TPD_HAVE_ADV_DRIFT_ELIMINATION
        } else if (buf.count==1 && cp>TPD_ADE_P1) {
          TPD_DEBUG("drift eliminated (1)\n");
        } else if (buf.count==1) {
          /* queue first good point, discard it if 2nd pt is bad */
          TPD_BUF_QUEUE(cx,cy,cd,cp);
        } else if (buf.count==2 && cp>TPD_ADE_P2) {
          TPD_DEBUG("drift eliminated (2)\n");
          TPD_BUF_UNQUEUE(fx,fy,fd,fp);
        #endif
        #else
        if(0) {
        #endif
        } else {
            buf_f = ((buf_f+1)%3);
            buf_c = ((buf_f+2)%3);
            buf_p = ((buf_f+1)%3);
            buf_kp[buf_f].x1 = (cd?cx:buf_kp[buf_c].x1);
            buf_kp[buf_f].y1 = (cd?cy:buf_kp[buf_c].y1);
            dx = buf_kp[buf_f].x1 - buf_kp[buf_c].x1;
            buf_kp[buf_f].count = (cd?(dx*dx<tpd_mode_keypad_tolerance?buf_kp[buf_c].count+1:1):0);
            if(buf_kp[buf_c].count<2) { if(down) {
                down=0;
                tpd_up(buf_kp[buf_p].x1, buf_kp[buf_p].y1,1,0);
                input_sync(tpd->dev); 
            } }
            if(buf_kp[buf_c].count>1 ||
               (buf_kp[buf_c].count==1 && (
                buf_kp[buf_p].count==0 || buf_kp[buf_f].count==0
                || (buf_kp[buf_f].x1-buf_kp[buf_c].x1)*(buf_kp[buf_c].x1-buf_kp[buf_p].x1)<=0))) {
                tpd_down(buf_kp[buf_c].x1, buf_kp[buf_c].y1,1,1, &px, &py);
                input_sync(tpd->dev);
                down = 1;
            }
            if(cd==0) { if(down) {
                down=0;
                tpd_up(buf_kp[buf_p].x1, buf_kp[buf_p].y1,1,0);
                input_sync(tpd->dev); 
                buf.count = 0;
            }}
            else mod_timer(&(tpd->timer),jiffies+TPD_DELAY);
        } mod_timer(&(tpd->timer),jiffies+TPD_DELAY);
        buf.count++;
    } else {

    // to avoid miss of tpd down when press light to heavy
    if(tpd_sw_status==0) {
        if(tpd_hw_status==1) {
            if(cd==0) stop_timer(true);
        } else return;
    } tpd_sw_status = 1;
    

    /* ================= buffering =================*/
    /* save new point in ni, get point from index */
    ni=TPD_BUF_NP(); 
    buf.x[ni]=cx;
    buf.y[ni]=cy;
    buf.d[ni]=cd;
    buf.p[ni]=cp;
    fx=(cx=buf.x[buf.index]);
    fy=(cy=buf.y[buf.index]);
    fd=(cp=buf.p[buf.index]);
    fp=(cd=buf.d[buf.index]);
    buf.index = ni;

    tpd_lpfx[tpd_lpfc]=cx;
    tpd_lpfy[tpd_lpfc]=cy;
    x1 = 0, y1 = 0, p1 = 0;
    for(i=tpd_lpfc;i<tpd_lpfc+5;i++) {
      x1 += (tpd_lpfx[i%5]*tpd_lpfw[i-tpd_lpfc]);
      y1 += (tpd_lpfy[i%5]*tpd_lpfw[i-tpd_lpfc]);
      if(tpd_lpfx[i%5]!=0 || tpd_lpfy[i%5]!=0) p1+=tpd_lpfw[i-tpd_lpfc];
    } 
    cx=x1/(p1?p1:1); cy=y1/(p1?p1:1);

    TPD_DEBUG(">%d [%8d %8d %8d %8d] - ",buf.count,cx,cy,cp,cd);

    /* pressure thresholding */
    if(cp>TPD_PRESSURE_MAX || (cx==TPD_RES_X && cy==TPD_RES_Y)) 
        cd=0,cp=TPD_PRESSURE_MAX+1;

    if(cd==1) {
      #ifdef TPD_HAVE_DRIFT_ELIMINATION
      /* drift elimination */
      if(buf.count==0) {
        TPD_DEBUG("drift eliminated (0)\n");
      #ifdef TPD_HAVE_ADV_DRIFT_ELIMINATION
      } else if (buf.count==1 && cp>TPD_ADE_P1) {
        TPD_DEBUG("drift eliminated (1)\n");
      } else if (buf.count==1) {
        /* queue first good point, discard it if 2nd pt is bad */
        TPD_BUF_QUEUE(cx,cy,cd,cp);
      } else if (buf.count==2 && cp>TPD_ADE_P2) {
        TPD_DEBUG("drift eliminated (2)\n");
        TPD_BUF_UNQUEUE(fx,fy,fd,fp);
      #endif
      #else
      if(0) {
      #endif
      } else {
        /* if a point is already queued, pop and send it */
        if(buf.queued) {
          TPD_BUF_UNQUEUE(fx,fy,fd,fp);
          /* if the queued point is a bad point.. */
          #ifdef TPD_HAVE_BUTTON
          /* if point is for btn, don't process it */
          if(cy>=TPD_BUTTON_HEIGHT) {}
          #else
          if(0) {}
          #endif
          else if(fp>TPD_PRESSURE_NICE && buf.avg_count<2) {
            /* average current point and queued point */
            cx = (cx+fx)/2;
            cy = (cy+fy)/2;
            buf.avg_count++;
          } else {
            TPD_DEBUG("pop and down\n");
            tpd_down(fx,fy,fd,fp, &px, &py);
            lx=fx,ly=fy;
            buf.avg_count=0;
          }
        }
        #ifdef TPD_HAVE_BUTTON
        /* queue points near bottom btns, to prevent mis-touch of menu */
        if(cy>TPD_BUTTON_HEIGHT-20 && cy<TPD_BUTTON_HEIGHT) {
          TPD_DEBUG("queued\n");
          TPD_BUF_QUEUE(cx,cy,cd,cp);
        }
        #else
        if(0) {}
        #endif
        /* discontinuity elimination - queueing */
        /* also point averaging */
        else if(buf.d[ni]==0 || cp>TPD_PRESSURE_NICE) {
          TPD_DEBUG("queued\n");
          TPD_BUF_QUEUE(cx,cy,cd,cp);
        } else {
          TPD_DEBUG("down\n");
          tpd_down(cx,cy,cd,cp, &px, &py);
          lx=cx,ly=cy;
          buf.effective++;
          buf.last = buf.count+1;
        }
      }
      buf.count++;
      mod_timer(&(tpd->timer),jiffies+TPD_DELAY);
    } else {
      if(buf.queued) {
        if(buf.count-buf.last>TPD_COUNT_TOLERANCE) {
          /* single point elimination */
          TPD_BUF_UNQUEUE(cx,cy,cd,cp);
          TPD_DEBUG("unqueue : ");
          if(buf.effective==0) {
            TPD_DEBUG("sp eliminated.\n");
            stop_timer(false);
          } else {
            /* track extension */
            if(cp<TPD_PRESSURE_NICE) { /* only when end-point is good..*/
              tpd_down(cx,cy,cd,cp, &px, &py);
              #ifdef TPD_HAVE_TRACK_EXTENSION
              if(buf.effective>0) {
                cx=cx+cx-px,cy=cy+cy-py;
                tpd_down(cx,cy,cd,cp, &px, &py);
                TPD_DEBUG("track extend.\n");
              }
              lx=cx,ly=cy;
              #endif
            } else TPD_DEBUG("end point is not good, discard\n");
            tpd_up(lx,ly,cd,cp);
            stop_timer(false);
          }
        } else {
          /* waiting for next down event */
          TPD_DEBUG("delay handling.\n");
          buf.count++;
          mod_timer(&(tpd->timer),jiffies+TPD_DELAY);
        }
      } else {
        TPD_DEBUG("no queue.\n");
        /* since no queue and no touch, stop timer after specific times of trial */
        /* only increase buf.count after real first down. */
        //if(buf.effective) buf.count++;
        if(buf.count || !buf.last) buf.count++;
        if(buf.count-buf.last>TPD_COUNT_TOLERANCE || buf.count==0) {
          tpd_up(lx,ly,0,TPD_PRESSURE_MAX+1);
          stop_timer(true);
        } else mod_timer(&(tpd->timer),jiffies+TPD_DELAY);
      }
    }
    }
    //printk("\n");
    //do_gettimeofday(&tv);
    //t2 = tv.tv_sec*1000000l+tv.tv_usec;
    //printk("%ld\n", t2-t1);
    return;
}

//#ifdef CONFIG_HAS_EARLYSUSPEND
/* platform device functions */
void tpd_suspend(struct early_suspend *h) {

    /*MT6573_IRQClearInt(MT6573_WDT_IRQ_LINE);
    MT6573_IRQMask(MT6573_TOUCH_IRQ_LINE);
    if(hwDisableClock(MT6573_PDN_PERI_TP,"Touch")==FALSE)
        TPD_DMESG("entering suspend mode - hwDisableClock failed.");
    if(hwDisableClock(MT6573_PDN_PERI_ADC,"Touch")==FALSE)
        TPD_DMESG("entering suspend mode - hwDisableClock failed.");*/
    tpd_hw_status = 0;
}
void tpd_resume(struct early_suspend *h) {
    /*if(hwEnableClock(MT6573_PDN_PERI_ADC,"Touch")==FALSE)
        TPD_DMESG("resume from suspend mode - hwEnableClock ADC failed.");
    if(hwEnableClock(MT6573_PDN_PERI_TP,"Touch")==FALSE)
        TPD_DMESG("resume from suspend mode - hwEnableClock TP failed.");*/

    //MT6573_IRQUnmask(MT6573_TOUCH_IRQ_LINE);
}
static int touch_event_handler(void *unused) {
    struct sched_param param = { .sched_priority = RTPM_PRIO_TPD };
    struct touch_info cinfo, sinfo;
    int pending = 0, down = 0;
    struct touch_info buf[3];
    int buf_p=1, buf_c=2, buf_f=0; 
    int dx;

    cinfo.pending=0;
    sched_setscheduler(current, SCHED_RR, &param);
    do {
        MT6516_EINTIRQUnmask(CUST_EINT_TOUCH_PANEL_NUM); // possibly to lose event?
        set_current_state(TASK_INTERRUPTIBLE);
        if (!kthread_should_stop()) {
            TPD_DEBUG_CHECK_NO_RESPONSE;
            do {
                if(pending) wait_event_interruptible_timeout(waiter, tpd_flag!=0, HZ/10);
                else wait_event_interruptible_timeout(waiter,tpd_flag!=0, HZ*2);
            } while(0);
            if(tpd_flag==0 && !pending) continue; // if timeout for no touch, then re-wait.
            if(tpd_flag!=0 && pending>0)  pending=0;
            tpd_flag=0;
            TPD_DEBUG_SET_TIME;
        }
        set_current_state(TASK_RUNNING);
        
        if(!pending) if(tpd_gettouchinfo(&cinfo, &sinfo)) continue; 
        if(pending>1) { pending--; continue; }
        if(cinfo.count==-1) continue;
        if(tpd_mode==TPD_MODE_KEYPAD && 
            ((tpd_mode_axis==0 && cinfo.y1>=tpd_mode_min && cinfo.y1<=tpd_mode_max) ||
             (tpd_mode_axis==1 && cinfo.x1>=tpd_mode_min && cinfo.x1<=tpd_mode_max))) {
            buf_f = ((buf_f+1)%3);
            buf_c = ((buf_f+2)%3);
            buf_p = ((buf_f+1)%3);
            buf[buf_f].x1 = cinfo.x1;
            buf[buf_f].y1 = cinfo.y1;
            dx = cinfo.x1 - buf[buf_c].x1;
            buf[buf_f].count = (cinfo.count?(dx*dx<tpd_mode_keypad_tolerance?buf[buf_c].count+1:1):0);
            if(buf[buf_c].count<2) if(tpd_up(raw_x1, raw_y1, buf[buf_p].x1, buf[buf_p].y1,&down)) input_sync(tpd->dev);
            if(buf[buf_c].count>1 ||
               (buf[buf_c].count==1 && (
                buf[buf_p].count==0 || buf[buf_f].count==0
                || (buf[buf_f].x1-buf[buf_c].x1)*(buf[buf_c].x1-buf[buf_p].x1)<=0))) {
                tpd_down(raw_x1, raw_y1, buf[buf_c].x1, buf[buf_c].y1, 1); 
                input_sync(tpd->dev);
                down=1;
            } 
            if(cinfo.count==0) if(tpd_up(raw_x1, raw_y1, buf[buf_p].x1, buf[buf_p].y1,&down)) input_sync(tpd->dev);
        } else {

        switch(cinfo.count) {
            case 0:
                if(cinfo.pending>0) pending+=cinfo.pending, cinfo.pending=0;
                else {
                    if(sinfo.count>=2) {
                        if(pending==0) pending+=1; 
                        else {
                            if(tpd_up(raw_x1, raw_y1, sinfo.x1, sinfo.y1, &down) + tpd_up(raw_x2, raw_y2, sinfo.x2,sinfo.y2, &down)) 
                                input_sync(tpd->dev);
                            sinfo.count = 0;
                            pending = 0;
                        }
                    } else if(sinfo.count==1) {
                        #ifdef TPD_HAVE_BUTTON
                        if(boot_mode!=NORMAL_BOOT && tpd->btn_state) tpd_button(cinfo.x1, cinfo.y1,0);
                        #endif
                        if(tpd_up(raw_x1, raw_y1, cinfo.x1,cinfo.y1, &down)) input_sync(tpd->dev);
                        sinfo.count = 0;
                        pending=0;
                    } else pending = 0;
                }
                TPD_DEBUG_PRINT_UP;
                break;
            case 1:
                if(sinfo.count>=3 || pending==1) {
                    pending = 0;
                    if(sinfo.count==3 && down>1) {
                        if(tpd_up(raw_x1, raw_y1, sinfo.x1,sinfo.y1, &down)) input_sync(tpd->dev);
                        /*tpd_down(cinfo.x1, cinfo.y1, 1);
                        if(
                          (cinfo.x1-sinfo.x1)*(cinfo.x1-sinfo.x1)+(cinfo.y1-sinfo.y1)*(cinfo.y1-sinfo.y1)
                        > (cinfo.x1-sinfo.x2)*(cinfo.x1-sinfo.x2)+(cinfo.y1-sinfo.y2)*(cinfo.y1-sinfo.y2)
                        ) {
                          if(tpd_up(sinfo.x1,sinfo.y1, &down)) input_sync(tpd->dev);
                        } else {
                          if(tpd_up(sinfo.x2,sinfo.y2, &down)) input_sync(tpd->dev);
                        }*/
                    }
                } else if(sinfo.count==2) {
                    if(pending==0) pending=1;
                    else {
                        if(tpd_up(raw_x1, raw_y1, cinfo.x1,cinfo.y1, &down) + tpd_up(raw_x2, raw_y2, sinfo.x2,sinfo.y2, &down))
                            input_sync(tpd->dev);
                        sinfo.x1 = cinfo.x1; sinfo.y1=cinfo.y1;
                    }
                    sinfo.count = 3;
                } else {
                    #ifdef TPD_HAVE_BUTTON
                    if(boot_mode!=NORMAL_BOOT && cinfo.y1>=TPD_RES_Y) { 
                        if(tpd_up(raw_x1, raw_y1, cinfo.x1, cinfo.y1, &down)) input_sync(tpd->dev);
                        tpd_button(cinfo.x1, cinfo.y1, 1);
                        sinfo.count = 1;
                    } else 
                    #endif 
                    do {
                        #ifdef TPD_HAVE_BUTTON
                        if(boot_mode!=NORMAL_BOOT && tpd->btn_state) tpd_button(cinfo.x1,cinfo.y1,0);
                        #endif 
                        tpd_down(raw_x1, raw_y1, cinfo.x1,cinfo.y1, cinfo.p);
                        input_sync(tpd->dev);
                        down = 1;
                        sinfo.count = 1;
                    } while(0);
                }
                TPD_DEBUG_PRINT_DOWN;
                break;
            case 2:
                // hold one finger, press another, this code will release both fingers
                if(sinfo.count==3) {
                    if(tpd_up(raw_x1, raw_y1, sinfo.x1, sinfo.y1, &down) + tpd_up(raw_x2, raw_y2, sinfo.x2, sinfo.y2, &down))
                        input_sync(tpd->dev);
                }
                tpd_smoothing(&cinfo, &sinfo);
                tpd_down(raw_x1, raw_y1, sinfo.x1, sinfo.y1, 1);
                tpd_down(raw_x2, raw_y2, sinfo.x2, sinfo.y2, 1);
                down = 2;
                sinfo.count = 2;
                input_sync(tpd->dev);
                TPD_DEBUG_PRINT_DOWN;
                break;
            default: break;
        }
    } 
    } while (!kthread_should_stop());
    return 0;
}
예제 #14
0
static int touch_event_handler(void *unused) {
    struct sched_param param = { .sched_priority = RTPM_PRIO_TPD };

    int index;
	uint8_t Firmware_version[3] = {0x20,0x00,0x00};

    sched_setscheduler(current, SCHED_RR, &param);
    do {
        set_current_state(TASK_INTERRUPTIBLE);
        if (!kthread_should_stop()) {
            TPD_DEBUG_CHECK_NO_RESPONSE;
            do {
				while (tpd_halt) {tpd_flag = 0;sinfo.TouchpointFlag=0; msleep(20);}
               		wait_event_interruptible(waiter,tpd_flag!=0);
					tpd_flag = 0;
            } while(0);

            TPD_DEBUG_SET_TIME;
        }
       		 set_current_state(TASK_RUNNING);
#if 0
			 if (tpd_show_version) {
	            tpd_show_version = 0;
			if(tpd_i2c_master_rs_send(i2c_client,Firmware_version,3<<8|1) < 0)
			{
					TPD_DMESG("I2C transfer error, line: %d\n", __LINE__);
			}
			else
			{
				TPD_DMESG(" mcs6024 Hardware version is %x\n",Firmware_version[0]);
				TPD_DMESG(" mcs6024 Firmware version is %x\n",Firmware_version[1]);
				TPD_DMESG(" mcs6024 Panel Type  is %x\n",Firmware_version[2]);
			}
		}
		
		 if((tpd_gettouchinfo(&cinfo)) 
            && (sinfo.TouchpointFlag==0) 
            && ((sinfo.VirtualKeyFlag & 0x03) == 0)) 
		 	continue; 
	
		TPD_DEBUG("sinfo.TouchpointFlag = %d\n",sinfo.TouchpointFlag);
		TPD_DEBUG("cinfo.TouchpointFlag = %d\n",cinfo.TouchpointFlag);
        TPD_DEBUG("sinfo.VirtualKeyFlag = %d\n",sinfo.VirtualKeyFlag);
		TPD_DEBUG("cinfo.VirtualKeyFlag = %d\n",cinfo.VirtualKeyFlag);

        #ifdef TPD_HAVE_BUTTON
        int index = (cinfo.VirtualKeyFlag >> 2) & 0x03;
        if (index >= TPD_KEY_COUNT)
            continue;
        
        if ((cinfo.VirtualKeyFlag & 0x03) == 1) {
            if ((sinfo.VirtualKeyFlag & 0x03) == 0) {
                tpd_down(tpd_keys_dim_local[index][0],tpd_keys_dim_local[index][1], tpd_keys_dim_local[index][0],tpd_keys_dim_local[index][1], 128);
                if (boot_mode != NORMAL_BOOT) 
                    tpd_button(tpd_keys_dim_local[index][0],tpd_keys_dim_local[index][1], 1);
            }
        } else {
            if ((sinfo.VirtualKeyFlag & 0x03) == 1) {
                tpd_up(tpd_keys_dim_local[index][0],tpd_keys_dim_local[index][1], tpd_keys_dim_local[index][0],tpd_keys_dim_local[index][1]);
                if (boot_mode != NORMAL_BOOT) 
                    tpd_button(tpd_keys_dim_local[index][0],tpd_keys_dim_local[index][1], 0);
            }
        }
        #endif
		 
		 for(index = 0;index<MAX_POINT;index++)
		 	{
				if(cinfo.TouchpointFlag&(1<<index))
				{
					raw_x[index] = cinfo.x[index];
					raw_y[index] = cinfo.y[index];
					tpd_down(raw_x[index], raw_y[index], cinfo.x[index],cinfo.y[index], 128);
					sinfo.x[index] = cinfo.x[index];
					sinfo.y[index] = cinfo.y[index];
					sinfo.TouchpointFlag |=(1<<index);
				}
				else
				{
					if(sinfo.TouchpointFlag&(1<<index))
					{
						tpd_up(raw_x[index], raw_y[index], sinfo.x[index], sinfo.y[index]);
						sinfo.TouchpointFlag &=~(1<<index);
					}

				}
		 	}

		 input_sync(tpd->dev);

#endif

		 msg21xx_data_disposal();

		
    } while (!kthread_should_stop());
    return 0;
}