OSDN Git Service

HID: wacom: generic: read the number of expected touches on a per collection basis
authorAaron Armstrong Skomra <skomra@gmail.com>
Wed, 12 Jun 2019 21:19:31 +0000 (14:19 -0700)
committerJiri Kosina <jkosina@suse.cz>
Thu, 13 Jun 2019 14:48:50 +0000 (16:48 +0200)
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>
drivers/hid/wacom_wac.c

index 67ecd14..104e6d1 100644 (file)
@@ -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);
 
        /*