2 * HID-input usage mapping quirks
4 * This is used to handle HID-input mappings for devices violating
5 * HUT 1.12 specification.
7 * Copyright (c) 2007-2008 Jiri Kosina
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the Free
13 * Software Foundation; either version 2 of the License
16 #include <linux/input.h>
17 #include <linux/hid.h>
19 #define map_rel(c) hid_map_usage(hidinput, usage, bit, max, EV_REL, (c))
20 #define map_key(c) hid_map_usage(hidinput, usage, bit, max, EV_KEY, (c))
22 #define map_key_clear(c) hid_map_usage_clear(hidinput, usage, bit, \
25 static int quirk_belkin_wkbd(struct hid_usage
*usage
,
26 struct hid_input
*hidinput
, unsigned long **bit
, int *max
)
28 if ((usage
->hid
& HID_USAGE_PAGE
) != HID_UP_CONSUMER
)
31 switch (usage
->hid
& HID_USAGE
) {
32 case 0x03a: map_key_clear(KEY_SOUND
); break;
33 case 0x03b: map_key_clear(KEY_CAMERA
); break;
34 case 0x03c: map_key_clear(KEY_DOCUMENTS
); break;
41 static int quirk_cherry_cymotion(struct hid_usage
*usage
,
42 struct hid_input
*hidinput
, unsigned long **bit
, int *max
)
44 if ((usage
->hid
& HID_USAGE_PAGE
) != HID_UP_CONSUMER
)
47 switch (usage
->hid
& HID_USAGE
) {
48 case 0x301: map_key_clear(KEY_PROG1
); break;
49 case 0x302: map_key_clear(KEY_PROG2
); break;
50 case 0x303: map_key_clear(KEY_PROG3
); break;
57 static int quirk_gyration_remote(struct hid_usage
*usage
,
58 struct hid_input
*hidinput
, unsigned long **bit
, int *max
)
60 if ((usage
->hid
& HID_USAGE_PAGE
) != HID_UP_LOGIVENDOR
)
63 set_bit(EV_REP
, hidinput
->input
->evbit
);
64 switch(usage
->hid
& HID_USAGE
) {
65 /* Reported on Gyration MCE Remote */
66 case 0x00d: map_key_clear(KEY_HOME
); break;
67 case 0x024: map_key_clear(KEY_DVD
); break;
68 case 0x025: map_key_clear(KEY_PVR
); break;
69 case 0x046: map_key_clear(KEY_MEDIA
); break;
70 case 0x047: map_key_clear(KEY_MP3
); break;
71 case 0x049: map_key_clear(KEY_CAMERA
); break;
72 case 0x04a: map_key_clear(KEY_VIDEO
); break;
80 static int quirk_chicony_tactical_pad(struct hid_usage
*usage
,
81 struct hid_input
*hidinput
, unsigned long **bit
, int *max
)
83 if ((usage
->hid
& HID_USAGE_PAGE
) != HID_UP_MSVENDOR
)
86 set_bit(EV_REP
, hidinput
->input
->evbit
);
87 switch (usage
->hid
& HID_USAGE
) {
88 case 0xff01: map_key_clear(BTN_1
); break;
89 case 0xff02: map_key_clear(BTN_2
); break;
90 case 0xff03: map_key_clear(BTN_3
); break;
91 case 0xff04: map_key_clear(BTN_4
); break;
92 case 0xff05: map_key_clear(BTN_5
); break;
93 case 0xff06: map_key_clear(BTN_6
); break;
94 case 0xff07: map_key_clear(BTN_7
); break;
95 case 0xff08: map_key_clear(BTN_8
); break;
96 case 0xff09: map_key_clear(BTN_9
); break;
97 case 0xff0a: map_key_clear(BTN_A
); break;
98 case 0xff0b: map_key_clear(BTN_B
); break;
105 static int quirk_petalynx_remote(struct hid_usage
*usage
,
106 struct hid_input
*hidinput
, unsigned long **bit
, int *max
)
108 if (((usage
->hid
& HID_USAGE_PAGE
) != HID_UP_LOGIVENDOR
) &&
109 ((usage
->hid
& HID_USAGE_PAGE
) != HID_UP_CONSUMER
))
112 if ((usage
->hid
& HID_USAGE_PAGE
) == HID_UP_LOGIVENDOR
)
113 switch(usage
->hid
& HID_USAGE
) {
114 case 0x05a: map_key_clear(KEY_TEXT
); break;
115 case 0x05b: map_key_clear(KEY_RED
); break;
116 case 0x05c: map_key_clear(KEY_GREEN
); break;
117 case 0x05d: map_key_clear(KEY_YELLOW
); break;
118 case 0x05e: map_key_clear(KEY_BLUE
); break;
123 if ((usage
->hid
& HID_USAGE_PAGE
) == HID_UP_CONSUMER
)
124 switch(usage
->hid
& HID_USAGE
) {
125 case 0x0f6: map_key_clear(KEY_NEXT
); break;
126 case 0x0fa: map_key_clear(KEY_BACK
); break;
133 static int quirk_cherry_genius_29e(struct hid_usage
*usage
,
134 struct hid_input
*hidinput
, unsigned long **bit
, int *max
)
136 if ((usage
->hid
& HID_USAGE_PAGE
) != HID_UP_CONSUMER
)
139 switch (usage
->hid
& HID_USAGE
) {
140 case 0x156: map_key_clear(KEY_WORDPROCESSOR
); break;
141 case 0x157: map_key_clear(KEY_SPREADSHEET
); break;
142 case 0x158: map_key_clear(KEY_PRESENTATION
); break;
143 case 0x15c: map_key_clear(KEY_STOP
); break;
151 static int quirk_btc_8193(struct hid_usage
*usage
, struct hid_input
*hidinput
,
152 unsigned long **bit
, int *max
)
154 if ((usage
->hid
& HID_USAGE_PAGE
) != HID_UP_CONSUMER
)
157 switch (usage
->hid
& HID_USAGE
) {
158 case 0x230: map_key(BTN_MOUSE
); break;
159 case 0x231: map_rel(REL_WHEEL
); break;
161 * this keyboard has a scrollwheel implemented in
162 * totally broken way. We map this usage temporarily
163 * to HWHEEL and handle it in the event quirk handler
165 case 0x232: map_rel(REL_HWHEEL
); break;
173 static int quirk_sunplus_wdesktop(struct hid_usage
*usage
,
174 struct hid_input
*hidinput
, unsigned long **bit
, int *max
)
176 if ((usage
->hid
& HID_USAGE_PAGE
) != HID_UP_CONSUMER
)
179 switch (usage
->hid
& HID_USAGE
) {
180 case 0x2003: map_key_clear(KEY_ZOOMIN
); break;
181 case 0x2103: map_key_clear(KEY_ZOOMOUT
); break;
188 #define VENDOR_ID_BELKIN 0x1020
189 #define DEVICE_ID_BELKIN_WIRELESS_KEYBOARD 0x0006
191 #define VENDOR_ID_CHERRY 0x046a
192 #define DEVICE_ID_CHERRY_CYMOTION 0x0023
194 #define VENDOR_ID_CHICONY 0x04f2
195 #define DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418
197 #define VENDOR_ID_EZKEY 0x0518
198 #define DEVICE_ID_BTC_8193 0x0002
200 #define VENDOR_ID_GYRATION 0x0c16
201 #define DEVICE_ID_GYRATION_REMOTE 0x0002
203 #define VENDOR_ID_MONTEREY 0x0566
204 #define DEVICE_ID_GENIUS_KB29E 0x3004
206 #define VENDOR_ID_PETALYNX 0x18b1
207 #define DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037
209 #define VENDOR_ID_SUNPLUS 0x04fc
210 #define DEVICE_ID_SUNPLUS_WDESKTOP 0x05d8
212 static const struct hid_input_blacklist
{
215 int (*quirk
)(struct hid_usage
*, struct hid_input
*, unsigned long **,
217 } hid_input_blacklist
[] = {
218 { VENDOR_ID_BELKIN
, DEVICE_ID_BELKIN_WIRELESS_KEYBOARD
, quirk_belkin_wkbd
},
220 { VENDOR_ID_CHERRY
, DEVICE_ID_CHERRY_CYMOTION
, quirk_cherry_cymotion
},
222 { VENDOR_ID_CHICONY
, DEVICE_ID_CHICONY_TACTICAL_PAD
, quirk_chicony_tactical_pad
},
224 { VENDOR_ID_EZKEY
, DEVICE_ID_BTC_8193
, quirk_btc_8193
},
226 { VENDOR_ID_GYRATION
, DEVICE_ID_GYRATION_REMOTE
, quirk_gyration_remote
},
228 { VENDOR_ID_MONTEREY
, DEVICE_ID_GENIUS_KB29E
, quirk_cherry_genius_29e
},
230 { VENDOR_ID_PETALYNX
, DEVICE_ID_PETALYNX_MAXTER_REMOTE
, quirk_petalynx_remote
},
232 { VENDOR_ID_SUNPLUS
, DEVICE_ID_SUNPLUS_WDESKTOP
, quirk_sunplus_wdesktop
},
237 int hidinput_mapping_quirks(struct hid_usage
*usage
,
238 struct hid_input
*hi
, unsigned long **bit
, int *max
)
240 struct hid_device
*device
= input_get_drvdata(hi
->input
);
243 while (hid_input_blacklist
[i
].quirk
) {
244 if (hid_input_blacklist
[i
].idVendor
== device
->vendor
&&
245 hid_input_blacklist
[i
].idProduct
== device
->product
)
246 return hid_input_blacklist
[i
].quirk(usage
, hi
, bit
,
253 int hidinput_event_quirks(struct hid_device
*hid
, struct hid_field
*field
, struct hid_usage
*usage
, __s32 value
)
255 struct input_dev
*input
;
257 input
= field
->hidinput
->input
;
259 if (((hid
->quirks
& HID_QUIRK_2WHEEL_MOUSE_HACK_5
) && (usage
->hid
== 0x00090005))
260 || ((hid
->quirks
& HID_QUIRK_2WHEEL_MOUSE_HACK_7
) && (usage
->hid
== 0x00090007))) {
261 if (value
) hid
->quirks
|= HID_QUIRK_2WHEEL_MOUSE_HACK_ON
;
262 else hid
->quirks
&= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON
;
266 if ((hid
->quirks
& HID_QUIRK_2WHEEL_MOUSE_HACK_B8
) &&
267 (usage
->type
== EV_REL
) &&
268 (usage
->code
== REL_WHEEL
)) {
269 hid
->delayed_value
= value
;
273 if ((hid
->quirks
& HID_QUIRK_2WHEEL_MOUSE_HACK_B8
) &&
274 (usage
->hid
== 0x000100b8)) {
275 input_event(input
, EV_REL
, value
? REL_HWHEEL
: REL_WHEEL
, hid
->delayed_value
);
279 if ((hid
->quirks
& HID_QUIRK_2WHEEL_MOUSE_HACK_ON
) && (usage
->code
== REL_WHEEL
)) {
280 input_event(input
, usage
->type
, REL_HWHEEL
, value
);
284 /* handle the temporary quirky mapping to HWHEEL */
285 if (hid
->quirks
& HID_QUIRK_HWHEEL_WHEEL_INVERT
&&
286 usage
->type
== EV_REL
&& usage
->code
== REL_HWHEEL
) {
287 input_event(input
, usage
->type
, REL_WHEEL
, -value
);
291 /* Gyration MCE remote "Sleep" key */
292 if (hid
->vendor
== VENDOR_ID_GYRATION
&&
293 hid
->product
== DEVICE_ID_GYRATION_REMOTE
&&
294 (usage
->hid
& HID_USAGE_PAGE
) == HID_UP_GENDESK
&&
295 (usage
->hid
& 0xff) == 0x82) {
296 input_event(input
, usage
->type
, usage
->code
, 1);
298 input_event(input
, usage
->type
, usage
->code
, 0);