diff options
author | Benjamin Tissoires <benjamin.tissoires@redhat.com> | 2018-04-24 04:04:33 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2018-04-26 08:17:31 -0400 |
commit | f07b3c1da92db108662f99417a212fc1eddc44d1 (patch) | |
tree | d4ad0e580dfab744d34460c80a361e78c7ff47dd | |
parent | e1b63c0148a7f8edf1691770ec0527fe86fb6ab8 (diff) |
HID: generic: create one input report per application type
It is not a good idea to try to fit all types of applications in the
same input report. There are a lot of devices that are needing
the quirk HID_MULTI_INPUT but this quirk doesn't match the actual HID
description as it is based on the report ID.
Given that most devices with MULTI_INPUT I can think of split nicely
the devices inputs into application, it is a good thing to split the
devices by default based on this assumption.
Also make hid-multitouch following this rule, to not have to deal
with too many input created.
While we are at it, fix some checkpatch complaints about converting
'unsigned' to 'unsigned int'.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | drivers/hid/hid-core.c | 19 | ||||
-rw-r--r-- | drivers/hid/hid-generic.c | 15 | ||||
-rw-r--r-- | drivers/hid/hid-gfrm.c | 2 | ||||
-rw-r--r-- | drivers/hid/hid-input.c | 17 | ||||
-rw-r--r-- | drivers/hid/hid-magicmouse.c | 6 | ||||
-rw-r--r-- | include/linux/hid.h | 10 |
6 files changed, 56 insertions, 13 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 5d7cc6bbbac6..68819106f4fc 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -57,7 +57,9 @@ MODULE_PARM_DESC(ignore_special_drivers, "Ignore any special drivers and handle | |||
57 | * Register a new report for a device. | 57 | * Register a new report for a device. |
58 | */ | 58 | */ |
59 | 59 | ||
60 | struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id) | 60 | struct hid_report *hid_register_report(struct hid_device *device, |
61 | unsigned int type, unsigned int id, | ||
62 | unsigned int application) | ||
61 | { | 63 | { |
62 | struct hid_report_enum *report_enum = device->report_enum + type; | 64 | struct hid_report_enum *report_enum = device->report_enum + type; |
63 | struct hid_report *report; | 65 | struct hid_report *report; |
@@ -78,6 +80,7 @@ struct hid_report *hid_register_report(struct hid_device *device, unsigned type, | |||
78 | report->type = type; | 80 | report->type = type; |
79 | report->size = 0; | 81 | report->size = 0; |
80 | report->device = device; | 82 | report->device = device; |
83 | report->application = application; | ||
81 | report_enum->report_id_hash[id] = report; | 84 | report_enum->report_id_hash[id] = report; |
82 | 85 | ||
83 | list_add_tail(&report->list, &report_enum->report_list); | 86 | list_add_tail(&report->list, &report_enum->report_list); |
@@ -221,11 +224,15 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign | |||
221 | { | 224 | { |
222 | struct hid_report *report; | 225 | struct hid_report *report; |
223 | struct hid_field *field; | 226 | struct hid_field *field; |
224 | unsigned usages; | 227 | unsigned int usages; |
225 | unsigned offset; | 228 | unsigned int offset; |
226 | unsigned i; | 229 | unsigned int i; |
230 | unsigned int application; | ||
231 | |||
232 | application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION); | ||
227 | 233 | ||
228 | report = hid_register_report(parser->device, report_type, parser->global.report_id); | 234 | report = hid_register_report(parser->device, report_type, |
235 | parser->global.report_id, application); | ||
229 | if (!report) { | 236 | if (!report) { |
230 | hid_err(parser->device, "hid_register_report failed\n"); | 237 | hid_err(parser->device, "hid_register_report failed\n"); |
231 | return -1; | 238 | return -1; |
@@ -259,7 +266,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign | |||
259 | 266 | ||
260 | field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL); | 267 | field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL); |
261 | field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL); | 268 | field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL); |
262 | field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION); | 269 | field->application = application; |
263 | 270 | ||
264 | for (i = 0; i < usages; i++) { | 271 | for (i = 0; i < usages; i++) { |
265 | unsigned j = i; | 272 | unsigned j = i; |
diff --git a/drivers/hid/hid-generic.c b/drivers/hid/hid-generic.c index c25b4718de44..3b6eccbc2519 100644 --- a/drivers/hid/hid-generic.c +++ b/drivers/hid/hid-generic.c | |||
@@ -56,6 +56,20 @@ static bool hid_generic_match(struct hid_device *hdev, | |||
56 | return true; | 56 | return true; |
57 | } | 57 | } |
58 | 58 | ||
59 | static int hid_generic_probe(struct hid_device *hdev, | ||
60 | const struct hid_device_id *id) | ||
61 | { | ||
62 | int ret; | ||
63 | |||
64 | hdev->quirks |= HID_QUIRK_INPUT_PER_APP; | ||
65 | |||
66 | ret = hid_parse(hdev); | ||
67 | if (ret) | ||
68 | return ret; | ||
69 | |||
70 | return hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
71 | } | ||
72 | |||
59 | static const struct hid_device_id hid_table[] = { | 73 | static const struct hid_device_id hid_table[] = { |
60 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, HID_ANY_ID, HID_ANY_ID) }, | 74 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, HID_ANY_ID, HID_ANY_ID) }, |
61 | { } | 75 | { } |
@@ -66,6 +80,7 @@ static struct hid_driver hid_generic = { | |||
66 | .name = "hid-generic", | 80 | .name = "hid-generic", |
67 | .id_table = hid_table, | 81 | .id_table = hid_table, |
68 | .match = hid_generic_match, | 82 | .match = hid_generic_match, |
83 | .probe = hid_generic_probe, | ||
69 | }; | 84 | }; |
70 | module_hid_driver(hid_generic); | 85 | module_hid_driver(hid_generic); |
71 | 86 | ||
diff --git a/drivers/hid/hid-gfrm.c b/drivers/hid/hid-gfrm.c index 075b1c020846..cf477f8c8f4c 100644 --- a/drivers/hid/hid-gfrm.c +++ b/drivers/hid/hid-gfrm.c | |||
@@ -116,7 +116,7 @@ static int gfrm_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
116 | * those reports reach gfrm_raw_event() from hid_input_report(). | 116 | * those reports reach gfrm_raw_event() from hid_input_report(). |
117 | */ | 117 | */ |
118 | if (!hid_register_report(hdev, HID_INPUT_REPORT, | 118 | if (!hid_register_report(hdev, HID_INPUT_REPORT, |
119 | GFRM100_SEARCH_KEY_REPORT_ID)) { | 119 | GFRM100_SEARCH_KEY_REPORT_ID, 0)) { |
120 | ret = -ENOMEM; | 120 | ret = -ENOMEM; |
121 | goto done; | 121 | goto done; |
122 | } | 122 | } |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index fd1c4fe70327..7463ee2a1df2 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -1610,6 +1610,20 @@ static struct hid_input *hidinput_match(struct hid_report *report) | |||
1610 | return NULL; | 1610 | return NULL; |
1611 | } | 1611 | } |
1612 | 1612 | ||
1613 | static struct hid_input *hidinput_match_application(struct hid_report *report) | ||
1614 | { | ||
1615 | struct hid_device *hid = report->device; | ||
1616 | struct hid_input *hidinput; | ||
1617 | |||
1618 | list_for_each_entry(hidinput, &hid->inputs, list) { | ||
1619 | if (hidinput->report && | ||
1620 | hidinput->report->application == report->application) | ||
1621 | return hidinput; | ||
1622 | } | ||
1623 | |||
1624 | return NULL; | ||
1625 | } | ||
1626 | |||
1613 | static inline void hidinput_configure_usages(struct hid_input *hidinput, | 1627 | static inline void hidinput_configure_usages(struct hid_input *hidinput, |
1614 | struct hid_report *report) | 1628 | struct hid_report *report) |
1615 | { | 1629 | { |
@@ -1670,6 +1684,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) | |||
1670 | */ | 1684 | */ |
1671 | if (hid->quirks & HID_QUIRK_MULTI_INPUT) | 1685 | if (hid->quirks & HID_QUIRK_MULTI_INPUT) |
1672 | hidinput = hidinput_match(report); | 1686 | hidinput = hidinput_match(report); |
1687 | else if (hid->maxapplication > 1 && | ||
1688 | (hid->quirks & HID_QUIRK_INPUT_PER_APP)) | ||
1689 | hidinput = hidinput_match_application(report); | ||
1673 | 1690 | ||
1674 | if (!hidinput) { | 1691 | if (!hidinput) { |
1675 | hidinput = hidinput_allocate(hid); | 1692 | hidinput = hidinput_allocate(hid); |
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index 42ed887ba0be..b454c4386157 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c | |||
@@ -531,12 +531,12 @@ static int magicmouse_probe(struct hid_device *hdev, | |||
531 | 531 | ||
532 | if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE) | 532 | if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE) |
533 | report = hid_register_report(hdev, HID_INPUT_REPORT, | 533 | report = hid_register_report(hdev, HID_INPUT_REPORT, |
534 | MOUSE_REPORT_ID); | 534 | MOUSE_REPORT_ID, 0); |
535 | else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ | 535 | else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ |
536 | report = hid_register_report(hdev, HID_INPUT_REPORT, | 536 | report = hid_register_report(hdev, HID_INPUT_REPORT, |
537 | TRACKPAD_REPORT_ID); | 537 | TRACKPAD_REPORT_ID, 0); |
538 | report = hid_register_report(hdev, HID_INPUT_REPORT, | 538 | report = hid_register_report(hdev, HID_INPUT_REPORT, |
539 | DOUBLE_REPORT_ID); | 539 | DOUBLE_REPORT_ID, 0); |
540 | } | 540 | } |
541 | 541 | ||
542 | if (!report) { | 542 | if (!report) { |
diff --git a/include/linux/hid.h b/include/linux/hid.h index 396068ccc197..bcc91bfdd2cb 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
@@ -341,6 +341,7 @@ struct hid_item { | |||
341 | /* BIT(8) reserved for backward compatibility, was HID_QUIRK_NO_EMPTY_INPUT */ | 341 | /* BIT(8) reserved for backward compatibility, was HID_QUIRK_NO_EMPTY_INPUT */ |
342 | /* BIT(9) reserved for backward compatibility, was NO_INIT_INPUT_REPORTS */ | 342 | /* BIT(9) reserved for backward compatibility, was NO_INIT_INPUT_REPORTS */ |
343 | #define HID_QUIRK_ALWAYS_POLL BIT(10) | 343 | #define HID_QUIRK_ALWAYS_POLL BIT(10) |
344 | #define HID_QUIRK_INPUT_PER_APP BIT(11) | ||
344 | #define HID_QUIRK_SKIP_OUTPUT_REPORTS BIT(16) | 345 | #define HID_QUIRK_SKIP_OUTPUT_REPORTS BIT(16) |
345 | #define HID_QUIRK_SKIP_OUTPUT_REPORT_ID BIT(17) | 346 | #define HID_QUIRK_SKIP_OUTPUT_REPORT_ID BIT(17) |
346 | #define HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP BIT(18) | 347 | #define HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP BIT(18) |
@@ -465,8 +466,9 @@ struct hid_field { | |||
465 | struct hid_report { | 466 | struct hid_report { |
466 | struct list_head list; | 467 | struct list_head list; |
467 | struct list_head hidinput_list; | 468 | struct list_head hidinput_list; |
468 | unsigned id; /* id of this report */ | 469 | unsigned int id; /* id of this report */ |
469 | unsigned type; /* report type */ | 470 | unsigned int type; /* report type */ |
471 | unsigned int application; /* application usage for this report */ | ||
470 | struct hid_field *field[HID_MAX_FIELDS]; /* fields of the report */ | 472 | struct hid_field *field[HID_MAX_FIELDS]; /* fields of the report */ |
471 | unsigned maxfield; /* maximum valid field index */ | 473 | unsigned maxfield; /* maximum valid field index */ |
472 | unsigned size; /* size of the report (bits) */ | 474 | unsigned size; /* size of the report (bits) */ |
@@ -861,7 +863,9 @@ void hid_output_report(struct hid_report *report, __u8 *data); | |||
861 | void __hid_request(struct hid_device *hid, struct hid_report *rep, int reqtype); | 863 | void __hid_request(struct hid_device *hid, struct hid_report *rep, int reqtype); |
862 | u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags); | 864 | u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags); |
863 | struct hid_device *hid_allocate_device(void); | 865 | struct hid_device *hid_allocate_device(void); |
864 | struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); | 866 | struct hid_report *hid_register_report(struct hid_device *device, |
867 | unsigned int type, unsigned int id, | ||
868 | unsigned int application); | ||
865 | int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); | 869 | int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); |
866 | struct hid_report *hid_validate_values(struct hid_device *hid, | 870 | struct hid_report *hid_validate_values(struct hid_device *hid, |
867 | unsigned int type, unsigned int id, | 871 | unsigned int type, unsigned int id, |