History

HID: input: accommodate priorities for slotted devices

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.

Benjamin Tissoires committed 4 years ago

Commit 5c200001 parent 87562fc2 files · +96 −8Browse files

Unified · Split

2 files
  1. drivers/hid/hid-input.c +95 −8
  2. include/linux/hid.h +1 −0
drivers/hid/hid-input.c+95−8
@@ -48,6 +48,16 @@ static const struct { · 47 unmodified lines
4848 __s32 y;
4949 } hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
5050
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+
5161 /*
5262 * hid-input will convert this list into priorities:
5363 * the first element will have the highest priority
@@ -57,17 +67,30 @@ static const struct { · 3 unmodified lines
5767 * hid-input will then shift the priority by 8 bits to leave some space
5868 * in case drivers want to interleave other fields.
5969 *
70+ * To accommodate slotted devices, the slot priority is
71+ * defined in the next 8 bits (defined by 0xff - slot).
72+ *
6073 * If drivers want to add fields before those, hid-input will
6174 * leave out the first 8 bits of the priority value.
6275 *
6376 * This still leaves us 65535 individual priority values.
6477 */
65−static const __u32 hidinput_usages_priorities[] = {
66− HID_DG_ERASER, /* Eraser (eraser touching) must always come before tipswitch */
67− HID_DG_INVERT, /* Invert must always come before In Range */
68− HID_DG_TIPSWITCH, /* Is the tip of the tool touching? */
69− HID_DG_TIPPRESSURE, /* Tip Pressure might emulate tip switch */
70− HID_DG_INRANGE, /* In Range needs to come after the other tool states */
78+static const struct usage_priority hidinput_usages_priorities[] = {
79+ { /* Eraser (eraser touching) must always come before tipswitch */
80+ .usage = HID_DG_ERASER,
81+ },
82+ { /* Invert must always come before In Range */
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+ },
7194 };
7295
7396 #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
612635 {
613636 struct input_dev *input = hidinput->input;
614637 struct hid_device *device = input_get_drvdata(input);
638+ const struct usage_priority *usage_priority = NULL;
615639 int max = 0, code;
616640 unsigned int i = 0;
617641 unsigned long *bit = NULL;
@@ -633,13 +657,26 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel · 15 unmodified lines
633657
634658 /* assign a priority based on the static list declared here */
635659 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+
637663 field->usages_priorities[usage_index] =
638664 (ARRAY_SIZE(hidinput_usages_priorities) - i) << 8;
639665 break;
640666 }
641667 }
642668
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+
643680 if (device->driver->input_mapping) {
644681 int ret = device->driver->input_mapping(device, hidinput, field,
645682 usage, &bit, &max);
@@ -2068,7 +2105,57 @@ static struct hid_input *hidinput_match_application(struct hid_report *report) · 1422 unmodified lines
20682105 static inline void hidinput_configure_usages(struct hid_input *hidinput,
20692106 struct hid_report *report)
20702107 {
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+ }
20722159
20732160 for (i = 0; i < report->maxfield; i++)
20742161 for (j = 0; j < report->field[i]->maxusage; j++)
include/linux/hid.h+1−0
@@ -492,6 +492,7 @@ struct hid_field { · 491 unmodified lines
492492 /* hidinput data */
493493 struct hid_input *hidinput; /* associated input structure */
494494 __u16 dpad; /* dpad input code */
495+ unsigned int slot_idx; /* slot index in a report */
495496 };
496497
497498 #define HID_MAX_FIELDS 256

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t