diff options
Diffstat (limited to 'drivers/hid')
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 | ||
746 | config 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 | |||
746 | config HID_ZEROPLUS | 754 | config 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 | |||
110 | obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o | 110 | obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o |
111 | obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o | 111 | obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o |
112 | obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o | 112 | obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o |
113 | obj-$(CONFIG_HID_XINMO) += hid-xinmo.o | ||
113 | obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o | 114 | obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o |
114 | obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o | 115 | obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o |
115 | obj-$(CONFIG_HID_WACOM) += hid-wacom.o | 116 | obj-$(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 | ||
1138 | void hid_output_report(struct hid_report *report, __u8 *data) | 1139 | void hid_output_report(struct hid_report *report, __u8 *data) |
@@ -1149,6 +1150,22 @@ void hid_output_report(struct hid_report *report, __u8 *data) | |||
1149 | EXPORT_SYMBOL_GPL(hid_output_report); | 1150 | EXPORT_SYMBOL_GPL(hid_output_report); |
1150 | 1151 | ||
1151 | /* | 1152 | /* |
1153 | * Allocator for buffer that is going to be passed to hid_output_report() | ||
1154 | */ | ||
1155 | u8 *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 | } | ||
1166 | EXPORT_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 | ||
1157 | int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) | 1174 | int 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 | ||
271 | static __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 | |||
271 | static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 291 | static __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 | }; |
433 | MODULE_DEVICE_TABLE(hid, kye_devices); | 444 | MODULE_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 | ||
652 | static int logi_dj_ll_start(struct hid_device *hid) | 660 | static 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"); | |||
36 | static unsigned int scroll_speed = 32; | 36 | static unsigned int scroll_speed = 32; |
37 | static int param_set_scroll_speed(const char *val, struct kernel_param *kp) { | 37 | static 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, | |||
394 | void picolcd_debug_out_report(struct picolcd_data *data, | 394 | void 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: | |||
593 | void picolcd_exit_framebuffer(struct picolcd_data *data) | 593 | void 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 | ||
263 | static const struct hid_device_id konepure_devices[] = { | 263 | static 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); | |||
300 | module_exit(konepure_exit); | 301 | module_exit(konepure_exit); |
301 | 302 | ||
302 | MODULE_AUTHOR("Stefan Achatz"); | 303 | MODULE_AUTHOR("Stefan Achatz"); |
303 | MODULE_DESCRIPTION("USB Roccat KonePure driver"); | 304 | MODULE_DESCRIPTION("USB Roccat KonePure/Optical driver"); |
304 | MODULE_LICENSE("GPL v2"); | 305 | MODULE_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 | */ | ||
28 | static 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 | |||
47 | static 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 | |||
52 | MODULE_DEVICE_TABLE(hid, xinmo_devices); | ||
53 | |||
54 | static struct hid_driver xinmo_driver = { | ||
55 | .name = "xinmo", | ||
56 | .id_table = xinmo_devices, | ||
57 | .event = xinmo_event | ||
58 | }; | ||
59 | |||
60 | module_hid_driver(xinmo_driver); | ||
61 | MODULE_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; | ||
289 | out_unlock: | 292 | out_unlock: |
290 | mutex_unlock(&minors_lock); | 293 | mutex_unlock(&minors_lock); |
291 | out: | 294 | out: |
@@ -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 | ||
308 | static 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 | |||
305 | static int hidraw_release(struct inode * inode, struct file * file) | 326 | static 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; | ||
334 | unlock: | ||
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 | ||
340 | static long hidraw_ioctl(struct file *file, unsigned int cmd, | 345 | static 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 | } |
556 | EXPORT_SYMBOL_GPL(hidraw_disconnect); | 556 | EXPORT_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); | |||
659 | MODULE_LICENSE("GPL"); | 659 | MODULE_LICENSE("GPL"); |
660 | MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>"); | 660 | MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>"); |
661 | MODULE_DESCRIPTION("User-space I/O driver support for HID subsystem"); | 661 | MODULE_DESCRIPTION("User-space I/O driver support for HID subsystem"); |
662 | MODULE_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 | ||