aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-core.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-06 12:30:36 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-06 12:30:36 -0400
commit22e04f6b4b04a8afe9af9239224591d06ba3b24d (patch)
tree9bb72350400153ab232e227a378f94e95ad27569 /drivers/hid/hid-core.c
parentec0ad730802173ec17e942f4b652a1819b1025b2 (diff)
parent4e5a494e4b4ba7e6aa1a8a285e98e3665fcb396e (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
Pull HID updates from Jiri Kosina: "Highlights: - conversion of HID subsystem to use devm-based resource management, from Benjamin Tissoires - i2c-hid support for DT bindings, from Benjamin Tissoires - much improved support for Win8-multitouch devices, from Benjamin Tissoires - cleanup of core code using common hidinput_input_event(), from David Herrmann - fix for bug in implement() access to the bit stream (causing oops) that has been present in the code for ages, but devices that are able to trigger it have started to appear only now, from Jiri Kosina - fixes for CVE-2013-2899, CVE-2013-2898, CVE-2013-2896, CVE-2013-2892, CVE-2013-2888 (all triggerable only by specially crafted malicious HW devices plugged into the system), from Kees Cook - hidraw oops fix, from Manoj Chourasia - various smaller fixes here and there, support for a bunch of new devices by various contributors" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (53 commits) HID: MAINTAINERS: add roccat drivers HID: hid-sensor-hub: change kmalloc + memcpy by kmemdup HID: hid-sensor-hub: move to devm_kzalloc HID: hid-sensor-hub: fix indentation accross the code HID: move HID_REPORT_TYPES closer to the report-definitions HID: check for NULL field when setting values HID: picolcd_core: validate output report details HID: sensor-hub: validate feature report details HID: ntrig: validate feature report details HID: pantherlord: validate output report details HID: hid-wiimote: print small buffers via %*phC HID: uhid: improve uhid example client HID: Correct the USB IDs for the new Macbook Air 6 HID: wiimote: add support for Guitar-Hero guitars HID: wiimote: add support for Guitar-Hero drums Input: introduce BTN/ABS bits for drums and guitars HID: battery: don't do DMA from stack HID: roccat: add support for KonePureOptical v2 HID: picolcd: Prevent NULL pointer dereference on _remove() HID: usbhid: quirk for N-Trig DuoSense Touch Screen ...
Diffstat (limited to 'drivers/hid/hid-core.c')
-rw-r--r--drivers/hid/hid-core.c159
1 files changed, 115 insertions, 44 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index b8f1c77f2f77..ae88a97f976e 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -63,6 +63,8 @@ struct hid_report *hid_register_report(struct hid_device *device, unsigned type,
63 struct hid_report_enum *report_enum = device->report_enum + type; 63 struct hid_report_enum *report_enum = device->report_enum + type;
64 struct hid_report *report; 64 struct hid_report *report;
65 65
66 if (id >= HID_MAX_IDS)
67 return NULL;
66 if (report_enum->report_id_hash[id]) 68 if (report_enum->report_id_hash[id])
67 return report_enum->report_id_hash[id]; 69 return report_enum->report_id_hash[id];
68 70
@@ -404,8 +406,10 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
404 406
405 case HID_GLOBAL_ITEM_TAG_REPORT_ID: 407 case HID_GLOBAL_ITEM_TAG_REPORT_ID:
406 parser->global.report_id = item_udata(item); 408 parser->global.report_id = item_udata(item);
407 if (parser->global.report_id == 0) { 409 if (parser->global.report_id == 0 ||
408 hid_err(parser->device, "report_id 0 is invalid\n"); 410 parser->global.report_id >= HID_MAX_IDS) {
411 hid_err(parser->device, "report_id %u is invalid\n",
412 parser->global.report_id);
409 return -1; 413 return -1;
410 } 414 }
411 return 0; 415 return 0;
@@ -450,7 +454,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
450 } 454 }
451 parser->local.delimiter_depth--; 455 parser->local.delimiter_depth--;
452 } 456 }
453 return 1; 457 return 0;
454 458
455 case HID_LOCAL_ITEM_TAG_USAGE: 459 case HID_LOCAL_ITEM_TAG_USAGE:
456 460
@@ -575,7 +579,7 @@ static void hid_close_report(struct hid_device *device)
575 for (i = 0; i < HID_REPORT_TYPES; i++) { 579 for (i = 0; i < HID_REPORT_TYPES; i++) {
576 struct hid_report_enum *report_enum = device->report_enum + i; 580 struct hid_report_enum *report_enum = device->report_enum + i;
577 581
578 for (j = 0; j < 256; j++) { 582 for (j = 0; j < HID_MAX_IDS; j++) {
579 struct hid_report *report = report_enum->report_id_hash[j]; 583 struct hid_report *report = report_enum->report_id_hash[j];
580 if (report) 584 if (report)
581 hid_free_report(report); 585 hid_free_report(report);
@@ -677,12 +681,61 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
677 return NULL; 681 return NULL;
678} 682}
679 683
680static void hid_scan_usage(struct hid_device *hid, u32 usage) 684static void hid_scan_input_usage(struct hid_parser *parser, u32 usage)
681{ 685{
686 struct hid_device *hid = parser->device;
687
682 if (usage == HID_DG_CONTACTID) 688 if (usage == HID_DG_CONTACTID)
683 hid->group = HID_GROUP_MULTITOUCH; 689 hid->group = HID_GROUP_MULTITOUCH;
684} 690}
685 691
692static void hid_scan_feature_usage(struct hid_parser *parser, u32 usage)
693{
694 if (usage == 0xff0000c5 && parser->global.report_count == 256 &&
695 parser->global.report_size == 8)
696 parser->scan_flags |= HID_SCAN_FLAG_MT_WIN_8;
697}
698
699static void hid_scan_collection(struct hid_parser *parser, unsigned type)
700{
701 struct hid_device *hid = parser->device;
702
703 if (((parser->global.usage_page << 16) == HID_UP_SENSOR) &&
704 type == HID_COLLECTION_PHYSICAL)
705 hid->group = HID_GROUP_SENSOR_HUB;
706}
707
708static int hid_scan_main(struct hid_parser *parser, struct hid_item *item)
709{
710 __u32 data;
711 int i;
712
713 data = item_udata(item);
714
715 switch (item->tag) {
716 case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION:
717 hid_scan_collection(parser, data & 0xff);
718 break;
719 case HID_MAIN_ITEM_TAG_END_COLLECTION:
720 break;
721 case HID_MAIN_ITEM_TAG_INPUT:
722 for (i = 0; i < parser->local.usage_index; i++)
723 hid_scan_input_usage(parser, parser->local.usage[i]);
724 break;
725 case HID_MAIN_ITEM_TAG_OUTPUT:
726 break;
727 case HID_MAIN_ITEM_TAG_FEATURE:
728 for (i = 0; i < parser->local.usage_index; i++)
729 hid_scan_feature_usage(parser, parser->local.usage[i]);
730 break;
731 }
732
733 /* Reset the local parser environment */
734 memset(&parser->local, 0, sizeof(parser->local));
735
736 return 0;
737}
738
686/* 739/*
687 * Scan a report descriptor before the device is added to the bus. 740 * Scan a report descriptor before the device is added to the bus.
688 * Sets device groups and other properties that determine what driver 741 * Sets device groups and other properties that determine what driver
@@ -690,48 +743,41 @@ static void hid_scan_usage(struct hid_device *hid, u32 usage)
690 */ 743 */
691static int hid_scan_report(struct hid_device *hid) 744static int hid_scan_report(struct hid_device *hid)
692{ 745{
693 unsigned int page = 0, delim = 0; 746 struct hid_parser *parser;
747 struct hid_item item;
694 __u8 *start = hid->dev_rdesc; 748 __u8 *start = hid->dev_rdesc;
695 __u8 *end = start + hid->dev_rsize; 749 __u8 *end = start + hid->dev_rsize;
696 unsigned int u, u_min = 0, u_max = 0; 750 static int (*dispatch_type[])(struct hid_parser *parser,
697 struct hid_item item; 751 struct hid_item *item) = {
752 hid_scan_main,
753 hid_parser_global,
754 hid_parser_local,
755 hid_parser_reserved
756 };
757
758 parser = vzalloc(sizeof(struct hid_parser));
759 if (!parser)
760 return -ENOMEM;
698 761
762 parser->device = hid;
699 hid->group = HID_GROUP_GENERIC; 763 hid->group = HID_GROUP_GENERIC;
700 while ((start = fetch_item(start, end, &item)) != NULL) {
701 if (item.format != HID_ITEM_FORMAT_SHORT)
702 return -EINVAL;
703 if (item.type == HID_ITEM_TYPE_GLOBAL) {
704 if (item.tag == HID_GLOBAL_ITEM_TAG_USAGE_PAGE)
705 page = item_udata(&item) << 16;
706 } else if (item.type == HID_ITEM_TYPE_LOCAL) {
707 if (delim > 1)
708 break;
709 u = item_udata(&item);
710 if (item.size <= 2)
711 u += page;
712 switch (item.tag) {
713 case HID_LOCAL_ITEM_TAG_DELIMITER:
714 delim += !!u;
715 break;
716 case HID_LOCAL_ITEM_TAG_USAGE:
717 hid_scan_usage(hid, u);
718 break;
719 case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
720 u_min = u;
721 break;
722 case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
723 u_max = u;
724 for (u = u_min; u <= u_max; u++)
725 hid_scan_usage(hid, u);
726 break;
727 }
728 } else if (page == HID_UP_SENSOR &&
729 item.type == HID_ITEM_TYPE_MAIN &&
730 item.tag == HID_MAIN_ITEM_TAG_BEGIN_COLLECTION &&
731 (item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL)
732 hid->group = HID_GROUP_SENSOR_HUB;
733 }
734 764
765 /*
766 * The parsing is simpler than the one in hid_open_report() as we should
767 * be robust against hid errors. Those errors will be raised by
768 * hid_open_report() anyway.
769 */
770 while ((start = fetch_item(start, end, &item)) != NULL)
771 dispatch_type[item.type](parser, &item);
772
773 /*
774 * Handle special flags set during scanning.
775 */
776 if ((parser->scan_flags & HID_SCAN_FLAG_MT_WIN_8) &&
777 (hid->group == HID_GROUP_MULTITOUCH))
778 hid->group = HID_GROUP_MULTITOUCH_WIN_8;
779
780 vfree(parser);
735 return 0; 781 return 0;
736} 782}
737 783
@@ -1128,7 +1174,8 @@ static void hid_output_field(const struct hid_device *hid,
1128} 1174}
1129 1175
1130/* 1176/*
1131 * Create a report. 1177 * Create a report. 'data' has to be allocated using
1178 * hid_alloc_report_buf() so that it has proper size.
1132 */ 1179 */
1133 1180
1134void hid_output_report(struct hid_report *report, __u8 *data) 1181void hid_output_report(struct hid_report *report, __u8 *data)
@@ -1145,6 +1192,22 @@ void hid_output_report(struct hid_report *report, __u8 *data)
1145EXPORT_SYMBOL_GPL(hid_output_report); 1192EXPORT_SYMBOL_GPL(hid_output_report);
1146 1193
1147/* 1194/*
1195 * Allocator for buffer that is going to be passed to hid_output_report()
1196 */
1197u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags)
1198{
1199 /*
1200 * 7 extra bytes are necessary to achieve proper functionality
1201 * of implement() working on 8 byte chunks
1202 */
1203
1204 int len = ((report->size - 1) >> 3) + 1 + (report->id > 0) + 7;
1205
1206 return kmalloc(len, flags);
1207}
1208EXPORT_SYMBOL_GPL(hid_alloc_report_buf);
1209
1210/*
1148 * Set a field value. The report this field belongs to has to be 1211 * Set a field value. The report this field belongs to has to be
1149 * created and transferred to the device, to set this value in the 1212 * created and transferred to the device, to set this value in the
1150 * device. 1213 * device.
@@ -1152,7 +1215,12 @@ EXPORT_SYMBOL_GPL(hid_output_report);
1152 1215
1153int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) 1216int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
1154{ 1217{
1155 unsigned size = field->report_size; 1218 unsigned size;
1219
1220 if (!field)
1221 return -1;
1222
1223 size = field->report_size;
1156 1224
1157 hid_dump_input(field->report->device, field->usage + offset, value); 1225 hid_dump_input(field->report->device, field->usage + offset, value);
1158 1226
@@ -1597,6 +1665,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
1597 { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, 1665 { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
1598 { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, 1666 { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
1599 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) }, 1667 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
1668 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
1600 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, 1669 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
1601 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) }, 1670 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) },
1602 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, 1671 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) },
@@ -1679,6 +1748,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
1679 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, 1748 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
1680 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, 1749 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
1681 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) }, 1750 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) },
1751 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE_OPTICAL) },
1682 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, 1752 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
1683 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) }, 1753 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) },
1684 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, 1754 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
@@ -1736,6 +1806,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
1736 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, 1806 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) },
1737 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET) }, 1807 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET) },
1738 { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) }, 1808 { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) },
1809 { HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE) },
1739 { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, 1810 { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
1740 { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, 1811 { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
1741 { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) }, 1812 { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) },