summaryrefslogtreecommitdiff
path: root/drivers/hid
diff options
context:
space:
mode:
authorAaron Armstrong Skomra <skomra@gmail.com>2019-06-12 14:19:31 -0700
committerJiri Kosina <jkosina@suse.cz>2019-06-13 16:48:50 +0200
commit15893fa40109f5e7c67eeb8da62267d0fdf0be9d (patch)
tree8d386f7e848dce1cd6dcb69fc604dce98eefda71 /drivers/hid
parentf4e11d599610a61e978f722f6ade660872a43816 (diff)
HID: wacom: generic: read the number of expected touches on a per collection basis
Bluetooth connections may contain more than one set of touches, or a partial set of touches, in one report. Set the number of expected touches when reading a collection instead of once per report (in the pre-report function). Accordingly, reset the number of touches expected after each sync. Signed-off-by: Aaron Armstrong Skomra <aaron.skomra@wacom.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/wacom_wac.c79
1 files changed, 63 insertions, 16 deletions
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 67ecd149ad21..104e6d1f4c80 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2563,25 +2563,9 @@ static void wacom_wac_finger_pre_report(struct hid_device *hdev,
case HID_DG_TIPSWITCH:
hid_data->last_slot_field = equivalent_usage;
break;
- case HID_DG_CONTACTCOUNT:
- hid_data->cc_report = report->id;
- hid_data->cc_index = i;
- hid_data->cc_value_index = j;
- break;
}
}
}
-
- if (hid_data->cc_report != 0 &&
- 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,
@@ -2591,6 +2575,7 @@ static void wacom_wac_finger_report(struct hid_device *hdev,
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
struct input_dev *input = wacom_wac->touch_input;
unsigned touch_max = wacom_wac->features.touch_max;
+ struct hid_data *hid_data = &wacom_wac->hid_data;
/* If more packets of data are expected, give us a chance to
* process them rather than immediately syncing a partial
@@ -2604,6 +2589,7 @@ static void wacom_wac_finger_report(struct hid_device *hdev,
input_sync(input);
wacom_wac->hid_data.num_received = 0;
+ hid_data->num_expected = 0;
/* keep touch state for pen event */
wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(wacom_wac);
@@ -2678,12 +2664,73 @@ static void wacom_report_events(struct hid_device *hdev,
}
}
+static void wacom_set_num_expected(struct hid_device *hdev,
+ struct hid_report *report,
+ int collection_index,
+ struct hid_field *field,
+ int field_index)
+{
+ struct wacom *wacom = hid_get_drvdata(hdev);
+ struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+ struct hid_data *hid_data = &wacom_wac->hid_data;
+ unsigned int original_collection_level =
+ hdev->collection[collection_index].level;
+ bool end_collection = false;
+ int i;
+
+ if (hid_data->num_expected)
+ return;
+
+ // find the contact count value for this segment
+ for (i = field_index; i < report->maxfield && !end_collection; i++) {
+ struct hid_field *field = report->field[i];
+ unsigned int field_level =
+ hdev->collection[field->usage[0].collection_index].level;
+ unsigned int j;
+
+ if (field_level != original_collection_level)
+ continue;
+
+ for (j = 0; j < field->maxusage; j++) {
+ struct hid_usage *usage = &field->usage[j];
+
+ if (usage->collection_index != collection_index) {
+ end_collection = true;
+ break;
+ }
+ if (wacom_equivalent_usage(usage->hid) == HID_DG_CONTACTCOUNT) {
+ hid_data->cc_report = report->id;
+ hid_data->cc_index = i;
+ hid_data->cc_value_index = j;
+
+ if (hid_data->cc_report != 0 &&
+ 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;
+ }
+ }
+ }
+ }
+
+ if (hid_data->cc_report == 0 || hid_data->cc_index < 0)
+ hid_data->num_expected = wacom_wac->features.touch_max;
+}
+
static int wacom_wac_collection(struct hid_device *hdev, struct hid_report *report,
int collection_index, struct hid_field *field,
int field_index)
{
struct wacom *wacom = hid_get_drvdata(hdev);
+ if (WACOM_FINGER_FIELD(field))
+ wacom_set_num_expected(hdev, report, collection_index, field,
+ field_index);
wacom_report_events(hdev, report, collection_index, field_index);
/*