diff options
author | davidycchen <davidycchen@google.com> | 2022-02-25 16:12:12 +0800 |
---|---|---|
committer | davidycchen <davidycchen@google.com> | 2022-03-07 16:28:12 +0800 |
commit | ba43ce7e908a9f7f8c234d8cf4a0aa4d4a4f87fa (patch) | |
tree | 8ddd32eae1cf1d69c015eac728ac54abf89b4a87 /syna_tcm2.c | |
parent | c5e2ea3daf0732f625ab00711168d53e05cf426d (diff) | |
download | synaptics_touch-ba43ce7e908a9f7f8c234d8cf4a0aa4d4a4f87fa.tar.gz |
synaptics: support finger leaves event for UDFPS
Bug: 220992096
Test: LHBM is off right after finger leaves.
Signed-off-by: davidycchen <davidycchen@google.com>
Change-Id: Ibc4fda47f8c3faca57b03b8a675e271c8051baa9
Diffstat (limited to 'syna_tcm2.c')
-rw-r--r-- | syna_tcm2.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/syna_tcm2.c b/syna_tcm2.c index 07b558c..2ca7ce5 100644 --- a/syna_tcm2.c +++ b/syna_tcm2.c @@ -1752,6 +1752,97 @@ static int syna_pinctrl_configure(struct syna_tcm *tcm, bool enable) } /** + * Report a finger down event on the long press gesture area then immediately + * report a cancel event(MT_TOOL_PALM). + */ +static void syna_report_cancel_event(struct syna_tcm *tcm) +{ + LOGI("Report cancel event for UDFPS"); + + syna_pal_mutex_lock(&tcm->tp_event_mutex); + + /* Finger down on UDFPS area. */ + input_mt_slot(tcm->input_dev, 0); + input_report_key(tcm->input_dev, BTN_TOUCH, 1); + input_mt_report_slot_state(tcm->input_dev, MT_TOOL_FINGER, 1); + input_report_abs(tcm->input_dev, ABS_MT_POSITION_X, tcm->hw_if->udfps_x); + input_report_abs(tcm->input_dev, ABS_MT_POSITION_Y, tcm->hw_if->udfps_y); + input_report_abs(tcm->input_dev, ABS_MT_TOUCH_MAJOR, 200); + input_report_abs(tcm->input_dev, ABS_MT_TOUCH_MINOR, 200); +#ifndef SKIP_PRESSURE + input_report_abs(tcm->input_dev, ABS_MT_PRESSURE, 1); +#endif + input_report_abs(tcm->input_dev, ABS_MT_ORIENTATION, 0); + input_sync(tcm->input_dev); + + /* Report MT_TOOL_PALM for canceling the touch event. */ + input_mt_slot(tcm->input_dev, 0); + input_report_key(tcm->input_dev, BTN_TOUCH, 1); + input_mt_report_slot_state(tcm->input_dev, MT_TOOL_PALM, 1); + input_sync(tcm->input_dev); + + /* Release touches. */ + input_mt_slot(tcm->input_dev, 0); + input_report_abs(tcm->input_dev, ABS_MT_PRESSURE, 0); + input_mt_report_slot_state(tcm->input_dev, MT_TOOL_FINGER, 0); + input_report_abs(tcm->input_dev, ABS_MT_TRACKING_ID, -1); + input_report_key(tcm->input_dev, BTN_TOUCH, 0); + input_sync(tcm->input_dev); + + syna_pal_mutex_unlock(&tcm->tp_event_mutex); +} + +static void syna_check_finger_status(struct syna_tcm *tcm) +{ + int retval = 0; + unsigned char code = 0; + u16 touch_mode, x, y, major, minor; + struct syna_hw_attn_data *attn = &tcm->hw_if->bdata_attn; + ktime_t timeout = ktime_add_ms(ktime_get(), 500); + LOGI("Check finger status"); + + while (ktime_get() < timeout) { + /* Clear the FIFO if there is pending data. */ + if (gpio_get_value(attn->irq_gpio) == attn->irq_on_state) { + retval = tcm->tcm_dev->read_message(tcm->tcm_dev, &code); + continue; + } + + retval = syna_tcm_get_dynamic_config(tcm->tcm_dev, DC_TOUCH_SCAN_MODE, + &touch_mode, RESP_IN_POLLING); + if (retval < 0) + continue; + + if (touch_mode != SCAN_LPWG_IDLE && touch_mode != SCAN_LPWG_ACTIVE) + return; + + LOGI("Poll finger events."); + while (ktime_get() < timeout) { + msleep(30); + syna_tcm_get_event_data(tcm->tcm_dev, + &code, + &tcm->event_data); + if (code == REPORT_TOUCH) { + x = syna_pal_le2_to_uint(&tcm->event_data.buf[1]); + y = syna_pal_le2_to_uint(&tcm->event_data.buf[3]); + major = tcm->event_data.buf[4]; + minor = tcm->event_data.buf[5]; + /* Touch reports coordinates and major/minor 0 + * when the finger leaves. + */ + if (x==0 && y==0 && major==0 && minor==0) { + syna_report_cancel_event(tcm); + return; + } + } else if (code == STATUS_INVALID) { + syna_report_cancel_event(tcm); + return; + } + } + } +} + +/** * syna_dev_resume() * * Resume from the suspend state. @@ -1786,6 +1877,9 @@ static int syna_dev_resume(struct device *dev) syna_pinctrl_configure(tcm, true); + if (hw_if->udfps_x != 0 && hw_if->udfps_y != 0) + syna_check_finger_status(tcm); + #ifdef RESET_ON_RESUME LOGI("Do reset on resume\n"); |