Multitouch devices in hybrid mode are reporting multiple times the same collection. We should accommodate for this in our handling of priorities by defining the slots they belong to.
Unified · Split
| @@ -48,6 +48,16 @@ static const struct { · 47 unmodified lines | |||
| 48 | __s32 y; | 48 | __s32 y; |
| 49 | } hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}}; | 49 | } hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}}; |
| 50 | 50 | ||
| 51 | struct usage_priority { | ||
| 52 | __u32 usage; /* the HID usage associated */ | ||
| 53 | bool global; /* we assume all usages to be slotted, | ||
| 54 | * unless global | ||
| 55 | */ | ||
| 56 | unsigned int slot_overwrite; /* for globals: allows to set the usage | ||
| 57 | * before or after the slots | ||
| 58 | */ | ||
| 59 | }; | ||
| 60 | |||
| 51 | /* | 61 | /* |
| 52 | * hid-input will convert this list into priorities: | 62 | * hid-input will convert this list into priorities: |
| 53 | * the first element will have the highest priority | 63 | * the first element will have the highest priority |
| @@ -57,17 +67,30 @@ static const struct { · 3 unmodified lines | |||
| 57 | * hid-input will then shift the priority by 8 bits to leave some space | 67 | * hid-input will then shift the priority by 8 bits to leave some space |
| 58 | * in case drivers want to interleave other fields. | 68 | * in case drivers want to interleave other fields. |
| 59 | * | 69 | * |
| 70 | * To accommodate slotted devices, the slot priority is | ||
| 71 | * defined in the next 8 bits (defined by 0xff - slot). | ||
| 72 | * | ||
| 60 | * If drivers want to add fields before those, hid-input will | 73 | * If drivers want to add fields before those, hid-input will |
| 61 | * leave out the first 8 bits of the priority value. | 74 | * leave out the first 8 bits of the priority value. |
| 62 | * | 75 | * |
| 63 | * This still leaves us 65535 individual priority values. | 76 | * This still leaves us 65535 individual priority values. |
| 64 | */ | 77 | */ |
| 65 | static const __u32 hidinput_usages_priorities[] = { | 78 | static const struct usage_priority hidinput_usages_priorities[] = { |
| 66 | HID_DG_ERASER, /* Eraser (eraser touching) must always come before tipswitch */ | 79 | { /* Eraser (eraser touching) must always come before tipswitch */ |
| 67 | HID_DG_INVERT, /* Invert must always come before In Range */ | 80 | .usage = HID_DG_ERASER, |
| 68 | HID_DG_TIPSWITCH, /* Is the tip of the tool touching? */ | 81 | }, |
| 69 | HID_DG_TIPPRESSURE, /* Tip Pressure might emulate tip switch */ | 82 | { /* Invert must always come before In Range */ |
| 70 | HID_DG_INRANGE, /* In Range needs to come after the other tool states */ | 83 | .usage = HID_DG_INVERT, |
| 84 | }, | ||
| 85 | { /* Is the tip of the tool touching? */ | ||
| 86 | .usage = HID_DG_TIPSWITCH, | ||
| 87 | }, | ||
| 88 | { /* Tip Pressure might emulate tip switch */ | ||
| 89 | .usage = HID_DG_TIPPRESSURE, | ||
| 90 | }, | ||
| 91 | { /* In Range needs to come after the other tool states */ | ||
| 92 | .usage = HID_DG_INRANGE, | ||
| 93 | }, | ||
| 71 | }; | 94 | }; |
| 72 | 95 | ||
| 73 | #define map_abs(c) hid_map_usage(hidinput, usage, &bit, &max, EV_ABS, (c)) | 96 | #define map_abs(c) hid_map_usage(hidinput, usage, &bit, &max, EV_ABS, (c)) |
| @@ -612,6 +635,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel · 538 unmodified lines | |||
| 612 | { | 635 | { |
| 613 | struct input_dev *input = hidinput->input; | 636 | struct input_dev *input = hidinput->input; |
| 614 | struct hid_device *device = input_get_drvdata(input); | 637 | struct hid_device *device = input_get_drvdata(input); |
| 638 | const struct usage_priority *usage_priority = NULL; | ||
| 615 | int max = 0, code; | 639 | int max = 0, code; |
| 616 | unsigned int i = 0; | 640 | unsigned int i = 0; |
| 617 | unsigned long *bit = NULL; | 641 | unsigned long *bit = NULL; |
| @@ -633,13 +657,26 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel · 15 unmodified lines | |||
| 633 | 657 | ||
| 634 | /* assign a priority based on the static list declared here */ | 658 | /* assign a priority based on the static list declared here */ |
| 635 | for (i = 0; i < ARRAY_SIZE(hidinput_usages_priorities); i++) { | 659 | for (i = 0; i < ARRAY_SIZE(hidinput_usages_priorities); i++) { |
| 636 | if (usage->hid == hidinput_usages_priorities[i]) { | 660 | if (usage->hid == hidinput_usages_priorities[i].usage) { |
| 661 | usage_priority = &hidinput_usages_priorities[i]; | ||
| 662 | |||
| 637 | field->usages_priorities[usage_index] = | 663 | field->usages_priorities[usage_index] = |
| 638 | (ARRAY_SIZE(hidinput_usages_priorities) - i) << 8; | 664 | (ARRAY_SIZE(hidinput_usages_priorities) - i) << 8; |
| 639 | break; | 665 | break; |
| 640 | } | 666 | } |
| 641 | } | 667 | } |
| 642 | 668 | ||
| 669 | /* | ||
| 670 | * For slotted devices, we need to also add the slot index | ||
| 671 | * in the priority. | ||
| 672 | */ | ||
| 673 | if (usage_priority && usage_priority->global) | ||
| 674 | field->usages_priorities[usage_index] |= | ||
| 675 | usage_priority->slot_overwrite; | ||
| 676 | else | ||
| 677 | field->usages_priorities[usage_index] |= | ||
| 678 | (0xff - field->slot_idx) << 16; | ||
| 679 | |||
| 643 | if (device->driver->input_mapping) { | 680 | if (device->driver->input_mapping) { |
| 644 | int ret = device->driver->input_mapping(device, hidinput, field, | 681 | int ret = device->driver->input_mapping(device, hidinput, field, |
| 645 | usage, &bit, &max); | 682 | usage, &bit, &max); |
| @@ -2068,7 +2105,57 @@ static struct hid_input *hidinput_match_application(struct hid_report *report) · 1422 unmodified lines | |||
| 2068 | static inline void hidinput_configure_usages(struct hid_input *hidinput, | 2105 | static inline void hidinput_configure_usages(struct hid_input *hidinput, |
| 2069 | struct hid_report *report) | 2106 | struct hid_report *report) |
| 2070 | { | 2107 | { |
| 2071 | int i, j; | 2108 | int i, j, k; |
| 2109 | int first_field_index = 0; | ||
| 2110 | int slot_collection_index = -1; | ||
| 2111 | int prev_collection_index = -1; | ||
| 2112 | unsigned int slot_idx = 0; | ||
| 2113 | struct hid_field *field; | ||
| 2114 | |||
| 2115 | /* | ||
| 2116 | * First tag all the fields that are part of a slot, | ||
| 2117 | * a slot needs to have one Contact ID in the collection | ||
| 2118 | */ | ||
| 2119 | for (i = 0; i < report->maxfield; i++) { | ||
| 2120 | field = report->field[i]; | ||
| 2121 | |||
| 2122 | /* ignore fields without usage */ | ||
| 2123 | if (field->maxusage < 1) | ||
| 2124 | continue; | ||
| 2125 | |||
| 2126 | /* | ||
| 2127 | * janitoring when collection_index changes | ||
| 2128 | */ | ||
| 2129 | if (prev_collection_index != field->usage->collection_index) { | ||
| 2130 | prev_collection_index = field->usage->collection_index; | ||
| 2131 | first_field_index = i; | ||
| 2132 | } | ||
| 2133 | |||
| 2134 | /* | ||
| 2135 | * if we already found a Contact ID in the collection, | ||
| 2136 | * tag and continue to the next. | ||
| 2137 | */ | ||
| 2138 | if (slot_collection_index == field->usage->collection_index) { | ||
| 2139 | field->slot_idx = slot_idx; | ||
| 2140 | continue; | ||
| 2141 | } | ||
| 2142 | |||
| 2143 | /* check if the current field has Contact ID */ | ||
| 2144 | for (j = 0; j < field->maxusage; j++) { | ||
| 2145 | if (field->usage[j].hid == HID_DG_CONTACTID) { | ||
| 2146 | slot_collection_index = field->usage->collection_index; | ||
| 2147 | slot_idx++; | ||
| 2148 | |||
| 2149 | /* | ||
| 2150 | * mark all previous fields and this one in the | ||
| 2151 | * current collection to be slotted. | ||
| 2152 | */ | ||
| 2153 | for (k = first_field_index; k <= i; k++) | ||
| 2154 | report->field[k]->slot_idx = slot_idx; | ||
| 2155 | break; | ||
| 2156 | } | ||
| 2157 | } | ||
| 2158 | } | ||
| 2072 | 2159 | ||
| 2073 | for (i = 0; i < report->maxfield; i++) | 2160 | for (i = 0; i < report->maxfield; i++) |
| 2074 | for (j = 0; j < report->field[i]->maxusage; j++) | 2161 | for (j = 0; j < report->field[i]->maxusage; j++) |
| @@ -492,6 +492,7 @@ struct hid_field { · 491 unmodified lines | |||
| 492 | /* hidinput data */ | 492 | /* hidinput data */ |
| 493 | struct hid_input *hidinput; /* associated input structure */ | 493 | struct hid_input *hidinput; /* associated input structure */ |
| 494 | __u16 dpad; /* dpad input code */ | 494 | __u16 dpad; /* dpad input code */ |
| 495 | unsigned int slot_idx; /* slot index in a report */ | ||
| 495 | }; | 496 | }; |
| 496 | 497 | ||
| 497 | #define HID_MAX_FIELDS 256 | 498 | #define HID_MAX_FIELDS 256 |