提交 5c20000a 编写于 作者: B Benjamin Tissoires 提交者: Jiri Kosina

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.
Signed-off-by: NBenjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: NPing Cheng <ping.cheng@wacom.com>
Acked-by: NPeter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: NJiri Kosina <jkosina@suse.cz>
上级 87562fcd
...@@ -48,6 +48,16 @@ static const struct { ...@@ -48,6 +48,16 @@ static const struct {
__s32 y; __s32 y;
} hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}}; } hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
struct usage_priority {
__u32 usage; /* the HID usage associated */
bool global; /* we assume all usages to be slotted,
* unless global
*/
unsigned int slot_overwrite; /* for globals: allows to set the usage
* before or after the slots
*/
};
/* /*
* hid-input will convert this list into priorities: * hid-input will convert this list into priorities:
* the first element will have the highest priority * the first element will have the highest priority
...@@ -57,17 +67,30 @@ static const struct { ...@@ -57,17 +67,30 @@ static const struct {
* hid-input will then shift the priority by 8 bits to leave some space * hid-input will then shift the priority by 8 bits to leave some space
* in case drivers want to interleave other fields. * in case drivers want to interleave other fields.
* *
* To accommodate slotted devices, the slot priority is
* defined in the next 8 bits (defined by 0xff - slot).
*
* If drivers want to add fields before those, hid-input will * If drivers want to add fields before those, hid-input will
* leave out the first 8 bits of the priority value. * leave out the first 8 bits of the priority value.
* *
* This still leaves us 65535 individual priority values. * This still leaves us 65535 individual priority values.
*/ */
static const __u32 hidinput_usages_priorities[] = { static const struct usage_priority hidinput_usages_priorities[] = {
HID_DG_ERASER, /* Eraser (eraser touching) must always come before tipswitch */ { /* Eraser (eraser touching) must always come before tipswitch */
HID_DG_INVERT, /* Invert must always come before In Range */ .usage = HID_DG_ERASER,
HID_DG_TIPSWITCH, /* Is the tip of the tool touching? */ },
HID_DG_TIPPRESSURE, /* Tip Pressure might emulate tip switch */ { /* Invert must always come before In Range */
HID_DG_INRANGE, /* In Range needs to come after the other tool states */ .usage = HID_DG_INVERT,
},
{ /* Is the tip of the tool touching? */
.usage = HID_DG_TIPSWITCH,
},
{ /* Tip Pressure might emulate tip switch */
.usage = HID_DG_TIPPRESSURE,
},
{ /* In Range needs to come after the other tool states */
.usage = HID_DG_INRANGE,
},
}; };
#define map_abs(c) hid_map_usage(hidinput, usage, &bit, &max, EV_ABS, (c)) #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 ...@@ -612,6 +635,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
{ {
struct input_dev *input = hidinput->input; struct input_dev *input = hidinput->input;
struct hid_device *device = input_get_drvdata(input); struct hid_device *device = input_get_drvdata(input);
const struct usage_priority *usage_priority = NULL;
int max = 0, code; int max = 0, code;
unsigned int i = 0; unsigned int i = 0;
unsigned long *bit = NULL; unsigned long *bit = NULL;
...@@ -633,13 +657,26 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel ...@@ -633,13 +657,26 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
/* assign a priority based on the static list declared here */ /* assign a priority based on the static list declared here */
for (i = 0; i < ARRAY_SIZE(hidinput_usages_priorities); i++) { for (i = 0; i < ARRAY_SIZE(hidinput_usages_priorities); i++) {
if (usage->hid == hidinput_usages_priorities[i]) { if (usage->hid == hidinput_usages_priorities[i].usage) {
usage_priority = &hidinput_usages_priorities[i];
field->usages_priorities[usage_index] = field->usages_priorities[usage_index] =
(ARRAY_SIZE(hidinput_usages_priorities) - i) << 8; (ARRAY_SIZE(hidinput_usages_priorities) - i) << 8;
break; break;
} }
} }
/*
* For slotted devices, we need to also add the slot index
* in the priority.
*/
if (usage_priority && usage_priority->global)
field->usages_priorities[usage_index] |=
usage_priority->slot_overwrite;
else
field->usages_priorities[usage_index] |=
(0xff - field->slot_idx) << 16;
if (device->driver->input_mapping) { if (device->driver->input_mapping) {
int ret = device->driver->input_mapping(device, hidinput, field, int ret = device->driver->input_mapping(device, hidinput, field,
usage, &bit, &max); usage, &bit, &max);
...@@ -2068,7 +2105,57 @@ static struct hid_input *hidinput_match_application(struct hid_report *report) ...@@ -2068,7 +2105,57 @@ static struct hid_input *hidinput_match_application(struct hid_report *report)
static inline void hidinput_configure_usages(struct hid_input *hidinput, static inline void hidinput_configure_usages(struct hid_input *hidinput,
struct hid_report *report) struct hid_report *report)
{ {
int i, j; int i, j, k;
int first_field_index = 0;
int slot_collection_index = -1;
int prev_collection_index = -1;
unsigned int slot_idx = 0;
struct hid_field *field;
/*
* First tag all the fields that are part of a slot,
* a slot needs to have one Contact ID in the collection
*/
for (i = 0; i < report->maxfield; i++) {
field = report->field[i];
/* ignore fields without usage */
if (field->maxusage < 1)
continue;
/*
* janitoring when collection_index changes
*/
if (prev_collection_index != field->usage->collection_index) {
prev_collection_index = field->usage->collection_index;
first_field_index = i;
}
/*
* if we already found a Contact ID in the collection,
* tag and continue to the next.
*/
if (slot_collection_index == field->usage->collection_index) {
field->slot_idx = slot_idx;
continue;
}
/* check if the current field has Contact ID */
for (j = 0; j < field->maxusage; j++) {
if (field->usage[j].hid == HID_DG_CONTACTID) {
slot_collection_index = field->usage->collection_index;
slot_idx++;
/*
* mark all previous fields and this one in the
* current collection to be slotted.
*/
for (k = first_field_index; k <= i; k++)
report->field[k]->slot_idx = slot_idx;
break;
}
}
}
for (i = 0; i < report->maxfield; i++) for (i = 0; i < report->maxfield; i++)
for (j = 0; j < report->field[i]->maxusage; j++) for (j = 0; j < report->field[i]->maxusage; j++)
......
...@@ -492,6 +492,7 @@ struct hid_field { ...@@ -492,6 +492,7 @@ struct hid_field {
/* hidinput data */ /* hidinput data */
struct hid_input *hidinput; /* associated input structure */ struct hid_input *hidinput; /* associated input structure */
__u16 dpad; /* dpad input code */ __u16 dpad; /* dpad input code */
unsigned int slot_idx; /* slot index in a report */
}; };
#define HID_MAX_FIELDS 256 #define HID_MAX_FIELDS 256
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册