diff options
| -rw-r--r-- | drivers/hid/hid-core.c | 76 | ||||
| -rw-r--r-- | drivers/hid/hid-generic.c | 68 | ||||
| -rw-r--r-- | include/linux/hid.h | 10 |
3 files changed, 125 insertions, 29 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index e6d586a22bbd..7297b1d1300c 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -830,31 +830,6 @@ static int hid_scan_report(struct hid_device *hid) | |||
| 830 | break; | 830 | break; |
| 831 | } | 831 | } |
| 832 | 832 | ||
| 833 | /* fall back to generic driver in case specific driver doesn't exist */ | ||
| 834 | switch (hid->group) { | ||
| 835 | case HID_GROUP_MULTITOUCH_WIN_8: | ||
| 836 | /* fall-through */ | ||
| 837 | case HID_GROUP_MULTITOUCH: | ||
| 838 | if (!IS_ENABLED(CONFIG_HID_MULTITOUCH)) | ||
| 839 | hid->group = HID_GROUP_GENERIC; | ||
| 840 | break; | ||
| 841 | case HID_GROUP_SENSOR_HUB: | ||
| 842 | if (!IS_ENABLED(CONFIG_HID_SENSOR_HUB)) | ||
| 843 | hid->group = HID_GROUP_GENERIC; | ||
| 844 | break; | ||
| 845 | case HID_GROUP_RMI: | ||
| 846 | if (!IS_ENABLED(CONFIG_HID_RMI)) | ||
| 847 | hid->group = HID_GROUP_GENERIC; | ||
| 848 | break; | ||
| 849 | case HID_GROUP_WACOM: | ||
| 850 | if (!IS_ENABLED(CONFIG_HID_WACOM)) | ||
| 851 | hid->group = HID_GROUP_GENERIC; | ||
| 852 | break; | ||
| 853 | case HID_GROUP_LOGITECH_DJ_DEVICE: | ||
| 854 | if (!IS_ENABLED(CONFIG_HID_LOGITECH_DJ)) | ||
| 855 | hid->group = HID_GROUP_GENERIC; | ||
| 856 | break; | ||
| 857 | } | ||
| 858 | vfree(parser); | 833 | vfree(parser); |
| 859 | return 0; | 834 | return 0; |
| 860 | } | 835 | } |
| @@ -1928,8 +1903,8 @@ static void hid_free_dynids(struct hid_driver *hdrv) | |||
| 1928 | spin_unlock(&hdrv->dyn_lock); | 1903 | spin_unlock(&hdrv->dyn_lock); |
| 1929 | } | 1904 | } |
| 1930 | 1905 | ||
| 1931 | static const struct hid_device_id *hid_match_device(struct hid_device *hdev, | 1906 | const struct hid_device_id *hid_match_device(struct hid_device *hdev, |
| 1932 | struct hid_driver *hdrv) | 1907 | struct hid_driver *hdrv) |
| 1933 | { | 1908 | { |
| 1934 | struct hid_dynid *dynid; | 1909 | struct hid_dynid *dynid; |
| 1935 | 1910 | ||
| @@ -1944,6 +1919,7 @@ static const struct hid_device_id *hid_match_device(struct hid_device *hdev, | |||
| 1944 | 1919 | ||
| 1945 | return hid_match_id(hdev, hdrv->id_table); | 1920 | return hid_match_id(hdev, hdrv->id_table); |
| 1946 | } | 1921 | } |
| 1922 | EXPORT_SYMBOL_GPL(hid_match_device); | ||
| 1947 | 1923 | ||
| 1948 | static int hid_bus_match(struct device *dev, struct device_driver *drv) | 1924 | static int hid_bus_match(struct device *dev, struct device_driver *drv) |
| 1949 | { | 1925 | { |
| @@ -1973,6 +1949,23 @@ static int hid_device_probe(struct device *dev) | |||
| 1973 | goto unlock; | 1949 | goto unlock; |
| 1974 | } | 1950 | } |
| 1975 | 1951 | ||
| 1952 | if (hdrv->match) { | ||
| 1953 | if (!hdrv->match(hdev, hid_ignore_special_drivers)) { | ||
| 1954 | ret = -ENODEV; | ||
| 1955 | goto unlock; | ||
| 1956 | } | ||
| 1957 | } else { | ||
| 1958 | /* | ||
| 1959 | * hid-generic implements .match(), so if | ||
| 1960 | * hid_ignore_special_drivers is set, we can safely | ||
| 1961 | * return. | ||
| 1962 | */ | ||
| 1963 | if (hid_ignore_special_drivers) { | ||
| 1964 | ret = -ENODEV; | ||
| 1965 | goto unlock; | ||
| 1966 | } | ||
| 1967 | } | ||
| 1968 | |||
| 1976 | hdev->driver = hdrv; | 1969 | hdev->driver = hdrv; |
| 1977 | if (hdrv->probe) { | 1970 | if (hdrv->probe) { |
| 1978 | ret = hdrv->probe(hdev, id); | 1971 | ret = hdrv->probe(hdev, id); |
| @@ -2069,7 +2062,7 @@ static int hid_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
| 2069 | return 0; | 2062 | return 0; |
| 2070 | } | 2063 | } |
| 2071 | 2064 | ||
| 2072 | static struct bus_type hid_bus_type = { | 2065 | struct bus_type hid_bus_type = { |
| 2073 | .name = "hid", | 2066 | .name = "hid", |
| 2074 | .dev_groups = hid_dev_groups, | 2067 | .dev_groups = hid_dev_groups, |
| 2075 | .drv_groups = hid_drv_groups, | 2068 | .drv_groups = hid_drv_groups, |
| @@ -2203,6 +2196,29 @@ void hid_destroy_device(struct hid_device *hdev) | |||
| 2203 | } | 2196 | } |
| 2204 | EXPORT_SYMBOL_GPL(hid_destroy_device); | 2197 | EXPORT_SYMBOL_GPL(hid_destroy_device); |
| 2205 | 2198 | ||
| 2199 | |||
| 2200 | static int __bus_add_driver(struct device_driver *drv, void *data) | ||
| 2201 | { | ||
| 2202 | struct hid_driver *added_hdrv = data; | ||
| 2203 | struct hid_driver *hdrv = to_hid_driver(drv); | ||
| 2204 | |||
| 2205 | if (hdrv->bus_add_driver) | ||
| 2206 | hdrv->bus_add_driver(added_hdrv); | ||
| 2207 | |||
| 2208 | return 0; | ||
| 2209 | } | ||
| 2210 | |||
| 2211 | static int __bus_removed_driver(struct device_driver *drv, void *data) | ||
| 2212 | { | ||
| 2213 | struct hid_driver *removed_hdrv = data; | ||
| 2214 | struct hid_driver *hdrv = to_hid_driver(drv); | ||
| 2215 | |||
| 2216 | if (hdrv->bus_removed_driver) | ||
| 2217 | hdrv->bus_removed_driver(removed_hdrv); | ||
| 2218 | |||
| 2219 | return 0; | ||
| 2220 | } | ||
| 2221 | |||
| 2206 | int __hid_register_driver(struct hid_driver *hdrv, struct module *owner, | 2222 | int __hid_register_driver(struct hid_driver *hdrv, struct module *owner, |
| 2207 | const char *mod_name) | 2223 | const char *mod_name) |
| 2208 | { | 2224 | { |
| @@ -2214,6 +2230,8 @@ int __hid_register_driver(struct hid_driver *hdrv, struct module *owner, | |||
| 2214 | INIT_LIST_HEAD(&hdrv->dyn_list); | 2230 | INIT_LIST_HEAD(&hdrv->dyn_list); |
| 2215 | spin_lock_init(&hdrv->dyn_lock); | 2231 | spin_lock_init(&hdrv->dyn_lock); |
| 2216 | 2232 | ||
| 2233 | bus_for_each_drv(&hid_bus_type, NULL, hdrv, __bus_add_driver); | ||
| 2234 | |||
| 2217 | return driver_register(&hdrv->driver); | 2235 | return driver_register(&hdrv->driver); |
| 2218 | } | 2236 | } |
| 2219 | EXPORT_SYMBOL_GPL(__hid_register_driver); | 2237 | EXPORT_SYMBOL_GPL(__hid_register_driver); |
| @@ -2222,6 +2240,8 @@ void hid_unregister_driver(struct hid_driver *hdrv) | |||
| 2222 | { | 2240 | { |
| 2223 | driver_unregister(&hdrv->driver); | 2241 | driver_unregister(&hdrv->driver); |
| 2224 | hid_free_dynids(hdrv); | 2242 | hid_free_dynids(hdrv); |
| 2243 | |||
| 2244 | bus_for_each_drv(&hid_bus_type, NULL, hdrv, __bus_removed_driver); | ||
| 2225 | } | 2245 | } |
| 2226 | EXPORT_SYMBOL_GPL(hid_unregister_driver); | 2246 | EXPORT_SYMBOL_GPL(hid_unregister_driver); |
| 2227 | 2247 | ||
diff --git a/drivers/hid/hid-generic.c b/drivers/hid/hid-generic.c index e288a4a06fe8..3c0a1bf433d7 100644 --- a/drivers/hid/hid-generic.c +++ b/drivers/hid/hid-generic.c | |||
| @@ -24,8 +24,71 @@ | |||
| 24 | 24 | ||
| 25 | #include <linux/hid.h> | 25 | #include <linux/hid.h> |
| 26 | 26 | ||
| 27 | static struct hid_driver hid_generic; | ||
| 28 | |||
| 29 | static int __unmap_hid_generic(struct device *dev, void *data) | ||
| 30 | { | ||
| 31 | struct hid_driver *hdrv = data; | ||
| 32 | struct hid_device *hdev = to_hid_device(dev); | ||
| 33 | |||
| 34 | /* only unbind matching devices already bound to hid-generic */ | ||
| 35 | if (hdev->driver != &hid_generic || | ||
| 36 | hid_match_device(hdev, hdrv) == NULL) | ||
| 37 | return 0; | ||
| 38 | |||
| 39 | if (dev->parent) /* Needed for USB */ | ||
| 40 | device_lock(dev->parent); | ||
| 41 | device_release_driver(dev); | ||
| 42 | if (dev->parent) | ||
| 43 | device_unlock(dev->parent); | ||
| 44 | |||
| 45 | return 0; | ||
| 46 | } | ||
| 47 | |||
| 48 | static void hid_generic_add_driver(struct hid_driver *hdrv) | ||
| 49 | { | ||
| 50 | bus_for_each_dev(&hid_bus_type, NULL, hdrv, __unmap_hid_generic); | ||
| 51 | } | ||
| 52 | |||
| 53 | static void hid_generic_removed_driver(struct hid_driver *hdrv) | ||
| 54 | { | ||
| 55 | int ret; | ||
| 56 | |||
| 57 | ret = driver_attach(&hid_generic.driver); | ||
| 58 | } | ||
| 59 | |||
| 60 | static int __check_hid_generic(struct device_driver *drv, void *data) | ||
| 61 | { | ||
| 62 | struct hid_driver *hdrv = to_hid_driver(drv); | ||
| 63 | struct hid_device *hdev = data; | ||
| 64 | |||
| 65 | if (hdrv == &hid_generic) | ||
| 66 | return 0; | ||
| 67 | |||
| 68 | return hid_match_device(hdev, hdrv) != NULL; | ||
| 69 | } | ||
| 70 | |||
| 71 | static bool hid_generic_match(struct hid_device *hdev, | ||
| 72 | bool ignore_special_driver) | ||
| 73 | { | ||
| 74 | if (ignore_special_driver) | ||
| 75 | return true; | ||
| 76 | |||
| 77 | if (hdev->quirks & HID_QUIRK_HAVE_SPECIAL_DRIVER) | ||
| 78 | return false; | ||
| 79 | |||
| 80 | /* | ||
| 81 | * If any other driver wants the device, leave the device to this other | ||
| 82 | * driver. | ||
| 83 | */ | ||
| 84 | if (bus_for_each_drv(&hid_bus_type, NULL, hdev, __check_hid_generic)) | ||
| 85 | return false; | ||
| 86 | |||
| 87 | return true; | ||
| 88 | } | ||
| 89 | |||
| 27 | static const struct hid_device_id hid_table[] = { | 90 | static const struct hid_device_id hid_table[] = { |
| 28 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_GENERIC, HID_ANY_ID, HID_ANY_ID) }, | 91 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, HID_ANY_ID, HID_ANY_ID) }, |
| 29 | { } | 92 | { } |
| 30 | }; | 93 | }; |
| 31 | MODULE_DEVICE_TABLE(hid, hid_table); | 94 | MODULE_DEVICE_TABLE(hid, hid_table); |
| @@ -33,6 +96,9 @@ MODULE_DEVICE_TABLE(hid, hid_table); | |||
| 33 | static struct hid_driver hid_generic = { | 96 | static struct hid_driver hid_generic = { |
| 34 | .name = "hid-generic", | 97 | .name = "hid-generic", |
| 35 | .id_table = hid_table, | 98 | .id_table = hid_table, |
| 99 | .match = hid_generic_match, | ||
| 100 | .bus_add_driver = hid_generic_add_driver, | ||
| 101 | .bus_removed_driver = hid_generic_removed_driver, | ||
| 36 | }; | 102 | }; |
| 37 | module_hid_driver(hid_generic); | 103 | module_hid_driver(hid_generic); |
| 38 | 104 | ||
diff --git a/include/linux/hid.h b/include/linux/hid.h index 83df331576a5..39cdeb205caa 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
| @@ -672,6 +672,7 @@ struct hid_usage_id { | |||
| 672 | * to be called) | 672 | * to be called) |
| 673 | * @dyn_list: list of dynamically added device ids | 673 | * @dyn_list: list of dynamically added device ids |
| 674 | * @dyn_lock: lock protecting @dyn_list | 674 | * @dyn_lock: lock protecting @dyn_list |
| 675 | * @match: check if the given device is handled by this driver | ||
| 675 | * @probe: new device inserted | 676 | * @probe: new device inserted |
| 676 | * @remove: device removed (NULL if not a hot-plug capable driver) | 677 | * @remove: device removed (NULL if not a hot-plug capable driver) |
| 677 | * @report_table: on which reports to call raw_event (NULL means all) | 678 | * @report_table: on which reports to call raw_event (NULL means all) |
| @@ -684,6 +685,8 @@ struct hid_usage_id { | |||
| 684 | * @input_mapped: invoked on input registering after mapping an usage | 685 | * @input_mapped: invoked on input registering after mapping an usage |
| 685 | * @input_configured: invoked just before the device is registered | 686 | * @input_configured: invoked just before the device is registered |
| 686 | * @feature_mapping: invoked on feature registering | 687 | * @feature_mapping: invoked on feature registering |
| 688 | * @bus_add_driver: invoked when a HID driver is about to be added | ||
| 689 | * @bus_removed_driver: invoked when a HID driver has been removed | ||
| 687 | * @suspend: invoked on suspend (NULL means nop) | 690 | * @suspend: invoked on suspend (NULL means nop) |
| 688 | * @resume: invoked on resume if device was not reset (NULL means nop) | 691 | * @resume: invoked on resume if device was not reset (NULL means nop) |
| 689 | * @reset_resume: invoked on resume if device was reset (NULL means nop) | 692 | * @reset_resume: invoked on resume if device was reset (NULL means nop) |
| @@ -712,6 +715,7 @@ struct hid_driver { | |||
| 712 | struct list_head dyn_list; | 715 | struct list_head dyn_list; |
| 713 | spinlock_t dyn_lock; | 716 | spinlock_t dyn_lock; |
| 714 | 717 | ||
| 718 | bool (*match)(struct hid_device *dev, bool ignore_special_driver); | ||
| 715 | int (*probe)(struct hid_device *dev, const struct hid_device_id *id); | 719 | int (*probe)(struct hid_device *dev, const struct hid_device_id *id); |
| 716 | void (*remove)(struct hid_device *dev); | 720 | void (*remove)(struct hid_device *dev); |
| 717 | 721 | ||
| @@ -737,6 +741,8 @@ struct hid_driver { | |||
| 737 | void (*feature_mapping)(struct hid_device *hdev, | 741 | void (*feature_mapping)(struct hid_device *hdev, |
| 738 | struct hid_field *field, | 742 | struct hid_field *field, |
| 739 | struct hid_usage *usage); | 743 | struct hid_usage *usage); |
| 744 | void (*bus_add_driver)(struct hid_driver *driver); | ||
| 745 | void (*bus_removed_driver)(struct hid_driver *driver); | ||
| 740 | #ifdef CONFIG_PM | 746 | #ifdef CONFIG_PM |
| 741 | int (*suspend)(struct hid_device *hdev, pm_message_t message); | 747 | int (*suspend)(struct hid_device *hdev, pm_message_t message); |
| 742 | int (*resume)(struct hid_device *hdev); | 748 | int (*resume)(struct hid_device *hdev); |
| @@ -815,6 +821,8 @@ extern bool hid_ignore(struct hid_device *); | |||
| 815 | extern int hid_add_device(struct hid_device *); | 821 | extern int hid_add_device(struct hid_device *); |
| 816 | extern void hid_destroy_device(struct hid_device *); | 822 | extern void hid_destroy_device(struct hid_device *); |
| 817 | 823 | ||
| 824 | extern struct bus_type hid_bus_type; | ||
| 825 | |||
| 818 | extern int __must_check __hid_register_driver(struct hid_driver *, | 826 | extern int __must_check __hid_register_driver(struct hid_driver *, |
| 819 | struct module *, const char *mod_name); | 827 | struct module *, const char *mod_name); |
| 820 | 828 | ||
| @@ -865,6 +873,8 @@ bool hid_match_one_id(const struct hid_device *hdev, | |||
| 865 | const struct hid_device_id *id); | 873 | const struct hid_device_id *id); |
| 866 | const struct hid_device_id *hid_match_id(const struct hid_device *hdev, | 874 | const struct hid_device_id *hid_match_id(const struct hid_device *hdev, |
| 867 | const struct hid_device_id *id); | 875 | const struct hid_device_id *id); |
| 876 | const struct hid_device_id *hid_match_device(struct hid_device *hdev, | ||
| 877 | struct hid_driver *hdrv); | ||
| 868 | s32 hid_snto32(__u32 value, unsigned n); | 878 | s32 hid_snto32(__u32 value, unsigned n); |
| 869 | __u32 hid_field_extract(const struct hid_device *hid, __u8 *report, | 879 | __u32 hid_field_extract(const struct hid_device *hid, __u8 *report, |
| 870 | unsigned offset, unsigned n); | 880 | unsigned offset, unsigned n); |
