summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2021-02-23 13:30:01 +0300
committerJiri Kosina <jkosina@suse.cz>2021-02-23 13:30:01 +0300
commit760f7e7b959580ee06d925ad737147a36b194e83 (patch)
treee3fa4327f2ee50ced8ad1038016dd5e8b7f9eb4f
parent88f38846bfb1a452a3d47e38aeab20a4ceb74294 (diff)
parent7c7d7ac7cebbf64a256b40ac7eb198cef8fd0642 (diff)
downloadlinux-760f7e7b959580ee06d925ad737147a36b194e83.tar.xz
Merge branch 'for-5.12/core' into for-linus
- improved handling of generic HID keyboard (no more splitting system and consumer controls away), in order to make it easier for userspace to figure out the details of the device easier. From Dmitry Torokhov. - report data sanitization fixes from Will McVicker and Randy Dunlap
-rw-r--r--drivers/hid/hid-core.c9
-rw-r--r--drivers/hid/hid-input.c10
2 files changed, 16 insertions, 3 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 56172fe6995c..097cb1ee3126 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -90,7 +90,7 @@ EXPORT_SYMBOL_GPL(hid_register_report);
* Register a new field for this report.
*/
-static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values)
+static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages)
{
struct hid_field *field;
@@ -101,7 +101,7 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
field = kzalloc((sizeof(struct hid_field) +
usages * sizeof(struct hid_usage) +
- values * sizeof(unsigned)), GFP_KERNEL);
+ usages * sizeof(unsigned)), GFP_KERNEL);
if (!field)
return NULL;
@@ -300,7 +300,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
usages = max_t(unsigned, parser->local.usage_index,
parser->global.report_count);
- field = hid_register_field(report, usages, parser->global.report_count);
+ field = hid_register_field(report, usages);
if (!field)
return 0;
@@ -1307,6 +1307,9 @@ EXPORT_SYMBOL_GPL(hid_open_report);
static s32 snto32(__u32 value, unsigned n)
{
+ if (!value || !n)
+ return 0;
+
switch (n) {
case 8: return ((__s8)value);
case 16: return ((__s16)value);
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 8ed7f468bd95..236bccd37760 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1856,6 +1856,16 @@ static struct hid_input *hidinput_match_application(struct hid_report *report)
list_for_each_entry(hidinput, &hid->inputs, list) {
if (hidinput->application == report->application)
return hidinput;
+
+ /*
+ * Keep SystemControl and ConsumerControl applications together
+ * with the main keyboard, if present.
+ */
+ if ((report->application == HID_GD_SYSTEM_CONTROL ||
+ report->application == HID_CP_CONSUMER_CONTROL) &&
+ hidinput->application == HID_GD_KEYBOARD) {
+ return hidinput;
+ }
}
return NULL;