/*=========================================================================== 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); }
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; } }