diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hid/hid-core.c | 474 | ||||
-rw-r--r-- | drivers/hid/hid-input.c | 2 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 44 | ||||
-rw-r--r-- | drivers/hid/usbhid/usbhid.h | 2 |
4 files changed, 435 insertions, 87 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 426ac5add585..017fc20167d4 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -534,9 +534,10 @@ static void hid_free_report(struct hid_report *report) | |||
534 | * Free a device structure, all reports, and all fields. | 534 | * Free a device structure, all reports, and all fields. |
535 | */ | 535 | */ |
536 | 536 | ||
537 | void hid_free_device(struct hid_device *device) | 537 | static void hid_device_release(struct device *dev) |
538 | { | 538 | { |
539 | unsigned i,j; | 539 | struct hid_device *device = container_of(dev, struct hid_device, dev); |
540 | unsigned i, j; | ||
540 | 541 | ||
541 | for (i = 0; i < HID_REPORT_TYPES; i++) { | 542 | for (i = 0; i < HID_REPORT_TYPES; i++) { |
542 | struct hid_report_enum *report_enum = device->report_enum + i; | 543 | struct hid_report_enum *report_enum = device->report_enum + i; |
@@ -552,7 +553,6 @@ void hid_free_device(struct hid_device *device) | |||
552 | kfree(device->collection); | 553 | kfree(device->collection); |
553 | kfree(device); | 554 | kfree(device); |
554 | } | 555 | } |
555 | EXPORT_SYMBOL_GPL(hid_free_device); | ||
556 | 556 | ||
557 | /* | 557 | /* |
558 | * Fetch a report description item from the data stream. We support long | 558 | * Fetch a report description item from the data stream. We support long |
@@ -622,18 +622,24 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item) | |||
622 | return NULL; | 622 | return NULL; |
623 | } | 623 | } |
624 | 624 | ||
625 | /* | 625 | /** |
626 | * hid_parse_report - parse device report | ||
627 | * | ||
628 | * @device: hid device | ||
629 | * @start: report start | ||
630 | * @size: report size | ||
631 | * | ||
626 | * Parse a report description into a hid_device structure. Reports are | 632 | * Parse a report description into a hid_device structure. Reports are |
627 | * enumerated, fields are attached to these reports. | 633 | * enumerated, fields are attached to these reports. |
634 | * 0 returned on success, otherwise nonzero error value. | ||
628 | */ | 635 | */ |
629 | 636 | int hid_parse_report(struct hid_device *device, __u8 *start, | |
630 | struct hid_device *hid_parse_report(__u8 *start, unsigned size) | 637 | unsigned size) |
631 | { | 638 | { |
632 | struct hid_device *device; | ||
633 | struct hid_parser *parser; | 639 | struct hid_parser *parser; |
634 | struct hid_item item; | 640 | struct hid_item item; |
635 | __u8 *end; | 641 | __u8 *end; |
636 | unsigned i; | 642 | int ret; |
637 | static int (*dispatch_type[])(struct hid_parser *parser, | 643 | static int (*dispatch_type[])(struct hid_parser *parser, |
638 | struct hid_item *item) = { | 644 | struct hid_item *item) = { |
639 | hid_parser_main, | 645 | hid_parser_main, |
@@ -642,76 +648,54 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) | |||
642 | hid_parser_reserved | 648 | hid_parser_reserved |
643 | }; | 649 | }; |
644 | 650 | ||
645 | if (!(device = kzalloc(sizeof(struct hid_device), GFP_KERNEL))) | 651 | device->rdesc = kmalloc(size, GFP_KERNEL); |
646 | return NULL; | 652 | if (device->rdesc == NULL) |
647 | 653 | return -ENOMEM; | |
648 | if (!(device->collection = kzalloc(sizeof(struct hid_collection) * | ||
649 | HID_DEFAULT_NUM_COLLECTIONS, GFP_KERNEL))) { | ||
650 | kfree(device); | ||
651 | return NULL; | ||
652 | } | ||
653 | device->collection_size = HID_DEFAULT_NUM_COLLECTIONS; | ||
654 | |||
655 | for (i = 0; i < HID_REPORT_TYPES; i++) | ||
656 | INIT_LIST_HEAD(&device->report_enum[i].report_list); | ||
657 | |||
658 | if (!(device->rdesc = kmalloc(size, GFP_KERNEL))) { | ||
659 | kfree(device->collection); | ||
660 | kfree(device); | ||
661 | return NULL; | ||
662 | } | ||
663 | memcpy(device->rdesc, start, size); | 654 | memcpy(device->rdesc, start, size); |
664 | device->rsize = size; | 655 | device->rsize = size; |
665 | 656 | ||
666 | if (!(parser = vmalloc(sizeof(struct hid_parser)))) { | 657 | parser = vmalloc(sizeof(struct hid_parser)); |
667 | kfree(device->rdesc); | 658 | if (!parser) { |
668 | kfree(device->collection); | 659 | ret = -ENOMEM; |
669 | kfree(device); | 660 | goto err; |
670 | return NULL; | ||
671 | } | 661 | } |
662 | |||
672 | memset(parser, 0, sizeof(struct hid_parser)); | 663 | memset(parser, 0, sizeof(struct hid_parser)); |
673 | parser->device = device; | 664 | parser->device = device; |
674 | 665 | ||
675 | end = start + size; | 666 | end = start + size; |
667 | ret = -EINVAL; | ||
676 | while ((start = fetch_item(start, end, &item)) != NULL) { | 668 | while ((start = fetch_item(start, end, &item)) != NULL) { |
677 | 669 | ||
678 | if (item.format != HID_ITEM_FORMAT_SHORT) { | 670 | if (item.format != HID_ITEM_FORMAT_SHORT) { |
679 | dbg_hid("unexpected long global item\n"); | 671 | dbg_hid("unexpected long global item\n"); |
680 | hid_free_device(device); | 672 | goto err; |
681 | vfree(parser); | ||
682 | return NULL; | ||
683 | } | 673 | } |
684 | 674 | ||
685 | if (dispatch_type[item.type](parser, &item)) { | 675 | if (dispatch_type[item.type](parser, &item)) { |
686 | dbg_hid("item %u %u %u %u parsing failed\n", | 676 | dbg_hid("item %u %u %u %u parsing failed\n", |
687 | item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag); | 677 | item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag); |
688 | hid_free_device(device); | 678 | goto err; |
689 | vfree(parser); | ||
690 | return NULL; | ||
691 | } | 679 | } |
692 | 680 | ||
693 | if (start == end) { | 681 | if (start == end) { |
694 | if (parser->collection_stack_ptr) { | 682 | if (parser->collection_stack_ptr) { |
695 | dbg_hid("unbalanced collection at end of report description\n"); | 683 | dbg_hid("unbalanced collection at end of report description\n"); |
696 | hid_free_device(device); | 684 | goto err; |
697 | vfree(parser); | ||
698 | return NULL; | ||
699 | } | 685 | } |
700 | if (parser->local.delimiter_depth) { | 686 | if (parser->local.delimiter_depth) { |
701 | dbg_hid("unbalanced delimiter at end of report description\n"); | 687 | dbg_hid("unbalanced delimiter at end of report description\n"); |
702 | hid_free_device(device); | 688 | goto err; |
703 | vfree(parser); | ||
704 | return NULL; | ||
705 | } | 689 | } |
706 | vfree(parser); | 690 | vfree(parser); |
707 | return device; | 691 | return 0; |
708 | } | 692 | } |
709 | } | 693 | } |
710 | 694 | ||
711 | dbg_hid("item fetching failed at offset %d\n", (int)(end - start)); | 695 | dbg_hid("item fetching failed at offset %d\n", (int)(end - start)); |
712 | hid_free_device(device); | 696 | err: |
713 | vfree(parser); | 697 | vfree(parser); |
714 | return NULL; | 698 | return ret; |
715 | } | 699 | } |
716 | EXPORT_SYMBOL_GPL(hid_parse_report); | 700 | EXPORT_SYMBOL_GPL(hid_parse_report); |
717 | 701 | ||
@@ -815,9 +799,73 @@ static __inline__ int search(__s32 *array, __s32 value, unsigned n) | |||
815 | return -1; | 799 | return -1; |
816 | } | 800 | } |
817 | 801 | ||
818 | static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, int interrupt) | 802 | /** |
803 | * hid_match_report - check if driver's raw_event should be called | ||
804 | * | ||
805 | * @hid: hid device | ||
806 | * @report_type: type to match against | ||
807 | * | ||
808 | * compare hid->driver->report_table->report_type to report->type | ||
809 | */ | ||
810 | static int hid_match_report(struct hid_device *hid, struct hid_report *report) | ||
819 | { | 811 | { |
812 | const struct hid_report_id *id = hid->driver->report_table; | ||
813 | |||
814 | if (!id) /* NULL means all */ | ||
815 | return 1; | ||
816 | |||
817 | for (; id->report_type != HID_TERMINATOR; id++) | ||
818 | if (id->report_type == HID_ANY_ID || | ||
819 | id->report_type == report->type) | ||
820 | return 1; | ||
821 | return 0; | ||
822 | } | ||
823 | |||
824 | /** | ||
825 | * hid_match_usage - check if driver's event should be called | ||
826 | * | ||
827 | * @hid: hid device | ||
828 | * @usage: usage to match against | ||
829 | * | ||
830 | * compare hid->driver->usage_table->usage_{type,code} to | ||
831 | * usage->usage_{type,code} | ||
832 | */ | ||
833 | static int hid_match_usage(struct hid_device *hid, struct hid_usage *usage) | ||
834 | { | ||
835 | const struct hid_usage_id *id = hid->driver->usage_table; | ||
836 | |||
837 | if (!id) /* NULL means all */ | ||
838 | return 1; | ||
839 | |||
840 | for (; id->usage_type != HID_ANY_ID - 1; id++) | ||
841 | if ((id->usage_hid == HID_ANY_ID || | ||
842 | id->usage_hid == usage->hid) && | ||
843 | (id->usage_type == HID_ANY_ID || | ||
844 | id->usage_type == usage->type) && | ||
845 | (id->usage_code == HID_ANY_ID || | ||
846 | id->usage_code == usage->code)) | ||
847 | return 1; | ||
848 | return 0; | ||
849 | } | ||
850 | |||
851 | static void hid_process_event(struct hid_device *hid, struct hid_field *field, | ||
852 | struct hid_usage *usage, __s32 value, int interrupt) | ||
853 | { | ||
854 | struct hid_driver *hdrv = hid->driver; | ||
855 | int ret; | ||
856 | |||
820 | hid_dump_input(usage, value); | 857 | hid_dump_input(usage, value); |
858 | |||
859 | if (hdrv && hdrv->event && hid_match_usage(hid, usage)) { | ||
860 | ret = hdrv->event(hid, field, usage, value); | ||
861 | if (ret != 0) { | ||
862 | if (ret < 0) | ||
863 | dbg_hid("%s's event failed with %d\n", | ||
864 | hdrv->name, ret); | ||
865 | return; | ||
866 | } | ||
867 | } | ||
868 | |||
821 | if (hid->claimed & HID_CLAIMED_INPUT) | 869 | if (hid->claimed & HID_CLAIMED_INPUT) |
822 | hidinput_hid_event(hid, field, usage, value); | 870 | hidinput_hid_event(hid, field, usage, value); |
823 | if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt && hid->hiddev_hid_event) | 871 | if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt && hid->hiddev_hid_event) |
@@ -946,44 +994,47 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) | |||
946 | } | 994 | } |
947 | EXPORT_SYMBOL_GPL(hid_set_field); | 995 | EXPORT_SYMBOL_GPL(hid_set_field); |
948 | 996 | ||
949 | int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt) | 997 | static struct hid_report *hid_get_report(struct hid_report_enum *report_enum, |
998 | const u8 *data) | ||
950 | { | 999 | { |
951 | struct hid_report_enum *report_enum = hid->report_enum + type; | ||
952 | struct hid_report *report; | 1000 | struct hid_report *report; |
953 | int n, rsize, i; | 1001 | unsigned int n = 0; /* Normally report number is 0 */ |
954 | 1002 | ||
955 | if (!hid) | 1003 | /* Device uses numbered reports, data[0] is report number */ |
956 | return -ENODEV; | 1004 | if (report_enum->numbered) |
1005 | n = *data; | ||
957 | 1006 | ||
958 | if (!size) { | 1007 | report = report_enum->report_id_hash[n]; |
959 | dbg_hid("empty report\n"); | 1008 | if (report == NULL) |
960 | return -1; | 1009 | dbg_hid("undefined report_id %u received\n", n); |
961 | } | ||
962 | 1010 | ||
963 | dbg_hid("report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un"); | 1011 | return report; |
1012 | } | ||
964 | 1013 | ||
965 | n = 0; /* Normally report number is 0 */ | 1014 | void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, |
966 | if (report_enum->numbered) { /* Device uses numbered reports, data[0] is report number */ | 1015 | int interrupt) |
967 | n = *data++; | 1016 | { |
968 | size--; | 1017 | struct hid_report_enum *report_enum = hid->report_enum + type; |
969 | } | 1018 | struct hid_report *report; |
1019 | unsigned int a; | ||
1020 | int rsize, csize = size; | ||
1021 | u8 *cdata = data; | ||
970 | 1022 | ||
971 | /* dump the report */ | 1023 | report = hid_get_report(report_enum, data); |
972 | dbg_hid("report %d (size %u) = ", n, size); | 1024 | if (!report) |
973 | for (i = 0; i < size; i++) | 1025 | return; |
974 | dbg_hid_line(" %02x", data[i]); | ||
975 | dbg_hid_line("\n"); | ||
976 | 1026 | ||
977 | if (!(report = report_enum->report_id_hash[n])) { | 1027 | if (report_enum->numbered) { |
978 | dbg_hid("undefined report_id %d received\n", n); | 1028 | cdata++; |
979 | return -1; | 1029 | csize--; |
980 | } | 1030 | } |
981 | 1031 | ||
982 | rsize = ((report->size - 1) >> 3) + 1; | 1032 | rsize = ((report->size - 1) >> 3) + 1; |
983 | 1033 | ||
984 | if (size < rsize) { | 1034 | if (csize < rsize) { |
985 | dbg_hid("report %d is too short, (%d < %d)\n", report->id, size, rsize); | 1035 | dbg_hid("report %d is too short, (%d < %d)\n", report->id, |
986 | memset(data + size, 0, rsize - size); | 1036 | csize, rsize); |
1037 | memset(cdata + csize, 0, rsize - csize); | ||
987 | } | 1038 | } |
988 | 1039 | ||
989 | if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event) | 1040 | if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event) |
@@ -996,24 +1047,295 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i | |||
996 | hidraw_report_event(hid, data, size); | 1047 | hidraw_report_event(hid, data, size); |
997 | } | 1048 | } |
998 | 1049 | ||
999 | for (n = 0; n < report->maxfield; n++) | 1050 | for (a = 0; a < report->maxfield; a++) |
1000 | hid_input_field(hid, report->field[n], data, interrupt); | 1051 | hid_input_field(hid, report->field[a], cdata, interrupt); |
1001 | 1052 | ||
1002 | if (hid->claimed & HID_CLAIMED_INPUT) | 1053 | if (hid->claimed & HID_CLAIMED_INPUT) |
1003 | hidinput_report_event(hid, report); | 1054 | hidinput_report_event(hid, report); |
1055 | } | ||
1056 | EXPORT_SYMBOL_GPL(hid_report_raw_event); | ||
1057 | |||
1058 | /** | ||
1059 | * hid_input_report - report data from lower layer (usb, bt...) | ||
1060 | * | ||
1061 | * @hid: hid device | ||
1062 | * @type: HID report type (HID_*_REPORT) | ||
1063 | * @data: report contents | ||
1064 | * @size: size of data parameter | ||
1065 | * @interrupt: called from atomic? | ||
1066 | * | ||
1067 | * This is data entry for lower layers. | ||
1068 | */ | ||
1069 | int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt) | ||
1070 | { | ||
1071 | struct hid_report_enum *report_enum = hid->report_enum + type; | ||
1072 | struct hid_driver *hdrv = hid->driver; | ||
1073 | struct hid_report *report; | ||
1074 | unsigned int i; | ||
1075 | int ret; | ||
1076 | |||
1077 | if (!hid || !hid->driver) | ||
1078 | return -ENODEV; | ||
1079 | |||
1080 | if (!size) { | ||
1081 | dbg_hid("empty report\n"); | ||
1082 | return -1; | ||
1083 | } | ||
1084 | |||
1085 | dbg_hid("report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un"); | ||
1086 | |||
1087 | report = hid_get_report(report_enum, data); | ||
1088 | if (!report) | ||
1089 | return -1; | ||
1090 | |||
1091 | /* dump the report */ | ||
1092 | dbg_hid("report %d (size %u) = ", report->id, size); | ||
1093 | for (i = 0; i < size; i++) | ||
1094 | dbg_hid_line(" %02x", data[i]); | ||
1095 | dbg_hid_line("\n"); | ||
1096 | |||
1097 | if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) { | ||
1098 | ret = hdrv->raw_event(hid, report, data, size); | ||
1099 | if (ret != 0) | ||
1100 | return ret < 0 ? ret : 0; | ||
1101 | } | ||
1102 | |||
1103 | hid_report_raw_event(hid, type, data, size, interrupt); | ||
1004 | 1104 | ||
1005 | return 0; | 1105 | return 0; |
1006 | } | 1106 | } |
1007 | EXPORT_SYMBOL_GPL(hid_input_report); | 1107 | EXPORT_SYMBOL_GPL(hid_input_report); |
1008 | 1108 | ||
1109 | static bool hid_match_one_id(struct hid_device *hdev, | ||
1110 | const struct hid_device_id *id) | ||
1111 | { | ||
1112 | return id->bus == hdev->bus && | ||
1113 | (id->vendor == HID_ANY_ID || id->vendor == hdev->vendor) && | ||
1114 | (id->product == HID_ANY_ID || id->product == hdev->product); | ||
1115 | } | ||
1116 | |||
1117 | static const struct hid_device_id *hid_match_id(struct hid_device *hdev, | ||
1118 | const struct hid_device_id *id) | ||
1119 | { | ||
1120 | for (; id->bus; id++) | ||
1121 | if (hid_match_one_id(hdev, id)) | ||
1122 | return id; | ||
1123 | |||
1124 | return NULL; | ||
1125 | } | ||
1126 | |||
1127 | static const struct hid_device_id hid_blacklist[] = { | ||
1128 | { } | ||
1129 | }; | ||
1130 | |||
1131 | static int hid_bus_match(struct device *dev, struct device_driver *drv) | ||
1132 | { | ||
1133 | struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver); | ||
1134 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); | ||
1135 | |||
1136 | if (!hid_match_id(hdev, hdrv->id_table)) | ||
1137 | return 0; | ||
1138 | |||
1139 | /* generic wants all non-blacklisted */ | ||
1140 | if (!strncmp(hdrv->name, "generic-", 8)) | ||
1141 | return !hid_match_id(hdev, hid_blacklist); | ||
1142 | |||
1143 | return 1; | ||
1144 | } | ||
1145 | |||
1146 | static int hid_device_probe(struct device *dev) | ||
1147 | { | ||
1148 | struct hid_driver *hdrv = container_of(dev->driver, | ||
1149 | struct hid_driver, driver); | ||
1150 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); | ||
1151 | const struct hid_device_id *id; | ||
1152 | int ret = 0; | ||
1153 | |||
1154 | if (!hdev->driver) { | ||
1155 | if (hdrv->probe) { | ||
1156 | ret = -ENODEV; | ||
1157 | |||
1158 | id = hid_match_id(hdev, hdrv->id_table); | ||
1159 | if (id) | ||
1160 | ret = hdrv->probe(hdev, id); | ||
1161 | } | ||
1162 | if (!ret) | ||
1163 | hdev->driver = hdrv; | ||
1164 | } | ||
1165 | return ret; | ||
1166 | } | ||
1167 | |||
1168 | static int hid_device_remove(struct device *dev) | ||
1169 | { | ||
1170 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); | ||
1171 | struct hid_driver *hdrv = hdev->driver; | ||
1172 | |||
1173 | if (hdrv) { | ||
1174 | if (hdrv->remove) | ||
1175 | hdrv->remove(hdev); | ||
1176 | hdev->driver = NULL; | ||
1177 | } | ||
1178 | |||
1179 | return 0; | ||
1180 | } | ||
1181 | |||
1182 | static int hid_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
1183 | { | ||
1184 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); | ||
1185 | |||
1186 | if (add_uevent_var(env, "HID_ID=%04X:%08X:%08X", | ||
1187 | hdev->bus, hdev->vendor, hdev->product)) | ||
1188 | return -ENOMEM; | ||
1189 | |||
1190 | if (add_uevent_var(env, "HID_NAME=%s", hdev->name)) | ||
1191 | return -ENOMEM; | ||
1192 | |||
1193 | if (add_uevent_var(env, "HID_PHYS=%s", hdev->phys)) | ||
1194 | return -ENOMEM; | ||
1195 | |||
1196 | if (add_uevent_var(env, "HID_UNIQ=%s", hdev->uniq)) | ||
1197 | return -ENOMEM; | ||
1198 | |||
1199 | if (add_uevent_var(env, "MODALIAS=hid:b%04Xv%08Xp%08X", | ||
1200 | hdev->bus, hdev->vendor, hdev->product)) | ||
1201 | return -ENOMEM; | ||
1202 | |||
1203 | return 0; | ||
1204 | } | ||
1205 | |||
1206 | static struct bus_type hid_bus_type = { | ||
1207 | .name = "hid", | ||
1208 | .match = hid_bus_match, | ||
1209 | .probe = hid_device_probe, | ||
1210 | .remove = hid_device_remove, | ||
1211 | .uevent = hid_uevent, | ||
1212 | }; | ||
1213 | |||
1214 | int hid_add_device(struct hid_device *hdev) | ||
1215 | { | ||
1216 | static atomic_t id = ATOMIC_INIT(0); | ||
1217 | int ret; | ||
1218 | |||
1219 | if (WARN_ON(hdev->status & HID_STAT_ADDED)) | ||
1220 | return -EBUSY; | ||
1221 | |||
1222 | /* XXX hack, any other cleaner solution < 20 bus_id bytes? */ | ||
1223 | sprintf(hdev->dev.bus_id, "%04X:%04X:%04X.%04X", hdev->bus, | ||
1224 | hdev->vendor, hdev->product, atomic_inc_return(&id)); | ||
1225 | |||
1226 | ret = device_add(&hdev->dev); | ||
1227 | if (!ret) | ||
1228 | hdev->status |= HID_STAT_ADDED; | ||
1229 | |||
1230 | return ret; | ||
1231 | } | ||
1232 | EXPORT_SYMBOL_GPL(hid_add_device); | ||
1233 | |||
1234 | /** | ||
1235 | * hid_allocate_device - allocate new hid device descriptor | ||
1236 | * | ||
1237 | * Allocate and initialize hid device, so that hid_destroy_device might be | ||
1238 | * used to free it. | ||
1239 | * | ||
1240 | * New hid_device pointer is returned on success, otherwise ERR_PTR encoded | ||
1241 | * error value. | ||
1242 | */ | ||
1243 | struct hid_device *hid_allocate_device(void) | ||
1244 | { | ||
1245 | struct hid_device *hdev; | ||
1246 | unsigned int i; | ||
1247 | int ret = -ENOMEM; | ||
1248 | |||
1249 | hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); | ||
1250 | if (hdev == NULL) | ||
1251 | return ERR_PTR(ret); | ||
1252 | |||
1253 | device_initialize(&hdev->dev); | ||
1254 | hdev->dev.release = hid_device_release; | ||
1255 | hdev->dev.bus = &hid_bus_type; | ||
1256 | |||
1257 | hdev->collection = kcalloc(HID_DEFAULT_NUM_COLLECTIONS, | ||
1258 | sizeof(struct hid_collection), GFP_KERNEL); | ||
1259 | if (hdev->collection == NULL) | ||
1260 | goto err; | ||
1261 | hdev->collection_size = HID_DEFAULT_NUM_COLLECTIONS; | ||
1262 | |||
1263 | for (i = 0; i < HID_REPORT_TYPES; i++) | ||
1264 | INIT_LIST_HEAD(&hdev->report_enum[i].report_list); | ||
1265 | |||
1266 | return hdev; | ||
1267 | err: | ||
1268 | put_device(&hdev->dev); | ||
1269 | return ERR_PTR(ret); | ||
1270 | } | ||
1271 | EXPORT_SYMBOL_GPL(hid_allocate_device); | ||
1272 | |||
1273 | static void hid_remove_device(struct hid_device *hdev) | ||
1274 | { | ||
1275 | if (hdev->status & HID_STAT_ADDED) { | ||
1276 | device_del(&hdev->dev); | ||
1277 | hdev->status &= ~HID_STAT_ADDED; | ||
1278 | } | ||
1279 | } | ||
1280 | |||
1281 | /** | ||
1282 | * hid_destroy_device - free previously allocated device | ||
1283 | * | ||
1284 | * @hdev: hid device | ||
1285 | * | ||
1286 | * If you allocate hid_device through hid_allocate_device, you should ever | ||
1287 | * free by this function. | ||
1288 | */ | ||
1289 | void hid_destroy_device(struct hid_device *hdev) | ||
1290 | { | ||
1291 | hid_remove_device(hdev); | ||
1292 | put_device(&hdev->dev); | ||
1293 | } | ||
1294 | EXPORT_SYMBOL_GPL(hid_destroy_device); | ||
1295 | |||
1296 | int __hid_register_driver(struct hid_driver *hdrv, struct module *owner, | ||
1297 | const char *mod_name) | ||
1298 | { | ||
1299 | hdrv->driver.name = hdrv->name; | ||
1300 | hdrv->driver.bus = &hid_bus_type; | ||
1301 | hdrv->driver.owner = owner; | ||
1302 | hdrv->driver.mod_name = mod_name; | ||
1303 | |||
1304 | return driver_register(&hdrv->driver); | ||
1305 | } | ||
1306 | EXPORT_SYMBOL_GPL(__hid_register_driver); | ||
1307 | |||
1308 | void hid_unregister_driver(struct hid_driver *hdrv) | ||
1309 | { | ||
1310 | driver_unregister(&hdrv->driver); | ||
1311 | } | ||
1312 | EXPORT_SYMBOL_GPL(hid_unregister_driver); | ||
1313 | |||
1009 | static int __init hid_init(void) | 1314 | static int __init hid_init(void) |
1010 | { | 1315 | { |
1011 | return hidraw_init(); | 1316 | int ret; |
1317 | |||
1318 | ret = bus_register(&hid_bus_type); | ||
1319 | if (ret) { | ||
1320 | printk(KERN_ERR "HID: can't register hid bus\n"); | ||
1321 | goto err; | ||
1322 | } | ||
1323 | |||
1324 | ret = hidraw_init(); | ||
1325 | if (ret) | ||
1326 | goto err_bus; | ||
1327 | |||
1328 | return 0; | ||
1329 | err_bus: | ||
1330 | bus_unregister(&hid_bus_type); | ||
1331 | err: | ||
1332 | return ret; | ||
1012 | } | 1333 | } |
1013 | 1334 | ||
1014 | static void __exit hid_exit(void) | 1335 | static void __exit hid_exit(void) |
1015 | { | 1336 | { |
1016 | hidraw_exit(); | 1337 | hidraw_exit(); |
1338 | bus_unregister(&hid_bus_type); | ||
1017 | } | 1339 | } |
1018 | 1340 | ||
1019 | module_init(hid_init); | 1341 | module_init(hid_init); |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 1b2e8dc3398d..4ae5603804e7 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -1032,7 +1032,7 @@ int hidinput_connect(struct hid_device *hid) | |||
1032 | input_dev->id.vendor = hid->vendor; | 1032 | input_dev->id.vendor = hid->vendor; |
1033 | input_dev->id.product = hid->product; | 1033 | input_dev->id.product = hid->product; |
1034 | input_dev->id.version = hid->version; | 1034 | input_dev->id.version = hid->version; |
1035 | input_dev->dev.parent = hid->dev; | 1035 | input_dev->dev.parent = hid->dev.parent; |
1036 | hidinput->input = input_dev; | 1036 | hidinput->input = input_dev; |
1037 | list_add_tail(&hidinput->list, &hid->inputs); | 1037 | list_add_tail(&hidinput->list, &hid->inputs); |
1038 | } | 1038 | } |
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 27fe4d8912cb..5955d05ae542 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -770,8 +770,15 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
770 | dbg_hid_line(" %02x", (unsigned char) rdesc[n]); | 770 | dbg_hid_line(" %02x", (unsigned char) rdesc[n]); |
771 | dbg_hid_line("\n"); | 771 | dbg_hid_line("\n"); |
772 | 772 | ||
773 | if (!(hid = hid_parse_report(rdesc, n))) { | 773 | hid = hid_allocate_device(); |
774 | if (IS_ERR(hid)) { | ||
775 | kfree(rdesc); | ||
776 | return NULL; | ||
777 | } | ||
778 | |||
779 | if (hid_parse_report(hid, rdesc, n)) { | ||
774 | dbg_hid("parsing report descriptor failed\n"); | 780 | dbg_hid("parsing report descriptor failed\n"); |
781 | hid_destroy_device(hid); | ||
775 | kfree(rdesc); | 782 | kfree(rdesc); |
776 | return NULL; | 783 | return NULL; |
777 | } | 784 | } |
@@ -798,10 +805,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
798 | if (insize > HID_MAX_BUFFER_SIZE) | 805 | if (insize > HID_MAX_BUFFER_SIZE) |
799 | insize = HID_MAX_BUFFER_SIZE; | 806 | insize = HID_MAX_BUFFER_SIZE; |
800 | 807 | ||
801 | if (hid_alloc_buffers(dev, hid)) { | 808 | if (hid_alloc_buffers(dev, hid)) |
802 | hid_free_buffers(dev, hid); | ||
803 | goto fail; | 809 | goto fail; |
804 | } | ||
805 | 810 | ||
806 | hid->name[0] = 0; | 811 | hid->name[0] = 0; |
807 | 812 | ||
@@ -881,7 +886,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
881 | 886 | ||
882 | hid->version = le16_to_cpu(hdesc->bcdHID); | 887 | hid->version = le16_to_cpu(hdesc->bcdHID); |
883 | hid->country = hdesc->bCountryCode; | 888 | hid->country = hdesc->bCountryCode; |
884 | hid->dev = &intf->dev; | 889 | hid->dev.parent = &intf->dev; |
885 | usbhid->intf = intf; | 890 | usbhid->intf = intf; |
886 | usbhid->ifnum = interface->desc.bInterfaceNumber; | 891 | usbhid->ifnum = interface->desc.bInterfaceNumber; |
887 | 892 | ||
@@ -925,7 +930,7 @@ fail: | |||
925 | hid_free_buffers(dev, hid); | 930 | hid_free_buffers(dev, hid); |
926 | kfree(usbhid); | 931 | kfree(usbhid); |
927 | fail_no_usbhid: | 932 | fail_no_usbhid: |
928 | hid_free_device(hid); | 933 | hid_destroy_device(hid); |
929 | 934 | ||
930 | return NULL; | 935 | return NULL; |
931 | } | 936 | } |
@@ -964,14 +969,14 @@ static void hid_disconnect(struct usb_interface *intf) | |||
964 | 969 | ||
965 | hid_free_buffers(hid_to_usb_dev(hid), hid); | 970 | hid_free_buffers(hid_to_usb_dev(hid), hid); |
966 | kfree(usbhid); | 971 | kfree(usbhid); |
967 | hid_free_device(hid); | 972 | hid_destroy_device(hid); |
968 | } | 973 | } |
969 | 974 | ||
970 | static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) | 975 | static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) |
971 | { | 976 | { |
972 | struct hid_device *hid; | 977 | struct hid_device *hid; |
973 | char path[64]; | 978 | char path[64]; |
974 | int i; | 979 | int i, ret; |
975 | char *c; | 980 | char *c; |
976 | 981 | ||
977 | dbg_hid("HID probe called for ifnum %d\n", | 982 | dbg_hid("HID probe called for ifnum %d\n", |
@@ -1037,7 +1042,12 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
1037 | printk(": USB HID v%x.%02x %s [%s] on %s\n", | 1042 | printk(": USB HID v%x.%02x %s [%s] on %s\n", |
1038 | hid->version >> 8, hid->version & 0xff, c, hid->name, path); | 1043 | hid->version >> 8, hid->version & 0xff, c, hid->name, path); |
1039 | 1044 | ||
1040 | return 0; | 1045 | ret = hid_add_device(hid); |
1046 | if (ret) { | ||
1047 | dev_err(&intf->dev, "can't add hid device: %d\n", ret); | ||
1048 | hid_disconnect(intf); | ||
1049 | } | ||
1050 | return ret; | ||
1041 | } | 1051 | } |
1042 | 1052 | ||
1043 | static int hid_suspend(struct usb_interface *intf, pm_message_t message) | 1053 | static int hid_suspend(struct usb_interface *intf, pm_message_t message) |
@@ -1107,9 +1117,22 @@ static struct usb_driver hid_driver = { | |||
1107 | .supports_autosuspend = 1, | 1117 | .supports_autosuspend = 1, |
1108 | }; | 1118 | }; |
1109 | 1119 | ||
1120 | static const struct hid_device_id hid_usb_table[] = { | ||
1121 | { HID_USB_DEVICE(HID_ANY_ID, HID_ANY_ID) }, | ||
1122 | { } | ||
1123 | }; | ||
1124 | |||
1125 | static struct hid_driver hid_usb_driver = { | ||
1126 | .name = "generic-usb", | ||
1127 | .id_table = hid_usb_table, | ||
1128 | }; | ||
1129 | |||
1110 | static int __init hid_init(void) | 1130 | static int __init hid_init(void) |
1111 | { | 1131 | { |
1112 | int retval; | 1132 | int retval; |
1133 | retval = hid_register_driver(&hid_usb_driver); | ||
1134 | if (retval) | ||
1135 | goto hid_register_fail; | ||
1113 | retval = usbhid_quirks_init(quirks_param); | 1136 | retval = usbhid_quirks_init(quirks_param); |
1114 | if (retval) | 1137 | if (retval) |
1115 | goto usbhid_quirks_init_fail; | 1138 | goto usbhid_quirks_init_fail; |
@@ -1127,6 +1150,8 @@ usb_register_fail: | |||
1127 | hiddev_init_fail: | 1150 | hiddev_init_fail: |
1128 | usbhid_quirks_exit(); | 1151 | usbhid_quirks_exit(); |
1129 | usbhid_quirks_init_fail: | 1152 | usbhid_quirks_init_fail: |
1153 | hid_unregister_driver(&hid_usb_driver); | ||
1154 | hid_register_fail: | ||
1130 | return retval; | 1155 | return retval; |
1131 | } | 1156 | } |
1132 | 1157 | ||
@@ -1135,6 +1160,7 @@ static void __exit hid_exit(void) | |||
1135 | usb_deregister(&hid_driver); | 1160 | usb_deregister(&hid_driver); |
1136 | hiddev_exit(); | 1161 | hiddev_exit(); |
1137 | usbhid_quirks_exit(); | 1162 | usbhid_quirks_exit(); |
1163 | hid_unregister_driver(&hid_usb_driver); | ||
1138 | } | 1164 | } |
1139 | 1165 | ||
1140 | module_init(hid_init); | 1166 | module_init(hid_init); |
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index 62d2d7c925bd..b47f991867e9 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h | |||
@@ -82,7 +82,7 @@ struct usbhid_device { | |||
82 | }; | 82 | }; |
83 | 83 | ||
84 | #define hid_to_usb_dev(hid_dev) \ | 84 | #define hid_to_usb_dev(hid_dev) \ |
85 | container_of(hid_dev->dev->parent, struct usb_device, dev) | 85 | container_of(hid_dev->dev.parent->parent, struct usb_device, dev) |
86 | 86 | ||
87 | #endif | 87 | #endif |
88 | 88 | ||