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@xxxxxxxxx> --- drivers/hid/wacom_wac.c | 79 ++++++++++++++++++++++++++++++++--------- 1 file 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); /* -- 2.17.1