diff options
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/hid-core.c | 20 |
1 files changed, 9 insertions, 11 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 9c8157fb6d75..67f3347afcf3 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <asm/byteorder.h> | 26 | #include <asm/byteorder.h> |
27 | #include <linux/input.h> | 27 | #include <linux/input.h> |
28 | #include <linux/wait.h> | 28 | #include <linux/wait.h> |
29 | #include <linux/vmalloc.h> | ||
29 | 30 | ||
30 | #include <linux/hid.h> | 31 | #include <linux/hid.h> |
31 | #include <linux/hiddev.h> | 32 | #include <linux/hiddev.h> |
@@ -654,12 +655,13 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) | |||
654 | memcpy(device->rdesc, start, size); | 655 | memcpy(device->rdesc, start, size); |
655 | device->rsize = size; | 656 | device->rsize = size; |
656 | 657 | ||
657 | if (!(parser = kzalloc(sizeof(struct hid_parser), GFP_KERNEL))) { | 658 | if (!(parser = vmalloc(sizeof(struct hid_parser)))) { |
658 | kfree(device->rdesc); | 659 | kfree(device->rdesc); |
659 | kfree(device->collection); | 660 | kfree(device->collection); |
660 | kfree(device); | 661 | kfree(device); |
661 | return NULL; | 662 | return NULL; |
662 | } | 663 | } |
664 | memset(parser, 0, sizeof(struct hid_parser)); | ||
663 | parser->device = device; | 665 | parser->device = device; |
664 | 666 | ||
665 | end = start + size; | 667 | end = start + size; |
@@ -668,7 +670,7 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) | |||
668 | if (item.format != HID_ITEM_FORMAT_SHORT) { | 670 | if (item.format != HID_ITEM_FORMAT_SHORT) { |
669 | dbg("unexpected long global item"); | 671 | dbg("unexpected long global item"); |
670 | hid_free_device(device); | 672 | hid_free_device(device); |
671 | kfree(parser); | 673 | vfree(parser); |
672 | return NULL; | 674 | return NULL; |
673 | } | 675 | } |
674 | 676 | ||
@@ -676,7 +678,7 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) | |||
676 | dbg("item %u %u %u %u parsing failed\n", | 678 | dbg("item %u %u %u %u parsing failed\n", |
677 | item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag); | 679 | item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag); |
678 | hid_free_device(device); | 680 | hid_free_device(device); |
679 | kfree(parser); | 681 | vfree(parser); |
680 | return NULL; | 682 | return NULL; |
681 | } | 683 | } |
682 | 684 | ||
@@ -684,23 +686,23 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) | |||
684 | if (parser->collection_stack_ptr) { | 686 | if (parser->collection_stack_ptr) { |
685 | dbg("unbalanced collection at end of report description"); | 687 | dbg("unbalanced collection at end of report description"); |
686 | hid_free_device(device); | 688 | hid_free_device(device); |
687 | kfree(parser); | 689 | vfree(parser); |
688 | return NULL; | 690 | return NULL; |
689 | } | 691 | } |
690 | if (parser->local.delimiter_depth) { | 692 | if (parser->local.delimiter_depth) { |
691 | dbg("unbalanced delimiter at end of report description"); | 693 | dbg("unbalanced delimiter at end of report description"); |
692 | hid_free_device(device); | 694 | hid_free_device(device); |
693 | kfree(parser); | 695 | vfree(parser); |
694 | return NULL; | 696 | return NULL; |
695 | } | 697 | } |
696 | kfree(parser); | 698 | vfree(parser); |
697 | return device; | 699 | return device; |
698 | } | 700 | } |
699 | } | 701 | } |
700 | 702 | ||
701 | dbg("item fetching failed at offset %d\n", (int)(end - start)); | 703 | dbg("item fetching failed at offset %d\n", (int)(end - start)); |
702 | hid_free_device(device); | 704 | hid_free_device(device); |
703 | kfree(parser); | 705 | vfree(parser); |
704 | return NULL; | 706 | return NULL; |
705 | } | 707 | } |
706 | EXPORT_SYMBOL_GPL(hid_parse_report); | 708 | EXPORT_SYMBOL_GPL(hid_parse_report); |
@@ -872,10 +874,6 @@ static void hid_output_field(struct hid_field *field, __u8 *data) | |||
872 | unsigned size = field->report_size; | 874 | unsigned size = field->report_size; |
873 | unsigned n; | 875 | unsigned n; |
874 | 876 | ||
875 | /* make sure the unused bits in the last byte are zeros */ | ||
876 | if (count > 0 && size > 0) | ||
877 | data[(offset+count*size-1)/8] = 0; | ||
878 | |||
879 | for (n = 0; n < count; n++) { | 877 | for (n = 0; n < count; n++) { |
880 | if (field->logical_minimum < 0) /* signed values */ | 878 | if (field->logical_minimum < 0) /* signed values */ |
881 | implement(data, offset + n * size, size, s32ton(field->value[n], size)); | 879 | implement(data, offset + n * size, size, s32ton(field->value[n], size)); |