Input: elants_i2c - support palm detection
authorJohnny Chuang <johnny.chuang@emc.com.tw>
Thu, 9 Apr 2020 19:42:42 +0000 (12:42 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Wed, 15 Apr 2020 04:28:34 +0000 (21:28 -0700)
Elan uses the least significant bit of byte 33 to signal the type of
contact (finger versus palm). The default value is 1 for all firmwares,
which is reported as MT_TOOL_FINGER. If firmware supports palm detection,
the bit will change to 0 and the driver will report such contact as
MT_TOOL_PALM.

Signed-off-by: Johnny Chuang <johnny.chuang@emc.com.tw>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Link: https://lore.kernel.org/r/1585551756-29066-1-git-send-email-johnny.chuang.emc@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
drivers/input/touchscreen/elants_i2c.c

index 14c577c..2289f96 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 
+#include <linux/bits.h>
 #include <linux/module.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
@@ -73,6 +74,7 @@
 #define FW_POS_STATE           1
 #define FW_POS_TOTAL           2
 #define FW_POS_XY              3
+#define FW_POS_TOOL_TYPE       33
 #define FW_POS_CHECKSUM                34
 #define FW_POS_WIDTH           35
 #define FW_POS_PRESSURE                45
@@ -842,6 +844,7 @@ static void elants_i2c_mt_event(struct elants_data *ts, u8 *buf)
 {
        struct input_dev *input = ts->input;
        unsigned int n_fingers;
+       unsigned int tool_type;
        u16 finger_state;
        int i;
 
@@ -852,6 +855,10 @@ static void elants_i2c_mt_event(struct elants_data *ts, u8 *buf)
        dev_dbg(&ts->client->dev,
                "n_fingers: %u, state: %04x\n",  n_fingers, finger_state);
 
+       /* Note: all fingers have the same tool type */
+       tool_type = buf[FW_POS_TOOL_TYPE] & BIT(0) ?
+                       MT_TOOL_FINGER : MT_TOOL_PALM;
+
        for (i = 0; i < MAX_CONTACT_NUM && n_fingers; i++) {
                if (finger_state & 1) {
                        unsigned int x, y, p, w;
@@ -867,7 +874,7 @@ static void elants_i2c_mt_event(struct elants_data *ts, u8 *buf)
                                i, x, y, p, w);
 
                        input_mt_slot(input, i);
-                       input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
+                       input_mt_report_slot_state(input, tool_type, true);
                        input_event(input, EV_ABS, ABS_MT_POSITION_X, x);
                        input_event(input, EV_ABS, ABS_MT_POSITION_Y, y);
                        input_event(input, EV_ABS, ABS_MT_PRESSURE, p);
@@ -1307,6 +1314,8 @@ static int elants_i2c_probe(struct i2c_client *client,
        input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, ts->y_max, 0, 0);
        input_set_abs_params(ts->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
        input_set_abs_params(ts->input, ABS_MT_PRESSURE, 0, 255, 0, 0);
+       input_set_abs_params(ts->input, ABS_MT_TOOL_TYPE,
+                            0, MT_TOOL_PALM, 0, 0);
        input_abs_set_res(ts->input, ABS_MT_POSITION_X, ts->x_res);
        input_abs_set_res(ts->input, ABS_MT_POSITION_Y, ts->y_res);
        input_abs_set_res(ts->input, ABS_MT_TOUCH_MAJOR, 1);