Commit 28a042a3 authored by Dmitry Torokhov's avatar Dmitry Torokhov Committed by Jiri Kosina

HID: multitouch: handle palm for touchscreens

Usually, there is no palm rejection for touchscreens. You don't rest
your palm on the touchscreen while interacting with it.
However, some wacom devices do so because you can rest your palm while
interacting with the stylus.

Unfortunately, the spec for touchscreens[1] is less precise than the one
for touchpads[2]. This leads to a situation where it's 'legitimate'
for a touchscreen to provide both tipswitch off and confidence off in the
same report.

Work around that by keeping the slot active for one frame where we report
MT_TOOL_PALM, and then synthesizing the release event in a separate frame.
frame
Acked-by: default avatarPeter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
[rebased and new commit message]
Signed-off-by: default avatarBenjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent f9024374
...@@ -118,6 +118,9 @@ struct mt_application { ...@@ -118,6 +118,9 @@ struct mt_application {
int left_button_state; /* left button state */ int left_button_state; /* left button state */
unsigned int mt_flags; /* flags to pass to input-mt */ unsigned int mt_flags; /* flags to pass to input-mt */
unsigned long *pending_palm_slots; /* slots where we reported palm
* and need to release */
__u8 num_received; /* how many contacts we received */ __u8 num_received; /* how many contacts we received */
__u8 num_expected; /* expected last contact index */ __u8 num_expected; /* expected last contact index */
__u8 buttons_count; /* number of physical buttons per touchpad */ __u8 buttons_count; /* number of physical buttons per touchpad */
...@@ -863,6 +866,28 @@ static int mt_compute_slot(struct mt_device *td, struct mt_application *app, ...@@ -863,6 +866,28 @@ static int mt_compute_slot(struct mt_device *td, struct mt_application *app,
return input_mt_get_slot_by_key(input, *slot->contactid); return input_mt_get_slot_by_key(input, *slot->contactid);
} }
static void mt_release_pending_palms(struct mt_device *td,
struct mt_application *app,
struct input_dev *input)
{
int slotnum;
bool need_sync = false;
for_each_set_bit(slotnum, app->pending_palm_slots, td->maxcontacts) {
clear_bit(slotnum, app->pending_palm_slots);
input_mt_slot(input, slotnum);
input_mt_report_slot_state(input, MT_TOOL_PALM, false);
need_sync = true;
}
if (need_sync) {
input_mt_sync_frame(input);
input_sync(input);
}
}
/* /*
* this function is called when a whole packet has been received and processed, * this function is called when a whole packet has been received and processed,
* so that it can decide what to send to the input layer. * so that it can decide what to send to the input layer.
...@@ -876,6 +901,9 @@ static void mt_sync_frame(struct mt_device *td, struct mt_application *app, ...@@ -876,6 +901,9 @@ static void mt_sync_frame(struct mt_device *td, struct mt_application *app,
input_mt_sync_frame(input); input_mt_sync_frame(input);
input_event(input, EV_MSC, MSC_TIMESTAMP, app->timestamp); input_event(input, EV_MSC, MSC_TIMESTAMP, app->timestamp);
input_sync(input); input_sync(input);
mt_release_pending_palms(td, app, input);
app->num_received = 0; app->num_received = 0;
app->left_button_state = 0; app->left_button_state = 0;
...@@ -970,8 +998,23 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input, ...@@ -970,8 +998,23 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input,
if (app->application == HID_GD_SYSTEM_MULTIAXIS) if (app->application == HID_GD_SYSTEM_MULTIAXIS)
tool = MT_TOOL_DIAL; tool = MT_TOOL_DIAL;
else if (unlikely(!confidence_state)) else if (unlikely(!confidence_state)) {
tool = MT_TOOL_PALM; tool = MT_TOOL_PALM;
if (!active &&
input_mt_is_active(&mt->slots[slotnum])) {
/*
* The non-confidence was reported for
* previously valid contact that is also no
* longer valid. We can't simply report
* lift-off as userspace will not be aware
* of non-confidence, so we need to split
* it into 2 events: active MT_TOOL_PALM
* and a separate liftoff.
*/
active = true;
set_bit(slotnum, app->pending_palm_slots);
}
}
input_mt_slot(input, slotnum); input_mt_slot(input, slotnum);
input_mt_report_slot_state(input, tool, active); input_mt_report_slot_state(input, tool, active);
...@@ -1197,6 +1240,13 @@ static int mt_touch_input_configured(struct hid_device *hdev, ...@@ -1197,6 +1240,13 @@ static int mt_touch_input_configured(struct hid_device *hdev,
if (td->is_buttonpad) if (td->is_buttonpad)
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit); __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
app->pending_palm_slots = devm_kcalloc(&hi->input->dev,
BITS_TO_LONGS(td->maxcontacts),
sizeof(long),
GFP_KERNEL);
if (!app->pending_palm_slots)
return -ENOMEM;
ret = input_mt_init_slots(input, td->maxcontacts, app->mt_flags); ret = input_mt_init_slots(input, td->maxcontacts, app->mt_flags);
if (ret) if (ret)
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment