aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2012-04-22 08:21:40 -0400
committerJiri Kosina <jkosina@suse.cz>2012-05-01 06:54:53 -0400
commita7197c2e4120ce40e7e3f5580336b9a1dc791220 (patch)
tree1f508022a41558ea29dc87baddcf8c2132f9bdd3
parent2a039bf5a6caa6b41c3839c1e3a19b20fb38270b (diff)
HID: Handle driver-specific device descriptor in core
The low-level driver can read the report descriptor, but it cannot determine driver-specific changes to it. The hid core can fixup and parse the report descriptor during driver attach, but does not have direct access to the descriptor when doing so. To be able to handle attach/detach of hid drivers properly, a semantic change to hid_parse_report() is needed. This function has been used in two ways, both as descriptor reader in the ll drivers and as a parsor in the probe of the drivers. This patch splits the usage by introducing hid_open_report(), and modifies the hid_parse() macro to call hid_open_report() instead. The only usage of hid_parse_report() is then to read and store the device descriptor. As a consequence, we can handle the report fixups automatically inside the hid core. Signed-off-by: Henrik Rydberg <rydberg@euromail.se> Tested-by: Nikolai Kondrashov <spbnick@gmail.com> Tested-by: Benjamin Tissoires <benjamin.tissoires@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/hid-core.c112
-rw-r--r--include/linux/hid.h14
2 files changed, 94 insertions, 32 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 4da66b4b977c..9ed4ff37dc2b 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -546,12 +546,11 @@ static void hid_free_report(struct hid_report *report)
546} 546}
547 547
548/* 548/*
549 * Free a device structure, all reports, and all fields. 549 * Close report. This function returns the device
550 * state to the point prior to hid_open_report().
550 */ 551 */
551 552static void hid_close_report(struct hid_device *device)
552static void hid_device_release(struct device *dev)
553{ 553{
554 struct hid_device *device = container_of(dev, struct hid_device, dev);
555 unsigned i, j; 554 unsigned i, j;
556 555
557 for (i = 0; i < HID_REPORT_TYPES; i++) { 556 for (i = 0; i < HID_REPORT_TYPES; i++) {
@@ -562,11 +561,34 @@ static void hid_device_release(struct device *dev)
562 if (report) 561 if (report)
563 hid_free_report(report); 562 hid_free_report(report);
564 } 563 }
564 memset(report_enum, 0, sizeof(*report_enum));
565 INIT_LIST_HEAD(&report_enum->report_list);
565 } 566 }
566 567
567 kfree(device->rdesc); 568 kfree(device->rdesc);
569 device->rdesc = NULL;
570 device->rsize = 0;
571
568 kfree(device->collection); 572 kfree(device->collection);
569 kfree(device); 573 device->collection = NULL;
574 device->collection_size = 0;
575 device->maxcollection = 0;
576 device->maxapplication = 0;
577
578 device->status &= ~HID_STAT_PARSED;
579}
580
581/*
582 * Free a device structure, all reports, and all fields.
583 */
584
585static void hid_device_release(struct device *dev)
586{
587 struct hid_device *hid = container_of(dev, struct hid_device, dev);
588
589 hid_close_report(hid);
590 kfree(hid->dev_rdesc);
591 kfree(hid);
570} 592}
571 593
572/* 594/*
@@ -643,15 +665,37 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
643 * @start: report start 665 * @start: report start
644 * @size: report size 666 * @size: report size
645 * 667 *
668 * Allocate the device report as read by the bus driver. This function should
669 * only be called from parse() in ll drivers.
670 */
671int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size)
672{
673 hid->dev_rdesc = kmemdup(start, size, GFP_KERNEL);
674 if (!hid->dev_rdesc)
675 return -ENOMEM;
676 hid->dev_rsize = size;
677 return 0;
678}
679EXPORT_SYMBOL_GPL(hid_parse_report);
680
681/**
682 * hid_open_report - open a driver-specific device report
683 *
684 * @device: hid device
685 *
646 * Parse a report description into a hid_device structure. Reports are 686 * Parse a report description into a hid_device structure. Reports are
647 * enumerated, fields are attached to these reports. 687 * enumerated, fields are attached to these reports.
648 * 0 returned on success, otherwise nonzero error value. 688 * 0 returned on success, otherwise nonzero error value.
689 *
690 * This function (or the equivalent hid_parse() macro) should only be
691 * called from probe() in drivers, before starting the device.
649 */ 692 */
650int hid_parse_report(struct hid_device *device, __u8 *start, 693int hid_open_report(struct hid_device *device)
651 unsigned size)
652{ 694{
653 struct hid_parser *parser; 695 struct hid_parser *parser;
654 struct hid_item item; 696 struct hid_item item;
697 unsigned int size;
698 __u8 *start;
655 __u8 *end; 699 __u8 *end;
656 int ret; 700 int ret;
657 static int (*dispatch_type[])(struct hid_parser *parser, 701 static int (*dispatch_type[])(struct hid_parser *parser,
@@ -662,6 +706,14 @@ int hid_parse_report(struct hid_device *device, __u8 *start,
662 hid_parser_reserved 706 hid_parser_reserved
663 }; 707 };
664 708
709 if (WARN_ON(device->status & HID_STAT_PARSED))
710 return -EBUSY;
711
712 start = device->dev_rdesc;
713 if (WARN_ON(!start))
714 return -ENODEV;
715 size = device->dev_rsize;
716
665 if (device->driver->report_fixup) 717 if (device->driver->report_fixup)
666 start = device->driver->report_fixup(device, start, &size); 718 start = device->driver->report_fixup(device, start, &size);
667 719
@@ -679,6 +731,15 @@ int hid_parse_report(struct hid_device *device, __u8 *start,
679 parser->device = device; 731 parser->device = device;
680 732
681 end = start + size; 733 end = start + size;
734
735 device->collection = kcalloc(HID_DEFAULT_NUM_COLLECTIONS,
736 sizeof(struct hid_collection), GFP_KERNEL);
737 if (!device->collection) {
738 ret = -ENOMEM;
739 goto err;
740 }
741 device->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
742
682 ret = -EINVAL; 743 ret = -EINVAL;
683 while ((start = fetch_item(start, end, &item)) != NULL) { 744 while ((start = fetch_item(start, end, &item)) != NULL) {
684 745
@@ -704,6 +765,7 @@ int hid_parse_report(struct hid_device *device, __u8 *start,
704 goto err; 765 goto err;
705 } 766 }
706 vfree(parser); 767 vfree(parser);
768 device->status |= HID_STAT_PARSED;
707 return 0; 769 return 0;
708 } 770 }
709 } 771 }
@@ -711,9 +773,10 @@ int hid_parse_report(struct hid_device *device, __u8 *start,
711 hid_err(device, "item fetching failed at offset %d\n", (int)(end - start)); 773 hid_err(device, "item fetching failed at offset %d\n", (int)(end - start));
712err: 774err:
713 vfree(parser); 775 vfree(parser);
776 hid_close_report(device);
714 return ret; 777 return ret;
715} 778}
716EXPORT_SYMBOL_GPL(hid_parse_report); 779EXPORT_SYMBOL_GPL(hid_open_report);
717 780
718/* 781/*
719 * Convert a signed n-bit integer to signed 32-bit integer. Common 782 * Convert a signed n-bit integer to signed 32-bit integer. Common
@@ -1718,12 +1781,14 @@ static int hid_device_probe(struct device *dev)
1718 if (hdrv->probe) { 1781 if (hdrv->probe) {
1719 ret = hdrv->probe(hdev, id); 1782 ret = hdrv->probe(hdev, id);
1720 } else { /* default probe */ 1783 } else { /* default probe */
1721 ret = hid_parse(hdev); 1784 ret = hid_open_report(hdev);
1722 if (!ret) 1785 if (!ret)
1723 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 1786 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
1724 } 1787 }
1725 if (ret) 1788 if (ret) {
1789 hid_close_report(hdev);
1726 hdev->driver = NULL; 1790 hdev->driver = NULL;
1791 }
1727 } 1792 }
1728unlock: 1793unlock:
1729 up(&hdev->driver_lock); 1794 up(&hdev->driver_lock);
@@ -1744,6 +1809,7 @@ static int hid_device_remove(struct device *dev)
1744 hdrv->remove(hdev); 1809 hdrv->remove(hdev);
1745 else /* default remove */ 1810 else /* default remove */
1746 hid_hw_stop(hdev); 1811 hid_hw_stop(hdev);
1812 hid_close_report(hdev);
1747 hdev->driver = NULL; 1813 hdev->driver = NULL;
1748 } 1814 }
1749 1815
@@ -2075,6 +2141,16 @@ int hid_add_device(struct hid_device *hdev)
2075 && (hid_ignore(hdev) || (hdev->quirks & HID_QUIRK_IGNORE))) 2141 && (hid_ignore(hdev) || (hdev->quirks & HID_QUIRK_IGNORE)))
2076 return -ENODEV; 2142 return -ENODEV;
2077 2143
2144 /*
2145 * Read the device report descriptor once and use as template
2146 * for the driver-specific modifications.
2147 */
2148 ret = hdev->ll_driver->parse(hdev);
2149 if (ret)
2150 return ret;
2151 if (!hdev->dev_rdesc)
2152 return -ENODEV;
2153
2078 /* XXX hack, any other cleaner solution after the driver core 2154 /* XXX hack, any other cleaner solution after the driver core
2079 * is converted to allow more than 20 bytes as the device name? */ 2155 * is converted to allow more than 20 bytes as the device name? */
2080 dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus, 2156 dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus,
@@ -2103,7 +2179,6 @@ EXPORT_SYMBOL_GPL(hid_add_device);
2103struct hid_device *hid_allocate_device(void) 2179struct hid_device *hid_allocate_device(void)
2104{ 2180{
2105 struct hid_device *hdev; 2181 struct hid_device *hdev;
2106 unsigned int i;
2107 int ret = -ENOMEM; 2182 int ret = -ENOMEM;
2108 2183
2109 hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); 2184 hdev = kzalloc(sizeof(*hdev), GFP_KERNEL);
@@ -2114,23 +2189,13 @@ struct hid_device *hid_allocate_device(void)
2114 hdev->dev.release = hid_device_release; 2189 hdev->dev.release = hid_device_release;
2115 hdev->dev.bus = &hid_bus_type; 2190 hdev->dev.bus = &hid_bus_type;
2116 2191
2117 hdev->collection = kcalloc(HID_DEFAULT_NUM_COLLECTIONS, 2192 hid_close_report(hdev);
2118 sizeof(struct hid_collection), GFP_KERNEL);
2119 if (hdev->collection == NULL)
2120 goto err;
2121 hdev->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
2122
2123 for (i = 0; i < HID_REPORT_TYPES; i++)
2124 INIT_LIST_HEAD(&hdev->report_enum[i].report_list);
2125 2193
2126 init_waitqueue_head(&hdev->debug_wait); 2194 init_waitqueue_head(&hdev->debug_wait);
2127 INIT_LIST_HEAD(&hdev->debug_list); 2195 INIT_LIST_HEAD(&hdev->debug_list);
2128 sema_init(&hdev->driver_lock, 1); 2196 sema_init(&hdev->driver_lock, 1);
2129 2197
2130 return hdev; 2198 return hdev;
2131err:
2132 put_device(&hdev->dev);
2133 return ERR_PTR(ret);
2134} 2199}
2135EXPORT_SYMBOL_GPL(hid_allocate_device); 2200EXPORT_SYMBOL_GPL(hid_allocate_device);
2136 2201
@@ -2141,6 +2206,9 @@ static void hid_remove_device(struct hid_device *hdev)
2141 hid_debug_unregister(hdev); 2206 hid_debug_unregister(hdev);
2142 hdev->status &= ~HID_STAT_ADDED; 2207 hdev->status &= ~HID_STAT_ADDED;
2143 } 2208 }
2209 kfree(hdev->dev_rdesc);
2210 hdev->dev_rdesc = NULL;
2211 hdev->dev_rsize = 0;
2144} 2212}
2145 2213
2146/** 2214/**
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 3a95da60fd3e..d8e7cc7f894f 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -467,6 +467,8 @@ struct hid_driver;
467struct hid_ll_driver; 467struct hid_ll_driver;
468 468
469struct hid_device { /* device report descriptor */ 469struct hid_device { /* device report descriptor */
470 __u8 *dev_rdesc;
471 unsigned dev_rsize;
470 __u8 *rdesc; 472 __u8 *rdesc;
471 unsigned rsize; 473 unsigned rsize;
472 struct hid_collection *collection; /* List of HID collections */ 474 struct hid_collection *collection; /* List of HID collections */
@@ -735,6 +737,7 @@ void hid_output_report(struct hid_report *report, __u8 *data);
735struct hid_device *hid_allocate_device(void); 737struct hid_device *hid_allocate_device(void);
736struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); 738struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id);
737int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); 739int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
740int hid_open_report(struct hid_device *device);
738int hid_check_keys_pressed(struct hid_device *hid); 741int hid_check_keys_pressed(struct hid_device *hid);
739int hid_connect(struct hid_device *hid, unsigned int connect_mask); 742int hid_connect(struct hid_device *hid, unsigned int connect_mask);
740void hid_disconnect(struct hid_device *hid); 743void hid_disconnect(struct hid_device *hid);
@@ -805,16 +808,7 @@ static inline void hid_map_usage_clear(struct hid_input *hidinput,
805 */ 808 */
806static inline int __must_check hid_parse(struct hid_device *hdev) 809static inline int __must_check hid_parse(struct hid_device *hdev)
807{ 810{
808 int ret; 811 return hid_open_report(hdev);
809
810 if (hdev->status & HID_STAT_PARSED)
811 return 0;
812
813 ret = hdev->ll_driver->parse(hdev);
814 if (!ret)
815 hdev->status |= HID_STAT_PARSED;
816
817 return ret;
818} 812}
819 813
820/** 814/**