summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Gerecke <killertofu@gmail.com>2015-07-21 21:07:24 +0300
committerJiri Kosina <jkosina@suse.com>2015-07-23 15:02:44 +0300
commit1b5d514a3d24996ddbe7c75685af9dfdeff125b5 (patch)
tree65d61caa2b70ca02e261cbb665f715f20507e67b
parent06324e0cb28e06cd7cf609d7c3099b12841a5dd6 (diff)
downloadlinux-1b5d514a3d24996ddbe7c75685af9dfdeff125b5.tar.xz
HID: wacom: Ignore contacts in excess of declared contact count
The reports sent from some touch devices (e.g. the Cintiq 24HDT) contain junk data in the contact slots which follow the final "valid" contact. To avoid forwarding it to usrspace, we store the reported contact count during the pre-process phase and then only process that many contacts. If a device sends its contacts across multiple reports (what Microsoft refers to as "hybrid" mode) then the contact count will be zero for reports other than the first. Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com> Signed-off-by: Jiri Kosina <jkosina@suse.com>
-rw-r--r--drivers/hid/wacom_wac.c30
-rw-r--r--drivers/hid/wacom_wac.h4
2 files changed, 33 insertions, 1 deletions
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 1d9d5d1d800d..09fe5d604c97 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1510,6 +1510,10 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
features->last_slot_field = usage->hid;
wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0);
break;
+ case HID_DG_CONTACTCOUNT:
+ wacom_wac->hid_data.cc_index = field->index;
+ wacom_wac->hid_data.cc_value_index = usage->usage_index;
+ break;
}
}
@@ -1521,6 +1525,10 @@ static void wacom_wac_finger_slot(struct wacom_wac *wacom_wac,
bool prox = hid_data->tipswitch &&
!wacom_wac->shared->stylus_in_proximity;
+ wacom_wac->hid_data.num_received++;
+ if (wacom_wac->hid_data.num_received > wacom_wac->hid_data.num_expected)
+ return;
+
if (mt) {
int slot;
@@ -1573,7 +1581,19 @@ static int wacom_wac_finger_event(struct hid_device *hdev,
static void wacom_wac_finger_pre_report(struct hid_device *hdev,
struct hid_report *report)
{
- return;
+ struct wacom *wacom = hid_get_drvdata(hdev);
+ struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+ struct hid_data* hid_data = &wacom_wac->hid_data;
+
+ if (hid_data->cc_index >= 0) {
+ struct hid_field *field = report->field[hid_data->cc_index];
+ int value = field->value[hid_data->cc_value_index];
+ if (value)
+ hid_data->num_expected = value;
+ }
+ else {
+ hid_data->num_expected = wacom_wac->features.touch_max;
+ }
}
static void wacom_wac_finger_report(struct hid_device *hdev,
@@ -1584,10 +1604,18 @@ static void wacom_wac_finger_report(struct hid_device *hdev,
struct input_dev *input = wacom_wac->touch_input;
unsigned touch_max = wacom_wac->features.touch_max;
+ /* If more packets of data are expected, give us a chance to
+ * process them rather than immediately syncing a partial
+ * update.
+ */
+ if (wacom_wac->hid_data.num_received < wacom_wac->hid_data.num_expected)
+ return;
+
if (touch_max > 1)
input_mt_sync_frame(input);
input_sync(input);
+ wacom_wac->hid_data.num_received = 0;
/* keep touch state for pen event */
wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(wacom_wac);
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 2978c303909d..c245a6628224 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -193,6 +193,10 @@ struct hid_data {
int width;
int height;
int id;
+ int cc_index;
+ int cc_value_index;
+ int num_expected;
+ int num_received;
};
struct wacom_wac {