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
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
51struct 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 priority63 * 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 space67 * 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 will73 * 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 */
65static const __u32 hidinput_usages_priorities[] = {78static 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
2068static inline void hidinput_configure_usages(struct hid_input *hidinput,2105static 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++)
include/linux/hid.h+1−0
@@ -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 256498#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