diff options
Diffstat (limited to 'drivers/hid/hid-core.c')
-rw-r--r-- | drivers/hid/hid-core.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 9072e0ed1876..2cd6880b6b17 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -126,7 +126,7 @@ static int open_collection(struct hid_parser *parser, unsigned type) | |||
126 | 126 | ||
127 | if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) { | 127 | if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) { |
128 | hid_err(parser->device, "collection stack overflow\n"); | 128 | hid_err(parser->device, "collection stack overflow\n"); |
129 | return -1; | 129 | return -EINVAL; |
130 | } | 130 | } |
131 | 131 | ||
132 | if (parser->device->maxcollection == parser->device->collection_size) { | 132 | if (parser->device->maxcollection == parser->device->collection_size) { |
@@ -134,7 +134,7 @@ static int open_collection(struct hid_parser *parser, unsigned type) | |||
134 | parser->device->collection_size * 2, GFP_KERNEL); | 134 | parser->device->collection_size * 2, GFP_KERNEL); |
135 | if (collection == NULL) { | 135 | if (collection == NULL) { |
136 | hid_err(parser->device, "failed to reallocate collection array\n"); | 136 | hid_err(parser->device, "failed to reallocate collection array\n"); |
137 | return -1; | 137 | return -ENOMEM; |
138 | } | 138 | } |
139 | memcpy(collection, parser->device->collection, | 139 | memcpy(collection, parser->device->collection, |
140 | sizeof(struct hid_collection) * | 140 | sizeof(struct hid_collection) * |
@@ -170,7 +170,7 @@ static int close_collection(struct hid_parser *parser) | |||
170 | { | 170 | { |
171 | if (!parser->collection_stack_ptr) { | 171 | if (!parser->collection_stack_ptr) { |
172 | hid_err(parser->device, "collection stack underflow\n"); | 172 | hid_err(parser->device, "collection stack underflow\n"); |
173 | return -1; | 173 | return -EINVAL; |
174 | } | 174 | } |
175 | parser->collection_stack_ptr--; | 175 | parser->collection_stack_ptr--; |
176 | return 0; | 176 | return 0; |
@@ -374,7 +374,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) | |||
374 | 374 | ||
375 | case HID_GLOBAL_ITEM_TAG_REPORT_SIZE: | 375 | case HID_GLOBAL_ITEM_TAG_REPORT_SIZE: |
376 | parser->global.report_size = item_udata(item); | 376 | parser->global.report_size = item_udata(item); |
377 | if (parser->global.report_size > 96) { | 377 | if (parser->global.report_size > 128) { |
378 | hid_err(parser->device, "invalid report_size %d\n", | 378 | hid_err(parser->device, "invalid report_size %d\n", |
379 | parser->global.report_size); | 379 | parser->global.report_size); |
380 | return -1; | 380 | return -1; |
@@ -757,6 +757,7 @@ int hid_open_report(struct hid_device *device) | |||
757 | struct hid_item item; | 757 | struct hid_item item; |
758 | unsigned int size; | 758 | unsigned int size; |
759 | __u8 *start; | 759 | __u8 *start; |
760 | __u8 *buf; | ||
760 | __u8 *end; | 761 | __u8 *end; |
761 | int ret; | 762 | int ret; |
762 | static int (*dispatch_type[])(struct hid_parser *parser, | 763 | static int (*dispatch_type[])(struct hid_parser *parser, |
@@ -775,12 +776,21 @@ int hid_open_report(struct hid_device *device) | |||
775 | return -ENODEV; | 776 | return -ENODEV; |
776 | size = device->dev_rsize; | 777 | size = device->dev_rsize; |
777 | 778 | ||
779 | buf = kmemdup(start, size, GFP_KERNEL); | ||
780 | if (buf == NULL) | ||
781 | return -ENOMEM; | ||
782 | |||
778 | if (device->driver->report_fixup) | 783 | if (device->driver->report_fixup) |
779 | start = device->driver->report_fixup(device, start, &size); | 784 | start = device->driver->report_fixup(device, buf, &size); |
785 | else | ||
786 | start = buf; | ||
780 | 787 | ||
781 | device->rdesc = kmemdup(start, size, GFP_KERNEL); | 788 | start = kmemdup(start, size, GFP_KERNEL); |
782 | if (device->rdesc == NULL) | 789 | kfree(buf); |
790 | if (start == NULL) | ||
783 | return -ENOMEM; | 791 | return -ENOMEM; |
792 | |||
793 | device->rdesc = start; | ||
784 | device->rsize = size; | 794 | device->rsize = size; |
785 | 795 | ||
786 | parser = vzalloc(sizeof(struct hid_parser)); | 796 | parser = vzalloc(sizeof(struct hid_parser)); |
@@ -1448,7 +1458,14 @@ void hid_disconnect(struct hid_device *hdev) | |||
1448 | } | 1458 | } |
1449 | EXPORT_SYMBOL_GPL(hid_disconnect); | 1459 | EXPORT_SYMBOL_GPL(hid_disconnect); |
1450 | 1460 | ||
1451 | /* a list of devices for which there is a specialized driver on HID bus */ | 1461 | /* |
1462 | * A list of devices for which there is a specialized driver on HID bus. | ||
1463 | * | ||
1464 | * Please note that for multitouch devices (driven by hid-multitouch driver), | ||
1465 | * there is a proper autodetection and autoloading in place (based on presence | ||
1466 | * of HID_DG_CONTACTID), so those devices don't need to be added to this list, | ||
1467 | * as we are doing the right thing in hid_scan_usage(). | ||
1468 | */ | ||
1452 | static const struct hid_device_id hid_have_special_driver[] = { | 1469 | static const struct hid_device_id hid_have_special_driver[] = { |
1453 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, | 1470 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, |
1454 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, | 1471 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, |
@@ -1628,6 +1645,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1628 | { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, | 1645 | { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, |
1629 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, | 1646 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, |
1630 | { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, | 1647 | { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, |
1648 | #if IS_ENABLED(CONFIG_HID_ROCCAT) | ||
1631 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, | 1649 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, |
1632 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, | 1650 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, |
1633 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, | 1651 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, |
@@ -1636,6 +1654,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1636 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, | 1654 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, |
1637 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) }, | 1655 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) }, |
1638 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) }, | 1656 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) }, |
1657 | #endif | ||
1639 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, | 1658 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, |
1640 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, | 1659 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, |
1641 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, | 1660 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, |