/*===========================================================================
FUNCTION      ts_key_timer
DESCRIPTION:  
              键盘定时器,去除滑动造成判断错误
DEPENDENCIES
  None
RETURN VALUE
  None
SIDE EFFECTS
  None
===========================================================================*/
static void ts_key_timer(unsigned long arg)
{
    struct ts *ts = (struct ts *)arg;

    TSSC("%s: key timer out!\n", __FUNCTION__);
    touch_extra_key_proc(ts);
}
static void ts_late_resume(struct early_suspend *h)
{
    struct ts *ts;
    ts = container_of(h, struct ts, early_suspend);

    enable_irq(ts->irq);
    /* Data has been read, OK to clear the data flag */
    writel(TSSC_CTL_STATE, TSSC_REG(CTL));

    TSSC("%s:msm_touch late resume\n!", __FUNCTION__);
}
/*===========================================================================
FUNCTION      touch_pass_extra_keycode
DESCRIPTION:  
              附加区域键值上报处理
DEPENDENCIES
  None
RETURN VALUE
  None
SIDE EFFECTS
  None
===========================================================================*/
static void touch_pass_extra_keycode(struct ts *ts)
{
    u32 key_code = record_extra_keycode.record_extra_key;

    if(KEY_RESERVED != key_code)
    {
        input_report_key(ts->key_input, key_code, !record_extra_keycode.bRelease);
        input_sync(ts->key_input);
    }

    TSSC("***EXTRA KEY TEST:key_code=%d, release=%d***\n", key_code, record_extra_keycode.bRelease);

    return;
}
static void ts_update_pen_state(struct ts *ts, int x, int y, int pressure)
{
    TSSC("{%d, %d}, pressure = %3d\n", x, y, pressure);
    if (pressure) {
        input_report_abs(ts->input, ABS_X, x);
        input_report_abs(ts->input, ABS_Y, y);
        input_report_abs(ts->input, ABS_PRESSURE, pressure);
        input_report_key(ts->input, BTN_TOUCH, !!pressure);
    } else {
        input_report_abs(ts->input, ABS_PRESSURE, 0);
        input_report_key(ts->input, BTN_TOUCH, 0);
    }

    input_sync(ts->input);
}
static void ts_early_suspend(struct early_suspend *h)
{
    struct ts *ts;
    ts = container_of(h, struct ts, early_suspend);

    del_timer_sync(&ts->timer);

#ifdef CONFIG_HUAWEI_TOUCHSCREEN_EXTRA_KEY
    if(ts->use_touch_key)
    {
        del_timer_sync(&ts->key_timer);
    }
#endif
    
    writel(0, TSSC_REG(CTL));

    disable_irq(ts->irq);

    TSSC("%s:msm_touch early suspend!\n", __FUNCTION__);
}
static void ts_update_pen_state(struct ts *ts, int x, int y, int pressure)
{
    TSSC("{%d, %d}, pressure = %3d\n", x, y, pressure);
    if (pressure) {
        // Calibrate
//        x = (x*msm_tscal_xscale + msm_tscal_xoffset + msm_tscal_scaler/2)/msm_tscal_scaler;
//        y = (y*msm_tscal_yscale + msm_tscal_yoffset + msm_tscal_scaler/2)/msm_tscal_scaler;
        x = (x*msm_tscal_xscale + msm_tscal_xoffset + 32768)/65536;
        y = (y*msm_tscal_yscale + msm_tscal_yoffset + 32768)/65536;

        input_report_abs(ts->input, ABS_X, x);
        input_report_abs(ts->input, ABS_Y, y);
        input_report_abs(ts->input, ABS_PRESSURE, pressure);
        input_report_key(ts->input, BTN_TOUCH, !!pressure);
    } else {
        input_report_abs(ts->input, ABS_PRESSURE, 0);
        input_report_key(ts->input, BTN_TOUCH, 0);
    }

    input_sync(ts->input);
}
Exemple #7
0
static void ts_update_pen_state(struct ts *ts, int x, int y, int pressure)
{
    TSSC("{%d, %d}, pressure = %3d\n", x, y, pressure);
    if (pressure) {
        // Calibrate
        printk(KERN_ERR "X= {%d}", x);
	printk(KERN_ERR "Y= {%d}", y);
        printk(KERN_INFO "Input Values: {%d, %d},",
                 x, y);

        x = (x*msm_tscal_xscale + msm_tscal_xoffset + msm_tscal_scaler/2)/msm_tscal_scaler;
        y = (y*msm_tscal_yscale + msm_tscal_yoffset + msm_tscal_scaler/2)/msm_tscal_scaler;

	printk(KERN_ERR "=X= {%d}", x);
	printk(KERN_ERR "=Y= {%d}", y);

        printk(KERN_INFO "Return Values: {%d, %d},",
                 x, y);





//	x = (x*msm_tscal_xscale + msm_tscal_xoffset + 32768)/65536;
//      y = (y*msm_tscal_yscale + msm_tscal_yoffset + 32768)/65536;

        input_report_abs(ts->input, ABS_X, x);
        input_report_abs(ts->input, ABS_Y, y);
	printk(KERN_ERR "=ABS_X= {%d}", ABS_X);
	printk(KERN_ERR "=ABS_Y= {%d}", ABS_Y);
        input_report_abs(ts->input, ABS_PRESSURE, pressure);
        input_report_key(ts->input, BTN_TOUCH, !!pressure);
    } else {
        input_report_abs(ts->input, ABS_PRESSURE, 0);
        input_report_key(ts->input, BTN_TOUCH, 0);
    }

    input_sync(ts->input);
}
static irqreturn_t ts_interrupt(int irq, void *dev_id)
{
    u32 avgs, x, y, lx, ly;
    u32 num_op, num_samp;
    u32 status;

    struct ts *ts = dev_id;

    status = readl(TSSC_REG(STATUS));
    avgs = readl(TSSC_REG(AVG12));
    x = avgs & 0xFFFF;
    y = avgs >> 16;

    ts->pen_up_count = 0;
    TSSC("ts_interrupt: status=0x%x, avgs=0x%x\n", status, avgs);
    /* For pen down make sure that the data just read is still valid.
     * The DATA bit will still be set if the ARM9 hasn't clobbered
     * the TSSC. If it's not set, then it doesn't need to be cleared
     * here, so just return.
     */
    if (!(readl(TSSC_REG(CTL)) & TSSC_CTL_DATA))
        goto out;

    /* Data has been read, OK to clear the data flag */
    //writel(TSSC_CTL_STATE, TSSC_REG(CTL));

    /* Valid samples are indicated by the sample number in the status
     * register being the number of expected samples and the number of
     * samples collected being zero (this check is due to ADC contention).
     */
    num_op = (status & TSSC_STS_OPN_BMSK) >> TSSC_STS_OPN_SHIFT;
    num_samp = (status & TSSC_STS_NUMSAMP_BMSK) >> TSSC_STS_NUMSAMP_SHFT;

    if ((num_op == TSSC_NUMBER_OF_OPERATIONS) && (num_samp == 0)) {
        /* TSSC can do Z axis measurment, but driver doesn't support
         * this yet.
         */
         
        /*
         * REMOVE THIS:
         * These x, y co-ordinates adjustments will be removed once
         * Android framework adds calibration framework.
         */
#ifdef CONFIG_ANDROID_TOUCHSCREEN_MSM_HACKS
        lx = ts->x_max - x;
        ly = ts->y_max - y;
#else
        lx = x;
        ly = y;
#endif

        TSSC("%s: x=%d, y=%d\n", __FUNCTION__, lx, ly);
        
        /*get rid of some wrong point*/
        if((lx == 0) || (lx == X_MAX) || (ly == 0) || (ly == Y_MAX))
        {
            TSSC("ts_outscale: x=%d, y=%d\n", lx, ly);
        }
        else
        {
            if(ts->is_first_point)
            {     
                ts->last_x = ts->save_x = lx;
                ts->last_y = ts->save_y = ly;
                ts->move_fast = false;
                ts->is_first_point = false; 
                if(ts->use_touch_key)
                {
#ifdef CONFIG_HUAWEI_TOUCHSCREEN_EXTRA_KEY
                    update_pen_and_key_state(ts, lx, ly, 255);
#else
                    ts_update_pen_state(ts, lx, ly, 255);
#endif
                }
                else
                {
                    ts_update_pen_state(ts, lx, ly, 255);
                }
            }
            else
            {
                if(((max(ts->last_x, lx)-min(ts->last_x, lx)) > TOUCH_OFFSET)
                    || ((max(ts->last_y, ly)-min(ts->last_y, ly)) > TOUCH_OFFSET) )
                {
                    ts->last_x = lx;
                    ts->last_y = ly;

                    if(sqr((int)ts->last_y - (int)ts->save_y) > 60)
                    {
                        ts->move_fast = true;
                    }
                    else
                    {
                        ts->move_fast = false;
                    }
                    ts->save_y = ly;
                    ts->save_x = lx;
                    
                    if(ts->use_touch_key)
                    {
#ifdef CONFIG_HUAWEI_TOUCHSCREEN_EXTRA_KEY
                        update_pen_and_key_state(ts, lx, ly, 255);
#else
                        ts_update_pen_state(ts, lx, ly, 255);
#endif
                    }
                    else
                    {
                        ts_update_pen_state(ts, lx, ly, 255);
                    }
                }
            }
        }
        //ts_update_pen_state(ts, lx, ly, 255);
        /* kick pen up timer - to make sure it expires again(!) */
        mod_timer(&ts->timer,
            jiffies + msecs_to_jiffies(TS_PENUP_TIMEOUT_MS));

    } else
        printk(KERN_INFO "Ignored interrupt: {%3d, %3d},"
                " op = %3d samp = %3d\n",
                 x, y, num_op, num_samp);

out:
    return IRQ_HANDLED;
}
/*===========================================================================
FUNCTION      update_pen_and_key_state
DESCRIPTION:  
              上报touch的坐标值或按键键值
DEPENDENCIES
  None
RETURN VALUE
  None
SIDE EFFECTS
  None
===========================================================================*/
static void update_pen_and_key_state(struct ts *ts, int x, int y, int pressure)
{
    u32  key_tmp = KEY_RESERVED;
    
    if(pressure)  /*press*/
    {
        if(is_in_extra_region(ts->last_x, ts->last_y))
        {
            /* 如果记录键值还没有释放,则返回 */
            if ((FALSE == record_extra_keycode.bRelease && KEY_RESERVED != record_extra_keycode.record_extra_key)
                || true == record_extra_keycode.touch_region_first )
            {
                if((ts->move_fast)&&(record_extra_keycode.touch_region_first == false))
                {
                     /* start timer */
                     TSSC("move fast, reset mod_key_timer. \n");
                     mod_timer(&ts->key_timer,
                        jiffies + msecs_to_jiffies(TS_KEY_DEBOUNCE_TIMER_MS));
                }
                return;
            }

            key_tmp = touch_get_extra_keycode(x, y) ;

            if (KEY_RESERVED != key_tmp)
            {
                record_extra_keycode.record_extra_key = key_tmp;
                record_extra_keycode.bRelease = FALSE;
                record_extra_keycode.bSentPress = FALSE;

                /* start timer */
                mod_timer(&ts->key_timer,
                    jiffies + msecs_to_jiffies(TS_KEY_DEBOUNCE_TIMER_MS));
            }
        }
        else
        {
            record_extra_keycode.touch_region_first = true;

            if (KEY_RESERVED != record_extra_keycode.record_extra_key 
                && FALSE == record_extra_keycode.bRelease
                && TRUE == record_extra_keycode.bSentPress)
            {
                /*当上报了键值后再进入touch区时,要上报release键*/
                record_extra_keycode.bRelease = TRUE;
                touch_pass_extra_keycode(ts);
                
                record_extra_keycode.bRelease = FALSE;
                record_extra_keycode.record_extra_key = KEY_RESERVED;
                record_extra_keycode.bSentPress= FALSE;
            }
            ts_update_pen_state(ts, x, y, pressure);
        }
    }
    else /*release*/
    {
        
        if(is_in_extra_region(ts->last_x, ts->last_y))
        {
            del_timer(&ts->key_timer);
            if (KEY_RESERVED != record_extra_keycode.record_extra_key 
                && FALSE == record_extra_keycode.bRelease
                && TRUE == record_extra_keycode.bSentPress)
            {
                record_extra_keycode.bRelease = TRUE;
                touch_pass_extra_keycode(ts);
            }
            else
            {
                /* up 按键不可丢弃*/
                ts_update_pen_state(ts, x, y, pressure);
            }

            record_extra_keycode.bRelease = FALSE;
            record_extra_keycode.record_extra_key = KEY_RESERVED;
            record_extra_keycode.bSentPress= FALSE;
        }
        else
        {
            ts_update_pen_state(ts, x, y, pressure);
        }

        record_extra_keycode.touch_region_first = false;
    }
}