From 1e9ee2c39d4f6887c2a8fc2641410a744d55ad03 Mon Sep 17 00:00:00 2001 From: Yufeng Shen Date: Tue, 9 Oct 2012 16:51:52 -0400 Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - release all fingers on resume Currently lid close/open can generate noise touch events on system suspend and resume. One case is that touch down is generated before suspend, and touch liftoff is processed on resume. The driver will discard any pending messages on resume which might make the system enter ghost finger state (touch down without ever liftoff). To workaround the ghost finger case, this patch forces release of all possible fingers on resume. And to avoid the unwanted click resulted from the forced release, move these fingers first to (0,0) and assign them with maximal PRESSURE and TOUCH_MAJOR value so to make them look like palms. Signed-off-by: Yufeng Shen BUG=chromium:154383 TEST=use evtest to monitor the touch device; put fingers on the touch device; close the lid; remove fingers after making sure the system enters suspend; Open the lid; Make sure to see finger move events with pressue and touch_major = 255 and the release events. Change-Id: Ic9f0659a2e731c2db03255eb2107be88b333541a Reviewed-on: https://gerrit.chromium.org/gerrit/35046 Reviewed-by: Daniel Kurtz Commit-Ready: Yufeng Shen Tested-by: Yufeng Shen --- drivers/input/touchscreen/atmel_mxt_ts.c | 47 ++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 44c3a28ca4a2..b5adc1f2f7e8 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -366,6 +366,9 @@ struct mxt_data { /* config file name */ char *config_file; + + /* map for the tracking id currently being used */ + bool current_id[MXT_MAX_FINGER]; }; /* global root node of the atmel_mxt_ts debugfs directory. */ @@ -458,6 +461,47 @@ static void mxt_dump_message(struct device *dev, message->message[5], message->message[6]); } +/* + * Release all the fingers that are being tracked. To avoid unwanted gestures, + * move all the fingers to (0,0) with largest PRESSURE and TOUCH_MAJOR. + * Userspace apps can use these info to filter out these events and/or cancel + * existing gestures. + */ +static void mxt_release_all_fingers(struct mxt_data *data) +{ + struct device *dev = &data->client->dev; + struct input_dev *input_dev = data->input_dev; + int id; + bool need_update = false; + for (id = 0; id < MXT_MAX_FINGER; id++) { + if (data->current_id[id]) { + dev_warn(dev, "Move touch %d to (0,0)\n", id); + input_mt_slot(input_dev, id); + input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, + true); + input_report_abs(input_dev, ABS_MT_POSITION_X, 0); + input_report_abs(input_dev, ABS_MT_POSITION_Y, 0); + input_report_abs(input_dev, ABS_MT_PRESSURE, 255); + input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, 255); + need_update = true; + } + } + if (need_update) + input_sync(data->input_dev); + + for (id = 0; id < MXT_MAX_FINGER; id++) { + if (data->current_id[id]) { + dev_warn(dev, "Release touch contact %d\n", id); + input_mt_slot(input_dev, id); + input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, + false); + data->current_id[id] = false; + } + } + if (need_update) + input_sync(data->input_dev); +} + static int mxt_wait_for_chg(struct mxt_data *data, unsigned int timeout_ms) { struct device *dev = &data->client->dev; @@ -771,6 +815,7 @@ static void mxt_input_touch(struct mxt_data *data, struct mxt_message *message) input_mt_slot(input_dev, id); input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, status & MXT_DETECT); + data->current_id[id] = status & MXT_DETECT; if (status & MXT_DETECT) { input_report_abs(input_dev, ABS_MT_POSITION_X, x); @@ -2688,6 +2733,8 @@ static int mxt_resume(struct device *dev) if (ret) dev_err(dev, "Handling message fails upon resume, %d\n", ret); + mxt_release_all_fingers(data); + mutex_lock(&input_dev->mutex); enable_irq(data->irq); -- 2.20.1