Input: elants_i2c - support palm detection
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>
This commit is contained in:
committed by
Dmitry Torokhov
parent
cd510679f4
commit
f27ad89327
@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <linux/bits.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
@ -73,6 +74,7 @@
|
|||||||
#define FW_POS_STATE 1
|
#define FW_POS_STATE 1
|
||||||
#define FW_POS_TOTAL 2
|
#define FW_POS_TOTAL 2
|
||||||
#define FW_POS_XY 3
|
#define FW_POS_XY 3
|
||||||
|
#define FW_POS_TOOL_TYPE 33
|
||||||
#define FW_POS_CHECKSUM 34
|
#define FW_POS_CHECKSUM 34
|
||||||
#define FW_POS_WIDTH 35
|
#define FW_POS_WIDTH 35
|
||||||
#define FW_POS_PRESSURE 45
|
#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;
|
struct input_dev *input = ts->input;
|
||||||
unsigned int n_fingers;
|
unsigned int n_fingers;
|
||||||
|
unsigned int tool_type;
|
||||||
u16 finger_state;
|
u16 finger_state;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -852,6 +855,10 @@ static void elants_i2c_mt_event(struct elants_data *ts, u8 *buf)
|
|||||||
dev_dbg(&ts->client->dev,
|
dev_dbg(&ts->client->dev,
|
||||||
"n_fingers: %u, state: %04x\n", n_fingers, finger_state);
|
"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++) {
|
for (i = 0; i < MAX_CONTACT_NUM && n_fingers; i++) {
|
||||||
if (finger_state & 1) {
|
if (finger_state & 1) {
|
||||||
unsigned int x, y, p, w;
|
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);
|
i, x, y, p, w);
|
||||||
|
|
||||||
input_mt_slot(input, i);
|
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_X, x);
|
||||||
input_event(input, EV_ABS, ABS_MT_POSITION_Y, y);
|
input_event(input, EV_ABS, ABS_MT_POSITION_Y, y);
|
||||||
input_event(input, EV_ABS, ABS_MT_PRESSURE, p);
|
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_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_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_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_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_POSITION_Y, ts->y_res);
|
||||||
input_abs_set_res(ts->input, ABS_MT_TOUCH_MAJOR, 1);
|
input_abs_set_res(ts->input, ABS_MT_TOUCH_MAJOR, 1);
|
||||||
|
Reference in New Issue
Block a user