diff options
-rw-r--r-- | drivers/hid/hid-input-quirks.c | 77 | ||||
-rw-r--r-- | drivers/hid/hid-input.c | 16 | ||||
-rw-r--r-- | include/linux/hid.h | 56 |
3 files changed, 103 insertions, 46 deletions
diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c index 16feea014494..8ec64b74d38d 100644 --- a/drivers/hid/hid-input-quirks.c +++ b/drivers/hid/hid-input-quirks.c | |||
@@ -16,16 +16,14 @@ | |||
16 | #include <linux/input.h> | 16 | #include <linux/input.h> |
17 | #include <linux/hid.h> | 17 | #include <linux/hid.h> |
18 | 18 | ||
19 | #define map_abs(c) do { usage->code = c; usage->type = EV_ABS; *bit = input->absbit; *max = ABS_MAX; } while (0) | 19 | #define map_rel(c) hid_map_usage(hidinput, usage, bit, max, EV_REL, (c)) |
20 | #define map_rel(c) do { usage->code = c; usage->type = EV_REL; *bit = input->relbit; *max = REL_MAX; } while (0) | 20 | #define map_key(c) hid_map_usage(hidinput, usage, bit, max, EV_KEY, (c)) |
21 | #define map_key(c) do { usage->code = c; usage->type = EV_KEY; *bit = input->keybit; *max = KEY_MAX; } while (0) | ||
22 | #define map_led(c) do { usage->code = c; usage->type = EV_LED; *bit = input->ledbit; *max = LED_MAX; } while (0) | ||
23 | 21 | ||
24 | #define map_abs_clear(c) do { map_abs(c); clear_bit(c, *bit); } while (0) | 22 | #define map_key_clear(c) hid_map_usage_clear(hidinput, usage, bit, \ |
25 | #define map_key_clear(c) do { map_key(c); clear_bit(c, *bit); } while (0) | 23 | max, EV_KEY, (c)) |
26 | 24 | ||
27 | static int quirk_belkin_wkbd(struct hid_usage *usage, struct input_dev *input, | 25 | static int quirk_belkin_wkbd(struct hid_usage *usage, |
28 | unsigned long **bit, int *max) | 26 | struct hid_input *hidinput, unsigned long **bit, int *max) |
29 | { | 27 | { |
30 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) | 28 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) |
31 | return 0; | 29 | return 0; |
@@ -40,8 +38,8 @@ static int quirk_belkin_wkbd(struct hid_usage *usage, struct input_dev *input, | |||
40 | return 1; | 38 | return 1; |
41 | } | 39 | } |
42 | 40 | ||
43 | static int quirk_cherry_cymotion(struct hid_usage *usage, struct input_dev *input, | 41 | static int quirk_cherry_cymotion(struct hid_usage *usage, |
44 | unsigned long **bit, int *max) | 42 | struct hid_input *hidinput, unsigned long **bit, int *max) |
45 | { | 43 | { |
46 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) | 44 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) |
47 | return 0; | 45 | return 0; |
@@ -56,13 +54,13 @@ static int quirk_cherry_cymotion(struct hid_usage *usage, struct input_dev *inpu | |||
56 | return 1; | 54 | return 1; |
57 | } | 55 | } |
58 | 56 | ||
59 | static int quirk_logitech_ultrax_remote(struct hid_usage *usage, struct input_dev *input, | 57 | static int quirk_logitech_ultrax_remote(struct hid_usage *usage, |
60 | unsigned long **bit, int *max) | 58 | struct hid_input *hidinput, unsigned long **bit, int *max) |
61 | { | 59 | { |
62 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) | 60 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) |
63 | return 0; | 61 | return 0; |
64 | 62 | ||
65 | set_bit(EV_REP, input->evbit); | 63 | set_bit(EV_REP, hidinput->input->evbit); |
66 | switch(usage->hid & HID_USAGE) { | 64 | switch(usage->hid & HID_USAGE) { |
67 | /* Reported on Logitech Ultra X Media Remote */ | 65 | /* Reported on Logitech Ultra X Media Remote */ |
68 | case 0x004: map_key_clear(KEY_AGAIN); break; | 66 | case 0x004: map_key_clear(KEY_AGAIN); break; |
@@ -89,13 +87,13 @@ static int quirk_logitech_ultrax_remote(struct hid_usage *usage, struct input_de | |||
89 | return 1; | 87 | return 1; |
90 | } | 88 | } |
91 | 89 | ||
92 | static int quirk_gyration_remote(struct hid_usage *usage, struct input_dev *input, | 90 | static int quirk_gyration_remote(struct hid_usage *usage, |
93 | unsigned long **bit, int *max) | 91 | struct hid_input *hidinput, unsigned long **bit, int *max) |
94 | { | 92 | { |
95 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) | 93 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) |
96 | return 0; | 94 | return 0; |
97 | 95 | ||
98 | set_bit(EV_REP, input->evbit); | 96 | set_bit(EV_REP, hidinput->input->evbit); |
99 | switch(usage->hid & HID_USAGE) { | 97 | switch(usage->hid & HID_USAGE) { |
100 | /* Reported on Gyration MCE Remote */ | 98 | /* Reported on Gyration MCE Remote */ |
101 | case 0x00d: map_key_clear(KEY_HOME); break; | 99 | case 0x00d: map_key_clear(KEY_HOME); break; |
@@ -112,13 +110,13 @@ static int quirk_gyration_remote(struct hid_usage *usage, struct input_dev *inpu | |||
112 | return 1; | 110 | return 1; |
113 | } | 111 | } |
114 | 112 | ||
115 | static int quirk_chicony_tactical_pad(struct hid_usage *usage, struct input_dev *input, | 113 | static int quirk_chicony_tactical_pad(struct hid_usage *usage, |
116 | unsigned long **bit, int *max) | 114 | struct hid_input *hidinput, unsigned long **bit, int *max) |
117 | { | 115 | { |
118 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR) | 116 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR) |
119 | return 0; | 117 | return 0; |
120 | 118 | ||
121 | set_bit(EV_REP, input->evbit); | 119 | set_bit(EV_REP, hidinput->input->evbit); |
122 | switch (usage->hid & HID_USAGE) { | 120 | switch (usage->hid & HID_USAGE) { |
123 | case 0xff01: map_key_clear(BTN_1); break; | 121 | case 0xff01: map_key_clear(BTN_1); break; |
124 | case 0xff02: map_key_clear(BTN_2); break; | 122 | case 0xff02: map_key_clear(BTN_2); break; |
@@ -137,9 +135,11 @@ static int quirk_chicony_tactical_pad(struct hid_usage *usage, struct input_dev | |||
137 | return 1; | 135 | return 1; |
138 | } | 136 | } |
139 | 137 | ||
140 | static int quirk_microsoft_ergonomy_kb(struct hid_usage *usage, struct input_dev *input, | 138 | static int quirk_microsoft_ergonomy_kb(struct hid_usage *usage, |
141 | unsigned long **bit, int *max) | 139 | struct hid_input *hidinput, unsigned long **bit, int *max) |
142 | { | 140 | { |
141 | struct input_dev *input = hidinput->input; | ||
142 | |||
143 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR) | 143 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR) |
144 | return 0; | 144 | return 0; |
145 | 145 | ||
@@ -160,13 +160,13 @@ static int quirk_microsoft_ergonomy_kb(struct hid_usage *usage, struct input_dev | |||
160 | return 1; | 160 | return 1; |
161 | } | 161 | } |
162 | 162 | ||
163 | static int quirk_microsoft_presenter_8k(struct hid_usage *usage, struct input_dev *input, | 163 | static int quirk_microsoft_presenter_8k(struct hid_usage *usage, |
164 | unsigned long **bit, int *max) | 164 | struct hid_input *hidinput, unsigned long **bit, int *max) |
165 | { | 165 | { |
166 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR) | 166 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR) |
167 | return 0; | 167 | return 0; |
168 | 168 | ||
169 | set_bit(EV_REP, input->evbit); | 169 | set_bit(EV_REP, hidinput->input->evbit); |
170 | switch(usage->hid & HID_USAGE) { | 170 | switch(usage->hid & HID_USAGE) { |
171 | case 0xfd08: map_key_clear(KEY_FORWARD); break; | 171 | case 0xfd08: map_key_clear(KEY_FORWARD); break; |
172 | case 0xfd09: map_key_clear(KEY_BACK); break; | 172 | case 0xfd09: map_key_clear(KEY_BACK); break; |
@@ -179,8 +179,8 @@ static int quirk_microsoft_presenter_8k(struct hid_usage *usage, struct input_de | |||
179 | return 1; | 179 | return 1; |
180 | } | 180 | } |
181 | 181 | ||
182 | static int quirk_petalynx_remote(struct hid_usage *usage, struct input_dev *input, | 182 | static int quirk_petalynx_remote(struct hid_usage *usage, |
183 | unsigned long **bit, int *max) | 183 | struct hid_input *hidinput, unsigned long **bit, int *max) |
184 | { | 184 | { |
185 | if (((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) && | 185 | if (((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) && |
186 | ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)) | 186 | ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)) |
@@ -207,8 +207,8 @@ static int quirk_petalynx_remote(struct hid_usage *usage, struct input_dev *inpu | |||
207 | return 1; | 207 | return 1; |
208 | } | 208 | } |
209 | 209 | ||
210 | static int quirk_logitech_wireless(struct hid_usage *usage, struct input_dev *input, | 210 | static int quirk_logitech_wireless(struct hid_usage *usage, |
211 | unsigned long **bit, int *max) | 211 | struct hid_input *hidinput, unsigned long **bit, int *max) |
212 | { | 212 | { |
213 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) | 213 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) |
214 | return 0; | 214 | return 0; |
@@ -259,8 +259,8 @@ static int quirk_logitech_wireless(struct hid_usage *usage, struct input_dev *in | |||
259 | return 1; | 259 | return 1; |
260 | } | 260 | } |
261 | 261 | ||
262 | static int quirk_cherry_genius_29e(struct hid_usage *usage, struct input_dev *input, | 262 | static int quirk_cherry_genius_29e(struct hid_usage *usage, |
263 | unsigned long **bit, int *max) | 263 | struct hid_input *hidinput, unsigned long **bit, int *max) |
264 | { | 264 | { |
265 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) | 265 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) |
266 | return 0; | 266 | return 0; |
@@ -277,7 +277,7 @@ static int quirk_cherry_genius_29e(struct hid_usage *usage, struct input_dev *in | |||
277 | return 1; | 277 | return 1; |
278 | } | 278 | } |
279 | 279 | ||
280 | static int quirk_btc_8193(struct hid_usage *usage, struct input_dev *input, | 280 | static int quirk_btc_8193(struct hid_usage *usage, struct hid_input *hidinput, |
281 | unsigned long **bit, int *max) | 281 | unsigned long **bit, int *max) |
282 | { | 282 | { |
283 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) | 283 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) |
@@ -299,8 +299,8 @@ static int quirk_btc_8193(struct hid_usage *usage, struct input_dev *input, | |||
299 | return 1; | 299 | return 1; |
300 | } | 300 | } |
301 | 301 | ||
302 | static int quirk_sunplus_wdesktop(struct hid_usage *usage, struct input_dev *input, | 302 | static int quirk_sunplus_wdesktop(struct hid_usage *usage, |
303 | unsigned long **bit, int *max) | 303 | struct hid_input *hidinput, unsigned long **bit, int *max) |
304 | { | 304 | { |
305 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) | 305 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) |
306 | return 0; | 306 | return 0; |
@@ -353,7 +353,8 @@ static int quirk_sunplus_wdesktop(struct hid_usage *usage, struct input_dev *inp | |||
353 | static const struct hid_input_blacklist { | 353 | static const struct hid_input_blacklist { |
354 | __u16 idVendor; | 354 | __u16 idVendor; |
355 | __u16 idProduct; | 355 | __u16 idProduct; |
356 | int (*quirk)(struct hid_usage *, struct input_dev *, unsigned long **, int *); | 356 | int (*quirk)(struct hid_usage *, struct hid_input *, unsigned long **, |
357 | int *); | ||
357 | } hid_input_blacklist[] = { | 358 | } hid_input_blacklist[] = { |
358 | { VENDOR_ID_BELKIN, DEVICE_ID_BELKIN_WIRELESS_KEYBOARD, quirk_belkin_wkbd }, | 359 | { VENDOR_ID_BELKIN, DEVICE_ID_BELKIN_WIRELESS_KEYBOARD, quirk_belkin_wkbd }, |
359 | 360 | ||
@@ -385,16 +386,16 @@ static const struct hid_input_blacklist { | |||
385 | }; | 386 | }; |
386 | 387 | ||
387 | int hidinput_mapping_quirks(struct hid_usage *usage, | 388 | int hidinput_mapping_quirks(struct hid_usage *usage, |
388 | struct input_dev *input, | 389 | struct hid_input *hi, unsigned long **bit, int *max) |
389 | unsigned long **bit, int *max) | ||
390 | { | 390 | { |
391 | struct hid_device *device = input_get_drvdata(input); | 391 | struct hid_device *device = input_get_drvdata(hi->input); |
392 | int i = 0; | 392 | int i = 0; |
393 | 393 | ||
394 | while (hid_input_blacklist[i].quirk) { | 394 | while (hid_input_blacklist[i].quirk) { |
395 | if (hid_input_blacklist[i].idVendor == device->vendor && | 395 | if (hid_input_blacklist[i].idVendor == device->vendor && |
396 | hid_input_blacklist[i].idProduct == device->product) | 396 | hid_input_blacklist[i].idProduct == device->product) |
397 | return hid_input_blacklist[i].quirk(usage, input, bit, max); | 397 | return hid_input_blacklist[i].quirk(usage, hi, bit, |
398 | max); | ||
398 | i++; | 399 | i++; |
399 | } | 400 | } |
400 | return 0; | 401 | return 0; |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 9fa7239ab310..be2c7a8ad254 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -76,13 +76,15 @@ static const struct { | |||
76 | __s32 y; | 76 | __s32 y; |
77 | } hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}}; | 77 | } hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}}; |
78 | 78 | ||
79 | #define map_abs(c) do { usage->code = c; usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; } while (0) | 79 | #define map_abs(c) hid_map_usage(hidinput, usage, &bit, &max, EV_ABS, (c)) |
80 | #define map_rel(c) do { usage->code = c; usage->type = EV_REL; bit = input->relbit; max = REL_MAX; } while (0) | 80 | #define map_rel(c) hid_map_usage(hidinput, usage, &bit, &max, EV_REL, (c)) |
81 | #define map_key(c) do { usage->code = c; usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; } while (0) | 81 | #define map_key(c) hid_map_usage(hidinput, usage, &bit, &max, EV_KEY, (c)) |
82 | #define map_led(c) do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0) | 82 | #define map_led(c) hid_map_usage(hidinput, usage, &bit, &max, EV_LED, (c)) |
83 | 83 | ||
84 | #define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0) | 84 | #define map_abs_clear(c) hid_map_usage_clear(hidinput, usage, &bit, \ |
85 | #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) | 85 | &max, EV_ABS, (c)) |
86 | #define map_key_clear(c) hid_map_usage_clear(hidinput, usage, &bit, \ | ||
87 | &max, EV_KEY, (c)) | ||
86 | 88 | ||
87 | #ifdef CONFIG_USB_HIDINPUT_POWERBOOK | 89 | #ifdef CONFIG_USB_HIDINPUT_POWERBOOK |
88 | 90 | ||
@@ -386,7 +388,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
386 | } | 388 | } |
387 | 389 | ||
388 | /* handle input mappings for quirky devices */ | 390 | /* handle input mappings for quirky devices */ |
389 | ret = hidinput_mapping_quirks(usage, input, &bit, &max); | 391 | ret = hidinput_mapping_quirks(usage, hidinput, &bit, &max); |
390 | if (ret) | 392 | if (ret) |
391 | goto mapped; | 393 | goto mapped; |
392 | 394 | ||
diff --git a/include/linux/hid.h b/include/linux/hid.h index ac2584fe65c5..986c0e7ea66a 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
@@ -655,7 +655,8 @@ extern void hidinput_disconnect(struct hid_device *); | |||
655 | int hid_set_field(struct hid_field *, unsigned, __s32); | 655 | int hid_set_field(struct hid_field *, unsigned, __s32); |
656 | int hid_input_report(struct hid_device *, int type, u8 *, int, int); | 656 | int hid_input_report(struct hid_device *, int type, u8 *, int, int); |
657 | int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field); | 657 | int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field); |
658 | int hidinput_mapping_quirks(struct hid_usage *, struct input_dev *, unsigned long **, int *); | 658 | int hidinput_mapping_quirks(struct hid_usage *, struct hid_input *, |
659 | unsigned long **, int *); | ||
659 | int hidinput_event_quirks(struct hid_device *, struct hid_field *, struct hid_usage *, __s32); | 660 | int hidinput_event_quirks(struct hid_device *, struct hid_field *, struct hid_usage *, __s32); |
660 | int hidinput_apple_event(struct hid_device *, struct input_dev *, struct hid_usage *, __s32); | 661 | int hidinput_apple_event(struct hid_device *, struct input_dev *, struct hid_usage *, __s32); |
661 | void hid_output_report(struct hid_report *report, __u8 *data); | 662 | void hid_output_report(struct hid_report *report, __u8 *data); |
@@ -663,6 +664,59 @@ struct hid_device *hid_allocate_device(void); | |||
663 | int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); | 664 | int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); |
664 | 665 | ||
665 | /** | 666 | /** |
667 | * hid_map_usage - map usage input bits | ||
668 | * | ||
669 | * @hidinput: hidinput which we are interested in | ||
670 | * @usage: usage to fill in | ||
671 | * @bit: pointer to input->{}bit (out parameter) | ||
672 | * @max: maximal valid usage->code to consider later (out parameter) | ||
673 | * @type: input event type (EV_KEY, EV_REL, ...) | ||
674 | * @c: code which corresponds to this usage and type | ||
675 | */ | ||
676 | static inline void hid_map_usage(struct hid_input *hidinput, | ||
677 | struct hid_usage *usage, unsigned long **bit, int *max, | ||
678 | __u8 type, __u16 c) | ||
679 | { | ||
680 | struct input_dev *input = hidinput->input; | ||
681 | |||
682 | usage->type = type; | ||
683 | usage->code = c; | ||
684 | |||
685 | switch (type) { | ||
686 | case EV_ABS: | ||
687 | *bit = input->absbit; | ||
688 | *max = ABS_MAX; | ||
689 | break; | ||
690 | case EV_REL: | ||
691 | *bit = input->relbit; | ||
692 | *max = REL_MAX; | ||
693 | break; | ||
694 | case EV_KEY: | ||
695 | *bit = input->keybit; | ||
696 | *max = KEY_MAX; | ||
697 | break; | ||
698 | case EV_LED: | ||
699 | *bit = input->ledbit; | ||
700 | *max = LED_MAX; | ||
701 | break; | ||
702 | } | ||
703 | } | ||
704 | |||
705 | /** | ||
706 | * hid_map_usage_clear - map usage input bits and clear the input bit | ||
707 | * | ||
708 | * The same as hid_map_usage, except the @c bit is also cleared in supported | ||
709 | * bits (@bit). | ||
710 | */ | ||
711 | static inline void hid_map_usage_clear(struct hid_input *hidinput, | ||
712 | struct hid_usage *usage, unsigned long **bit, int *max, | ||
713 | __u8 type, __u16 c) | ||
714 | { | ||
715 | hid_map_usage(hidinput, usage, bit, max, type, c); | ||
716 | clear_bit(c, *bit); | ||
717 | } | ||
718 | |||
719 | /** | ||
666 | * hid_parse - parse HW reports | 720 | * hid_parse - parse HW reports |
667 | * | 721 | * |
668 | * @hdev: hid device | 722 | * @hdev: hid device |