aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2017-11-20 05:48:41 -0500
committerJiri Kosina <jkosina@suse.cz>2017-11-21 05:14:48 -0500
commitd5d3e202753cc023100a854788a4ad83d7c2821a (patch)
tree6eef3c995780949d8301f909023ceb8a1d91c729
parent20df15783a44a289aaa8c8f83b3f715f9040c9c2 (diff)
HID: core: move the dynamic quirks handling in core
usbhid has a list of dynamic quirks in addition to a list of static quirks. There is not much USB specific in that, so move this part of the module in core so we can have one central place for quirks. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/Makefile2
-rw-r--r--drivers/hid/hid-core.c10
-rw-r--r--drivers/hid/hid-quirks.c399
-rw-r--r--drivers/hid/usbhid/Makefile2
-rw-r--r--drivers/hid/usbhid/hid-core.c10
-rw-r--r--drivers/hid/usbhid/hid-quirks.c402
-rw-r--r--include/linux/hid.h10
7 files changed, 418 insertions, 417 deletions
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 235bd2a7b333..2be460d44c69 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -2,7 +2,7 @@
2# 2#
3# Makefile for the HID driver 3# Makefile for the HID driver
4# 4#
5hid-y := hid-core.o hid-input.o 5hid-y := hid-core.o hid-input.o hid-quirks.o
6hid-$(CONFIG_DEBUG_FS) += hid-debug.o 6hid-$(CONFIG_DEBUG_FS) += hid-debug.o
7 7
8obj-$(CONFIG_HID) += hid.o 8obj-$(CONFIG_HID) += hid.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index f3fcb836a1f9..e11caea05f8d 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1597,8 +1597,8 @@ unlock:
1597} 1597}
1598EXPORT_SYMBOL_GPL(hid_input_report); 1598EXPORT_SYMBOL_GPL(hid_input_report);
1599 1599
1600static bool hid_match_one_id(struct hid_device *hdev, 1600bool hid_match_one_id(const struct hid_device *hdev,
1601 const struct hid_device_id *id) 1601 const struct hid_device_id *id)
1602{ 1602{
1603 return (id->bus == HID_BUS_ANY || id->bus == hdev->bus) && 1603 return (id->bus == HID_BUS_ANY || id->bus == hdev->bus) &&
1604 (id->group == HID_GROUP_ANY || id->group == hdev->group) && 1604 (id->group == HID_GROUP_ANY || id->group == hdev->group) &&
@@ -1606,7 +1606,7 @@ static bool hid_match_one_id(struct hid_device *hdev,
1606 (id->product == HID_ANY_ID || id->product == hdev->product); 1606 (id->product == HID_ANY_ID || id->product == hdev->product);
1607} 1607}
1608 1608
1609const struct hid_device_id *hid_match_id(struct hid_device *hdev, 1609const struct hid_device_id *hid_match_id(const struct hid_device *hdev,
1610 const struct hid_device_id *id) 1610 const struct hid_device_id *id)
1611{ 1611{
1612 for (; id->bus; id++) 1612 for (; id->bus; id++)
@@ -2613,6 +2613,7 @@ static struct bus_type hid_bus_type = {
2613 .remove = hid_device_remove, 2613 .remove = hid_device_remove,
2614 .uevent = hid_uevent, 2614 .uevent = hid_uevent,
2615}; 2615};
2616EXPORT_SYMBOL(hid_bus_type);
2616 2617
2617/* a list of devices that shouldn't be handled by HID core at all */ 2618/* a list of devices that shouldn't be handled by HID core at all */
2618static const struct hid_device_id hid_ignore_list[] = { 2619static const struct hid_device_id hid_ignore_list[] = {
@@ -2931,6 +2932,8 @@ int hid_add_device(struct hid_device *hdev)
2931 if (WARN_ON(hdev->status & HID_STAT_ADDED)) 2932 if (WARN_ON(hdev->status & HID_STAT_ADDED))
2932 return -EBUSY; 2933 return -EBUSY;
2933 2934
2935 hdev->quirks = hid_lookup_quirk(hdev);
2936
2934 /* we need to kill them here, otherwise they will stay allocated to 2937 /* we need to kill them here, otherwise they will stay allocated to
2935 * wait for coming driver */ 2938 * wait for coming driver */
2936 if (hid_ignore(hdev)) 2939 if (hid_ignore(hdev))
@@ -3117,6 +3120,7 @@ static void __exit hid_exit(void)
3117 hid_debug_exit(); 3120 hid_debug_exit();
3118 hidraw_exit(); 3121 hidraw_exit();
3119 bus_unregister(&hid_bus_type); 3122 bus_unregister(&hid_bus_type);
3123 hid_quirks_exit(HID_BUS_ANY);
3120} 3124}
3121 3125
3122module_init(hid_init); 3126module_init(hid_init);
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
new file mode 100644
index 000000000000..ffb513a82581
--- /dev/null
+++ b/drivers/hid/hid-quirks.c
@@ -0,0 +1,399 @@
1/*
2 * HID quirks support for Linux
3 *
4 * Copyright (c) 1999 Andreas Gal
5 * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
6 * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
7 * Copyright (c) 2006-2007 Jiri Kosina
8 * Copyright (c) 2007 Paul Walmsley
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/hid.h>
19#include <linux/export.h>
20#include <linux/slab.h>
21#include <linux/mutex.h>
22
23#include "hid-ids.h"
24
25/*
26 * Alphabetically sorted by vendor then product.
27 */
28
29const struct hid_device_id hid_quirks[] = {
30 { HID_USB_DEVICE(USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD), HID_QUIRK_BADPAD },
31 { HID_USB_DEVICE(USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR), HID_QUIRK_BADPAD },
32 { HID_USB_DEVICE(USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016), HID_QUIRK_FULLSPEED_INTERVAL },
33 { HID_USB_DEVICE(USB_VENDOR_ID_AIREN, USB_DEVICE_ID_AIREN_SLIMPLUS), HID_QUIRK_NOGET },
34 { HID_USB_DEVICE(USB_VENDOR_ID_AKAI_09E8, USB_DEVICE_ID_AKAI_09E8_MIDIMIX), HID_QUIRK_NO_INIT_REPORTS },
35 { HID_USB_DEVICE(USB_VENDOR_ID_AKAI, USB_DEVICE_ID_AKAI_MPKMINI2), HID_QUIRK_NO_INIT_REPORTS },
36 { HID_USB_DEVICE(USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD), HID_QUIRK_BADPAD },
37 { HID_USB_DEVICE(USB_VENDOR_ID_AMI, USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE), HID_QUIRK_ALWAYS_POLL },
38 { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM), HID_QUIRK_NOGET },
39 { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC), HID_QUIRK_NOGET },
40 { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM), HID_QUIRK_NOGET },
41 { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U), HID_QUIRK_NOGET },
42 { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS1758), HID_QUIRK_NOGET },
43 { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS682), HID_QUIRK_NOGET },
44 { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS692), HID_QUIRK_NOGET },
45 { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM), HID_QUIRK_NOGET },
46 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH), HID_QUIRK_MULTI_INPUT },
47 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
48 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS), HID_QUIRK_MULTI_INPUT },
49 { HID_USB_DEVICE(USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD), HID_QUIRK_BADPAD },
50 { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK), HID_QUIRK_NOGET },
51 { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295), HID_QUIRK_NOGET },
52 { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK), HID_QUIRK_NOGET },
53 { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FIGHTERSTICK), HID_QUIRK_NOGET },
54 { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE), HID_QUIRK_NOGET },
55 { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE), HID_QUIRK_NOGET },
56 { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS), HID_QUIRK_NOGET },
57 { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_THROTTLE), HID_QUIRK_NOGET },
58 { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB), HID_QUIRK_NO_INIT_REPORTS },
59 { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB_RAPIDFIRE), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
60 { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB), HID_QUIRK_NO_INIT_REPORTS },
61 { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB_RAPIDFIRE), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
62 { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70R), HID_QUIRK_NO_INIT_REPORTS },
63 { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K95RGB), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
64 { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_M65RGB), HID_QUIRK_NO_INIT_REPORTS },
65 { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
66 { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_STRAFE), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
67 { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51), HID_QUIRK_NOGET },
68 { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
69 { HID_USB_DEVICE(USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC), HID_QUIRK_NOGET },
70 { HID_USB_DEVICE(USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_2NES2SNES), HID_QUIRK_MULTI_INPUT },
71 { HID_USB_DEVICE(USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_4NES4SNES), HID_QUIRK_MULTI_INPUT },
72 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR), HID_QUIRK_MULTI_INPUT },
73 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1), HID_QUIRK_MULTI_INPUT },
74 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3), HID_QUIRK_MULTI_INPUT },
75 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU), HID_QUIRK_MULTI_INPUT },
76 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER), HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET },
77 { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_QUIRK_ALWAYS_POLL },
78 { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700), HID_QUIRK_NOGET },
79 { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II), HID_QUIRK_MULTI_INPUT },
80 { HID_USB_DEVICE(USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH_2968), HID_QUIRK_MULTI_INPUT },
81 { HID_USB_DEVICE(USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH), HID_QUIRK_MULTI_INPUT },
82 { HID_USB_DEVICE(USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER), HID_QUIRK_NO_INIT_REPORTS },
83 { HID_USB_DEVICE(USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28), HID_QUIRK_NOGET },
84 { HID_USB_DEVICE(USB_VENDOR_ID_FUTABA, USB_DEVICE_ID_LED_DISPLAY), HID_QUIRK_NO_INIT_REPORTS },
85 { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD), HID_QUIRK_MULTI_INPUT },
86 { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
87 { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
88 { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
89 { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096), HID_QUIRK_NO_INIT_REPORTS },
90 { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A), HID_QUIRK_ALWAYS_POLL },
91 { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A), HID_QUIRK_ALWAYS_POLL },
92 { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
93 { HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6680), HID_QUIRK_MULTI_INPUT },
94 { HID_USB_DEVICE(USB_VENDOR_ID_INNOMEDIA, USB_DEVICE_ID_INNEX_GENESIS_ATARI), HID_QUIRK_MULTI_INPUT },
95 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X), HID_QUIRK_MULTI_INPUT },
96 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X), HID_QUIRK_MULTI_INPUT },
97 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2), HID_QUIRK_MULTI_INPUT },
98 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912), HID_QUIRK_MULTI_INPUT },
99 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE_ID2), HID_QUIRK_ALWAYS_POLL },
100 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C007), HID_QUIRK_ALWAYS_POLL },
101 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C077), HID_QUIRK_ALWAYS_POLL },
102 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KEYBOARD_G710_PLUS), HID_QUIRK_NOGET },
103 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C01A), HID_QUIRK_ALWAYS_POLL },
104 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C05A), HID_QUIRK_ALWAYS_POLL },
105 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C06A), HID_QUIRK_ALWAYS_POLL },
106 { HID_USB_DEVICE(USB_VENDOR_ID_MCS, USB_DEVICE_ID_MCS_GAMEPADBLOCK), HID_QUIRK_MULTI_INPUT },
107 { HID_USB_DEVICE(USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS), HID_QUIRK_NOGET },
108 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER), HID_QUIRK_NO_INIT_REPORTS },
109 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2), HID_QUIRK_NO_INIT_REPORTS },
110 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2), HID_QUIRK_NO_INIT_REPORTS },
111 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2), HID_QUIRK_NO_INIT_REPORTS },
112 { HID_USB_DEVICE(USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER), HID_QUIRK_MULTI_INPUT },
113 { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL), HID_QUIRK_NO_INIT_REPORTS },
114 { HID_USB_DEVICE(USB_VENDOR_ID_MULTIPLE_1781, USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD), HID_QUIRK_MULTI_INPUT },
115 { HID_USB_DEVICE(USB_VENDOR_ID_NATSU, USB_DEVICE_ID_NATSU_GAMEPAD), HID_QUIRK_BADPAD },
116 { HID_USB_DEVICE(USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD), HID_QUIRK_BADPAD },
117 { HID_USB_DEVICE(USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750), HID_QUIRK_NO_INIT_REPORTS },
118 { HID_USB_DEVICE(USB_VENDOR_ID_NEXTWINDOW, USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN), HID_QUIRK_MULTI_INPUT},
119 { HID_USB_DEVICE(USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE), HID_QUIRK_NO_INIT_REPORTS },
120 { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE), HID_QUIRK_NO_INIT_REPORTS },
121 { HID_USB_DEVICE(USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK), HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
122 { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_1610), HID_QUIRK_NOGET },
123 { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_1640), HID_QUIRK_NOGET },
124 { HID_USB_DEVICE(USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL), HID_QUIRK_HIDINPUT_FORCE },
125 { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1), HID_QUIRK_NO_INIT_REPORTS },
126 { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2), HID_QUIRK_NO_INIT_REPORTS },
127 { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN), HID_QUIRK_NO_INIT_REPORTS },
128 { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
129 { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4D22), HID_QUIRK_ALWAYS_POLL },
130 { HID_USB_DEVICE(USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS), HID_QUIRK_NOGET },
131 { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001), HID_QUIRK_NOGET },
132 { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003), HID_QUIRK_NOGET },
133 { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008), HID_QUIRK_NOGET },
134 { HID_USB_DEVICE(USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER), HID_QUIRK_NO_INIT_REPORTS },
135 { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD), HID_QUIRK_BADPAD },
136 { HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD2), HID_QUIRK_NO_INIT_REPORTS },
137 { HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD), HID_QUIRK_NO_INIT_REPORTS },
138 { HID_USB_DEVICE(USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB), HID_QUIRK_NOGET },
139 { HID_USB_DEVICE(USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD), HID_QUIRK_NO_INIT_REPORTS },
140 { HID_USB_DEVICE(USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780), HID_QUIRK_NOGET },
141 { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS1030_TOUCH), HID_QUIRK_NOGET },
142 { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH), HID_QUIRK_NOGET },
143 { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH), HID_QUIRK_NOGET },
144 { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS_TS), HID_QUIRK_NO_INIT_REPORTS },
145 { HID_USB_DEVICE(USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE), HID_QUIRK_NOGET },
146 { HID_USB_DEVICE(USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1), HID_QUIRK_NOGET },
147 { HID_USB_DEVICE(USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2), HID_QUIRK_NOGET },
148 { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD), HID_QUIRK_NO_INIT_REPORTS },
149 { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1), HID_QUIRK_NO_INIT_REPORTS },
150 { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2), HID_QUIRK_NO_INIT_REPORTS },
151 { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD), HID_QUIRK_NO_INIT_REPORTS },
152 { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP_V103), HID_QUIRK_NO_INIT_REPORTS },
153 { HID_USB_DEVICE(USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD), HID_QUIRK_BADPAD },
154 { HID_USB_DEVICE(USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS), HID_QUIRK_MULTI_INPUT },
155 { HID_USB_DEVICE(USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8882), HID_QUIRK_NOGET },
156 { HID_USB_DEVICE(USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8883), HID_QUIRK_NOGET },
157 { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD), HID_QUIRK_NOGET },
158 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5), HID_QUIRK_MULTI_INPUT },
159 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60), HID_QUIRK_MULTI_INPUT },
160 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH), HID_QUIRK_MULTI_INPUT },
161 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH), HID_QUIRK_MULTI_INPUT },
162 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET), HID_QUIRK_MULTI_INPUT },
163 { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
164 { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
165
166 { 0 }
167};
168
169/* Dynamic HID quirks list - specified at runtime */
170struct quirks_list_struct {
171 struct hid_device_id hid_bl_item;
172 struct list_head node;
173};
174
175static LIST_HEAD(dquirks_list);
176static DEFINE_MUTEX(dquirks_lock);
177
178/* Runtime ("dynamic") quirks manipulation functions */
179
180/**
181 * hid_exists_dquirk: find any dynamic quirks for a HID device
182 * @hdev: the HID device to match
183 *
184 * Description:
185 * Scans dquirks_list for a matching dynamic quirk and returns
186 * the pointer to the relevant struct hid_device_id if found.
187 * Must be called with a read lock held on dquirks_lock.
188 *
189 * Returns: NULL if no quirk found, struct hid_device_id * if found.
190 */
191static struct hid_device_id *hid_exists_dquirk(const struct hid_device *hdev)
192{
193 struct quirks_list_struct *q;
194 struct hid_device_id *bl_entry = NULL;
195
196 list_for_each_entry(q, &dquirks_list, node) {
197 if (hid_match_one_id(hdev, &q->hid_bl_item)) {
198 bl_entry = &q->hid_bl_item;
199 break;
200 }
201 }
202
203 if (bl_entry != NULL)
204 dbg_hid("Found dynamic quirk 0x%lx for HID device 0x%hx:0x%hx\n",
205 bl_entry->driver_data, bl_entry->vendor,
206 bl_entry->product);
207
208 return bl_entry;
209}
210
211
212/**
213 * hid_modify_dquirk: add/replace a HID quirk
214 * @id: the HID device to match
215 * @quirks: the unsigned long quirks value to add/replace
216 *
217 * Description:
218 * If an dynamic quirk exists in memory for this device, replace its
219 * quirks value with what was provided. Otherwise, add the quirk
220 * to the dynamic quirks list.
221 *
222 * Returns: 0 OK, -error on failure.
223 */
224static int hid_modify_dquirk(const struct hid_device_id *id,
225 const unsigned long quirks)
226{
227 struct hid_device *hdev;
228 struct quirks_list_struct *q_new, *q;
229 int list_edited = 0;
230 int ret = 0;
231
232 hdev = kzalloc(sizeof(*hdev), GFP_KERNEL);
233 if (!hdev)
234 return -ENOMEM;
235
236 q_new = kmalloc(sizeof(struct quirks_list_struct), GFP_KERNEL);
237 if (!q_new) {
238 ret = -ENOMEM;
239 goto out;
240 }
241
242 hdev->bus = q_new->hid_bl_item.bus = id->bus;
243 hdev->group = q_new->hid_bl_item.group = id->group;
244 hdev->vendor = q_new->hid_bl_item.vendor = id->vendor;
245 hdev->product = q_new->hid_bl_item.product = id->product;
246 q_new->hid_bl_item.driver_data = quirks;
247
248 mutex_lock(&dquirks_lock);
249
250 list_for_each_entry(q, &dquirks_list, node) {
251
252 if (hid_match_one_id(hdev, &q->hid_bl_item)) {
253
254 list_replace(&q->node, &q_new->node);
255 kfree(q);
256 list_edited = 1;
257 break;
258
259 }
260
261 }
262
263 if (!list_edited)
264 list_add_tail(&q_new->node, &dquirks_list);
265
266 mutex_unlock(&dquirks_lock);
267
268 out:
269 kfree(hdev);
270 return ret;
271}
272
273/**
274 * hid_remove_all_dquirks: remove all runtime HID quirks from memory
275 * @bus: bus to match against. Use HID_BUS_ANY if all need to be removed.
276 *
277 * Description:
278 * Free all memory associated with dynamic quirks - called before
279 * module unload.
280 *
281 */
282static void hid_remove_all_dquirks(__u16 bus)
283{
284 struct quirks_list_struct *q, *temp;
285
286 mutex_lock(&dquirks_lock);
287 list_for_each_entry_safe(q, temp, &dquirks_list, node) {
288 if (bus == HID_BUS_ANY || bus == q->hid_bl_item.bus) {
289 list_del(&q->node);
290 kfree(q);
291 }
292 }
293 mutex_unlock(&dquirks_lock);
294
295}
296
297/**
298 * hid_quirks_init: apply HID quirks specified at module load time
299 */
300int hid_quirks_init(char **quirks_param, __u16 bus, int count)
301{
302 struct hid_device_id id = { 0 };
303 int n = 0, m;
304 unsigned short int vendor, product;
305 u32 quirks;
306
307 id.bus = bus;
308
309 for (; n < count && quirks_param[n]; n++) {
310
311 m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x",
312 &vendor, &product, &quirks);
313
314 id.vendor = (__u16)vendor;
315 id.product = (__u16)product;
316
317 if (m != 3 ||
318 hid_modify_dquirk(&id, quirks) != 0) {
319 pr_warn("Could not parse HID quirk module param %s\n",
320 quirks_param[n]);
321 }
322 }
323
324 return 0;
325}
326EXPORT_SYMBOL_GPL(hid_quirks_init);
327
328/**
329 * hid_quirks_exit: release memory associated with dynamic_quirks
330 * @bus: a bus to match against
331 *
332 * Description:
333 * Release all memory associated with dynamic quirks for a given bus.
334 * Called upon module unload.
335 * Use HID_BUS_ANY to remove all dynamic quirks.
336 *
337 * Returns: nothing
338 */
339void hid_quirks_exit(__u16 bus)
340{
341 hid_remove_all_dquirks(bus);
342}
343EXPORT_SYMBOL_GPL(hid_quirks_exit);
344
345/**
346 * hid_exists_squirk: return any static quirks for a HID device
347 * @hdev: the HID device to match
348 *
349 * Description:
350 * Given a HID device, return a pointer to the quirked hid_device_id entry
351 * associated with that device.
352 *
353 * Returns: pointer if quirk found, or NULL if no quirks found.
354 */
355static const struct hid_device_id *hid_exists_squirk(const struct hid_device *hdev)
356{
357 const struct hid_device_id *bl_entry;
358
359 bl_entry = hid_match_id(hdev, hid_quirks);
360
361 if (bl_entry != NULL)
362 dbg_hid("Found squirk 0x%lx for HID device 0x%hx:0x%hx\n",
363 bl_entry->driver_data, bl_entry->vendor,
364 bl_entry->product);
365 return bl_entry;
366}
367
368/**
369 * hid_lookup_quirk: return any quirks associated with a HID device
370 * @hdev: the HID device to look for
371 *
372 * Description:
373 * Given a HID device, return any quirks associated with that device.
374 *
375 * Returns: an unsigned long quirks value.
376 */
377unsigned long hid_lookup_quirk(const struct hid_device *hdev)
378{
379 unsigned long quirks = 0;
380 const struct hid_device_id *quirk_entry = NULL;
381
382 /* NCR devices must not be queried for reports */
383 if (hdev->bus == BUS_USB &&
384 hdev->vendor == USB_VENDOR_ID_NCR &&
385 hdev->product >= USB_DEVICE_ID_NCR_FIRST &&
386 hdev->product <= USB_DEVICE_ID_NCR_LAST)
387 return HID_QUIRK_NO_INIT_REPORTS;
388
389 mutex_lock(&dquirks_lock);
390 quirk_entry = hid_exists_dquirk(hdev);
391 if (!quirk_entry)
392 quirk_entry = hid_exists_squirk(hdev);
393 if (quirk_entry)
394 quirks = quirk_entry->driver_data;
395 mutex_unlock(&dquirks_lock);
396
397 return quirks;
398}
399EXPORT_SYMBOL_GPL(hid_lookup_quirk);
diff --git a/drivers/hid/usbhid/Makefile b/drivers/hid/usbhid/Makefile
index 0ff227d0c033..b6349e30bd93 100644
--- a/drivers/hid/usbhid/Makefile
+++ b/drivers/hid/usbhid/Makefile
@@ -3,7 +3,7 @@
3# Makefile for the USB input drivers 3# Makefile for the USB input drivers
4# 4#
5 5
6usbhid-y := hid-core.o hid-quirks.o 6usbhid-y := hid-core.o
7usbhid-$(CONFIG_USB_HIDDEV) += hiddev.o 7usbhid-$(CONFIG_USB_HIDDEV) += hiddev.o
8usbhid-$(CONFIG_HID_PID) += hid-pidff.o 8usbhid-$(CONFIG_HID_PID) += hid-pidff.o
9 9
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 640dfb937c69..cd1ccb6b90c9 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -978,8 +978,7 @@ static int usbhid_parse(struct hid_device *hid)
978 int num_descriptors; 978 int num_descriptors;
979 size_t offset = offsetof(struct hid_descriptor, desc); 979 size_t offset = offsetof(struct hid_descriptor, desc);
980 980
981 quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor), 981 quirks = hid_lookup_quirk(hid);
982 le16_to_cpu(dev->descriptor.idProduct));
983 982
984 if (quirks & HID_QUIRK_IGNORE) 983 if (quirks & HID_QUIRK_IGNORE)
985 return -ENODEV; 984 return -ENODEV;
@@ -1329,7 +1328,6 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
1329 hid->vendor = le16_to_cpu(dev->descriptor.idVendor); 1328 hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
1330 hid->product = le16_to_cpu(dev->descriptor.idProduct); 1329 hid->product = le16_to_cpu(dev->descriptor.idProduct);
1331 hid->name[0] = 0; 1330 hid->name[0] = 0;
1332 hid->quirks = usbhid_lookup_quirk(hid->vendor, hid->product);
1333 if (intf->cur_altsetting->desc.bInterfaceProtocol == 1331 if (intf->cur_altsetting->desc.bInterfaceProtocol ==
1334 USB_INTERFACE_PROTOCOL_MOUSE) 1332 USB_INTERFACE_PROTOCOL_MOUSE)
1335 hid->type = HID_TYPE_USBMOUSE; 1333 hid->type = HID_TYPE_USBMOUSE;
@@ -1641,7 +1639,7 @@ static int __init hid_init(void)
1641{ 1639{
1642 int retval = -ENOMEM; 1640 int retval = -ENOMEM;
1643 1641
1644 retval = usbhid_quirks_init(quirks_param); 1642 retval = hid_quirks_init(quirks_param, BUS_USB, MAX_USBHID_BOOT_QUIRKS);
1645 if (retval) 1643 if (retval)
1646 goto usbhid_quirks_init_fail; 1644 goto usbhid_quirks_init_fail;
1647 retval = usb_register(&hid_driver); 1645 retval = usb_register(&hid_driver);
@@ -1651,7 +1649,7 @@ static int __init hid_init(void)
1651 1649
1652 return 0; 1650 return 0;
1653usb_register_fail: 1651usb_register_fail:
1654 usbhid_quirks_exit(); 1652 hid_quirks_exit(BUS_USB);
1655usbhid_quirks_init_fail: 1653usbhid_quirks_init_fail:
1656 return retval; 1654 return retval;
1657} 1655}
@@ -1659,7 +1657,7 @@ usbhid_quirks_init_fail:
1659static void __exit hid_exit(void) 1657static void __exit hid_exit(void)
1660{ 1658{
1661 usb_deregister(&hid_driver); 1659 usb_deregister(&hid_driver);
1662 usbhid_quirks_exit(); 1660 hid_quirks_exit(BUS_USB);
1663} 1661}
1664 1662
1665module_init(hid_init); 1663module_init(hid_init);
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
deleted file mode 100644
index 331f7f34ec14..000000000000
--- a/drivers/hid/usbhid/hid-quirks.c
+++ /dev/null
@@ -1,402 +0,0 @@
1/*
2 * USB HID quirks support for Linux
3 *
4 * Copyright (c) 1999 Andreas Gal
5 * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
6 * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
7 * Copyright (c) 2006-2007 Jiri Kosina
8 * Copyright (c) 2007 Paul Walmsley
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/hid.h>
19#include <linux/export.h>
20#include <linux/slab.h>
21
22#include "../hid-ids.h"
23
24/*
25 * Alphabetically sorted blacklist by quirk type.
26 */
27
28static const struct hid_blacklist {
29 __u16 idVendor;
30 __u16 idProduct;
31 __u32 quirks;
32} hid_blacklist[] = {
33 { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD },
34 { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD },
35 { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
36 { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
37 { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET },
38 { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT },
39 { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
40 { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
41 { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
42 { USB_VENDOR_ID_NATSU, USB_DEVICE_ID_NATSU_GAMEPAD, HID_QUIRK_BADPAD },
43 { USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD, HID_QUIRK_BADPAD },
44 { USB_VENDOR_ID_NEXTWINDOW, USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN, HID_QUIRK_MULTI_INPUT},
45 { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
46 { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
47
48 { USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL },
49
50 { USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II, HID_QUIRK_MULTI_INPUT },
51 { USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH, HID_QUIRK_MULTI_INPUT },
52 { USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH_2968, HID_QUIRK_MULTI_INPUT },
53 { USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD, HID_QUIRK_MULTI_INPUT },
54 { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
55 { USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS, HID_QUIRK_MULTI_INPUT },
56
57 { USB_VENDOR_ID_AIREN, USB_DEVICE_ID_AIREN_SLIMPLUS, HID_QUIRK_NOGET },
58 { USB_VENDOR_ID_AKAI, USB_DEVICE_ID_AKAI_MPKMINI2, HID_QUIRK_NO_INIT_REPORTS },
59 { USB_VENDOR_ID_AKAI_09E8, USB_DEVICE_ID_AKAI_09E8_MIDIMIX, HID_QUIRK_NO_INIT_REPORTS },
60 { USB_VENDOR_ID_AMI, USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE, HID_QUIRK_ALWAYS_POLL },
61 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
62 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
63 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
64 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
65 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
66 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS682, HID_QUIRK_NOGET },
67 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS692, HID_QUIRK_NOGET },
68 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS1758, HID_QUIRK_NOGET },
69 { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FIGHTERSTICK, HID_QUIRK_NOGET },
70 { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK, HID_QUIRK_NOGET },
71 { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE, HID_QUIRK_NOGET },
72 { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE, HID_QUIRK_NOGET },
73 { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_THROTTLE, HID_QUIRK_NOGET },
74 { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS, HID_QUIRK_NOGET },
75 { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK, HID_QUIRK_NOGET },
76 { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
77 { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL },
78 { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70R, HID_QUIRK_NO_INIT_REPORTS },
79 { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_M65RGB, HID_QUIRK_NO_INIT_REPORTS },
80 { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K95RGB, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
81 { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB, HID_QUIRK_NO_INIT_REPORTS },
82 { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB, HID_QUIRK_NO_INIT_REPORTS },
83 { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_STRAFE, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
84 { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB_RAPIDFIRE, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
85 { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB_RAPIDFIRE, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
86 { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
87 { USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51, HID_QUIRK_NOGET },
88 { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL },
89 { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
90 { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT },
91 { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3, HID_QUIRK_MULTI_INPUT },
92 { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR, HID_QUIRK_MULTI_INPUT },
93 { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1, HID_QUIRK_MULTI_INPUT },
94 { USB_VENDOR_ID_ELAN, HID_ANY_ID, HID_QUIRK_ALWAYS_POLL },
95 { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
96 { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
97 { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
98 { USB_VENDOR_ID_FUTABA, USB_DEVICE_ID_LED_DISPLAY, HID_QUIRK_NO_INIT_REPORTS },
99 { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A, HID_QUIRK_ALWAYS_POLL },
100 { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A, HID_QUIRK_ALWAYS_POLL },
101 { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL },
102 { USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6680, HID_QUIRK_MULTI_INPUT },
103 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C007, HID_QUIRK_ALWAYS_POLL },
104 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C077, HID_QUIRK_ALWAYS_POLL },
105 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KEYBOARD_G710_PLUS, HID_QUIRK_NOGET },
106 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C01A, HID_QUIRK_ALWAYS_POLL },
107 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C05A, HID_QUIRK_ALWAYS_POLL },
108 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C06A, HID_QUIRK_ALWAYS_POLL },
109 { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
110 { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2, HID_QUIRK_NO_INIT_REPORTS },
111 { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2, HID_QUIRK_NO_INIT_REPORTS },
112 { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2, HID_QUIRK_NO_INIT_REPORTS },
113 { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS },
114 { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
115 { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS },
116 { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS },
117 { USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_1610, HID_QUIRK_NOGET },
118 { USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_1640, HID_QUIRK_NOGET },
119 { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL },
120 { USB_VENDOR_ID_KYE, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE_ID2, HID_QUIRK_ALWAYS_POLL },
121 { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
122 { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
123 { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS },
124 { USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4D22, HID_QUIRK_ALWAYS_POLL },
125 { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET },
126 { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET },
127 { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003, HID_QUIRK_NOGET },
128 { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET },
129 { USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER, HID_QUIRK_NO_INIT_REPORTS },
130 { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET },
131 { USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET },
132 { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH, HID_QUIRK_NOGET },
133 { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH, HID_QUIRK_NOGET },
134 { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS_TS, HID_QUIRK_NO_INIT_REPORTS },
135 { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS1030_TOUCH, HID_QUIRK_NOGET },
136 { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
137 { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET },
138 { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET },
139 { USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8882, HID_QUIRK_NOGET },
140 { USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8883, HID_QUIRK_NOGET },
141 { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
142 { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT },
143 { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60, HID_QUIRK_MULTI_INPUT },
144 { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT },
145 { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH, HID_QUIRK_MULTI_INPUT },
146 { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET, HID_QUIRK_MULTI_INPUT },
147 { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
148
149 { USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
150
151 { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE },
152
153 { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH, HID_QUIRK_MULTI_INPUT },
154 { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS, HID_QUIRK_MULTI_INPUT },
155 { USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD, HID_QUIRK_NO_INIT_REPORTS },
156 { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X, HID_QUIRK_MULTI_INPUT },
157 { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2, HID_QUIRK_MULTI_INPUT },
158 { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X, HID_QUIRK_MULTI_INPUT },
159 { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912, HID_QUIRK_MULTI_INPUT },
160 { USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS },
161 { USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD, HID_QUIRK_NO_INIT_REPORTS },
162 { USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD2, HID_QUIRK_NO_INIT_REPORTS },
163 { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1, HID_QUIRK_NO_INIT_REPORTS },
164 { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2, HID_QUIRK_NO_INIT_REPORTS },
165 { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD, HID_QUIRK_NO_INIT_REPORTS },
166 { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD, HID_QUIRK_NO_INIT_REPORTS },
167 { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP_V103, HID_QUIRK_NO_INIT_REPORTS },
168 { USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096, HID_QUIRK_NO_INIT_REPORTS },
169 { USB_VENDOR_ID_MULTIPLE_1781, USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD, HID_QUIRK_MULTI_INPUT },
170 { USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_2NES2SNES, HID_QUIRK_MULTI_INPUT },
171 { USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_4NES4SNES, HID_QUIRK_MULTI_INPUT },
172 { USB_VENDOR_ID_INNOMEDIA, USB_DEVICE_ID_INNEX_GENESIS_ATARI, HID_QUIRK_MULTI_INPUT },
173 { USB_VENDOR_ID_MCS, USB_DEVICE_ID_MCS_GAMEPADBLOCK, HID_QUIRK_MULTI_INPUT },
174
175 { 0, 0 }
176};
177
178/* Dynamic HID quirks list - specified at runtime */
179struct quirks_list_struct {
180 struct hid_blacklist hid_bl_item;
181 struct list_head node;
182};
183
184static LIST_HEAD(dquirks_list);
185static DECLARE_RWSEM(dquirks_rwsem);
186
187/* Runtime ("dynamic") quirks manipulation functions */
188
189/**
190 * usbhid_exists_dquirk: find any dynamic quirks for a USB HID device
191 * @idVendor: the 16-bit USB vendor ID, in native byteorder
192 * @idProduct: the 16-bit USB product ID, in native byteorder
193 *
194 * Description:
195 * Scans dquirks_list for a matching dynamic quirk and returns
196 * the pointer to the relevant struct hid_blacklist if found.
197 * Must be called with a read lock held on dquirks_rwsem.
198 *
199 * Returns: NULL if no quirk found, struct hid_blacklist * if found.
200 */
201static struct hid_blacklist *usbhid_exists_dquirk(const u16 idVendor,
202 const u16 idProduct)
203{
204 struct quirks_list_struct *q;
205 struct hid_blacklist *bl_entry = NULL;
206
207 list_for_each_entry(q, &dquirks_list, node) {
208 if (q->hid_bl_item.idVendor == idVendor &&
209 q->hid_bl_item.idProduct == idProduct) {
210 bl_entry = &q->hid_bl_item;
211 break;
212 }
213 }
214
215 if (bl_entry != NULL)
216 dbg_hid("Found dynamic quirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
217 bl_entry->quirks, bl_entry->idVendor,
218 bl_entry->idProduct);
219
220 return bl_entry;
221}
222
223
224/**
225 * usbhid_modify_dquirk: add/replace a HID quirk
226 * @idVendor: the 16-bit USB vendor ID, in native byteorder
227 * @idProduct: the 16-bit USB product ID, in native byteorder
228 * @quirks: the u32 quirks value to add/replace
229 *
230 * Description:
231 * If an dynamic quirk exists in memory for this (idVendor,
232 * idProduct) pair, replace its quirks value with what was
233 * provided. Otherwise, add the quirk to the dynamic quirks list.
234 *
235 * Returns: 0 OK, -error on failure.
236 */
237static int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct,
238 const u32 quirks)
239{
240 struct quirks_list_struct *q_new, *q;
241 int list_edited = 0;
242
243 if (!idVendor) {
244 dbg_hid("Cannot add a quirk with idVendor = 0\n");
245 return -EINVAL;
246 }
247
248 q_new = kmalloc(sizeof(struct quirks_list_struct), GFP_KERNEL);
249 if (!q_new)
250 return -ENOMEM;
251
252 q_new->hid_bl_item.idVendor = idVendor;
253 q_new->hid_bl_item.idProduct = idProduct;
254 q_new->hid_bl_item.quirks = quirks;
255
256 down_write(&dquirks_rwsem);
257
258 list_for_each_entry(q, &dquirks_list, node) {
259
260 if (q->hid_bl_item.idVendor == idVendor &&
261 q->hid_bl_item.idProduct == idProduct) {
262
263 list_replace(&q->node, &q_new->node);
264 kfree(q);
265 list_edited = 1;
266 break;
267
268 }
269
270 }
271
272 if (!list_edited)
273 list_add_tail(&q_new->node, &dquirks_list);
274
275 up_write(&dquirks_rwsem);
276
277 return 0;
278}
279
280/**
281 * usbhid_remove_all_dquirks: remove all runtime HID quirks from memory
282 *
283 * Description:
284 * Free all memory associated with dynamic quirks - called before
285 * module unload.
286 *
287 */
288static void usbhid_remove_all_dquirks(void)
289{
290 struct quirks_list_struct *q, *temp;
291
292 down_write(&dquirks_rwsem);
293 list_for_each_entry_safe(q, temp, &dquirks_list, node) {
294 list_del(&q->node);
295 kfree(q);
296 }
297 up_write(&dquirks_rwsem);
298
299}
300
301/**
302 * usbhid_quirks_init: apply USB HID quirks specified at module load time
303 */
304int usbhid_quirks_init(char **quirks_param)
305{
306 u16 idVendor, idProduct;
307 u32 quirks;
308 int n = 0, m;
309
310 for (; n < MAX_USBHID_BOOT_QUIRKS && quirks_param[n]; n++) {
311
312 m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x",
313 &idVendor, &idProduct, &quirks);
314
315 if (m != 3 ||
316 usbhid_modify_dquirk(idVendor, idProduct, quirks) != 0) {
317 pr_warn("Could not parse HID quirk module param %s\n",
318 quirks_param[n]);
319 }
320 }
321
322 return 0;
323}
324
325/**
326 * usbhid_quirks_exit: release memory associated with dynamic_quirks
327 *
328 * Description:
329 * Release all memory associated with dynamic quirks. Called upon
330 * module unload.
331 *
332 * Returns: nothing
333 */
334void usbhid_quirks_exit(void)
335{
336 usbhid_remove_all_dquirks();
337}
338
339/**
340 * usbhid_exists_squirk: return any static quirks for a USB HID device
341 * @idVendor: the 16-bit USB vendor ID, in native byteorder
342 * @idProduct: the 16-bit USB product ID, in native byteorder
343 *
344 * Description:
345 * Given a USB vendor ID and product ID, return a pointer to
346 * the hid_blacklist entry associated with that device.
347 *
348 * Returns: pointer if quirk found, or NULL if no quirks found.
349 */
350static const struct hid_blacklist *usbhid_exists_squirk(const u16 idVendor,
351 const u16 idProduct)
352{
353 const struct hid_blacklist *bl_entry = NULL;
354 int n = 0;
355
356 for (; hid_blacklist[n].idVendor; n++)
357 if (hid_blacklist[n].idVendor == idVendor &&
358 (hid_blacklist[n].idProduct == (__u16) HID_ANY_ID ||
359 hid_blacklist[n].idProduct == idProduct))
360 bl_entry = &hid_blacklist[n];
361
362 if (bl_entry != NULL)
363 dbg_hid("Found squirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
364 bl_entry->quirks, bl_entry->idVendor,
365 bl_entry->idProduct);
366 return bl_entry;
367}
368
369/**
370 * usbhid_lookup_quirk: return any quirks associated with a USB HID device
371 * @idVendor: the 16-bit USB vendor ID, in native byteorder
372 * @idProduct: the 16-bit USB product ID, in native byteorder
373 *
374 * Description:
375 * Given a USB vendor ID and product ID, return any quirks associated
376 * with that device.
377 *
378 * Returns: a u32 quirks value.
379 */
380u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
381{
382 u32 quirks = 0;
383 const struct hid_blacklist *bl_entry = NULL;
384
385 /* NCR devices must not be queried for reports */
386 if (idVendor == USB_VENDOR_ID_NCR &&
387 idProduct >= USB_DEVICE_ID_NCR_FIRST &&
388 idProduct <= USB_DEVICE_ID_NCR_LAST)
389 return HID_QUIRK_NO_INIT_REPORTS;
390
391 down_read(&dquirks_rwsem);
392 bl_entry = usbhid_exists_dquirk(idVendor, idProduct);
393 if (!bl_entry)
394 bl_entry = usbhid_exists_squirk(idVendor, idProduct);
395 if (bl_entry)
396 quirks = bl_entry->quirks;
397 up_read(&dquirks_rwsem);
398
399 return quirks;
400}
401
402EXPORT_SYMBOL_GPL(usbhid_lookup_quirk);
diff --git a/include/linux/hid.h b/include/linux/hid.h
index d491027a7c22..129a0d71e06a 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -860,7 +860,9 @@ int hid_open_report(struct hid_device *device);
860int hid_check_keys_pressed(struct hid_device *hid); 860int hid_check_keys_pressed(struct hid_device *hid);
861int hid_connect(struct hid_device *hid, unsigned int connect_mask); 861int hid_connect(struct hid_device *hid, unsigned int connect_mask);
862void hid_disconnect(struct hid_device *hid); 862void hid_disconnect(struct hid_device *hid);
863const struct hid_device_id *hid_match_id(struct hid_device *hdev, 863bool hid_match_one_id(const struct hid_device *hdev,
864 const struct hid_device_id *id);
865const struct hid_device_id *hid_match_id(const struct hid_device *hdev,
864 const struct hid_device_id *id); 866 const struct hid_device_id *id);
865s32 hid_snto32(__u32 value, unsigned n); 867s32 hid_snto32(__u32 value, unsigned n);
866__u32 hid_field_extract(const struct hid_device *hid, __u8 *report, 868__u32 hid_field_extract(const struct hid_device *hid, __u8 *report,
@@ -1098,9 +1100,9 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
1098 int interrupt); 1100 int interrupt);
1099 1101
1100/* HID quirks API */ 1102/* HID quirks API */
1101u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct); 1103unsigned long hid_lookup_quirk(const struct hid_device *hdev);
1102int usbhid_quirks_init(char **quirks_param); 1104int hid_quirks_init(char **quirks_param, __u16 bus, int count);
1103void usbhid_quirks_exit(void); 1105void hid_quirks_exit(__u16 bus);
1104 1106
1105#ifdef CONFIG_HID_PID 1107#ifdef CONFIG_HID_PID
1106int hid_pidff_init(struct hid_device *hid); 1108int hid_pidff_init(struct hid_device *hid);