diff options
| author | Jiri Kosina <jkosina@suse.cz> | 2018-08-20 12:05:17 -0400 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2018-08-20 12:05:17 -0400 |
| commit | 415d2b3392d7a80903e0f97f051201aa02bf20e9 (patch) | |
| tree | 47492d2386a0e7f00ef645313cb44ae4960b7e7e /drivers/hid | |
| parent | 4f65245f2d178b9cba48350620d76faa4a098841 (diff) | |
| parent | b8e759b8f6dab1c473c30ac12709095d0b81078e (diff) | |
Merge branch 'for-4.19/cougar' into for-linus
New device support for hid-cougar
Diffstat (limited to 'drivers/hid')
| -rw-r--r-- | drivers/hid/Kconfig | 10 | ||||
| -rw-r--r-- | drivers/hid/Makefile | 1 | ||||
| -rw-r--r-- | drivers/hid/hid-core.c | 32 | ||||
| -rw-r--r-- | drivers/hid/hid-cougar.c | 312 | ||||
| -rw-r--r-- | drivers/hid/hid-debug.c | 6 | ||||
| -rw-r--r-- | drivers/hid/hid-ids.h | 3 | ||||
| -rw-r--r-- | drivers/hid/hid-picolcd_fb.c | 3 | ||||
| -rw-r--r-- | drivers/hid/hid-sensor-hub.c | 3 | ||||
| -rw-r--r-- | drivers/hid/hidraw.c | 2 | ||||
| -rw-r--r-- | drivers/hid/intel-ish-hid/ishtp-hid-client.c | 4 | ||||
| -rw-r--r-- | drivers/hid/usbhid/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/hid/wacom_sys.c | 22 |
12 files changed, 371 insertions, 29 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index a49a10437c40..61e1953ff921 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
| @@ -207,6 +207,16 @@ config HID_CORSAIR | |||
| 207 | - Vengeance K90 | 207 | - Vengeance K90 |
| 208 | - Scimitar PRO RGB | 208 | - Scimitar PRO RGB |
| 209 | 209 | ||
| 210 | config HID_COUGAR | ||
| 211 | tristate "Cougar devices" | ||
| 212 | depends on HID | ||
| 213 | help | ||
| 214 | Support for Cougar devices that are not fully compliant with the | ||
| 215 | HID standard. | ||
| 216 | |||
| 217 | Supported devices: | ||
| 218 | - Cougar 500k Gaming Keyboard | ||
| 219 | |||
| 210 | config HID_PRODIKEYS | 220 | config HID_PRODIKEYS |
| 211 | tristate "Prodikeys PC-MIDI Keyboard support" | 221 | tristate "Prodikeys PC-MIDI Keyboard support" |
| 212 | depends on HID && SND | 222 | depends on HID && SND |
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 511e1cbff768..bd7ac53b75c5 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
| @@ -35,6 +35,7 @@ obj-$(CONFIG_HID_CHERRY) += hid-cherry.o | |||
| 35 | obj-$(CONFIG_HID_CHICONY) += hid-chicony.o | 35 | obj-$(CONFIG_HID_CHICONY) += hid-chicony.o |
| 36 | obj-$(CONFIG_HID_CMEDIA) += hid-cmedia.o | 36 | obj-$(CONFIG_HID_CMEDIA) += hid-cmedia.o |
| 37 | obj-$(CONFIG_HID_CORSAIR) += hid-corsair.o | 37 | obj-$(CONFIG_HID_CORSAIR) += hid-corsair.o |
| 38 | obj-$(CONFIG_HID_COUGAR) += hid-cougar.o | ||
| 38 | obj-$(CONFIG_HID_CP2112) += hid-cp2112.o | 39 | obj-$(CONFIG_HID_CP2112) += hid-cp2112.o |
| 39 | obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o | 40 | obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o |
| 40 | obj-$(CONFIG_HID_DRAGONRISE) += hid-dr.o | 41 | obj-$(CONFIG_HID_DRAGONRISE) += hid-dr.o |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index a460ec147aee..402ad974b31c 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -134,8 +134,11 @@ static int open_collection(struct hid_parser *parser, unsigned type) | |||
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | if (parser->device->maxcollection == parser->device->collection_size) { | 136 | if (parser->device->maxcollection == parser->device->collection_size) { |
| 137 | collection = kmalloc(sizeof(struct hid_collection) * | 137 | collection = kmalloc( |
| 138 | parser->device->collection_size * 2, GFP_KERNEL); | 138 | array3_size(sizeof(struct hid_collection), |
| 139 | parser->device->collection_size, | ||
| 140 | 2), | ||
| 141 | GFP_KERNEL); | ||
| 139 | if (collection == NULL) { | 142 | if (collection == NULL) { |
| 140 | hid_err(parser->device, "failed to reallocate collection array\n"); | 143 | hid_err(parser->device, "failed to reallocate collection array\n"); |
| 141 | return -ENOMEM; | 144 | return -ENOMEM; |
| @@ -1278,7 +1281,7 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, | |||
| 1278 | __s32 max = field->logical_maximum; | 1281 | __s32 max = field->logical_maximum; |
| 1279 | __s32 *value; | 1282 | __s32 *value; |
| 1280 | 1283 | ||
| 1281 | value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC); | 1284 | value = kmalloc_array(count, sizeof(__s32), GFP_ATOMIC); |
| 1282 | if (!value) | 1285 | if (!value) |
| 1283 | return; | 1286 | return; |
| 1284 | 1287 | ||
| @@ -1936,6 +1939,29 @@ static int hid_bus_match(struct device *dev, struct device_driver *drv) | |||
| 1936 | return hid_match_device(hdev, hdrv) != NULL; | 1939 | return hid_match_device(hdev, hdrv) != NULL; |
| 1937 | } | 1940 | } |
| 1938 | 1941 | ||
| 1942 | /** | ||
| 1943 | * hid_compare_device_paths - check if both devices share the same path | ||
| 1944 | * @hdev_a: hid device | ||
| 1945 | * @hdev_b: hid device | ||
| 1946 | * @separator: char to use as separator | ||
| 1947 | * | ||
| 1948 | * Check if two devices share the same path up to the last occurrence of | ||
| 1949 | * the separator char. Both paths must exist (i.e., zero-length paths | ||
| 1950 | * don't match). | ||
| 1951 | */ | ||
| 1952 | bool hid_compare_device_paths(struct hid_device *hdev_a, | ||
| 1953 | struct hid_device *hdev_b, char separator) | ||
| 1954 | { | ||
| 1955 | int n1 = strrchr(hdev_a->phys, separator) - hdev_a->phys; | ||
| 1956 | int n2 = strrchr(hdev_b->phys, separator) - hdev_b->phys; | ||
| 1957 | |||
| 1958 | if (n1 != n2 || n1 <= 0 || n2 <= 0) | ||
| 1959 | return false; | ||
| 1960 | |||
| 1961 | return !strncmp(hdev_a->phys, hdev_b->phys, n1); | ||
| 1962 | } | ||
| 1963 | EXPORT_SYMBOL_GPL(hid_compare_device_paths); | ||
| 1964 | |||
| 1939 | static int hid_device_probe(struct device *dev) | 1965 | static int hid_device_probe(struct device *dev) |
| 1940 | { | 1966 | { |
| 1941 | struct hid_driver *hdrv = to_hid_driver(dev->driver); | 1967 | struct hid_driver *hdrv = to_hid_driver(dev->driver); |
diff --git a/drivers/hid/hid-cougar.c b/drivers/hid/hid-cougar.c new file mode 100644 index 000000000000..ad2e87de7dc5 --- /dev/null +++ b/drivers/hid/hid-cougar.c | |||
| @@ -0,0 +1,312 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0+ | ||
| 2 | /* | ||
| 3 | * HID driver for Cougar 500k Gaming Keyboard | ||
| 4 | * | ||
| 5 | * Copyright (c) 2018 Daniel M. Lambea <dmlambea@gmail.com> | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/hid.h> | ||
| 9 | #include <linux/module.h> | ||
| 10 | |||
| 11 | #include "hid-ids.h" | ||
| 12 | |||
| 13 | MODULE_AUTHOR("Daniel M. Lambea <dmlambea@gmail.com>"); | ||
| 14 | MODULE_DESCRIPTION("Cougar 500k Gaming Keyboard"); | ||
| 15 | MODULE_LICENSE("GPL"); | ||
| 16 | MODULE_INFO(key_mappings, "G1-G6 are mapped to F13-F18"); | ||
| 17 | |||
| 18 | static int cougar_g6_is_space = 1; | ||
| 19 | module_param_named(g6_is_space, cougar_g6_is_space, int, 0600); | ||
| 20 | MODULE_PARM_DESC(g6_is_space, | ||
| 21 | "If set, G6 programmable key sends SPACE instead of F18 (0=off, 1=on) (default=1)"); | ||
| 22 | |||
| 23 | |||
| 24 | #define COUGAR_VENDOR_USAGE 0xff00ff00 | ||
| 25 | |||
| 26 | #define COUGAR_FIELD_CODE 1 | ||
| 27 | #define COUGAR_FIELD_ACTION 2 | ||
| 28 | |||
| 29 | #define COUGAR_KEY_G1 0x83 | ||
| 30 | #define COUGAR_KEY_G2 0x84 | ||
| 31 | #define COUGAR_KEY_G3 0x85 | ||
| 32 | #define COUGAR_KEY_G4 0x86 | ||
| 33 | #define COUGAR_KEY_G5 0x87 | ||
| 34 | #define COUGAR_KEY_G6 0x78 | ||
| 35 | #define COUGAR_KEY_FN 0x0d | ||
| 36 | #define COUGAR_KEY_MR 0x6f | ||
| 37 | #define COUGAR_KEY_M1 0x80 | ||
| 38 | #define COUGAR_KEY_M2 0x81 | ||
| 39 | #define COUGAR_KEY_M3 0x82 | ||
| 40 | #define COUGAR_KEY_LEDS 0x67 | ||
| 41 | #define COUGAR_KEY_LOCK 0x6e | ||
| 42 | |||
| 43 | |||
| 44 | /* Default key mappings. The special key COUGAR_KEY_G6 is defined first | ||
| 45 | * because it is more frequent to use the spacebar rather than any other | ||
| 46 | * special keys. Depending on the value of the parameter 'g6_is_space', | ||
| 47 | * the mapping will be updated in the probe function. | ||
| 48 | */ | ||
| 49 | static unsigned char cougar_mapping[][2] = { | ||
| 50 | { COUGAR_KEY_G6, KEY_SPACE }, | ||
| 51 | { COUGAR_KEY_G1, KEY_F13 }, | ||
| 52 | { COUGAR_KEY_G2, KEY_F14 }, | ||
| 53 | { COUGAR_KEY_G3, KEY_F15 }, | ||
| 54 | { COUGAR_KEY_G4, KEY_F16 }, | ||
| 55 | { COUGAR_KEY_G5, KEY_F17 }, | ||
| 56 | { COUGAR_KEY_LOCK, KEY_SCREENLOCK }, | ||
| 57 | /* The following keys are handled by the hardware itself, so no special | ||
| 58 | * treatment is required: | ||
| 59 | { COUGAR_KEY_FN, KEY_RESERVED }, | ||
| 60 | { COUGAR_KEY_MR, KEY_RESERVED }, | ||
| 61 | { COUGAR_KEY_M1, KEY_RESERVED }, | ||
| 62 | { COUGAR_KEY_M2, KEY_RESERVED }, | ||
| 63 | { COUGAR_KEY_M3, KEY_RESERVED }, | ||
| 64 | { COUGAR_KEY_LEDS, KEY_RESERVED }, | ||
| 65 | */ | ||
| 66 | { 0, 0 }, | ||
| 67 | }; | ||
| 68 | |||
| 69 | struct cougar_shared { | ||
| 70 | struct list_head list; | ||
| 71 | struct kref kref; | ||
| 72 | bool enabled; | ||
| 73 | struct hid_device *dev; | ||
| 74 | struct input_dev *input; | ||
| 75 | }; | ||
| 76 | |||
| 77 | struct cougar { | ||
| 78 | bool special_intf; | ||
| 79 | struct cougar_shared *shared; | ||
| 80 | }; | ||
| 81 | |||
| 82 | static LIST_HEAD(cougar_udev_list); | ||
| 83 | static DEFINE_MUTEX(cougar_udev_list_lock); | ||
| 84 | |||
| 85 | static void cougar_fix_g6_mapping(struct hid_device *hdev) | ||
| 86 | { | ||
| 87 | int i; | ||
| 88 | |||
| 89 | for (i = 0; cougar_mapping[i][0]; i++) { | ||
| 90 | if (cougar_mapping[i][0] == COUGAR_KEY_G6) { | ||
| 91 | cougar_mapping[i][1] = | ||
| 92 | cougar_g6_is_space ? KEY_SPACE : KEY_F18; | ||
| 93 | hid_info(hdev, "G6 mapped to %s\n", | ||
| 94 | cougar_g6_is_space ? "space" : "F18"); | ||
| 95 | return; | ||
| 96 | } | ||
| 97 | } | ||
| 98 | hid_warn(hdev, "no mapping defined for G6/spacebar"); | ||
| 99 | } | ||
| 100 | |||
| 101 | /* | ||
| 102 | * Constant-friendly rdesc fixup for mouse interface | ||
| 103 | */ | ||
| 104 | static __u8 *cougar_report_fixup(struct hid_device *hdev, __u8 *rdesc, | ||
| 105 | unsigned int *rsize) | ||
| 106 | { | ||
| 107 | if (rdesc[2] == 0x09 && rdesc[3] == 0x02 && | ||
| 108 | (rdesc[115] | rdesc[116] << 8) >= HID_MAX_USAGES) { | ||
| 109 | hid_info(hdev, | ||
| 110 | "usage count exceeds max: fixing up report descriptor\n"); | ||
| 111 | rdesc[115] = ((HID_MAX_USAGES-1) & 0xff); | ||
| 112 | rdesc[116] = ((HID_MAX_USAGES-1) >> 8); | ||
| 113 | } | ||
| 114 | return rdesc; | ||
| 115 | } | ||
| 116 | |||
| 117 | static struct cougar_shared *cougar_get_shared_data(struct hid_device *hdev) | ||
| 118 | { | ||
| 119 | struct cougar_shared *shared; | ||
| 120 | |||
| 121 | /* Try to find an already-probed interface from the same device */ | ||
| 122 | list_for_each_entry(shared, &cougar_udev_list, list) { | ||
| 123 | if (hid_compare_device_paths(hdev, shared->dev, '/')) { | ||
| 124 | kref_get(&shared->kref); | ||
| 125 | return shared; | ||
| 126 | } | ||
| 127 | } | ||
| 128 | return NULL; | ||
| 129 | } | ||
| 130 | |||
| 131 | static void cougar_release_shared_data(struct kref *kref) | ||
| 132 | { | ||
| 133 | struct cougar_shared *shared = container_of(kref, | ||
| 134 | struct cougar_shared, kref); | ||
| 135 | |||
| 136 | mutex_lock(&cougar_udev_list_lock); | ||
| 137 | list_del(&shared->list); | ||
| 138 | mutex_unlock(&cougar_udev_list_lock); | ||
| 139 | |||
| 140 | kfree(shared); | ||
| 141 | } | ||
| 142 | |||
| 143 | static void cougar_remove_shared_data(void *resource) | ||
| 144 | { | ||
| 145 | struct cougar *cougar = resource; | ||
| 146 | |||
| 147 | if (cougar->shared) { | ||
| 148 | kref_put(&cougar->shared->kref, cougar_release_shared_data); | ||
| 149 | cougar->shared = NULL; | ||
| 150 | } | ||
| 151 | } | ||
| 152 | |||
| 153 | /* | ||
| 154 | * Bind the device group's shared data to this cougar struct. | ||
| 155 | * If no shared data exists for this group, create and initialize it. | ||
| 156 | */ | ||
| 157 | static int cougar_bind_shared_data(struct hid_device *hdev, struct cougar *cougar) | ||
| 158 | { | ||
| 159 | struct cougar_shared *shared; | ||
| 160 | int error = 0; | ||
| 161 | |||
| 162 | mutex_lock(&cougar_udev_list_lock); | ||
| 163 | |||
| 164 | shared = cougar_get_shared_data(hdev); | ||
| 165 | if (!shared) { | ||
| 166 | shared = kzalloc(sizeof(*shared), GFP_KERNEL); | ||
| 167 | if (!shared) { | ||
| 168 | error = -ENOMEM; | ||
| 169 | goto out; | ||
| 170 | } | ||
| 171 | |||
| 172 | kref_init(&shared->kref); | ||
| 173 | shared->dev = hdev; | ||
| 174 | list_add_tail(&shared->list, &cougar_udev_list); | ||
| 175 | } | ||
| 176 | |||
| 177 | cougar->shared = shared; | ||
| 178 | |||
| 179 | error = devm_add_action(&hdev->dev, cougar_remove_shared_data, cougar); | ||
| 180 | if (error) { | ||
| 181 | mutex_unlock(&cougar_udev_list_lock); | ||
| 182 | cougar_remove_shared_data(cougar); | ||
| 183 | return error; | ||
| 184 | } | ||
| 185 | |||
| 186 | out: | ||
| 187 | mutex_unlock(&cougar_udev_list_lock); | ||
| 188 | return error; | ||
| 189 | } | ||
| 190 | |||
| 191 | static int cougar_probe(struct hid_device *hdev, | ||
| 192 | const struct hid_device_id *id) | ||
| 193 | { | ||
| 194 | struct cougar *cougar; | ||
| 195 | struct hid_input *next, *hidinput = NULL; | ||
| 196 | unsigned int connect_mask; | ||
| 197 | int error; | ||
| 198 | |||
| 199 | cougar = devm_kzalloc(&hdev->dev, sizeof(*cougar), GFP_KERNEL); | ||
| 200 | if (!cougar) | ||
| 201 | return -ENOMEM; | ||
| 202 | hid_set_drvdata(hdev, cougar); | ||
| 203 | |||
| 204 | error = hid_parse(hdev); | ||
| 205 | if (error) { | ||
| 206 | hid_err(hdev, "parse failed\n"); | ||
| 207 | goto fail; | ||
| 208 | } | ||
| 209 | |||
| 210 | if (hdev->collection->usage == COUGAR_VENDOR_USAGE) { | ||
| 211 | cougar->special_intf = true; | ||
| 212 | connect_mask = HID_CONNECT_HIDRAW; | ||
| 213 | } else | ||
| 214 | connect_mask = HID_CONNECT_DEFAULT; | ||
| 215 | |||
| 216 | error = hid_hw_start(hdev, connect_mask); | ||
| 217 | if (error) { | ||
| 218 | hid_err(hdev, "hw start failed\n"); | ||
| 219 | goto fail; | ||
| 220 | } | ||
| 221 | |||
| 222 | error = cougar_bind_shared_data(hdev, cougar); | ||
| 223 | if (error) | ||
| 224 | goto fail_stop_and_cleanup; | ||
| 225 | |||
| 226 | /* The custom vendor interface will use the hid_input registered | ||
| 227 | * for the keyboard interface, in order to send translated key codes | ||
| 228 | * to it. | ||
| 229 | */ | ||
| 230 | if (hdev->collection->usage == HID_GD_KEYBOARD) { | ||
| 231 | cougar_fix_g6_mapping(hdev); | ||
| 232 | list_for_each_entry_safe(hidinput, next, &hdev->inputs, list) { | ||
| 233 | if (hidinput->registered && hidinput->input != NULL) { | ||
| 234 | cougar->shared->input = hidinput->input; | ||
| 235 | cougar->shared->enabled = true; | ||
| 236 | break; | ||
| 237 | } | ||
| 238 | } | ||
| 239 | } else if (hdev->collection->usage == COUGAR_VENDOR_USAGE) { | ||
| 240 | error = hid_hw_open(hdev); | ||
| 241 | if (error) | ||
| 242 | goto fail_stop_and_cleanup; | ||
| 243 | } | ||
| 244 | return 0; | ||
| 245 | |||
| 246 | fail_stop_and_cleanup: | ||
| 247 | hid_hw_stop(hdev); | ||
| 248 | fail: | ||
| 249 | hid_set_drvdata(hdev, NULL); | ||
| 250 | return error; | ||
| 251 | } | ||
| 252 | |||
| 253 | /* | ||
| 254 | * Convert events from vendor intf to input key events | ||
| 255 | */ | ||
| 256 | static int cougar_raw_event(struct hid_device *hdev, struct hid_report *report, | ||
| 257 | u8 *data, int size) | ||
| 258 | { | ||
| 259 | struct cougar *cougar; | ||
| 260 | unsigned char code, action; | ||
| 261 | int i; | ||
| 262 | |||
| 263 | cougar = hid_get_drvdata(hdev); | ||
| 264 | if (!cougar->special_intf || !cougar->shared || | ||
| 265 | !cougar->shared->input || !cougar->shared->enabled) | ||
| 266 | return 0; | ||
| 267 | |||
| 268 | code = data[COUGAR_FIELD_CODE]; | ||
| 269 | action = data[COUGAR_FIELD_ACTION]; | ||
| 270 | for (i = 0; cougar_mapping[i][0]; i++) { | ||
| 271 | if (code == cougar_mapping[i][0]) { | ||
| 272 | input_event(cougar->shared->input, EV_KEY, | ||
| 273 | cougar_mapping[i][1], action); | ||
| 274 | input_sync(cougar->shared->input); | ||
| 275 | return 0; | ||
| 276 | } | ||
| 277 | } | ||
| 278 | hid_warn(hdev, "unmapped special key code %x: ignoring\n", code); | ||
| 279 | return 0; | ||
| 280 | } | ||
| 281 | |||
| 282 | static void cougar_remove(struct hid_device *hdev) | ||
| 283 | { | ||
| 284 | struct cougar *cougar = hid_get_drvdata(hdev); | ||
| 285 | |||
| 286 | if (cougar) { | ||
| 287 | /* Stop the vendor intf to process more events */ | ||
| 288 | if (cougar->shared) | ||
| 289 | cougar->shared->enabled = false; | ||
| 290 | if (cougar->special_intf) | ||
| 291 | hid_hw_close(hdev); | ||
| 292 | } | ||
| 293 | hid_hw_stop(hdev); | ||
| 294 | } | ||
| 295 | |||
| 296 | static struct hid_device_id cougar_id_table[] = { | ||
| 297 | { HID_USB_DEVICE(USB_VENDOR_ID_SOLID_YEAR, | ||
| 298 | USB_DEVICE_ID_COUGAR_500K_GAMING_KEYBOARD) }, | ||
| 299 | {} | ||
| 300 | }; | ||
| 301 | MODULE_DEVICE_TABLE(hid, cougar_id_table); | ||
| 302 | |||
| 303 | static struct hid_driver cougar_driver = { | ||
| 304 | .name = "cougar", | ||
| 305 | .id_table = cougar_id_table, | ||
| 306 | .report_fixup = cougar_report_fixup, | ||
| 307 | .probe = cougar_probe, | ||
| 308 | .remove = cougar_remove, | ||
| 309 | .raw_event = cougar_raw_event, | ||
| 310 | }; | ||
| 311 | |||
| 312 | module_hid_driver(cougar_driver); | ||
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 4db8e140f709..b48100236df8 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c | |||
| @@ -457,7 +457,7 @@ static char *resolv_usage_page(unsigned page, struct seq_file *f) { | |||
| 457 | char *buf = NULL; | 457 | char *buf = NULL; |
| 458 | 458 | ||
| 459 | if (!f) { | 459 | if (!f) { |
| 460 | buf = kzalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC); | 460 | buf = kzalloc(HID_DEBUG_BUFSIZE, GFP_ATOMIC); |
| 461 | if (!buf) | 461 | if (!buf) |
| 462 | return ERR_PTR(-ENOMEM); | 462 | return ERR_PTR(-ENOMEM); |
| 463 | } | 463 | } |
| @@ -685,7 +685,7 @@ void hid_dump_report(struct hid_device *hid, int type, u8 *data, | |||
| 685 | char *buf; | 685 | char *buf; |
| 686 | unsigned int i; | 686 | unsigned int i; |
| 687 | 687 | ||
| 688 | buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC); | 688 | buf = kmalloc(HID_DEBUG_BUFSIZE, GFP_ATOMIC); |
| 689 | 689 | ||
| 690 | if (!buf) | 690 | if (!buf) |
| 691 | return; | 691 | return; |
| @@ -1088,7 +1088,7 @@ static int hid_debug_events_open(struct inode *inode, struct file *file) | |||
| 1088 | goto out; | 1088 | goto out; |
| 1089 | } | 1089 | } |
| 1090 | 1090 | ||
| 1091 | if (!(list->hid_debug_buf = kzalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_KERNEL))) { | 1091 | if (!(list->hid_debug_buf = kzalloc(HID_DEBUG_BUFSIZE, GFP_KERNEL))) { |
| 1092 | err = -ENOMEM; | 1092 | err = -ENOMEM; |
| 1093 | kfree(list); | 1093 | kfree(list); |
| 1094 | goto out; | 1094 | goto out; |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index c7981ddd8776..a1ee8f643f24 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
| @@ -1001,6 +1001,9 @@ | |||
| 1001 | #define USB_VENDOR_ID_SINO_LITE 0x1345 | 1001 | #define USB_VENDOR_ID_SINO_LITE 0x1345 |
| 1002 | #define USB_DEVICE_ID_SINO_LITE_CONTROLLER 0x3008 | 1002 | #define USB_DEVICE_ID_SINO_LITE_CONTROLLER 0x3008 |
| 1003 | 1003 | ||
| 1004 | #define USB_VENDOR_ID_SOLID_YEAR 0x060b | ||
| 1005 | #define USB_DEVICE_ID_COUGAR_500K_GAMING_KEYBOARD 0x500a | ||
| 1006 | |||
| 1004 | #define USB_VENDOR_ID_SOUNDGRAPH 0x15c2 | 1007 | #define USB_VENDOR_ID_SOUNDGRAPH 0x15c2 |
| 1005 | #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034 | 1008 | #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034 |
| 1006 | #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST 0x0046 | 1009 | #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST 0x0046 |
diff --git a/drivers/hid/hid-picolcd_fb.c b/drivers/hid/hid-picolcd_fb.c index 7f965e231433..864a084b6cba 100644 --- a/drivers/hid/hid-picolcd_fb.c +++ b/drivers/hid/hid-picolcd_fb.c | |||
| @@ -394,7 +394,8 @@ static int picolcd_set_par(struct fb_info *info) | |||
| 394 | return -EINVAL; | 394 | return -EINVAL; |
| 395 | 395 | ||
| 396 | o_fb = fbdata->bitmap; | 396 | o_fb = fbdata->bitmap; |
| 397 | tmp_fb = kmalloc(PICOLCDFB_SIZE*info->var.bits_per_pixel, GFP_KERNEL); | 397 | tmp_fb = kmalloc_array(PICOLCDFB_SIZE, info->var.bits_per_pixel, |
| 398 | GFP_KERNEL); | ||
| 398 | if (!tmp_fb) | 399 | if (!tmp_fb) |
| 399 | return -ENOMEM; | 400 | return -ENOMEM; |
| 400 | 401 | ||
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index 25363fc571bc..50af72baa5ca 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c | |||
| @@ -624,7 +624,8 @@ static int sensor_hub_probe(struct hid_device *hdev, | |||
| 624 | ret = -EINVAL; | 624 | ret = -EINVAL; |
| 625 | goto err_stop_hw; | 625 | goto err_stop_hw; |
| 626 | } | 626 | } |
| 627 | sd->hid_sensor_hub_client_devs = devm_kzalloc(&hdev->dev, dev_cnt * | 627 | sd->hid_sensor_hub_client_devs = devm_kcalloc(&hdev->dev, |
| 628 | dev_cnt, | ||
| 628 | sizeof(struct mfd_cell), | 629 | sizeof(struct mfd_cell), |
| 629 | GFP_KERNEL); | 630 | GFP_KERNEL); |
| 630 | if (sd->hid_sensor_hub_client_devs == NULL) { | 631 | if (sd->hid_sensor_hub_client_devs == NULL) { |
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index b39844adea47..4a44e48e08b2 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c | |||
| @@ -218,7 +218,7 @@ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t | |||
| 218 | goto out; | 218 | goto out; |
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | buf = kmalloc(count * sizeof(__u8), GFP_KERNEL); | 221 | buf = kmalloc(count, GFP_KERNEL); |
| 222 | if (!buf) { | 222 | if (!buf) { |
| 223 | ret = -ENOMEM; | 223 | ret = -ENOMEM; |
| 224 | goto out; | 224 | goto out; |
diff --git a/drivers/hid/intel-ish-hid/ishtp-hid-client.c b/drivers/hid/intel-ish-hid/ishtp-hid-client.c index acc2536c8094..2d28cffc1404 100644 --- a/drivers/hid/intel-ish-hid/ishtp-hid-client.c +++ b/drivers/hid/intel-ish-hid/ishtp-hid-client.c | |||
| @@ -121,9 +121,9 @@ static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf, | |||
| 121 | } | 121 | } |
| 122 | client_data->hid_dev_count = (unsigned int)*payload; | 122 | client_data->hid_dev_count = (unsigned int)*payload; |
| 123 | if (!client_data->hid_devices) | 123 | if (!client_data->hid_devices) |
| 124 | client_data->hid_devices = devm_kzalloc( | 124 | client_data->hid_devices = devm_kcalloc( |
| 125 | &client_data->cl_device->dev, | 125 | &client_data->cl_device->dev, |
| 126 | client_data->hid_dev_count * | 126 | client_data->hid_dev_count, |
| 127 | sizeof(struct device_info), | 127 | sizeof(struct device_info), |
| 128 | GFP_KERNEL); | 128 | GFP_KERNEL); |
| 129 | if (!client_data->hid_devices) { | 129 | if (!client_data->hid_devices) { |
diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig index 0108c5991a04..e50d8fe4d36c 100644 --- a/drivers/hid/usbhid/Kconfig +++ b/drivers/hid/usbhid/Kconfig | |||
| @@ -14,7 +14,7 @@ config USB_HID | |||
| 14 | 14 | ||
| 15 | You can't use this driver and the HIDBP (Boot Protocol) keyboard | 15 | You can't use this driver and the HIDBP (Boot Protocol) keyboard |
| 16 | and mouse drivers at the same time. More information is available: | 16 | and mouse drivers at the same time. More information is available: |
| 17 | <file:Documentation/input/input.txt>. | 17 | <file:Documentation/input/input.rst>. |
| 18 | 18 | ||
| 19 | If unsure, say Y. | 19 | If unsure, say Y. |
| 20 | 20 | ||
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 545986cfb978..ffe59a19b3a3 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c | |||
| @@ -703,18 +703,6 @@ struct wacom_hdev_data { | |||
| 703 | static LIST_HEAD(wacom_udev_list); | 703 | static LIST_HEAD(wacom_udev_list); |
| 704 | static DEFINE_MUTEX(wacom_udev_list_lock); | 704 | static DEFINE_MUTEX(wacom_udev_list_lock); |
| 705 | 705 | ||
| 706 | static bool compare_device_paths(struct hid_device *hdev_a, | ||
| 707 | struct hid_device *hdev_b, char separator) | ||
| 708 | { | ||
| 709 | int n1 = strrchr(hdev_a->phys, separator) - hdev_a->phys; | ||
| 710 | int n2 = strrchr(hdev_b->phys, separator) - hdev_b->phys; | ||
| 711 | |||
| 712 | if (n1 != n2 || n1 <= 0 || n2 <= 0) | ||
| 713 | return false; | ||
| 714 | |||
| 715 | return !strncmp(hdev_a->phys, hdev_b->phys, n1); | ||
| 716 | } | ||
| 717 | |||
| 718 | static bool wacom_are_sibling(struct hid_device *hdev, | 706 | static bool wacom_are_sibling(struct hid_device *hdev, |
| 719 | struct hid_device *sibling) | 707 | struct hid_device *sibling) |
| 720 | { | 708 | { |
| @@ -737,10 +725,10 @@ static bool wacom_are_sibling(struct hid_device *hdev, | |||
| 737 | * the same physical parent device path. | 725 | * the same physical parent device path. |
| 738 | */ | 726 | */ |
| 739 | if (hdev->vendor == sibling->vendor && hdev->product == sibling->product) { | 727 | if (hdev->vendor == sibling->vendor && hdev->product == sibling->product) { |
| 740 | if (!compare_device_paths(hdev, sibling, '/')) | 728 | if (!hid_compare_device_paths(hdev, sibling, '/')) |
| 741 | return false; | 729 | return false; |
| 742 | } else { | 730 | } else { |
| 743 | if (!compare_device_paths(hdev, sibling, '.')) | 731 | if (!hid_compare_device_paths(hdev, sibling, '.')) |
| 744 | return false; | 732 | return false; |
| 745 | } | 733 | } |
| 746 | 734 | ||
| @@ -787,7 +775,7 @@ static struct wacom_hdev_data *wacom_get_hdev_data(struct hid_device *hdev) | |||
| 787 | 775 | ||
| 788 | /* Try to find an already-probed interface from the same device */ | 776 | /* Try to find an already-probed interface from the same device */ |
| 789 | list_for_each_entry(data, &wacom_udev_list, list) { | 777 | list_for_each_entry(data, &wacom_udev_list, list) { |
| 790 | if (compare_device_paths(hdev, data->dev, '/')) { | 778 | if (hid_compare_device_paths(hdev, data->dev, '/')) { |
| 791 | kref_get(&data->kref); | 779 | kref_get(&data->kref); |
| 792 | return data; | 780 | return data; |
| 793 | } | 781 | } |
| @@ -1371,7 +1359,7 @@ static int wacom_led_groups_alloc_and_register_one(struct device *dev, | |||
| 1371 | if (!devres_open_group(dev, &wacom->led.groups[group_id], GFP_KERNEL)) | 1359 | if (!devres_open_group(dev, &wacom->led.groups[group_id], GFP_KERNEL)) |
| 1372 | return -ENOMEM; | 1360 | return -ENOMEM; |
| 1373 | 1361 | ||
| 1374 | leds = devm_kzalloc(dev, sizeof(struct wacom_led) * count, GFP_KERNEL); | 1362 | leds = devm_kcalloc(dev, count, sizeof(struct wacom_led), GFP_KERNEL); |
| 1375 | if (!leds) { | 1363 | if (!leds) { |
| 1376 | error = -ENOMEM; | 1364 | error = -ENOMEM; |
| 1377 | goto err; | 1365 | goto err; |
| @@ -1471,7 +1459,7 @@ static int wacom_led_groups_allocate(struct wacom *wacom, int count) | |||
| 1471 | struct wacom_group_leds *groups; | 1459 | struct wacom_group_leds *groups; |
| 1472 | int error; | 1460 | int error; |
| 1473 | 1461 | ||
| 1474 | groups = devm_kzalloc(dev, sizeof(struct wacom_group_leds) * count, | 1462 | groups = devm_kcalloc(dev, count, sizeof(struct wacom_group_leds), |
| 1475 | GFP_KERNEL); | 1463 | GFP_KERNEL); |
| 1476 | if (!groups) | 1464 | if (!groups) |
| 1477 | return -ENOMEM; | 1465 | return -ENOMEM; |
