diff options
author | Jiri Slaby <jirislaby@gmail.com> | 2008-05-16 05:49:16 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2008-10-14 17:50:48 -0400 |
commit | c500c9714011edab021591340042787722db9cf0 (patch) | |
tree | d6bb0fe483c9f1c71c3d757e9c13d261ca01cd5f | |
parent | 85cdaf524b7ddab627e7d15405693f2511ef7505 (diff) |
HID: hid, make parsing event driven
Next step for complete hid bus, this patch includes:
- call parser either from probe or from hid-core if there is no probe.
- add ll_driver structure and centralize some stuff there (open, close...)
- split and merge usb_hid_configure and hid_probe into several functions
to allow hooks/fixes between them
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | drivers/hid/hid-core.c | 24 | ||||
-rw-r--r-- | drivers/hid/hid-input.c | 20 | ||||
-rw-r--r-- | drivers/hid/hidraw.c | 6 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 330 | ||||
-rw-r--r-- | include/linux/hid.h | 104 | ||||
-rw-r--r-- | net/bluetooth/hidp/core.c | 191 | ||||
-rw-r--r-- | net/bluetooth/hidp/hidp.h | 2 |
7 files changed, 438 insertions, 239 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 017fc20167d4..3dacbcd7e41c 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -648,6 +648,9 @@ int hid_parse_report(struct hid_device *device, __u8 *start, | |||
648 | hid_parser_reserved | 648 | hid_parser_reserved |
649 | }; | 649 | }; |
650 | 650 | ||
651 | if (device->driver->report_fixup) | ||
652 | device->driver->report_fixup(device, start, size); | ||
653 | |||
651 | device->rdesc = kmalloc(size, GFP_KERNEL); | 654 | device->rdesc = kmalloc(size, GFP_KERNEL); |
652 | if (device->rdesc == NULL) | 655 | if (device->rdesc == NULL) |
653 | return -ENOMEM; | 656 | return -ENOMEM; |
@@ -1152,15 +1155,20 @@ static int hid_device_probe(struct device *dev) | |||
1152 | int ret = 0; | 1155 | int ret = 0; |
1153 | 1156 | ||
1154 | if (!hdev->driver) { | 1157 | if (!hdev->driver) { |
1155 | if (hdrv->probe) { | 1158 | id = hid_match_id(hdev, hdrv->id_table); |
1156 | ret = -ENODEV; | 1159 | if (id == NULL) |
1160 | return -ENODEV; | ||
1157 | 1161 | ||
1158 | id = hid_match_id(hdev, hdrv->id_table); | 1162 | hdev->driver = hdrv; |
1159 | if (id) | 1163 | if (hdrv->probe) { |
1160 | ret = hdrv->probe(hdev, id); | 1164 | ret = hdrv->probe(hdev, id); |
1165 | } else { /* default probe */ | ||
1166 | ret = hid_parse(hdev); | ||
1167 | if (!ret) | ||
1168 | ret = hid_hw_start(hdev); | ||
1161 | } | 1169 | } |
1162 | if (!ret) | 1170 | if (ret) |
1163 | hdev->driver = hdrv; | 1171 | hdev->driver = NULL; |
1164 | } | 1172 | } |
1165 | return ret; | 1173 | return ret; |
1166 | } | 1174 | } |
@@ -1173,6 +1181,8 @@ static int hid_device_remove(struct device *dev) | |||
1173 | if (hdrv) { | 1181 | if (hdrv) { |
1174 | if (hdrv->remove) | 1182 | if (hdrv->remove) |
1175 | hdrv->remove(hdev); | 1183 | hdrv->remove(hdev); |
1184 | else /* default remove */ | ||
1185 | hid_hw_stop(hdev); | ||
1176 | hdev->driver = NULL; | 1186 | hdev->driver = NULL; |
1177 | } | 1187 | } |
1178 | 1188 | ||
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 4ae5603804e7..9fa7239ab310 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -390,6 +390,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
390 | if (ret) | 390 | if (ret) |
391 | goto mapped; | 391 | goto mapped; |
392 | 392 | ||
393 | if (device->driver->input_mapping) { | ||
394 | int ret = device->driver->input_mapping(device, hidinput, field, | ||
395 | usage, &bit, &max); | ||
396 | if (ret > 0) | ||
397 | goto mapped; | ||
398 | if (ret < 0) | ||
399 | goto ignore; | ||
400 | } | ||
401 | |||
393 | switch (usage->hid & HID_USAGE_PAGE) { | 402 | switch (usage->hid & HID_USAGE_PAGE) { |
394 | 403 | ||
395 | case HID_UP_UNDEFINED: | 404 | case HID_UP_UNDEFINED: |
@@ -755,6 +764,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
755 | } | 764 | } |
756 | 765 | ||
757 | mapped: | 766 | mapped: |
767 | if (device->driver->input_mapped && device->driver->input_mapped(device, | ||
768 | hidinput, field, usage, &bit, &max) < 0) | ||
769 | goto ignore; | ||
770 | |||
758 | if (device->quirks & HID_QUIRK_MIGHTYMOUSE) { | 771 | if (device->quirks & HID_QUIRK_MIGHTYMOUSE) { |
759 | if (usage->hid == HID_GD_Z) | 772 | if (usage->hid == HID_GD_Z) |
760 | map_rel(REL_HWHEEL); | 773 | map_rel(REL_HWHEEL); |
@@ -961,14 +974,14 @@ static int hidinput_open(struct input_dev *dev) | |||
961 | { | 974 | { |
962 | struct hid_device *hid = input_get_drvdata(dev); | 975 | struct hid_device *hid = input_get_drvdata(dev); |
963 | 976 | ||
964 | return hid->hid_open(hid); | 977 | return hid->ll_driver->open(hid); |
965 | } | 978 | } |
966 | 979 | ||
967 | static void hidinput_close(struct input_dev *dev) | 980 | static void hidinput_close(struct input_dev *dev) |
968 | { | 981 | { |
969 | struct hid_device *hid = input_get_drvdata(dev); | 982 | struct hid_device *hid = input_get_drvdata(dev); |
970 | 983 | ||
971 | hid->hid_close(hid); | 984 | hid->ll_driver->close(hid); |
972 | } | 985 | } |
973 | 986 | ||
974 | /* | 987 | /* |
@@ -1019,7 +1032,8 @@ int hidinput_connect(struct hid_device *hid) | |||
1019 | } | 1032 | } |
1020 | 1033 | ||
1021 | input_set_drvdata(input_dev, hid); | 1034 | input_set_drvdata(input_dev, hid); |
1022 | input_dev->event = hid->hidinput_input_event; | 1035 | input_dev->event = |
1036 | hid->ll_driver->hidinput_input_event; | ||
1023 | input_dev->open = hidinput_open; | 1037 | input_dev->open = hidinput_open; |
1024 | input_dev->close = hidinput_close; | 1038 | input_dev->close = hidinput_close; |
1025 | input_dev->setkeycode = hidinput_setkeycode; | 1039 | input_dev->setkeycode = hidinput_setkeycode; |
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index c40f0403edaf..4be240e74d4f 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c | |||
@@ -181,7 +181,7 @@ static int hidraw_open(struct inode *inode, struct file *file) | |||
181 | 181 | ||
182 | dev = hidraw_table[minor]; | 182 | dev = hidraw_table[minor]; |
183 | if (!dev->open++) | 183 | if (!dev->open++) |
184 | dev->hid->hid_open(dev->hid); | 184 | dev->hid->ll_driver->open(dev->hid); |
185 | 185 | ||
186 | out_unlock: | 186 | out_unlock: |
187 | spin_unlock(&minors_lock); | 187 | spin_unlock(&minors_lock); |
@@ -207,7 +207,7 @@ static int hidraw_release(struct inode * inode, struct file * file) | |||
207 | dev = hidraw_table[minor]; | 207 | dev = hidraw_table[minor]; |
208 | if (!dev->open--) { | 208 | if (!dev->open--) { |
209 | if (list->hidraw->exist) | 209 | if (list->hidraw->exist) |
210 | dev->hid->hid_close(dev->hid); | 210 | dev->hid->ll_driver->close(dev->hid); |
211 | else | 211 | else |
212 | kfree(list->hidraw); | 212 | kfree(list->hidraw); |
213 | } | 213 | } |
@@ -367,7 +367,7 @@ void hidraw_disconnect(struct hid_device *hid) | |||
367 | device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); | 367 | device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); |
368 | 368 | ||
369 | if (hidraw->open) { | 369 | if (hidraw->open) { |
370 | hid->hid_close(hid); | 370 | hid->ll_driver->close(hid); |
371 | wake_up_interruptible(&hidraw->wait); | 371 | wake_up_interruptible(&hidraw->wait); |
372 | } else { | 372 | } else { |
373 | kfree(hidraw); | 373 | kfree(hidraw); |
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 5955d05ae542..d2a3461909a3 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -701,17 +701,84 @@ static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum) | |||
701 | kfree(buf); | 701 | kfree(buf); |
702 | } | 702 | } |
703 | 703 | ||
704 | static struct hid_device *usb_hid_configure(struct usb_interface *intf) | 704 | static int usbhid_start_finish(struct hid_device *hid) |
705 | { | 705 | { |
706 | struct usb_interface *intf = to_usb_interface(hid->dev.parent); | ||
707 | char path[64], *type; | ||
708 | unsigned int i; | ||
709 | |||
710 | usbhid_init_reports(hid); | ||
711 | hid_dump_device(hid); | ||
712 | if (hid->quirks & HID_QUIRK_RESET_LEDS) | ||
713 | usbhid_set_leds(hid); | ||
714 | |||
715 | if (!hidinput_connect(hid)) | ||
716 | hid->claimed |= HID_CLAIMED_INPUT; | ||
717 | if (!hiddev_connect(hid)) | ||
718 | hid->claimed |= HID_CLAIMED_HIDDEV; | ||
719 | if (!hidraw_connect(hid)) | ||
720 | hid->claimed |= HID_CLAIMED_HIDRAW; | ||
721 | |||
722 | if (!hid->claimed) { | ||
723 | printk(KERN_ERR "HID device claimed by neither input, hiddev " | ||
724 | "nor hidraw\n"); | ||
725 | return -ENODEV; | ||
726 | } | ||
727 | |||
728 | if ((hid->claimed & HID_CLAIMED_INPUT)) | ||
729 | hid_ff_init(hid); | ||
730 | |||
731 | if (hid->quirks & HID_QUIRK_SONY_PS3_CONTROLLER) | ||
732 | hid_fixup_sony_ps3_controller(interface_to_usbdev(intf), | ||
733 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
734 | |||
735 | printk(KERN_INFO); | ||
736 | |||
737 | if (hid->claimed & HID_CLAIMED_INPUT) | ||
738 | printk("input"); | ||
739 | if ((hid->claimed & HID_CLAIMED_INPUT) && | ||
740 | ((hid->claimed & HID_CLAIMED_HIDDEV) || | ||
741 | hid->claimed & HID_CLAIMED_HIDRAW)) | ||
742 | printk(","); | ||
743 | if (hid->claimed & HID_CLAIMED_HIDDEV) | ||
744 | printk("hiddev%d", hid->minor); | ||
745 | if ((hid->claimed & HID_CLAIMED_INPUT) && | ||
746 | (hid->claimed & HID_CLAIMED_HIDDEV) && | ||
747 | (hid->claimed & HID_CLAIMED_HIDRAW)) | ||
748 | printk(","); | ||
749 | if (hid->claimed & HID_CLAIMED_HIDRAW) | ||
750 | printk("hidraw%d", ((struct hidraw *)hid->hidraw)->minor); | ||
751 | |||
752 | type = "Device"; | ||
753 | for (i = 0; i < hid->maxcollection; i++) { | ||
754 | if (hid->collection[i].type == HID_COLLECTION_APPLICATION && | ||
755 | (hid->collection[i].usage & HID_USAGE_PAGE) == | ||
756 | HID_UP_GENDESK && | ||
757 | (hid->collection[i].usage & 0xffff) < | ||
758 | ARRAY_SIZE(hid_types)) { | ||
759 | type = hid_types[hid->collection[i].usage & 0xffff]; | ||
760 | break; | ||
761 | } | ||
762 | } | ||
763 | |||
764 | usb_make_path(interface_to_usbdev(intf), path, 63); | ||
765 | |||
766 | printk(": USB HID v%x.%02x %s [%s] on %s\n", | ||
767 | hid->version >> 8, hid->version & 0xff, type, hid->name, path); | ||
768 | |||
769 | return 0; | ||
770 | } | ||
771 | |||
772 | static int usbhid_parse(struct hid_device *hid) | ||
773 | { | ||
774 | struct usb_interface *intf = to_usb_interface(hid->dev.parent); | ||
706 | struct usb_host_interface *interface = intf->cur_altsetting; | 775 | struct usb_host_interface *interface = intf->cur_altsetting; |
707 | struct usb_device *dev = interface_to_usbdev (intf); | 776 | struct usb_device *dev = interface_to_usbdev (intf); |
708 | struct hid_descriptor *hdesc; | 777 | struct hid_descriptor *hdesc; |
709 | struct hid_device *hid; | ||
710 | u32 quirks = 0; | 778 | u32 quirks = 0; |
711 | unsigned int insize = 0, rsize = 0; | 779 | unsigned int rsize = 0; |
712 | char *rdesc; | 780 | char *rdesc; |
713 | int n, len; | 781 | int ret, n; |
714 | struct usbhid_device *usbhid; | ||
715 | 782 | ||
716 | quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor), | 783 | quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor), |
717 | le16_to_cpu(dev->descriptor.idProduct)); | 784 | le16_to_cpu(dev->descriptor.idProduct)); |
@@ -725,40 +792,44 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
725 | } | 792 | } |
726 | 793 | ||
727 | if (quirks & HID_QUIRK_IGNORE) | 794 | if (quirks & HID_QUIRK_IGNORE) |
728 | return NULL; | 795 | return -ENODEV; |
729 | 796 | ||
730 | if ((quirks & HID_QUIRK_IGNORE_MOUSE) && | 797 | if ((quirks & HID_QUIRK_IGNORE_MOUSE) && |
731 | (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)) | 798 | (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)) |
732 | return NULL; | 799 | return -ENODEV; |
733 | |||
734 | 800 | ||
735 | if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && | 801 | if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && |
736 | (!interface->desc.bNumEndpoints || | 802 | (!interface->desc.bNumEndpoints || |
737 | usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) { | 803 | usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) { |
738 | dbg_hid("class descriptor not present\n"); | 804 | dbg_hid("class descriptor not present\n"); |
739 | return NULL; | 805 | return -ENODEV; |
740 | } | 806 | } |
741 | 807 | ||
808 | hid->version = le16_to_cpu(hdesc->bcdHID); | ||
809 | hid->country = hdesc->bCountryCode; | ||
810 | |||
742 | for (n = 0; n < hdesc->bNumDescriptors; n++) | 811 | for (n = 0; n < hdesc->bNumDescriptors; n++) |
743 | if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT) | 812 | if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT) |
744 | rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength); | 813 | rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength); |
745 | 814 | ||
746 | if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) { | 815 | if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) { |
747 | dbg_hid("weird size of report descriptor (%u)\n", rsize); | 816 | dbg_hid("weird size of report descriptor (%u)\n", rsize); |
748 | return NULL; | 817 | return -EINVAL; |
749 | } | 818 | } |
750 | 819 | ||
751 | if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) { | 820 | if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) { |
752 | dbg_hid("couldn't allocate rdesc memory\n"); | 821 | dbg_hid("couldn't allocate rdesc memory\n"); |
753 | return NULL; | 822 | return -ENOMEM; |
754 | } | 823 | } |
755 | 824 | ||
756 | hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0); | 825 | hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0); |
757 | 826 | ||
758 | if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) { | 827 | ret = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, |
828 | HID_DT_REPORT, rdesc, rsize); | ||
829 | if (ret < 0) { | ||
759 | dbg_hid("reading report descriptor failed\n"); | 830 | dbg_hid("reading report descriptor failed\n"); |
760 | kfree(rdesc); | 831 | kfree(rdesc); |
761 | return NULL; | 832 | goto err; |
762 | } | 833 | } |
763 | 834 | ||
764 | usbhid_fixup_report_descriptor(le16_to_cpu(dev->descriptor.idVendor), | 835 | usbhid_fixup_report_descriptor(le16_to_cpu(dev->descriptor.idVendor), |
@@ -770,24 +841,36 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
770 | dbg_hid_line(" %02x", (unsigned char) rdesc[n]); | 841 | dbg_hid_line(" %02x", (unsigned char) rdesc[n]); |
771 | dbg_hid_line("\n"); | 842 | dbg_hid_line("\n"); |
772 | 843 | ||
773 | hid = hid_allocate_device(); | 844 | ret = hid_parse_report(hid, rdesc, rsize); |
774 | if (IS_ERR(hid)) { | 845 | kfree(rdesc); |
775 | kfree(rdesc); | 846 | if (ret) { |
776 | return NULL; | ||
777 | } | ||
778 | |||
779 | if (hid_parse_report(hid, rdesc, n)) { | ||
780 | dbg_hid("parsing report descriptor failed\n"); | 847 | dbg_hid("parsing report descriptor failed\n"); |
781 | hid_destroy_device(hid); | 848 | goto err; |
782 | kfree(rdesc); | ||
783 | return NULL; | ||
784 | } | 849 | } |
785 | 850 | ||
786 | kfree(rdesc); | ||
787 | hid->quirks = quirks; | 851 | hid->quirks = quirks; |
788 | 852 | ||
789 | if (!(usbhid = kzalloc(sizeof(struct usbhid_device), GFP_KERNEL))) | 853 | return 0; |
790 | goto fail_no_usbhid; | 854 | err: |
855 | return ret; | ||
856 | } | ||
857 | |||
858 | static int usbhid_start(struct hid_device *hid) | ||
859 | { | ||
860 | struct usb_interface *intf = to_usb_interface(hid->dev.parent); | ||
861 | struct usb_host_interface *interface = intf->cur_altsetting; | ||
862 | struct usb_device *dev = interface_to_usbdev(intf); | ||
863 | struct usbhid_device *usbhid; | ||
864 | unsigned int n, insize = 0; | ||
865 | int ret; | ||
866 | |||
867 | WARN_ON(hid->driver_data); | ||
868 | |||
869 | usbhid = kzalloc(sizeof(struct usbhid_device), GFP_KERNEL); | ||
870 | if (usbhid == NULL) { | ||
871 | ret = -ENOMEM; | ||
872 | goto err; | ||
873 | } | ||
791 | 874 | ||
792 | hid->driver_data = usbhid; | 875 | hid->driver_data = usbhid; |
793 | usbhid->hid = hid; | 876 | usbhid->hid = hid; |
@@ -805,27 +888,12 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
805 | if (insize > HID_MAX_BUFFER_SIZE) | 888 | if (insize > HID_MAX_BUFFER_SIZE) |
806 | insize = HID_MAX_BUFFER_SIZE; | 889 | insize = HID_MAX_BUFFER_SIZE; |
807 | 890 | ||
808 | if (hid_alloc_buffers(dev, hid)) | 891 | if (hid_alloc_buffers(dev, hid)) { |
892 | ret = -ENOMEM; | ||
809 | goto fail; | 893 | goto fail; |
810 | |||
811 | hid->name[0] = 0; | ||
812 | |||
813 | if (dev->manufacturer) | ||
814 | strlcpy(hid->name, dev->manufacturer, sizeof(hid->name)); | ||
815 | |||
816 | if (dev->product) { | ||
817 | if (dev->manufacturer) | ||
818 | strlcat(hid->name, " ", sizeof(hid->name)); | ||
819 | strlcat(hid->name, dev->product, sizeof(hid->name)); | ||
820 | } | 894 | } |
821 | 895 | ||
822 | if (!strlen(hid->name)) | ||
823 | snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x", | ||
824 | le16_to_cpu(dev->descriptor.idVendor), | ||
825 | le16_to_cpu(dev->descriptor.idProduct)); | ||
826 | |||
827 | for (n = 0; n < interface->desc.bNumEndpoints; n++) { | 896 | for (n = 0; n < interface->desc.bNumEndpoints; n++) { |
828 | |||
829 | struct usb_endpoint_descriptor *endpoint; | 897 | struct usb_endpoint_descriptor *endpoint; |
830 | int pipe; | 898 | int pipe; |
831 | int interval; | 899 | int interval; |
@@ -837,7 +905,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
837 | interval = endpoint->bInterval; | 905 | interval = endpoint->bInterval; |
838 | 906 | ||
839 | /* Some vendors give fullspeed interval on highspeed devides */ | 907 | /* Some vendors give fullspeed interval on highspeed devides */ |
840 | if (quirks & HID_QUIRK_FULLSPEED_INTERVAL && | 908 | if (hid->quirks & HID_QUIRK_FULLSPEED_INTERVAL && |
841 | dev->speed == USB_SPEED_HIGH) { | 909 | dev->speed == USB_SPEED_HIGH) { |
842 | interval = fls(endpoint->bInterval*8); | 910 | interval = fls(endpoint->bInterval*8); |
843 | printk(KERN_INFO "%s: Fixing fullspeed to highspeed interval: %d -> %d\n", | 911 | printk(KERN_INFO "%s: Fixing fullspeed to highspeed interval: %d -> %d\n", |
@@ -848,6 +916,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
848 | if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) | 916 | if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) |
849 | interval = hid_mousepoll_interval; | 917 | interval = hid_mousepoll_interval; |
850 | 918 | ||
919 | ret = -ENOMEM; | ||
851 | if (usb_endpoint_dir_in(endpoint)) { | 920 | if (usb_endpoint_dir_in(endpoint)) { |
852 | if (usbhid->urbin) | 921 | if (usbhid->urbin) |
853 | continue; | 922 | continue; |
@@ -873,6 +942,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
873 | 942 | ||
874 | if (!usbhid->urbin) { | 943 | if (!usbhid->urbin) { |
875 | err_hid("couldn't find an input interrupt endpoint"); | 944 | err_hid("couldn't find an input interrupt endpoint"); |
945 | ret = -ENODEV; | ||
876 | goto fail; | 946 | goto fail; |
877 | } | 947 | } |
878 | 948 | ||
@@ -884,44 +954,26 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
884 | spin_lock_init(&usbhid->outlock); | 954 | spin_lock_init(&usbhid->outlock); |
885 | spin_lock_init(&usbhid->ctrllock); | 955 | spin_lock_init(&usbhid->ctrllock); |
886 | 956 | ||
887 | hid->version = le16_to_cpu(hdesc->bcdHID); | ||
888 | hid->country = hdesc->bCountryCode; | ||
889 | hid->dev.parent = &intf->dev; | ||
890 | usbhid->intf = intf; | 957 | usbhid->intf = intf; |
891 | usbhid->ifnum = interface->desc.bInterfaceNumber; | 958 | usbhid->ifnum = interface->desc.bInterfaceNumber; |
892 | 959 | ||
893 | hid->bus = BUS_USB; | ||
894 | hid->vendor = le16_to_cpu(dev->descriptor.idVendor); | ||
895 | hid->product = le16_to_cpu(dev->descriptor.idProduct); | ||
896 | |||
897 | usb_make_path(dev, hid->phys, sizeof(hid->phys)); | ||
898 | strlcat(hid->phys, "/input", sizeof(hid->phys)); | ||
899 | len = strlen(hid->phys); | ||
900 | if (len < sizeof(hid->phys) - 1) | ||
901 | snprintf(hid->phys + len, sizeof(hid->phys) - len, | ||
902 | "%d", intf->altsetting[0].desc.bInterfaceNumber); | ||
903 | |||
904 | if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0) | ||
905 | hid->uniq[0] = 0; | ||
906 | |||
907 | usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL); | 960 | usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL); |
908 | if (!usbhid->urbctrl) | 961 | if (!usbhid->urbctrl) { |
962 | ret = -ENOMEM; | ||
909 | goto fail; | 963 | goto fail; |
964 | } | ||
910 | 965 | ||
911 | usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr, | 966 | usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr, |
912 | usbhid->ctrlbuf, 1, hid_ctrl, hid); | 967 | usbhid->ctrlbuf, 1, hid_ctrl, hid); |
913 | usbhid->urbctrl->setup_dma = usbhid->cr_dma; | 968 | usbhid->urbctrl->setup_dma = usbhid->cr_dma; |
914 | usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma; | 969 | usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma; |
915 | usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); | 970 | usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); |
916 | hid->hidinput_input_event = usb_hidinput_input_event; | 971 | |
917 | hid->hid_open = usbhid_open; | 972 | ret = usbhid_start_finish(hid); |
918 | hid->hid_close = usbhid_close; | 973 | if (ret) |
919 | #ifdef CONFIG_USB_HIDDEV | 974 | goto fail; |
920 | hid->hiddev_hid_event = hiddev_hid_event; | 975 | |
921 | hid->hiddev_report_event = hiddev_report_event; | 976 | return 0; |
922 | #endif | ||
923 | hid->hid_output_raw_report = usbhid_output_raw_report; | ||
924 | return hid; | ||
925 | 977 | ||
926 | fail: | 978 | fail: |
927 | usb_free_urb(usbhid->urbin); | 979 | usb_free_urb(usbhid->urbin); |
@@ -929,24 +981,18 @@ fail: | |||
929 | usb_free_urb(usbhid->urbctrl); | 981 | usb_free_urb(usbhid->urbctrl); |
930 | hid_free_buffers(dev, hid); | 982 | hid_free_buffers(dev, hid); |
931 | kfree(usbhid); | 983 | kfree(usbhid); |
932 | fail_no_usbhid: | 984 | err: |
933 | hid_destroy_device(hid); | 985 | return ret; |
934 | |||
935 | return NULL; | ||
936 | } | 986 | } |
937 | 987 | ||
938 | static void hid_disconnect(struct usb_interface *intf) | 988 | static void usbhid_stop(struct hid_device *hid) |
939 | { | 989 | { |
940 | struct hid_device *hid = usb_get_intfdata (intf); | 990 | struct usbhid_device *usbhid = hid->driver_data; |
941 | struct usbhid_device *usbhid; | ||
942 | 991 | ||
943 | if (!hid) | 992 | if (WARN_ON(!usbhid)) |
944 | return; | 993 | return; |
945 | 994 | ||
946 | usbhid = hid->driver_data; | ||
947 | |||
948 | spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ | 995 | spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ |
949 | usb_set_intfdata(intf, NULL); | ||
950 | set_bit(HID_DISCONNECTED, &usbhid->iofl); | 996 | set_bit(HID_DISCONNECTED, &usbhid->iofl); |
951 | spin_unlock_irq(&usbhid->inlock); | 997 | spin_unlock_irq(&usbhid->inlock); |
952 | usb_kill_urb(usbhid->urbin); | 998 | usb_kill_urb(usbhid->urbin); |
@@ -963,93 +1009,99 @@ static void hid_disconnect(struct usb_interface *intf) | |||
963 | if (hid->claimed & HID_CLAIMED_HIDRAW) | 1009 | if (hid->claimed & HID_CLAIMED_HIDRAW) |
964 | hidraw_disconnect(hid); | 1010 | hidraw_disconnect(hid); |
965 | 1011 | ||
1012 | hid->claimed = 0; | ||
1013 | |||
966 | usb_free_urb(usbhid->urbin); | 1014 | usb_free_urb(usbhid->urbin); |
967 | usb_free_urb(usbhid->urbctrl); | 1015 | usb_free_urb(usbhid->urbctrl); |
968 | usb_free_urb(usbhid->urbout); | 1016 | usb_free_urb(usbhid->urbout); |
969 | 1017 | ||
970 | hid_free_buffers(hid_to_usb_dev(hid), hid); | 1018 | hid_free_buffers(hid_to_usb_dev(hid), hid); |
971 | kfree(usbhid); | 1019 | kfree(usbhid); |
972 | hid_destroy_device(hid); | 1020 | hid->driver_data = NULL; |
973 | } | 1021 | } |
974 | 1022 | ||
1023 | static struct hid_ll_driver usb_hid_driver = { | ||
1024 | .parse = usbhid_parse, | ||
1025 | .start = usbhid_start, | ||
1026 | .stop = usbhid_stop, | ||
1027 | .open = usbhid_open, | ||
1028 | .close = usbhid_close, | ||
1029 | .hidinput_input_event = usb_hidinput_input_event, | ||
1030 | }; | ||
1031 | |||
975 | static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) | 1032 | static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) |
976 | { | 1033 | { |
1034 | struct usb_device *dev = interface_to_usbdev(intf); | ||
977 | struct hid_device *hid; | 1035 | struct hid_device *hid; |
978 | char path[64]; | 1036 | size_t len; |
979 | int i, ret; | 1037 | int ret; |
980 | char *c; | ||
981 | 1038 | ||
982 | dbg_hid("HID probe called for ifnum %d\n", | 1039 | dbg_hid("HID probe called for ifnum %d\n", |
983 | intf->altsetting->desc.bInterfaceNumber); | 1040 | intf->altsetting->desc.bInterfaceNumber); |
984 | 1041 | ||
985 | if (!(hid = usb_hid_configure(intf))) | 1042 | hid = hid_allocate_device(); |
986 | return -ENODEV; | 1043 | if (IS_ERR(hid)) |
987 | 1044 | return PTR_ERR(hid); | |
988 | usbhid_init_reports(hid); | ||
989 | hid_dump_device(hid); | ||
990 | if (hid->quirks & HID_QUIRK_RESET_LEDS) | ||
991 | usbhid_set_leds(hid); | ||
992 | |||
993 | if (!hidinput_connect(hid)) | ||
994 | hid->claimed |= HID_CLAIMED_INPUT; | ||
995 | if (!hiddev_connect(hid)) | ||
996 | hid->claimed |= HID_CLAIMED_HIDDEV; | ||
997 | if (!hidraw_connect(hid)) | ||
998 | hid->claimed |= HID_CLAIMED_HIDRAW; | ||
999 | 1045 | ||
1000 | usb_set_intfdata(intf, hid); | 1046 | usb_set_intfdata(intf, hid); |
1047 | hid->ll_driver = &usb_hid_driver; | ||
1048 | hid->hid_output_raw_report = usbhid_output_raw_report; | ||
1049 | #ifdef CONFIG_USB_HIDDEV | ||
1050 | hid->hiddev_hid_event = hiddev_hid_event; | ||
1051 | hid->hiddev_report_event = hiddev_report_event; | ||
1052 | #endif | ||
1053 | hid->dev.parent = &intf->dev; | ||
1054 | hid->bus = BUS_USB; | ||
1055 | hid->vendor = le16_to_cpu(dev->descriptor.idVendor); | ||
1056 | hid->product = le16_to_cpu(dev->descriptor.idProduct); | ||
1057 | hid->name[0] = 0; | ||
1001 | 1058 | ||
1002 | if (!hid->claimed) { | 1059 | if (dev->manufacturer) |
1003 | printk ("HID device claimed by neither input, hiddev nor hidraw\n"); | 1060 | strlcpy(hid->name, dev->manufacturer, sizeof(hid->name)); |
1004 | hid_disconnect(intf); | ||
1005 | return -ENODEV; | ||
1006 | } | ||
1007 | |||
1008 | if ((hid->claimed & HID_CLAIMED_INPUT)) | ||
1009 | hid_ff_init(hid); | ||
1010 | |||
1011 | if (hid->quirks & HID_QUIRK_SONY_PS3_CONTROLLER) | ||
1012 | hid_fixup_sony_ps3_controller(interface_to_usbdev(intf), | ||
1013 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
1014 | |||
1015 | printk(KERN_INFO); | ||
1016 | |||
1017 | if (hid->claimed & HID_CLAIMED_INPUT) | ||
1018 | printk("input"); | ||
1019 | if ((hid->claimed & HID_CLAIMED_INPUT) && ((hid->claimed & HID_CLAIMED_HIDDEV) || | ||
1020 | hid->claimed & HID_CLAIMED_HIDRAW)) | ||
1021 | printk(","); | ||
1022 | if (hid->claimed & HID_CLAIMED_HIDDEV) | ||
1023 | printk("hiddev%d", hid->minor); | ||
1024 | if ((hid->claimed & HID_CLAIMED_INPUT) && (hid->claimed & HID_CLAIMED_HIDDEV) && | ||
1025 | (hid->claimed & HID_CLAIMED_HIDRAW)) | ||
1026 | printk(","); | ||
1027 | if (hid->claimed & HID_CLAIMED_HIDRAW) | ||
1028 | printk("hidraw%d", ((struct hidraw*)hid->hidraw)->minor); | ||
1029 | 1061 | ||
1030 | c = "Device"; | 1062 | if (dev->product) { |
1031 | for (i = 0; i < hid->maxcollection; i++) { | 1063 | if (dev->manufacturer) |
1032 | if (hid->collection[i].type == HID_COLLECTION_APPLICATION && | 1064 | strlcat(hid->name, " ", sizeof(hid->name)); |
1033 | (hid->collection[i].usage & HID_USAGE_PAGE) == HID_UP_GENDESK && | 1065 | strlcat(hid->name, dev->product, sizeof(hid->name)); |
1034 | (hid->collection[i].usage & 0xffff) < ARRAY_SIZE(hid_types)) { | ||
1035 | c = hid_types[hid->collection[i].usage & 0xffff]; | ||
1036 | break; | ||
1037 | } | ||
1038 | } | 1066 | } |
1039 | 1067 | ||
1040 | usb_make_path(interface_to_usbdev(intf), path, 63); | 1068 | if (!strlen(hid->name)) |
1069 | snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x", | ||
1070 | le16_to_cpu(dev->descriptor.idVendor), | ||
1071 | le16_to_cpu(dev->descriptor.idProduct)); | ||
1041 | 1072 | ||
1042 | printk(": USB HID v%x.%02x %s [%s] on %s\n", | 1073 | usb_make_path(dev, hid->phys, sizeof(hid->phys)); |
1043 | hid->version >> 8, hid->version & 0xff, c, hid->name, path); | 1074 | strlcat(hid->phys, "/input", sizeof(hid->phys)); |
1075 | len = strlen(hid->phys); | ||
1076 | if (len < sizeof(hid->phys) - 1) | ||
1077 | snprintf(hid->phys + len, sizeof(hid->phys) - len, | ||
1078 | "%d", intf->altsetting[0].desc.bInterfaceNumber); | ||
1079 | |||
1080 | if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0) | ||
1081 | hid->uniq[0] = 0; | ||
1044 | 1082 | ||
1045 | ret = hid_add_device(hid); | 1083 | ret = hid_add_device(hid); |
1046 | if (ret) { | 1084 | if (ret) { |
1047 | dev_err(&intf->dev, "can't add hid device: %d\n", ret); | 1085 | dev_err(&intf->dev, "can't add hid device: %d\n", ret); |
1048 | hid_disconnect(intf); | 1086 | goto err; |
1049 | } | 1087 | } |
1088 | |||
1089 | return 0; | ||
1090 | err: | ||
1091 | hid_destroy_device(hid); | ||
1050 | return ret; | 1092 | return ret; |
1051 | } | 1093 | } |
1052 | 1094 | ||
1095 | static void hid_disconnect(struct usb_interface *intf) | ||
1096 | { | ||
1097 | struct hid_device *hid = usb_get_intfdata(intf); | ||
1098 | |||
1099 | if (WARN_ON(!hid)) | ||
1100 | return; | ||
1101 | |||
1102 | hid_destroy_device(hid); | ||
1103 | } | ||
1104 | |||
1053 | static int hid_suspend(struct usb_interface *intf, pm_message_t message) | 1105 | static int hid_suspend(struct usb_interface *intf, pm_message_t message) |
1054 | { | 1106 | { |
1055 | struct hid_device *hid = usb_get_intfdata (intf); | 1107 | struct hid_device *hid = usb_get_intfdata (intf); |
diff --git a/include/linux/hid.h b/include/linux/hid.h index c4bea0eda85b..ac2584fe65c5 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
@@ -419,6 +419,7 @@ struct hid_control_fifo { | |||
419 | #define HID_CLAIMED_HIDRAW 4 | 419 | #define HID_CLAIMED_HIDRAW 4 |
420 | 420 | ||
421 | #define HID_STAT_ADDED 1 | 421 | #define HID_STAT_ADDED 1 |
422 | #define HID_STAT_PARSED 2 | ||
422 | 423 | ||
423 | #define HID_CTRL_RUNNING 1 | 424 | #define HID_CTRL_RUNNING 1 |
424 | #define HID_OUT_RUNNING 2 | 425 | #define HID_OUT_RUNNING 2 |
@@ -435,6 +436,7 @@ struct hid_input { | |||
435 | }; | 436 | }; |
436 | 437 | ||
437 | struct hid_driver; | 438 | struct hid_driver; |
439 | struct hid_ll_driver; | ||
438 | 440 | ||
439 | struct hid_device { /* device report descriptor */ | 441 | struct hid_device { /* device report descriptor */ |
440 | __u8 *rdesc; | 442 | __u8 *rdesc; |
@@ -452,6 +454,7 @@ struct hid_device { /* device report descriptor */ | |||
452 | 454 | ||
453 | struct device dev; /* device */ | 455 | struct device dev; /* device */ |
454 | struct hid_driver *driver; | 456 | struct hid_driver *driver; |
457 | struct hid_ll_driver *ll_driver; | ||
455 | 458 | ||
456 | unsigned int status; /* see STAT flags above */ | 459 | unsigned int status; /* see STAT flags above */ |
457 | unsigned claimed; /* Claimed by hidinput, hiddev? */ | 460 | unsigned claimed; /* Claimed by hidinput, hiddev? */ |
@@ -471,11 +474,6 @@ struct hid_device { /* device report descriptor */ | |||
471 | 474 | ||
472 | __s32 delayed_value; /* For A4 Tech mice hwheel quirk */ | 475 | __s32 delayed_value; /* For A4 Tech mice hwheel quirk */ |
473 | 476 | ||
474 | /* device-specific function pointers */ | ||
475 | int (*hidinput_input_event) (struct input_dev *, unsigned int, unsigned int, int); | ||
476 | int (*hid_open) (struct hid_device *); | ||
477 | void (*hid_close) (struct hid_device *); | ||
478 | |||
479 | /* hiddev event handler */ | 477 | /* hiddev event handler */ |
480 | void (*hiddev_hid_event) (struct hid_device *, struct hid_field *field, | 478 | void (*hiddev_hid_event) (struct hid_device *, struct hid_field *field, |
481 | struct hid_usage *, __s32); | 479 | struct hid_usage *, __s32); |
@@ -561,9 +559,22 @@ struct hid_usage_id { | |||
561 | * @raw_event: if report in report_table, this hook is called (NULL means nop) | 559 | * @raw_event: if report in report_table, this hook is called (NULL means nop) |
562 | * @usage_table: on which events to call event (NULL means all) | 560 | * @usage_table: on which events to call event (NULL means all) |
563 | * @event: if usage in usage_table, this hook is called (NULL means nop) | 561 | * @event: if usage in usage_table, this hook is called (NULL means nop) |
562 | * @report_fixup: called before report descriptor parsing (NULL means nop) | ||
563 | * @input_mapping: invoked on input registering before mapping an usage | ||
564 | * @input_mapped: invoked on input registering after mapping an usage | ||
564 | * | 565 | * |
565 | * raw_event and event should return 0 on no action performed, 1 when no | 566 | * raw_event and event should return 0 on no action performed, 1 when no |
566 | * further processing should be done and negative on error | 567 | * further processing should be done and negative on error |
568 | * | ||
569 | * input_mapping shall return a negative value to completely ignore this usage | ||
570 | * (e.g. doubled or invalid usage), zero to continue with parsing of this | ||
571 | * usage by generic code (no special handling needed) or positive to skip | ||
572 | * generic parsing (needed special handling which was done in the hook already) | ||
573 | * input_mapped shall return negative to inform the layer that this usage | ||
574 | * should not be considered for further processing or zero to notify that | ||
575 | * no processing was performed and should be done in a generic manner | ||
576 | * Both these functions may be NULL which means the same behavior as returning | ||
577 | * zero from them. | ||
567 | */ | 578 | */ |
568 | struct hid_driver { | 579 | struct hid_driver { |
569 | char *name; | 580 | char *name; |
@@ -578,10 +589,43 @@ struct hid_driver { | |||
578 | const struct hid_usage_id *usage_table; | 589 | const struct hid_usage_id *usage_table; |
579 | int (*event)(struct hid_device *hdev, struct hid_field *field, | 590 | int (*event)(struct hid_device *hdev, struct hid_field *field, |
580 | struct hid_usage *usage, __s32 value); | 591 | struct hid_usage *usage, __s32 value); |
592 | |||
593 | void (*report_fixup)(struct hid_device *hdev, __u8 *buf, | ||
594 | unsigned int size); | ||
595 | |||
596 | int (*input_mapping)(struct hid_device *hdev, | ||
597 | struct hid_input *hidinput, struct hid_field *field, | ||
598 | struct hid_usage *usage, unsigned long **bit, int *max); | ||
599 | int (*input_mapped)(struct hid_device *hdev, | ||
600 | struct hid_input *hidinput, struct hid_field *field, | ||
601 | struct hid_usage *usage, unsigned long **bit, int *max); | ||
581 | /* private: */ | 602 | /* private: */ |
582 | struct device_driver driver; | 603 | struct device_driver driver; |
583 | }; | 604 | }; |
584 | 605 | ||
606 | /** | ||
607 | * hid_ll_driver - low level driver callbacks | ||
608 | * @start: called on probe to start the device | ||
609 | * @stop: called on remove | ||
610 | * @open: called by input layer on open | ||
611 | * @close: called by input layer on close | ||
612 | * @hidinput_input_event: event input event (e.g. ff or leds) | ||
613 | * @parse: this method is called only once to parse the device data, | ||
614 | * shouldn't allocate anything to not leak memory | ||
615 | */ | ||
616 | struct hid_ll_driver { | ||
617 | int (*start)(struct hid_device *hdev); | ||
618 | void (*stop)(struct hid_device *hdev); | ||
619 | |||
620 | int (*open)(struct hid_device *hdev); | ||
621 | void (*close)(struct hid_device *hdev); | ||
622 | |||
623 | int (*hidinput_input_event) (struct input_dev *idev, unsigned int type, | ||
624 | unsigned int code, int value); | ||
625 | |||
626 | int (*parse)(struct hid_device *hdev); | ||
627 | }; | ||
628 | |||
585 | /* Applications from HID Usage Tables 4/8/99 Version 1.1 */ | 629 | /* Applications from HID Usage Tables 4/8/99 Version 1.1 */ |
586 | /* We ignore a few input applications that are not widely used */ | 630 | /* We ignore a few input applications that are not widely used */ |
587 | #define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001) || (a == 0x000d0002)) | 631 | #define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001) || (a == 0x000d0002)) |
@@ -618,6 +662,56 @@ void hid_output_report(struct hid_report *report, __u8 *data); | |||
618 | struct hid_device *hid_allocate_device(void); | 662 | struct hid_device *hid_allocate_device(void); |
619 | int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); | 663 | int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); |
620 | 664 | ||
665 | /** | ||
666 | * hid_parse - parse HW reports | ||
667 | * | ||
668 | * @hdev: hid device | ||
669 | * | ||
670 | * Call this from probe after you set up the device (if needed). Your | ||
671 | * report_fixup will be called (if non-NULL) after reading raw report from | ||
672 | * device before passing it to hid layer for real parsing. | ||
673 | */ | ||
674 | static inline int __must_check hid_parse(struct hid_device *hdev) | ||
675 | { | ||
676 | int ret; | ||
677 | |||
678 | if (hdev->status & HID_STAT_PARSED) | ||
679 | return 0; | ||
680 | |||
681 | ret = hdev->ll_driver->parse(hdev); | ||
682 | if (!ret) | ||
683 | hdev->status |= HID_STAT_PARSED; | ||
684 | |||
685 | return ret; | ||
686 | } | ||
687 | |||
688 | /** | ||
689 | * hid_hw_start - start underlaying HW | ||
690 | * | ||
691 | * @hdev: hid device | ||
692 | * | ||
693 | * Call this in probe function *after* hid_parse. This will setup HW buffers | ||
694 | * and start the device (if not deffered to device open). hid_hw_stop must be | ||
695 | * called if this was successfull. | ||
696 | */ | ||
697 | static inline int __must_check hid_hw_start(struct hid_device *hdev) | ||
698 | { | ||
699 | return hdev->ll_driver->start(hdev); | ||
700 | } | ||
701 | |||
702 | /** | ||
703 | * hid_hw_stop - stop underlaying HW | ||
704 | * | ||
705 | * @hdev: hid device | ||
706 | * | ||
707 | * This is usually called from remove function or from probe when something | ||
708 | * failed and hid_hw_start was called already. | ||
709 | */ | ||
710 | static inline void hid_hw_stop(struct hid_device *hdev) | ||
711 | { | ||
712 | hdev->ll_driver->stop(hdev); | ||
713 | } | ||
714 | |||
621 | void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, | 715 | void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, |
622 | int interrupt); | 716 | int interrupt); |
623 | 717 | ||
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 56a51f91591a..d8029cfcd452 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -623,9 +623,15 @@ static struct device *hidp_get_device(struct hidp_session *session) | |||
623 | static int hidp_setup_input(struct hidp_session *session, | 623 | static int hidp_setup_input(struct hidp_session *session, |
624 | struct hidp_connadd_req *req) | 624 | struct hidp_connadd_req *req) |
625 | { | 625 | { |
626 | struct input_dev *input = session->input; | 626 | struct input_dev *input; |
627 | int i; | 627 | int i; |
628 | 628 | ||
629 | input = input_allocate_device(); | ||
630 | if (!input) | ||
631 | return -ENOMEM; | ||
632 | |||
633 | session->input = input; | ||
634 | |||
629 | input_set_drvdata(input, session); | 635 | input_set_drvdata(input, session); |
630 | 636 | ||
631 | input->name = "Bluetooth HID Boot Protocol Device"; | 637 | input->name = "Bluetooth HID Boot Protocol Device"; |
@@ -698,55 +704,117 @@ static void hidp_setup_quirks(struct hid_device *hid) | |||
698 | hid->quirks = hidp_blacklist[n].quirks; | 704 | hid->quirks = hidp_blacklist[n].quirks; |
699 | } | 705 | } |
700 | 706 | ||
707 | static int hidp_parse(struct hid_device *hid) | ||
708 | { | ||
709 | struct hidp_session *session = hid->driver_data; | ||
710 | struct hidp_connadd_req *req = session->req; | ||
711 | unsigned char *buf; | ||
712 | int ret; | ||
713 | |||
714 | buf = kmalloc(req->rd_size, GFP_KERNEL); | ||
715 | if (!buf) | ||
716 | return -ENOMEM; | ||
717 | |||
718 | if (copy_from_user(buf, req->rd_data, req->rd_size)) { | ||
719 | kfree(buf); | ||
720 | return -EFAULT; | ||
721 | } | ||
722 | |||
723 | ret = hid_parse_report(session->hid, buf, req->rd_size); | ||
724 | |||
725 | kfree(buf); | ||
726 | |||
727 | if (ret) | ||
728 | return ret; | ||
729 | |||
730 | session->req = NULL; | ||
731 | |||
732 | hidp_setup_quirks(hid); | ||
733 | return 0; | ||
734 | } | ||
735 | |||
736 | static int hidp_start(struct hid_device *hid) | ||
737 | { | ||
738 | struct hidp_session *session = hid->driver_data; | ||
739 | struct hid_report *report; | ||
740 | |||
741 | list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT]. | ||
742 | report_list, list) | ||
743 | hidp_send_report(session, report); | ||
744 | |||
745 | list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT]. | ||
746 | report_list, list) | ||
747 | hidp_send_report(session, report); | ||
748 | |||
749 | if (hidinput_connect(hid) == 0) | ||
750 | hid->claimed |= HID_CLAIMED_INPUT; | ||
751 | |||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | static void hidp_stop(struct hid_device *hid) | ||
756 | { | ||
757 | struct hidp_session *session = hid->driver_data; | ||
758 | |||
759 | skb_queue_purge(&session->ctrl_transmit); | ||
760 | skb_queue_purge(&session->intr_transmit); | ||
761 | |||
762 | if (hid->claimed & HID_CLAIMED_INPUT) | ||
763 | hidinput_disconnect(hid); | ||
764 | hid->claimed = 0; | ||
765 | } | ||
766 | |||
767 | static struct hid_ll_driver hidp_hid_driver = { | ||
768 | .parse = hidp_parse, | ||
769 | .start = hidp_start, | ||
770 | .stop = hidp_stop, | ||
771 | .open = hidp_open, | ||
772 | .close = hidp_close, | ||
773 | .hidinput_input_event = hidp_hidinput_event, | ||
774 | }; | ||
775 | |||
701 | static int hidp_setup_hid(struct hidp_session *session, | 776 | static int hidp_setup_hid(struct hidp_session *session, |
702 | struct hidp_connadd_req *req) | 777 | struct hidp_connadd_req *req) |
703 | { | 778 | { |
704 | struct hid_device *hid = session->hid; | 779 | struct hid_device *hid; |
705 | struct hid_report *report; | ||
706 | bdaddr_t src, dst; | 780 | bdaddr_t src, dst; |
707 | int ret; | 781 | int ret; |
708 | 782 | ||
709 | baswap(&src, &bt_sk(session->ctrl_sock->sk)->src); | 783 | hid = hid_allocate_device(); |
710 | baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst); | 784 | if (IS_ERR(hid)) { |
785 | ret = PTR_ERR(session->hid); | ||
786 | goto err; | ||
787 | } | ||
711 | 788 | ||
789 | session->hid = hid; | ||
790 | session->req = req; | ||
712 | hid->driver_data = session; | 791 | hid->driver_data = session; |
713 | 792 | ||
714 | hid->country = req->country; | 793 | baswap(&src, &bt_sk(session->ctrl_sock->sk)->src); |
794 | baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst); | ||
715 | 795 | ||
716 | hid->bus = BUS_BLUETOOTH; | 796 | hid->bus = BUS_BLUETOOTH; |
717 | hid->vendor = req->vendor; | 797 | hid->vendor = req->vendor; |
718 | hid->product = req->product; | 798 | hid->product = req->product; |
719 | hid->version = req->version; | 799 | hid->version = req->version; |
800 | hid->country = req->country; | ||
720 | 801 | ||
721 | strncpy(hid->name, req->name, 128); | 802 | strncpy(hid->name, req->name, 128); |
722 | strncpy(hid->phys, batostr(&src), 64); | 803 | strncpy(hid->phys, batostr(&src), 64); |
723 | strncpy(hid->uniq, batostr(&dst), 64); | 804 | strncpy(hid->uniq, batostr(&dst), 64); |
724 | 805 | ||
725 | hid->dev.parent = hidp_get_device(session); | 806 | hid->dev.parent = hidp_get_device(session); |
726 | 807 | hid->ll_driver = &hidp_hid_driver; | |
727 | hid->hid_open = hidp_open; | ||
728 | hid->hid_close = hidp_close; | ||
729 | |||
730 | hid->hidinput_input_event = hidp_hidinput_event; | ||
731 | |||
732 | hidp_setup_quirks(hid); | ||
733 | |||
734 | list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) | ||
735 | hidp_send_report(session, report); | ||
736 | |||
737 | list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list) | ||
738 | hidp_send_report(session, report); | ||
739 | |||
740 | if (hidinput_connect(hid) == 0) | ||
741 | hid->claimed |= HID_CLAIMED_INPUT; | ||
742 | 808 | ||
743 | ret = hid_add_device(hid); | 809 | ret = hid_add_device(hid); |
744 | if (ret) { | 810 | if (ret) |
745 | if (hid->claimed & HID_CLAIMED_INPUT) | 811 | goto err_hid; |
746 | hidinput_disconnect(hid); | ||
747 | skb_queue_purge(&session->intr_transmit); | ||
748 | } | ||
749 | 812 | ||
813 | return 0; | ||
814 | err_hid: | ||
815 | hid_destroy_device(hid); | ||
816 | session->hid = NULL; | ||
817 | err: | ||
750 | return ret; | 818 | return ret; |
751 | } | 819 | } |
752 | 820 | ||
@@ -767,46 +835,6 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, | |||
767 | 835 | ||
768 | BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size); | 836 | BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size); |
769 | 837 | ||
770 | if (req->rd_size > 0) { | ||
771 | unsigned char *buf = kmalloc(req->rd_size, GFP_KERNEL); | ||
772 | |||
773 | if (!buf) { | ||
774 | kfree(session); | ||
775 | return -ENOMEM; | ||
776 | } | ||
777 | |||
778 | if (copy_from_user(buf, req->rd_data, req->rd_size)) { | ||
779 | kfree(buf); | ||
780 | kfree(session); | ||
781 | return -EFAULT; | ||
782 | } | ||
783 | |||
784 | session->hid = hid_allocate_device(); | ||
785 | if (IS_ERR(session->hid)) { | ||
786 | kfree(buf); | ||
787 | kfree(session); | ||
788 | return PTR_ERR(session->hid); | ||
789 | } | ||
790 | |||
791 | err = hid_parse_report(session->hid, buf, req->rd_size); | ||
792 | |||
793 | kfree(buf); | ||
794 | |||
795 | if (err) { | ||
796 | hid_destroy_device(session->hid); | ||
797 | kfree(session); | ||
798 | return -EINVAL; | ||
799 | } | ||
800 | } | ||
801 | |||
802 | if (!session->hid) { | ||
803 | session->input = input_allocate_device(); | ||
804 | if (!session->input) { | ||
805 | kfree(session); | ||
806 | return -ENOMEM; | ||
807 | } | ||
808 | } | ||
809 | |||
810 | down_write(&hidp_session_sem); | 838 | down_write(&hidp_session_sem); |
811 | 839 | ||
812 | s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst); | 840 | s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst); |
@@ -834,16 +862,16 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, | |||
834 | session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID); | 862 | session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID); |
835 | session->idle_to = req->idle_to; | 863 | session->idle_to = req->idle_to; |
836 | 864 | ||
837 | if (session->input) { | 865 | if (req->rd_size > 0) { |
838 | err = hidp_setup_input(session, req); | ||
839 | if (err < 0) | ||
840 | goto failed; | ||
841 | } | ||
842 | |||
843 | if (session->hid) { | ||
844 | err = hidp_setup_hid(session, req); | 866 | err = hidp_setup_hid(session, req); |
845 | if (err) | 867 | if (err) |
846 | goto failed; | 868 | goto err_skb; |
869 | } | ||
870 | |||
871 | if (!session->hid) { | ||
872 | err = hidp_setup_input(session, req); | ||
873 | if (err < 0) | ||
874 | goto err_skb; | ||
847 | } | 875 | } |
848 | 876 | ||
849 | __hidp_link_session(session); | 877 | __hidp_link_session(session); |
@@ -871,16 +899,15 @@ unlink: | |||
871 | 899 | ||
872 | __hidp_unlink_session(session); | 900 | __hidp_unlink_session(session); |
873 | 901 | ||
874 | if (session->input) { | 902 | if (session->input) |
875 | input_unregister_device(session->input); | 903 | input_unregister_device(session->input); |
876 | session->input = NULL; /* don't try to free it here */ | ||
877 | } | ||
878 | |||
879 | failed: | ||
880 | up_write(&hidp_session_sem); | ||
881 | |||
882 | if (session->hid) | 904 | if (session->hid) |
883 | hid_destroy_device(session->hid); | 905 | hid_destroy_device(session->hid); |
906 | err_skb: | ||
907 | skb_queue_purge(&session->ctrl_transmit); | ||
908 | skb_queue_purge(&session->intr_transmit); | ||
909 | failed: | ||
910 | up_write(&hidp_session_sem); | ||
884 | 911 | ||
885 | input_free_device(session->input); | 912 | input_free_device(session->input); |
886 | kfree(session); | 913 | kfree(session); |
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h index 343fb0566b3e..e503c89057ad 100644 --- a/net/bluetooth/hidp/hidp.h +++ b/net/bluetooth/hidp/hidp.h | |||
@@ -151,6 +151,8 @@ struct hidp_session { | |||
151 | 151 | ||
152 | struct sk_buff_head ctrl_transmit; | 152 | struct sk_buff_head ctrl_transmit; |
153 | struct sk_buff_head intr_transmit; | 153 | struct sk_buff_head intr_transmit; |
154 | |||
155 | struct hidp_connadd_req *req; | ||
154 | }; | 156 | }; |
155 | 157 | ||
156 | static inline void hidp_schedule(struct hidp_session *session) | 158 | static inline void hidp_schedule(struct hidp_session *session) |