aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/Kconfig8
-rw-r--r--drivers/hid/Makefile1
-rw-r--r--drivers/hid/hid-core.c31
-rw-r--r--drivers/hid/hid-holtekff.c2
-rw-r--r--drivers/hid/hid-ids.h12
-rw-r--r--drivers/hid/hid-input.c12
-rw-r--r--drivers/hid/hid-kye.c45
-rw-r--r--drivers/hid/hid-logitech-dj.c12
-rw-r--r--drivers/hid/hid-magicmouse.c2
-rw-r--r--drivers/hid/hid-ntrig.c15
-rw-r--r--drivers/hid/hid-picolcd_cir.c3
-rw-r--r--drivers/hid/hid-picolcd_core.c2
-rw-r--r--drivers/hid/hid-picolcd_debugfs.c23
-rw-r--r--drivers/hid/hid-picolcd_fb.c6
-rw-r--r--drivers/hid/hid-pl.c10
-rw-r--r--drivers/hid/hid-roccat-arvo.c6
-rw-r--r--drivers/hid/hid-roccat-isku.c2
-rw-r--r--drivers/hid/hid-roccat-kone.c4
-rw-r--r--drivers/hid/hid-roccat-koneplus.c2
-rw-r--r--drivers/hid/hid-roccat-konepure.c3
-rw-r--r--drivers/hid/hid-roccat-kovaplus.c2
-rw-r--r--drivers/hid/hid-sensor-hub.c5
-rw-r--r--drivers/hid/hid-speedlink.c11
-rw-r--r--drivers/hid/hid-xinmo.c61
-rw-r--r--drivers/hid/hidraw.c80
-rw-r--r--drivers/hid/i2c-hid/i2c-hid.c4
-rw-r--r--drivers/hid/uhid.c1
-rw-r--r--drivers/hid/usbhid/hid-core.c5
-rw-r--r--drivers/hid/usbhid/hid-quirks.c2
29 files changed, 261 insertions, 111 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 14ef6ab69790..3d7c9f67b6d7 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -743,6 +743,14 @@ config HID_WIIMOTE
743 To compile this driver as a module, choose M here: the 743 To compile this driver as a module, choose M here: the
744 module will be called hid-wiimote. 744 module will be called hid-wiimote.
745 745
746config HID_XINMO
747 tristate "Xin-Mo non-fully compliant devices"
748 depends on HID
749 ---help---
750 Support for Xin-Mo devices that are not fully compliant with the HID
751 standard. Currently only supports the Xin-Mo Dual Arcade. Say Y here
752 if you have a Xin-Mo Dual Arcade controller.
753
746config HID_ZEROPLUS 754config HID_ZEROPLUS
747 tristate "Zeroplus based game controller support" 755 tristate "Zeroplus based game controller support"
748 depends on HID 756 depends on HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 6f687287e212..a959f4aecaf5 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -110,6 +110,7 @@ obj-$(CONFIG_HID_TIVO) += hid-tivo.o
110obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o 110obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o
111obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o 111obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o
112obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o 112obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o
113obj-$(CONFIG_HID_XINMO) += hid-xinmo.o
113obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o 114obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o
114obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o 115obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o
115obj-$(CONFIG_HID_WACOM) += hid-wacom.o 116obj-$(CONFIG_HID_WACOM) += hid-wacom.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 5ea7d51e45b9..2ac13ca6edaa 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -454,7 +454,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
454 } 454 }
455 parser->local.delimiter_depth--; 455 parser->local.delimiter_depth--;
456 } 456 }
457 return 1; 457 return 0;
458 458
459 case HID_LOCAL_ITEM_TAG_USAGE: 459 case HID_LOCAL_ITEM_TAG_USAGE:
460 460
@@ -1132,7 +1132,8 @@ static void hid_output_field(const struct hid_device *hid,
1132} 1132}
1133 1133
1134/* 1134/*
1135 * Create a report. 1135 * Create a report. 'data' has to be allocated using
1136 * hid_alloc_report_buf() so that it has proper size.
1136 */ 1137 */
1137 1138
1138void hid_output_report(struct hid_report *report, __u8 *data) 1139void hid_output_report(struct hid_report *report, __u8 *data)
@@ -1149,6 +1150,22 @@ void hid_output_report(struct hid_report *report, __u8 *data)
1149EXPORT_SYMBOL_GPL(hid_output_report); 1150EXPORT_SYMBOL_GPL(hid_output_report);
1150 1151
1151/* 1152/*
1153 * Allocator for buffer that is going to be passed to hid_output_report()
1154 */
1155u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags)
1156{
1157 /*
1158 * 7 extra bytes are necessary to achieve proper functionality
1159 * of implement() working on 8 byte chunks
1160 */
1161
1162 int len = ((report->size - 1) >> 3) + 1 + (report->id > 0) + 7;
1163
1164 return kmalloc(len, flags);
1165}
1166EXPORT_SYMBOL_GPL(hid_alloc_report_buf);
1167
1168/*
1152 * Set a field value. The report this field belongs to has to be 1169 * Set a field value. The report this field belongs to has to be
1153 * created and transferred to the device, to set this value in the 1170 * created and transferred to the device, to set this value in the
1154 * device. 1171 * device.
@@ -1156,7 +1173,12 @@ EXPORT_SYMBOL_GPL(hid_output_report);
1156 1173
1157int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) 1174int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
1158{ 1175{
1159 unsigned size = field->report_size; 1176 unsigned size;
1177
1178 if (!field)
1179 return -1;
1180
1181 size = field->report_size;
1160 1182
1161 hid_dump_input(field->report->device, field->usage + offset, value); 1183 hid_dump_input(field->report->device, field->usage + offset, value);
1162 1184
@@ -1601,6 +1623,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
1601 { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, 1623 { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
1602 { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, 1624 { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
1603 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) }, 1625 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
1626 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
1604 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, 1627 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
1605 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) }, 1628 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) },
1606 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, 1629 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) },
@@ -1683,6 +1706,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
1683 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, 1706 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
1684 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, 1707 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
1685 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) }, 1708 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) },
1709 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE_OPTICAL) },
1686 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, 1710 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
1687 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) }, 1711 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) },
1688 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, 1712 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
@@ -1740,6 +1764,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
1740 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, 1764 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) },
1741 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET) }, 1765 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET) },
1742 { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) }, 1766 { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) },
1767 { HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE) },
1743 { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, 1768 { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
1744 { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, 1769 { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
1745 { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) }, 1770 { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) },
diff --git a/drivers/hid/hid-holtekff.c b/drivers/hid/hid-holtekff.c
index 9a8f05124525..9325545fc3ae 100644
--- a/drivers/hid/hid-holtekff.c
+++ b/drivers/hid/hid-holtekff.c
@@ -98,7 +98,7 @@ static void holtekff_send(struct holtekff_device *holtekff,
98 holtekff->field->value[i] = data[i]; 98 holtekff->field->value[i] = data[i];
99 } 99 }
100 100
101 dbg_hid("sending %*ph\n", 7, data); 101 dbg_hid("sending %7ph\n", data);
102 102
103 hid_hw_request(hid, holtekff->field->report, HID_REQ_SET_REPORT); 103 hid_hw_request(hid, holtekff->field->report, HID_REQ_SET_REPORT);
104} 104}
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index ffe4c7ae3340..e60e8d530697 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -135,9 +135,9 @@
135#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b 135#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b
136#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI 0x0255 136#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI 0x0255
137#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO 0x0256 137#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO 0x0256
138#define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI 0x0291 138#define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI 0x0290
139#define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO 0x0292 139#define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO 0x0291
140#define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS 0x0293 140#define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS 0x0292
141#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a 141#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a
142#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b 142#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b
143#define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240 143#define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240
@@ -482,6 +482,7 @@
482#define USB_VENDOR_ID_KYE 0x0458 482#define USB_VENDOR_ID_KYE 0x0458
483#define USB_DEVICE_ID_KYE_ERGO_525V 0x0087 483#define USB_DEVICE_ID_KYE_ERGO_525V 0x0087
484#define USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE 0x0138 484#define USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE 0x0138
485#define USB_DEVICE_ID_GENIUS_GX_IMPERATOR 0x4018
485#define USB_DEVICE_ID_KYE_GPEN_560 0x5003 486#define USB_DEVICE_ID_KYE_GPEN_560 0x5003
486#define USB_DEVICE_ID_KYE_EASYPEN_I405X 0x5010 487#define USB_DEVICE_ID_KYE_EASYPEN_I405X 0x5010
487#define USB_DEVICE_ID_KYE_MOUSEPEN_I608X 0x5011 488#define USB_DEVICE_ID_KYE_MOUSEPEN_I608X 0x5011
@@ -658,6 +659,7 @@
658#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16 0x0012 659#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16 0x0012
659#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17 0x0013 660#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17 0x0013
660#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18 0x0014 661#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18 0x0014
662#define USB_DEVICE_ID_NTRIG_DUOSENSE 0x1500
661 663
662#define USB_VENDOR_ID_ONTRAK 0x0a07 664#define USB_VENDOR_ID_ONTRAK 0x0a07
663#define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 665#define USB_DEVICE_ID_ONTRAK_ADU100 0x0064
@@ -716,6 +718,7 @@
716#define USB_DEVICE_ID_ROCCAT_KONE 0x2ced 718#define USB_DEVICE_ID_ROCCAT_KONE 0x2ced
717#define USB_DEVICE_ID_ROCCAT_KONEPLUS 0x2d51 719#define USB_DEVICE_ID_ROCCAT_KONEPLUS 0x2d51
718#define USB_DEVICE_ID_ROCCAT_KONEPURE 0x2dbe 720#define USB_DEVICE_ID_ROCCAT_KONEPURE 0x2dbe
721#define USB_DEVICE_ID_ROCCAT_KONEPURE_OPTICAL 0x2db4
719#define USB_DEVICE_ID_ROCCAT_KONEXTD 0x2e22 722#define USB_DEVICE_ID_ROCCAT_KONEXTD 0x2e22
720#define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50 723#define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50
721#define USB_DEVICE_ID_ROCCAT_LUA 0x2c2e 724#define USB_DEVICE_ID_ROCCAT_LUA 0x2c2e
@@ -887,6 +890,9 @@
887#define USB_VENDOR_ID_XAT 0x2505 890#define USB_VENDOR_ID_XAT 0x2505
888#define USB_DEVICE_ID_XAT_CSR 0x0220 891#define USB_DEVICE_ID_XAT_CSR 0x0220
889 892
893#define USB_VENDOR_ID_XIN_MO 0x16c0
894#define USB_DEVICE_ID_XIN_MO_DUAL_ARCADE 0x05e1
895
890#define USB_VENDOR_ID_XIROKU 0x1477 896#define USB_VENDOR_ID_XIROKU 0x1477
891#define USB_DEVICE_ID_XIROKU_SPX 0x1006 897#define USB_DEVICE_ID_XIROKU_SPX 0x1006
892#define USB_DEVICE_ID_XIROKU_MPX 0x1007 898#define USB_DEVICE_ID_XIROKU_MPX 0x1007
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 7480799e535c..3fc4034a4367 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -340,7 +340,7 @@ static int hidinput_get_battery_property(struct power_supply *psy,
340{ 340{
341 struct hid_device *dev = container_of(psy, struct hid_device, battery); 341 struct hid_device *dev = container_of(psy, struct hid_device, battery);
342 int ret = 0; 342 int ret = 0;
343 __u8 buf[2] = {}; 343 __u8 *buf;
344 344
345 switch (prop) { 345 switch (prop) {
346 case POWER_SUPPLY_PROP_PRESENT: 346 case POWER_SUPPLY_PROP_PRESENT:
@@ -349,12 +349,19 @@ static int hidinput_get_battery_property(struct power_supply *psy,
349 break; 349 break;
350 350
351 case POWER_SUPPLY_PROP_CAPACITY: 351 case POWER_SUPPLY_PROP_CAPACITY:
352
353 buf = kmalloc(2 * sizeof(__u8), GFP_KERNEL);
354 if (!buf) {
355 ret = -ENOMEM;
356 break;
357 }
352 ret = dev->hid_get_raw_report(dev, dev->battery_report_id, 358 ret = dev->hid_get_raw_report(dev, dev->battery_report_id,
353 buf, sizeof(buf), 359 buf, 2,
354 dev->battery_report_type); 360 dev->battery_report_type);
355 361
356 if (ret != 2) { 362 if (ret != 2) {
357 ret = -ENODATA; 363 ret = -ENODATA;
364 kfree(buf);
358 break; 365 break;
359 } 366 }
360 ret = 0; 367 ret = 0;
@@ -364,6 +371,7 @@ static int hidinput_get_battery_property(struct power_supply *psy,
364 buf[1] <= dev->battery_max) 371 buf[1] <= dev->battery_max)
365 val->intval = (100 * (buf[1] - dev->battery_min)) / 372 val->intval = (100 * (buf[1] - dev->battery_min)) /
366 (dev->battery_max - dev->battery_min); 373 (dev->battery_max - dev->battery_min);
374 kfree(buf);
367 break; 375 break;
368 376
369 case POWER_SUPPLY_PROP_MODEL_NAME: 377 case POWER_SUPPLY_PROP_MODEL_NAME:
diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c
index 1e2ee2aa84a0..73845120295e 100644
--- a/drivers/hid/hid-kye.c
+++ b/drivers/hid/hid-kye.c
@@ -268,6 +268,26 @@ static __u8 easypen_m610x_rdesc_fixed[] = {
268 0xC0 /* End Collection */ 268 0xC0 /* End Collection */
269}; 269};
270 270
271static __u8 *kye_consumer_control_fixup(struct hid_device *hdev, __u8 *rdesc,
272 unsigned int *rsize, int offset, const char *device_name) {
273 /*
274 * the fixup that need to be done:
275 * - change Usage Maximum in the Comsumer Control
276 * (report ID 3) to a reasonable value
277 */
278 if (*rsize >= offset + 31 &&
279 /* Usage Page (Consumer Devices) */
280 rdesc[offset] == 0x05 && rdesc[offset + 1] == 0x0c &&
281 /* Usage (Consumer Control) */
282 rdesc[offset + 2] == 0x09 && rdesc[offset + 3] == 0x01 &&
283 /* Usage Maximum > 12287 */
284 rdesc[offset + 10] == 0x2a && rdesc[offset + 12] > 0x2f) {
285 hid_info(hdev, "fixing up %s report descriptor\n", device_name);
286 rdesc[offset + 12] = 0x2f;
287 }
288 return rdesc;
289}
290
271static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, 291static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
272 unsigned int *rsize) 292 unsigned int *rsize)
273{ 293{
@@ -315,23 +335,12 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
315 } 335 }
316 break; 336 break;
317 case USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE: 337 case USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE:
318 /* 338 rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104,
319 * the fixup that need to be done: 339 "Genius Gila Gaming Mouse");
320 * - change Usage Maximum in the Comsumer Control 340 break;
321 * (report ID 3) to a reasonable value 341 case USB_DEVICE_ID_GENIUS_GX_IMPERATOR:
322 */ 342 rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 83,
323 if (*rsize >= 135 && 343 "Genius Gx Imperator Keyboard");
324 /* Usage Page (Consumer Devices) */
325 rdesc[104] == 0x05 && rdesc[105] == 0x0c &&
326 /* Usage (Consumer Control) */
327 rdesc[106] == 0x09 && rdesc[107] == 0x01 &&
328 /* Usage Maximum > 12287 */
329 rdesc[114] == 0x2a && rdesc[116] > 0x2f) {
330 hid_info(hdev,
331 "fixing up Genius Gila Gaming Mouse "
332 "report descriptor\n");
333 rdesc[116] = 0x2f;
334 }
335 break; 344 break;
336 } 345 }
337 return rdesc; 346 return rdesc;
@@ -428,6 +437,8 @@ static const struct hid_device_id kye_devices[] = {
428 USB_DEVICE_ID_KYE_EASYPEN_M610X) }, 437 USB_DEVICE_ID_KYE_EASYPEN_M610X) },
429 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 438 { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
430 USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) }, 439 USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
440 { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
441 USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
431 { } 442 { }
432}; 443};
433MODULE_DEVICE_TABLE(hid, kye_devices); 444MODULE_DEVICE_TABLE(hid, kye_devices);
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index cd33084c7860..d0e5963c1ba1 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -619,7 +619,7 @@ static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
619 619
620 struct hid_field *field; 620 struct hid_field *field;
621 struct hid_report *report; 621 struct hid_report *report;
622 unsigned char data[8]; 622 unsigned char *data;
623 int offset; 623 int offset;
624 624
625 dbg_hid("%s: %s, type:%d | code:%d | value:%d\n", 625 dbg_hid("%s: %s, type:%d | code:%d | value:%d\n",
@@ -635,6 +635,13 @@ static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
635 return -1; 635 return -1;
636 } 636 }
637 hid_set_field(field, offset, value); 637 hid_set_field(field, offset, value);
638
639 data = hid_alloc_report_buf(field->report, GFP_ATOMIC);
640 if (!data) {
641 dev_warn(&dev->dev, "failed to allocate report buf memory\n");
642 return -1;
643 }
644
638 hid_output_report(field->report, &data[0]); 645 hid_output_report(field->report, &data[0]);
639 646
640 output_report_enum = &dj_rcv_hiddev->report_enum[HID_OUTPUT_REPORT]; 647 output_report_enum = &dj_rcv_hiddev->report_enum[HID_OUTPUT_REPORT];
@@ -645,8 +652,9 @@ static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
645 652
646 hid_hw_request(dj_rcv_hiddev, report, HID_REQ_SET_REPORT); 653 hid_hw_request(dj_rcv_hiddev, report, HID_REQ_SET_REPORT);
647 654
648 return 0; 655 kfree(data);
649 656
657 return 0;
650} 658}
651 659
652static int logi_dj_ll_start(struct hid_device *hid) 660static int logi_dj_ll_start(struct hid_device *hid)
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index 5bc37343eb22..a32f5a24b27c 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -36,7 +36,7 @@ MODULE_PARM_DESC(emulate_scroll_wheel, "Emulate a scroll wheel");
36static unsigned int scroll_speed = 32; 36static unsigned int scroll_speed = 32;
37static int param_set_scroll_speed(const char *val, struct kernel_param *kp) { 37static int param_set_scroll_speed(const char *val, struct kernel_param *kp) {
38 unsigned long speed; 38 unsigned long speed;
39 if (!val || strict_strtoul(val, 0, &speed) || speed > 63) 39 if (!val || kstrtoul(val, 0, &speed) || speed > 63)
40 return -EINVAL; 40 return -EINVAL;
41 scroll_speed = speed; 41 scroll_speed = speed;
42 return 0; 42 return 0;
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
index ef95102515e4..600f2075512f 100644
--- a/drivers/hid/hid-ntrig.c
+++ b/drivers/hid/hid-ntrig.c
@@ -115,7 +115,8 @@ static inline int ntrig_get_mode(struct hid_device *hdev)
115 struct hid_report *report = hdev->report_enum[HID_FEATURE_REPORT]. 115 struct hid_report *report = hdev->report_enum[HID_FEATURE_REPORT].
116 report_id_hash[0x0d]; 116 report_id_hash[0x0d];
117 117
118 if (!report) 118 if (!report || report->maxfield < 1 ||
119 report->field[0]->report_count < 1)
119 return -EINVAL; 120 return -EINVAL;
120 121
121 hid_hw_request(hdev, report, HID_REQ_GET_REPORT); 122 hid_hw_request(hdev, report, HID_REQ_GET_REPORT);
@@ -237,7 +238,7 @@ static ssize_t set_min_width(struct device *dev,
237 238
238 unsigned long val; 239 unsigned long val;
239 240
240 if (strict_strtoul(buf, 0, &val)) 241 if (kstrtoul(buf, 0, &val))
241 return -EINVAL; 242 return -EINVAL;
242 243
243 if (val > nd->sensor_physical_width) 244 if (val > nd->sensor_physical_width)
@@ -272,7 +273,7 @@ static ssize_t set_min_height(struct device *dev,
272 273
273 unsigned long val; 274 unsigned long val;
274 275
275 if (strict_strtoul(buf, 0, &val)) 276 if (kstrtoul(buf, 0, &val))
276 return -EINVAL; 277 return -EINVAL;
277 278
278 if (val > nd->sensor_physical_height) 279 if (val > nd->sensor_physical_height)
@@ -306,7 +307,7 @@ static ssize_t set_activate_slack(struct device *dev,
306 307
307 unsigned long val; 308 unsigned long val;
308 309
309 if (strict_strtoul(buf, 0, &val)) 310 if (kstrtoul(buf, 0, &val))
310 return -EINVAL; 311 return -EINVAL;
311 312
312 if (val > 0x7f) 313 if (val > 0x7f)
@@ -341,7 +342,7 @@ static ssize_t set_activation_width(struct device *dev,
341 342
342 unsigned long val; 343 unsigned long val;
343 344
344 if (strict_strtoul(buf, 0, &val)) 345 if (kstrtoul(buf, 0, &val))
345 return -EINVAL; 346 return -EINVAL;
346 347
347 if (val > nd->sensor_physical_width) 348 if (val > nd->sensor_physical_width)
@@ -377,7 +378,7 @@ static ssize_t set_activation_height(struct device *dev,
377 378
378 unsigned long val; 379 unsigned long val;
379 380
380 if (strict_strtoul(buf, 0, &val)) 381 if (kstrtoul(buf, 0, &val))
381 return -EINVAL; 382 return -EINVAL;
382 383
383 if (val > nd->sensor_physical_height) 384 if (val > nd->sensor_physical_height)
@@ -411,7 +412,7 @@ static ssize_t set_deactivate_slack(struct device *dev,
411 412
412 unsigned long val; 413 unsigned long val;
413 414
414 if (strict_strtoul(buf, 0, &val)) 415 if (kstrtoul(buf, 0, &val))
415 return -EINVAL; 416 return -EINVAL;
416 417
417 /* 418 /*
diff --git a/drivers/hid/hid-picolcd_cir.c b/drivers/hid/hid-picolcd_cir.c
index e346038f0f11..59d5eb1e742c 100644
--- a/drivers/hid/hid-picolcd_cir.c
+++ b/drivers/hid/hid-picolcd_cir.c
@@ -145,6 +145,7 @@ void picolcd_exit_cir(struct picolcd_data *data)
145 struct rc_dev *rdev = data->rc_dev; 145 struct rc_dev *rdev = data->rc_dev;
146 146
147 data->rc_dev = NULL; 147 data->rc_dev = NULL;
148 rc_unregister_device(rdev); 148 if (rdev)
149 rc_unregister_device(rdev);
149} 150}
150 151
diff --git a/drivers/hid/hid-picolcd_core.c b/drivers/hid/hid-picolcd_core.c
index b48092d0e139..acbb021065ec 100644
--- a/drivers/hid/hid-picolcd_core.c
+++ b/drivers/hid/hid-picolcd_core.c
@@ -290,7 +290,7 @@ static ssize_t picolcd_operation_mode_store(struct device *dev,
290 buf += 10; 290 buf += 10;
291 cnt -= 10; 291 cnt -= 10;
292 } 292 }
293 if (!report) 293 if (!report || report->maxfield != 1)
294 return -EINVAL; 294 return -EINVAL;
295 295
296 while (cnt > 0 && (buf[cnt-1] == '\n' || buf[cnt-1] == '\r')) 296 while (cnt > 0 && (buf[cnt-1] == '\n' || buf[cnt-1] == '\r'))
diff --git a/drivers/hid/hid-picolcd_debugfs.c b/drivers/hid/hid-picolcd_debugfs.c
index 59ab8e157e6b..024cdf3c2297 100644
--- a/drivers/hid/hid-picolcd_debugfs.c
+++ b/drivers/hid/hid-picolcd_debugfs.c
@@ -394,7 +394,7 @@ static void dump_buff_as_hex(char *dst, size_t dst_sz, const u8 *data,
394void picolcd_debug_out_report(struct picolcd_data *data, 394void picolcd_debug_out_report(struct picolcd_data *data,
395 struct hid_device *hdev, struct hid_report *report) 395 struct hid_device *hdev, struct hid_report *report)
396{ 396{
397 u8 raw_data[70]; 397 u8 *raw_data;
398 int raw_size = (report->size >> 3) + 1; 398 int raw_size = (report->size >> 3) + 1;
399 char *buff; 399 char *buff;
400#define BUFF_SZ 256 400#define BUFF_SZ 256
@@ -407,20 +407,20 @@ void picolcd_debug_out_report(struct picolcd_data *data,
407 if (!buff) 407 if (!buff)
408 return; 408 return;
409 409
410 snprintf(buff, BUFF_SZ, "\nout report %d (size %d) = ", 410 raw_data = hid_alloc_report_buf(report, GFP_ATOMIC);
411 report->id, raw_size); 411 if (!raw_data) {
412 hid_debug_event(hdev, buff);
413 if (raw_size + 5 > sizeof(raw_data)) {
414 kfree(buff); 412 kfree(buff);
415 hid_debug_event(hdev, " TOO BIG\n");
416 return; 413 return;
417 } else {
418 raw_data[0] = report->id;
419 hid_output_report(report, raw_data);
420 dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size);
421 hid_debug_event(hdev, buff);
422 } 414 }
423 415
416 snprintf(buff, BUFF_SZ, "\nout report %d (size %d) = ",
417 report->id, raw_size);
418 hid_debug_event(hdev, buff);
419 raw_data[0] = report->id;
420 hid_output_report(report, raw_data);
421 dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size);
422 hid_debug_event(hdev, buff);
423
424 switch (report->id) { 424 switch (report->id) {
425 case REPORT_LED_STATE: 425 case REPORT_LED_STATE:
426 /* 1 data byte with GPO state */ 426 /* 1 data byte with GPO state */
@@ -644,6 +644,7 @@ void picolcd_debug_out_report(struct picolcd_data *data,
644 break; 644 break;
645 } 645 }
646 wake_up_interruptible(&hdev->debug_wait); 646 wake_up_interruptible(&hdev->debug_wait);
647 kfree(raw_data);
647 kfree(buff); 648 kfree(buff);
648} 649}
649 650
diff --git a/drivers/hid/hid-picolcd_fb.c b/drivers/hid/hid-picolcd_fb.c
index 591f6b22aa94..c930ab8554ea 100644
--- a/drivers/hid/hid-picolcd_fb.c
+++ b/drivers/hid/hid-picolcd_fb.c
@@ -593,10 +593,14 @@ err_nomem:
593void picolcd_exit_framebuffer(struct picolcd_data *data) 593void picolcd_exit_framebuffer(struct picolcd_data *data)
594{ 594{
595 struct fb_info *info = data->fb_info; 595 struct fb_info *info = data->fb_info;
596 struct picolcd_fb_data *fbdata = info->par; 596 struct picolcd_fb_data *fbdata;
597 unsigned long flags; 597 unsigned long flags;
598 598
599 if (!info)
600 return;
601
599 device_remove_file(&data->hdev->dev, &dev_attr_fb_update_rate); 602 device_remove_file(&data->hdev->dev, &dev_attr_fb_update_rate);
603 fbdata = info->par;
600 604
601 /* disconnect framebuffer from HID dev */ 605 /* disconnect framebuffer from HID dev */
602 spin_lock_irqsave(&fbdata->lock, flags); 606 spin_lock_irqsave(&fbdata->lock, flags);
diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c
index d29112fa5cd5..2dcd7d98dbd6 100644
--- a/drivers/hid/hid-pl.c
+++ b/drivers/hid/hid-pl.c
@@ -132,8 +132,14 @@ static int plff_init(struct hid_device *hid)
132 strong = &report->field[0]->value[2]; 132 strong = &report->field[0]->value[2];
133 weak = &report->field[0]->value[3]; 133 weak = &report->field[0]->value[3];
134 debug("detected single-field device"); 134 debug("detected single-field device");
135 } else if (report->maxfield >= 4 && report->field[0]->maxusage == 1 && 135 } else if (report->field[0]->maxusage == 1 &&
136 report->field[0]->usage[0].hid == (HID_UP_LED | 0x43)) { 136 report->field[0]->usage[0].hid ==
137 (HID_UP_LED | 0x43) &&
138 report->maxfield >= 4 &&
139 report->field[0]->report_count >= 1 &&
140 report->field[1]->report_count >= 1 &&
141 report->field[2]->report_count >= 1 &&
142 report->field[3]->report_count >= 1) {
137 report->field[0]->value[0] = 0x00; 143 report->field[0]->value[0] = 0x00;
138 report->field[1]->value[0] = 0x00; 144 report->field[1]->value[0] = 0x00;
139 strong = &report->field[2]->value[0]; 145 strong = &report->field[2]->value[0];
diff --git a/drivers/hid/hid-roccat-arvo.c b/drivers/hid/hid-roccat-arvo.c
index 327f9b8ed1f4..071ee9e2fd9f 100644
--- a/drivers/hid/hid-roccat-arvo.c
+++ b/drivers/hid/hid-roccat-arvo.c
@@ -59,7 +59,7 @@ static ssize_t arvo_sysfs_set_mode_key(struct device *dev,
59 unsigned long state; 59 unsigned long state;
60 int retval; 60 int retval;
61 61
62 retval = strict_strtoul(buf, 10, &state); 62 retval = kstrtoul(buf, 10, &state);
63 if (retval) 63 if (retval)
64 return retval; 64 return retval;
65 65
@@ -107,7 +107,7 @@ static ssize_t arvo_sysfs_set_key_mask(struct device *dev,
107 unsigned long key_mask; 107 unsigned long key_mask;
108 int retval; 108 int retval;
109 109
110 retval = strict_strtoul(buf, 10, &key_mask); 110 retval = kstrtoul(buf, 10, &key_mask);
111 if (retval) 111 if (retval)
112 return retval; 112 return retval;
113 113
@@ -159,7 +159,7 @@ static ssize_t arvo_sysfs_set_actual_profile(struct device *dev,
159 unsigned long profile; 159 unsigned long profile;
160 int retval; 160 int retval;
161 161
162 retval = strict_strtoul(buf, 10, &profile); 162 retval = kstrtoul(buf, 10, &profile);
163 if (retval) 163 if (retval)
164 return retval; 164 return retval;
165 165
diff --git a/drivers/hid/hid-roccat-isku.c b/drivers/hid/hid-roccat-isku.c
index 8023751d5257..5dd0ea4eb4f7 100644
--- a/drivers/hid/hid-roccat-isku.c
+++ b/drivers/hid/hid-roccat-isku.c
@@ -82,7 +82,7 @@ static ssize_t isku_sysfs_set_actual_profile(struct device *dev,
82 isku = hid_get_drvdata(dev_get_drvdata(dev)); 82 isku = hid_get_drvdata(dev_get_drvdata(dev));
83 usb_dev = interface_to_usbdev(to_usb_interface(dev)); 83 usb_dev = interface_to_usbdev(to_usb_interface(dev));
84 84
85 retval = strict_strtoul(buf, 10, &profile); 85 retval = kstrtoul(buf, 10, &profile);
86 if (retval) 86 if (retval)
87 return retval; 87 return retval;
88 88
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c
index 7fae070788fa..00ab287f7384 100644
--- a/drivers/hid/hid-roccat-kone.c
+++ b/drivers/hid/hid-roccat-kone.c
@@ -456,7 +456,7 @@ static ssize_t kone_sysfs_set_tcu(struct device *dev,
456 kone = hid_get_drvdata(dev_get_drvdata(dev)); 456 kone = hid_get_drvdata(dev_get_drvdata(dev));
457 usb_dev = interface_to_usbdev(to_usb_interface(dev)); 457 usb_dev = interface_to_usbdev(to_usb_interface(dev));
458 458
459 retval = strict_strtoul(buf, 10, &state); 459 retval = kstrtoul(buf, 10, &state);
460 if (retval) 460 if (retval)
461 return retval; 461 return retval;
462 462
@@ -545,7 +545,7 @@ static ssize_t kone_sysfs_set_startup_profile(struct device *dev,
545 kone = hid_get_drvdata(dev_get_drvdata(dev)); 545 kone = hid_get_drvdata(dev_get_drvdata(dev));
546 usb_dev = interface_to_usbdev(to_usb_interface(dev)); 546 usb_dev = interface_to_usbdev(to_usb_interface(dev));
547 547
548 retval = strict_strtoul(buf, 10, &new_startup_profile); 548 retval = kstrtoul(buf, 10, &new_startup_profile);
549 if (retval) 549 if (retval)
550 return retval; 550 return retval;
551 551
diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c
index 6a48fa3c7da9..26b9663ddf47 100644
--- a/drivers/hid/hid-roccat-koneplus.c
+++ b/drivers/hid/hid-roccat-koneplus.c
@@ -246,7 +246,7 @@ static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev,
246 koneplus = hid_get_drvdata(dev_get_drvdata(dev)); 246 koneplus = hid_get_drvdata(dev_get_drvdata(dev));
247 usb_dev = interface_to_usbdev(to_usb_interface(dev)); 247 usb_dev = interface_to_usbdev(to_usb_interface(dev));
248 248
249 retval = strict_strtoul(buf, 10, &profile); 249 retval = kstrtoul(buf, 10, &profile);
250 if (retval) 250 if (retval)
251 return retval; 251 return retval;
252 252
diff --git a/drivers/hid/hid-roccat-konepure.c b/drivers/hid/hid-roccat-konepure.c
index c79d0b06c143..5850959d48f5 100644
--- a/drivers/hid/hid-roccat-konepure.c
+++ b/drivers/hid/hid-roccat-konepure.c
@@ -262,6 +262,7 @@ static int konepure_raw_event(struct hid_device *hdev,
262 262
263static const struct hid_device_id konepure_devices[] = { 263static const struct hid_device_id konepure_devices[] = {
264 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) }, 264 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) },
265 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE_OPTICAL) },
265 { } 266 { }
266}; 267};
267 268
@@ -300,5 +301,5 @@ module_init(konepure_init);
300module_exit(konepure_exit); 301module_exit(konepure_exit);
301 302
302MODULE_AUTHOR("Stefan Achatz"); 303MODULE_AUTHOR("Stefan Achatz");
303MODULE_DESCRIPTION("USB Roccat KonePure driver"); 304MODULE_DESCRIPTION("USB Roccat KonePure/Optical driver");
304MODULE_LICENSE("GPL v2"); 305MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c
index b8b37789b864..c2a17e45c99c 100644
--- a/drivers/hid/hid-roccat-kovaplus.c
+++ b/drivers/hid/hid-roccat-kovaplus.c
@@ -282,7 +282,7 @@ static ssize_t kovaplus_sysfs_set_actual_profile(struct device *dev,
282 kovaplus = hid_get_drvdata(dev_get_drvdata(dev)); 282 kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
283 usb_dev = interface_to_usbdev(to_usb_interface(dev)); 283 usb_dev = interface_to_usbdev(to_usb_interface(dev));
284 284
285 retval = strict_strtoul(buf, 10, &profile); 285 retval = kstrtoul(buf, 10, &profile);
286 if (retval) 286 if (retval)
287 return retval; 287 return retval;
288 288
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
index ca7498107327..6fca30eb377d 100644
--- a/drivers/hid/hid-sensor-hub.c
+++ b/drivers/hid/hid-sensor-hub.c
@@ -221,7 +221,8 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
221 221
222 mutex_lock(&data->mutex); 222 mutex_lock(&data->mutex);
223 report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT); 223 report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT);
224 if (!report || (field_index >= report->maxfield)) { 224 if (!report || (field_index >= report->maxfield) ||
225 report->field[field_index]->report_count < 1) {
225 ret = -EINVAL; 226 ret = -EINVAL;
226 goto done_proc; 227 goto done_proc;
227 } 228 }
@@ -416,7 +417,7 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
416 return 1; 417 return 1;
417 418
418 ptr = raw_data; 419 ptr = raw_data;
419 ptr++; /*Skip report id*/ 420 ptr++; /* Skip report id */
420 421
421 spin_lock_irqsave(&pdata->lock, flags); 422 spin_lock_irqsave(&pdata->lock, flags);
422 423
diff --git a/drivers/hid/hid-speedlink.c b/drivers/hid/hid-speedlink.c
index a2f587d004e1..7112f3e832ee 100644
--- a/drivers/hid/hid-speedlink.c
+++ b/drivers/hid/hid-speedlink.c
@@ -3,7 +3,7 @@
3 * Fixes "jumpy" cursor and removes nonexistent keyboard LEDS from 3 * Fixes "jumpy" cursor and removes nonexistent keyboard LEDS from
4 * the HID descriptor. 4 * the HID descriptor.
5 * 5 *
6 * Copyright (c) 2011 Stefan Kriwanek <mail@stefankriwanek.de> 6 * Copyright (c) 2011, 2013 Stefan Kriwanek <dev@stefankriwanek.de>
7 */ 7 */
8 8
9/* 9/*
@@ -46,8 +46,13 @@ static int speedlink_event(struct hid_device *hdev, struct hid_field *field,
46 struct hid_usage *usage, __s32 value) 46 struct hid_usage *usage, __s32 value)
47{ 47{
48 /* No other conditions due to usage_table. */ 48 /* No other conditions due to usage_table. */
49 /* Fix "jumpy" cursor (invalid events sent by device). */ 49
50 if (value == 256) 50 /* This fixes the "jumpy" cursor occuring due to invalid events sent
51 * by the device. Some devices only send them with value==+256, others
52 * don't. However, catching abs(value)>=256 is restrictive enough not
53 * to interfere with devices that were bug-free (has been tested).
54 */
55 if (abs(value) >= 256)
51 return 1; 56 return 1;
52 /* Drop useless distance 0 events (on button clicks etc.) as well */ 57 /* Drop useless distance 0 events (on button clicks etc.) as well */
53 if (value == 0) 58 if (value == 0)
diff --git a/drivers/hid/hid-xinmo.c b/drivers/hid/hid-xinmo.c
new file mode 100644
index 000000000000..7df5227a7e61
--- /dev/null
+++ b/drivers/hid/hid-xinmo.c
@@ -0,0 +1,61 @@
1/*
2 * HID driver for Xin-Mo devices, currently only the Dual Arcade controller.
3 * Fixes the negative axis event values (the devices sends -2) to match the
4 * logical axis minimum of the HID report descriptor (the report announces
5 * -1). It is needed because hid-input discards out of bounds values.
6 * (This module is based on "hid-saitek" and "hid-lg".)
7 *
8 * Copyright (c) 2013 Olivier Scherler
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the Free
14 * Software Foundation; either version 2 of the License, or (at your option)
15 * any later version.
16 */
17
18#include <linux/device.h>
19#include <linux/hid.h>
20#include <linux/module.h>
21#include <linux/kernel.h>
22
23#include "hid-ids.h"
24
25/*
26 * Fix negative events that are out of bounds.
27 */
28static int xinmo_event(struct hid_device *hdev, struct hid_field *field,
29 struct hid_usage *usage, __s32 value)
30{
31 switch (usage->code) {
32 case ABS_X:
33 case ABS_Y:
34 case ABS_Z:
35 case ABS_RX:
36 if (value < -1) {
37 input_event(field->hidinput->input, usage->type,
38 usage->code, -1);
39 return 1;
40 }
41 break;
42 }
43
44 return 0;
45}
46
47static const struct hid_device_id xinmo_devices[] = {
48 { HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE) },
49 { }
50};
51
52MODULE_DEVICE_TABLE(hid, xinmo_devices);
53
54static struct hid_driver xinmo_driver = {
55 .name = "xinmo",
56 .id_table = xinmo_devices,
57 .event = xinmo_event
58};
59
60module_hid_driver(xinmo_driver);
61MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 6f1feb2c2e97..8918dd12bb69 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -113,7 +113,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer,
113 __u8 *buf; 113 __u8 *buf;
114 int ret = 0; 114 int ret = 0;
115 115
116 if (!hidraw_table[minor]) { 116 if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
117 ret = -ENODEV; 117 ret = -ENODEV;
118 goto out; 118 goto out;
119 } 119 }
@@ -253,6 +253,7 @@ static int hidraw_open(struct inode *inode, struct file *file)
253 unsigned int minor = iminor(inode); 253 unsigned int minor = iminor(inode);
254 struct hidraw *dev; 254 struct hidraw *dev;
255 struct hidraw_list *list; 255 struct hidraw_list *list;
256 unsigned long flags;
256 int err = 0; 257 int err = 0;
257 258
258 if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) { 259 if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) {
@@ -261,16 +262,11 @@ static int hidraw_open(struct inode *inode, struct file *file)
261 } 262 }
262 263
263 mutex_lock(&minors_lock); 264 mutex_lock(&minors_lock);
264 if (!hidraw_table[minor]) { 265 if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
265 err = -ENODEV; 266 err = -ENODEV;
266 goto out_unlock; 267 goto out_unlock;
267 } 268 }
268 269
269 list->hidraw = hidraw_table[minor];
270 mutex_init(&list->read_mutex);
271 list_add_tail(&list->node, &hidraw_table[minor]->list);
272 file->private_data = list;
273
274 dev = hidraw_table[minor]; 270 dev = hidraw_table[minor];
275 if (!dev->open++) { 271 if (!dev->open++) {
276 err = hid_hw_power(dev->hid, PM_HINT_FULLON); 272 err = hid_hw_power(dev->hid, PM_HINT_FULLON);
@@ -283,9 +279,16 @@ static int hidraw_open(struct inode *inode, struct file *file)
283 if (err < 0) { 279 if (err < 0) {
284 hid_hw_power(dev->hid, PM_HINT_NORMAL); 280 hid_hw_power(dev->hid, PM_HINT_NORMAL);
285 dev->open--; 281 dev->open--;
282 goto out_unlock;
286 } 283 }
287 } 284 }
288 285
286 list->hidraw = hidraw_table[minor];
287 mutex_init(&list->read_mutex);
288 spin_lock_irqsave(&hidraw_table[minor]->list_lock, flags);
289 list_add_tail(&list->node, &hidraw_table[minor]->list);
290 spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags);
291 file->private_data = list;
289out_unlock: 292out_unlock:
290 mutex_unlock(&minors_lock); 293 mutex_unlock(&minors_lock);
291out: 294out:
@@ -302,39 +305,41 @@ static int hidraw_fasync(int fd, struct file *file, int on)
302 return fasync_helper(fd, file, on, &list->fasync); 305 return fasync_helper(fd, file, on, &list->fasync);
303} 306}
304 307
308static void drop_ref(struct hidraw *hidraw, int exists_bit)
309{
310 if (exists_bit) {
311 hid_hw_close(hidraw->hid);
312 hidraw->exist = 0;
313 if (hidraw->open)
314 wake_up_interruptible(&hidraw->wait);
315 } else {
316 --hidraw->open;
317 }
318
319 if (!hidraw->open && !hidraw->exist) {
320 device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
321 hidraw_table[hidraw->minor] = NULL;
322 kfree(hidraw);
323 }
324}
325
305static int hidraw_release(struct inode * inode, struct file * file) 326static int hidraw_release(struct inode * inode, struct file * file)
306{ 327{
307 unsigned int minor = iminor(inode); 328 unsigned int minor = iminor(inode);
308 struct hidraw *dev;
309 struct hidraw_list *list = file->private_data; 329 struct hidraw_list *list = file->private_data;
310 int ret; 330 unsigned long flags;
311 int i;
312 331
313 mutex_lock(&minors_lock); 332 mutex_lock(&minors_lock);
314 if (!hidraw_table[minor]) {
315 ret = -ENODEV;
316 goto unlock;
317 }
318 333
334 spin_lock_irqsave(&hidraw_table[minor]->list_lock, flags);
319 list_del(&list->node); 335 list_del(&list->node);
320 dev = hidraw_table[minor]; 336 spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags);
321 if (!--dev->open) {
322 if (list->hidraw->exist) {
323 hid_hw_power(dev->hid, PM_HINT_NORMAL);
324 hid_hw_close(dev->hid);
325 } else {
326 kfree(list->hidraw);
327 }
328 }
329
330 for (i = 0; i < HIDRAW_BUFFER_SIZE; ++i)
331 kfree(list->buffer[i].value);
332 kfree(list); 337 kfree(list);
333 ret = 0;
334unlock:
335 mutex_unlock(&minors_lock);
336 338
337 return ret; 339 drop_ref(hidraw_table[minor], 0);
340
341 mutex_unlock(&minors_lock);
342 return 0;
338} 343}
339 344
340static long hidraw_ioctl(struct file *file, unsigned int cmd, 345static long hidraw_ioctl(struct file *file, unsigned int cmd,
@@ -457,7 +462,9 @@ int hidraw_report_event(struct hid_device *hid, u8 *data, int len)
457 struct hidraw *dev = hid->hidraw; 462 struct hidraw *dev = hid->hidraw;
458 struct hidraw_list *list; 463 struct hidraw_list *list;
459 int ret = 0; 464 int ret = 0;
465 unsigned long flags;
460 466
467 spin_lock_irqsave(&dev->list_lock, flags);
461 list_for_each_entry(list, &dev->list, node) { 468 list_for_each_entry(list, &dev->list, node) {
462 int new_head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1); 469 int new_head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1);
463 470
@@ -472,6 +479,7 @@ int hidraw_report_event(struct hid_device *hid, u8 *data, int len)
472 list->head = new_head; 479 list->head = new_head;
473 kill_fasync(&list->fasync, SIGIO, POLL_IN); 480 kill_fasync(&list->fasync, SIGIO, POLL_IN);
474 } 481 }
482 spin_unlock_irqrestore(&dev->list_lock, flags);
475 483
476 wake_up_interruptible(&dev->wait); 484 wake_up_interruptible(&dev->wait);
477 return ret; 485 return ret;
@@ -519,6 +527,7 @@ int hidraw_connect(struct hid_device *hid)
519 } 527 }
520 528
521 init_waitqueue_head(&dev->wait); 529 init_waitqueue_head(&dev->wait);
530 spin_lock_init(&dev->list_lock);
522 INIT_LIST_HEAD(&dev->list); 531 INIT_LIST_HEAD(&dev->list);
523 532
524 dev->hid = hid; 533 dev->hid = hid;
@@ -539,18 +548,9 @@ void hidraw_disconnect(struct hid_device *hid)
539 struct hidraw *hidraw = hid->hidraw; 548 struct hidraw *hidraw = hid->hidraw;
540 549
541 mutex_lock(&minors_lock); 550 mutex_lock(&minors_lock);
542 hidraw->exist = 0;
543 551
544 device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); 552 drop_ref(hidraw, 1);
545 553
546 hidraw_table[hidraw->minor] = NULL;
547
548 if (hidraw->open) {
549 hid_hw_close(hid);
550 wake_up_interruptible(&hidraw->wait);
551 } else {
552 kfree(hidraw);
553 }
554 mutex_unlock(&minors_lock); 554 mutex_unlock(&minors_lock);
555} 555}
556EXPORT_SYMBOL_GPL(hidraw_disconnect); 556EXPORT_SYMBOL_GPL(hidraw_disconnect);
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index 879b0ed701a3..3cb7d966da9e 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -824,8 +824,8 @@ static int i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid)
824 * bytes 2-3 -> bcdVersion (has to be 1.00) */ 824 * bytes 2-3 -> bcdVersion (has to be 1.00) */
825 ret = i2c_hid_command(client, &hid_descr_cmd, ihid->hdesc_buffer, 4); 825 ret = i2c_hid_command(client, &hid_descr_cmd, ihid->hdesc_buffer, 4);
826 826
827 i2c_hid_dbg(ihid, "%s, ihid->hdesc_buffer: %*ph\n", 827 i2c_hid_dbg(ihid, "%s, ihid->hdesc_buffer: %4ph\n", __func__,
828 __func__, 4, ihid->hdesc_buffer); 828 ihid->hdesc_buffer);
829 829
830 if (ret) { 830 if (ret) {
831 dev_err(&client->dev, 831 dev_err(&client->dev,
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c
index fc307e0422af..9ab7dfc6c72c 100644
--- a/drivers/hid/uhid.c
+++ b/drivers/hid/uhid.c
@@ -659,3 +659,4 @@ module_exit(uhid_exit);
659MODULE_LICENSE("GPL"); 659MODULE_LICENSE("GPL");
660MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>"); 660MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>");
661MODULE_DESCRIPTION("User-space I/O driver support for HID subsystem"); 661MODULE_DESCRIPTION("User-space I/O driver support for HID subsystem");
662MODULE_ALIAS("devname:" UHID_NAME);
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 99418285222c..ada164e1b3a1 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -535,7 +535,6 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
535{ 535{
536 int head; 536 int head;
537 struct usbhid_device *usbhid = hid->driver_data; 537 struct usbhid_device *usbhid = hid->driver_data;
538 int len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
539 538
540 if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN) 539 if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
541 return; 540 return;
@@ -546,7 +545,7 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
546 return; 545 return;
547 } 546 }
548 547
549 usbhid->out[usbhid->outhead].raw_report = kmalloc(len, GFP_ATOMIC); 548 usbhid->out[usbhid->outhead].raw_report = hid_alloc_report_buf(report, GFP_ATOMIC);
550 if (!usbhid->out[usbhid->outhead].raw_report) { 549 if (!usbhid->out[usbhid->outhead].raw_report) {
551 hid_warn(hid, "output queueing failed\n"); 550 hid_warn(hid, "output queueing failed\n");
552 return; 551 return;
@@ -595,7 +594,7 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
595 } 594 }
596 595
597 if (dir == USB_DIR_OUT) { 596 if (dir == USB_DIR_OUT) {
598 usbhid->ctrl[usbhid->ctrlhead].raw_report = kmalloc(len, GFP_ATOMIC); 597 usbhid->ctrl[usbhid->ctrlhead].raw_report = hid_alloc_report_buf(report, GFP_ATOMIC);
599 if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) { 598 if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) {
600 hid_warn(hid, "control queueing failed\n"); 599 hid_warn(hid, "control queueing failed\n");
601 return; 600 return;
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 19b8360f2330..07345521f421 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -109,6 +109,8 @@ static const struct hid_blacklist {
109 { USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD, HID_QUIRK_NO_INIT_REPORTS }, 109 { USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD, HID_QUIRK_NO_INIT_REPORTS },
110 { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X, HID_QUIRK_MULTI_INPUT }, 110 { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X, HID_QUIRK_MULTI_INPUT },
111 { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X, HID_QUIRK_MULTI_INPUT }, 111 { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X, HID_QUIRK_MULTI_INPUT },
112 { USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS },
113
112 { 0, 0 } 114 { 0, 0 }
113}; 115};
114 116