aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2018-08-20 12:05:17 -0400
committerJiri Kosina <jkosina@suse.cz>2018-08-20 12:05:17 -0400
commit415d2b3392d7a80903e0f97f051201aa02bf20e9 (patch)
tree47492d2386a0e7f00ef645313cb44ae4960b7e7e /drivers/hid
parent4f65245f2d178b9cba48350620d76faa4a098841 (diff)
parentb8e759b8f6dab1c473c30ac12709095d0b81078e (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/Kconfig10
-rw-r--r--drivers/hid/Makefile1
-rw-r--r--drivers/hid/hid-core.c32
-rw-r--r--drivers/hid/hid-cougar.c312
-rw-r--r--drivers/hid/hid-debug.c6
-rw-r--r--drivers/hid/hid-ids.h3
-rw-r--r--drivers/hid/hid-picolcd_fb.c3
-rw-r--r--drivers/hid/hid-sensor-hub.c3
-rw-r--r--drivers/hid/hidraw.c2
-rw-r--r--drivers/hid/intel-ish-hid/ishtp-hid-client.c4
-rw-r--r--drivers/hid/usbhid/Kconfig2
-rw-r--r--drivers/hid/wacom_sys.c22
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
210config 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
210config HID_PRODIKEYS 220config 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
35obj-$(CONFIG_HID_CHICONY) += hid-chicony.o 35obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
36obj-$(CONFIG_HID_CMEDIA) += hid-cmedia.o 36obj-$(CONFIG_HID_CMEDIA) += hid-cmedia.o
37obj-$(CONFIG_HID_CORSAIR) += hid-corsair.o 37obj-$(CONFIG_HID_CORSAIR) += hid-corsair.o
38obj-$(CONFIG_HID_COUGAR) += hid-cougar.o
38obj-$(CONFIG_HID_CP2112) += hid-cp2112.o 39obj-$(CONFIG_HID_CP2112) += hid-cp2112.o
39obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o 40obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
40obj-$(CONFIG_HID_DRAGONRISE) += hid-dr.o 41obj-$(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 */
1952bool 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}
1963EXPORT_SYMBOL_GPL(hid_compare_device_paths);
1964
1939static int hid_device_probe(struct device *dev) 1965static 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
13MODULE_AUTHOR("Daniel M. Lambea <dmlambea@gmail.com>");
14MODULE_DESCRIPTION("Cougar 500k Gaming Keyboard");
15MODULE_LICENSE("GPL");
16MODULE_INFO(key_mappings, "G1-G6 are mapped to F13-F18");
17
18static int cougar_g6_is_space = 1;
19module_param_named(g6_is_space, cougar_g6_is_space, int, 0600);
20MODULE_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 */
49static 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
69struct 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
77struct cougar {
78 bool special_intf;
79 struct cougar_shared *shared;
80};
81
82static LIST_HEAD(cougar_udev_list);
83static DEFINE_MUTEX(cougar_udev_list_lock);
84
85static 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 */
104static __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
117static 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
131static 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
143static 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 */
157static 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
186out:
187 mutex_unlock(&cougar_udev_list_lock);
188 return error;
189}
190
191static 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
246fail_stop_and_cleanup:
247 hid_hw_stop(hdev);
248fail:
249 hid_set_drvdata(hdev, NULL);
250 return error;
251}
252
253/*
254 * Convert events from vendor intf to input key events
255 */
256static 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
282static 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
296static 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};
301MODULE_DEVICE_TABLE(hid, cougar_id_table);
302
303static 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
312module_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 {
703static LIST_HEAD(wacom_udev_list); 703static LIST_HEAD(wacom_udev_list);
704static DEFINE_MUTEX(wacom_udev_list_lock); 704static DEFINE_MUTEX(wacom_udev_list_lock);
705 705
706static 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
718static bool wacom_are_sibling(struct hid_device *hdev, 706static 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;