blob: 192a03b2897145ba00155ebe8d5e74f887ae2cdd [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * $Id: hid-input.c,v 1.2 2002/04/23 00:59:25 rdamazio Exp $
3 *
4 * Copyright (c) 2000-2001 Vojtech Pavlik
5 *
6 * USB HID to Linux Input mapping
7 */
8
9/*
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * Should you need to contact me, the author, you can do so either by
25 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
26 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
27 */
28
29#include <linux/module.h>
30#include <linux/slab.h>
31#include <linux/kernel.h>
32#include <linux/input.h>
33#include <linux/usb.h>
Dmitry Torokhov16a334c2005-06-30 00:49:08 -050034#include <linux/usb_input.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
36#undef DEBUG
37
38#include "hid.h"
39
40#define unk KEY_UNKNOWN
41
Arjan van de Ven4c4c9432005-11-29 09:43:42 +010042static const unsigned char hid_keyboard[256] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070043 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
44 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
45 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
46 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
47 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
48 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
49 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
50 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
51 115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk,
52 122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
53 unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
54 unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
55 unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
56 unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
57 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
58 150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
59};
60
Arjan van de Ven4c4c9432005-11-29 09:43:42 +010061static const struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -070062 __s32 x;
63 __s32 y;
64} hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
65
66#define map_abs(c) do { usage->code = c; usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; } while (0)
67#define map_rel(c) do { usage->code = c; usage->type = EV_REL; bit = input->relbit; max = REL_MAX; } while (0)
68#define map_key(c) do { usage->code = c; usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; } while (0)
69#define map_led(c) do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0)
70#define map_ff(c) do { usage->code = c; usage->type = EV_FF; bit = input->ffbit; max = FF_MAX; } while (0)
71
72#define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0)
73#define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0)
74#define map_ff_effect(c) do { set_bit(c, input->ffbit); } while (0)
75
76static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
77 struct hid_usage *usage)
78{
Dmitry Torokhovc5b7c7c2005-09-15 02:01:47 -050079 struct input_dev *input = hidinput->input;
80 struct hid_device *device = input->private;
Vojtech Pavlik8a409b02005-09-05 00:08:08 -050081 int max = 0, code;
82 unsigned long *bit = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070083
84 field->hidinput = hidinput;
85
86#ifdef DEBUG
87 printk(KERN_DEBUG "Mapping: ");
88 resolv_usage(usage->hid);
89 printk(" ---> ");
90#endif
91
92 if (field->flags & HID_MAIN_ITEM_CONSTANT)
93 goto ignore;
94
95 switch (usage->hid & HID_USAGE_PAGE) {
96
97 case HID_UP_UNDEFINED:
98 goto ignore;
99
100 case HID_UP_KEYBOARD:
101
102 set_bit(EV_REP, input->evbit);
103
104 if ((usage->hid & HID_USAGE) < 256) {
105 if (!hid_keyboard[usage->hid & HID_USAGE]) goto ignore;
106 map_key_clear(hid_keyboard[usage->hid & HID_USAGE]);
107 } else
108 map_key(KEY_UNKNOWN);
109
110 break;
111
112 case HID_UP_BUTTON:
113
114 code = ((usage->hid - 1) & 0xf);
115
116 switch (field->application) {
117 case HID_GD_MOUSE:
118 case HID_GD_POINTER: code += 0x110; break;
119 case HID_GD_JOYSTICK: code += 0x120; break;
120 case HID_GD_GAMEPAD: code += 0x130; break;
121 default:
122 switch (field->physical) {
123 case HID_GD_MOUSE:
124 case HID_GD_POINTER: code += 0x110; break;
125 case HID_GD_JOYSTICK: code += 0x120; break;
126 case HID_GD_GAMEPAD: code += 0x130; break;
127 default: code += 0x100;
128 }
129 }
130
131 map_key(code);
132 break;
133
Vojtech Pavlik0aebfda2005-09-05 00:07:59 -0500134
135 case HID_UP_SIMULATION:
136
137 switch (usage->hid & 0xffff) {
138 case 0xba: map_abs(ABS_RUDDER); break;
139 case 0xbb: map_abs(ABS_THROTTLE); break;
Dmitry Torokhovff60dde2005-12-17 11:42:54 -0500140 default: goto ignore;
Vojtech Pavlik0aebfda2005-09-05 00:07:59 -0500141 }
142 break;
143
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 case HID_UP_GENDESK:
145
146 if ((usage->hid & 0xf0) == 0x80) { /* SystemControl */
147 switch (usage->hid & 0xf) {
148 case 0x1: map_key_clear(KEY_POWER); break;
149 case 0x2: map_key_clear(KEY_SLEEP); break;
150 case 0x3: map_key_clear(KEY_WAKEUP); break;
151 default: goto unknown;
152 }
153 break;
154 }
155
156 if ((usage->hid & 0xf0) == 0x90) { /* D-pad */
157 switch (usage->hid) {
158 case HID_GD_UP: usage->hat_dir = 1; break;
159 case HID_GD_DOWN: usage->hat_dir = 5; break;
160 case HID_GD_RIGHT: usage->hat_dir = 3; break;
161 case HID_GD_LEFT: usage->hat_dir = 7; break;
162 default: goto unknown;
163 }
164 if (field->dpad) {
165 map_abs(field->dpad);
166 goto ignore;
167 }
168 map_abs(ABS_HAT0X);
169 break;
170 }
171
172 switch (usage->hid) {
173
174 /* These usage IDs map directly to the usage codes. */
175 case HID_GD_X: case HID_GD_Y: case HID_GD_Z:
176 case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ:
177 case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL:
Dmitry Torokhov05f091ab2005-05-29 02:29:01 -0500178 if (field->flags & HID_MAIN_ITEM_RELATIVE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 map_rel(usage->hid & 0xf);
180 else
181 map_abs(usage->hid & 0xf);
182 break;
183
184 case HID_GD_HATSWITCH:
185 usage->hat_min = field->logical_minimum;
186 usage->hat_max = field->logical_maximum;
187 map_abs(ABS_HAT0X);
188 break;
189
190 case HID_GD_START: map_key_clear(BTN_START); break;
191 case HID_GD_SELECT: map_key_clear(BTN_SELECT); break;
192
193 default: goto unknown;
194 }
195
196 break;
197
198 case HID_UP_LED:
199 if (((usage->hid - 1) & 0xffff) >= LED_MAX)
200 goto ignore;
201 map_led((usage->hid - 1) & 0xffff);
202 break;
203
204 case HID_UP_DIGITIZER:
205
206 switch (usage->hid & 0xff) {
207
208 case 0x30: /* TipPressure */
209 if (!test_bit(BTN_TOUCH, input->keybit)) {
210 device->quirks |= HID_QUIRK_NOTOUCH;
211 set_bit(EV_KEY, input->evbit);
212 set_bit(BTN_TOUCH, input->keybit);
213 }
214
215 map_abs_clear(ABS_PRESSURE);
216 break;
217
218 case 0x32: /* InRange */
219 switch (field->physical & 0xff) {
220 case 0x21: map_key(BTN_TOOL_MOUSE); break;
221 case 0x22: map_key(BTN_TOOL_FINGER); break;
222 default: map_key(BTN_TOOL_PEN); break;
223 }
224 break;
225
226 case 0x3c: /* Invert */
227 map_key_clear(BTN_TOOL_RUBBER);
228 break;
229
230 case 0x33: /* Touch */
231 case 0x42: /* TipSwitch */
232 case 0x43: /* TipSwitch2 */
233 device->quirks &= ~HID_QUIRK_NOTOUCH;
234 map_key_clear(BTN_TOUCH);
235 break;
236
237 case 0x44: /* BarrelSwitch */
238 map_key_clear(BTN_STYLUS);
239 break;
240
241 default: goto unknown;
242 }
243 break;
244
245 case HID_UP_CONSUMER: /* USB HUT v1.1, pages 56-62 */
246
247 switch (usage->hid & HID_USAGE) {
248 case 0x000: goto ignore;
249 case 0x034: map_key_clear(KEY_SLEEP); break;
250 case 0x036: map_key_clear(BTN_MISC); break;
Micah F. Galizia39fd7482005-09-05 00:12:15 -0500251 case 0x045: map_key_clear(KEY_RADIO); break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 case 0x08a: map_key_clear(KEY_WWW); break;
Vojtech Pavlik8a409b02005-09-05 00:08:08 -0500253 case 0x08d: map_key_clear(KEY_PROGRAM); break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 case 0x095: map_key_clear(KEY_HELP); break;
Vojtech Pavlik8a409b02005-09-05 00:08:08 -0500255 case 0x09c: map_key_clear(KEY_CHANNELUP); break;
256 case 0x09d: map_key_clear(KEY_CHANNELDOWN); break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 case 0x0b0: map_key_clear(KEY_PLAY); break;
258 case 0x0b1: map_key_clear(KEY_PAUSE); break;
259 case 0x0b2: map_key_clear(KEY_RECORD); break;
260 case 0x0b3: map_key_clear(KEY_FASTFORWARD); break;
261 case 0x0b4: map_key_clear(KEY_REWIND); break;
262 case 0x0b5: map_key_clear(KEY_NEXTSONG); break;
263 case 0x0b6: map_key_clear(KEY_PREVIOUSSONG); break;
264 case 0x0b7: map_key_clear(KEY_STOPCD); break;
265 case 0x0b8: map_key_clear(KEY_EJECTCD); break;
266 case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break;
267 case 0x0e0: map_abs_clear(ABS_VOLUME); break;
268 case 0x0e2: map_key_clear(KEY_MUTE); break;
269 case 0x0e5: map_key_clear(KEY_BASSBOOST); break;
270 case 0x0e9: map_key_clear(KEY_VOLUMEUP); break;
271 case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break;
272 case 0x183: map_key_clear(KEY_CONFIG); break;
273 case 0x18a: map_key_clear(KEY_MAIL); break;
274 case 0x192: map_key_clear(KEY_CALC); break;
275 case 0x194: map_key_clear(KEY_FILE); break;
Vojtech Pavlik8a409b02005-09-05 00:08:08 -0500276 case 0x1a7: map_key_clear(KEY_DOCUMENTS); break;
277 case 0x201: map_key_clear(KEY_NEW); break;
278 case 0x207: map_key_clear(KEY_SAVE); break;
279 case 0x208: map_key_clear(KEY_PRINT); break;
280 case 0x209: map_key_clear(KEY_PROPS); break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 case 0x21a: map_key_clear(KEY_UNDO); break;
282 case 0x21b: map_key_clear(KEY_COPY); break;
283 case 0x21c: map_key_clear(KEY_CUT); break;
284 case 0x21d: map_key_clear(KEY_PASTE); break;
285 case 0x221: map_key_clear(KEY_FIND); break;
286 case 0x223: map_key_clear(KEY_HOMEPAGE); break;
287 case 0x224: map_key_clear(KEY_BACK); break;
288 case 0x225: map_key_clear(KEY_FORWARD); break;
289 case 0x226: map_key_clear(KEY_STOP); break;
290 case 0x227: map_key_clear(KEY_REFRESH); break;
291 case 0x22a: map_key_clear(KEY_BOOKMARKS); break;
292 case 0x238: map_rel(REL_HWHEEL); break;
Vojtech Pavlik8a409b02005-09-05 00:08:08 -0500293 case 0x279: map_key_clear(KEY_REDO); break;
294 case 0x289: map_key_clear(KEY_REPLY); break;
295 case 0x28b: map_key_clear(KEY_FORWARDMAIL); break;
296 case 0x28c: map_key_clear(KEY_SEND); break;
297 default: goto ignore;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 }
299 break;
300
301 case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */
302
303 set_bit(EV_REP, input->evbit);
304 switch (usage->hid & HID_USAGE) {
305 case 0x021: map_key_clear(KEY_PRINT); break;
306 case 0x070: map_key_clear(KEY_HP); break;
307 case 0x071: map_key_clear(KEY_CAMERA); break;
308 case 0x072: map_key_clear(KEY_SOUND); break;
309 case 0x073: map_key_clear(KEY_QUESTION); break;
310 case 0x080: map_key_clear(KEY_EMAIL); break;
311 case 0x081: map_key_clear(KEY_CHAT); break;
312 case 0x082: map_key_clear(KEY_SEARCH); break;
313 case 0x083: map_key_clear(KEY_CONNECT); break;
314 case 0x084: map_key_clear(KEY_FINANCE); break;
315 case 0x085: map_key_clear(KEY_SPORT); break;
316 case 0x086: map_key_clear(KEY_SHOP); break;
317 default: goto ignore;
318 }
319 break;
320
321 case HID_UP_MSVENDOR:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 goto ignore;
Dmitry Torokhov05f091ab2005-05-29 02:29:01 -0500323
Stelian Pope875ce32005-09-05 01:57:33 -0500324 case HID_UP_CUSTOM: /* Reported on Logitech and Powerbook USB keyboards */
325
326 set_bit(EV_REP, input->evbit);
327 switch(usage->hid & HID_USAGE) {
328 case 0x003: map_key_clear(KEY_FN); break;
329 default: goto ignore;
330 }
331 break;
332
333 case HID_UP_LOGIVENDOR: /* Reported on Logitech Ultra X Media Remote */
Micah F. Galizia39fd7482005-09-05 00:12:15 -0500334
335 set_bit(EV_REP, input->evbit);
336 switch(usage->hid & HID_USAGE) {
337 case 0x004: map_key_clear(KEY_AGAIN); break;
338 case 0x00d: map_key_clear(KEY_HOME); break;
339 case 0x024: map_key_clear(KEY_SHUFFLE); break;
340 case 0x025: map_key_clear(KEY_TV); break;
341 case 0x026: map_key_clear(KEY_MENU); break;
342 case 0x031: map_key_clear(KEY_AUDIO); break;
343 case 0x032: map_key_clear(KEY_SUBTITLE); break;
344 case 0x033: map_key_clear(KEY_LAST); break;
345 case 0x047: map_key_clear(KEY_MP3); break;
346 case 0x048: map_key_clear(KEY_DVD); break;
347 case 0x049: map_key_clear(KEY_MEDIA); break;
348 case 0x04a: map_key_clear(KEY_VIDEO); break;
349 case 0x04b: map_key_clear(KEY_ANGLE); break;
350 case 0x04c: map_key_clear(KEY_LANGUAGE); break;
351 case 0x04d: map_key_clear(KEY_SUBTITLE); break;
352 case 0x051: map_key_clear(KEY_RED); break;
353 case 0x052: map_key_clear(KEY_CLOSE); break;
354 default: goto ignore;
355 }
356 break;
357
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 case HID_UP_PID:
359
360 set_bit(EV_FF, input->evbit);
361 switch(usage->hid & HID_USAGE) {
362 case 0x26: map_ff_effect(FF_CONSTANT); goto ignore;
363 case 0x27: map_ff_effect(FF_RAMP); goto ignore;
364 case 0x28: map_ff_effect(FF_CUSTOM); goto ignore;
365 case 0x30: map_ff_effect(FF_SQUARE); map_ff_effect(FF_PERIODIC); goto ignore;
366 case 0x31: map_ff_effect(FF_SINE); map_ff_effect(FF_PERIODIC); goto ignore;
367 case 0x32: map_ff_effect(FF_TRIANGLE); map_ff_effect(FF_PERIODIC); goto ignore;
368 case 0x33: map_ff_effect(FF_SAW_UP); map_ff_effect(FF_PERIODIC); goto ignore;
369 case 0x34: map_ff_effect(FF_SAW_DOWN); map_ff_effect(FF_PERIODIC); goto ignore;
370 case 0x40: map_ff_effect(FF_SPRING); goto ignore;
371 case 0x41: map_ff_effect(FF_DAMPER); goto ignore;
372 case 0x42: map_ff_effect(FF_INERTIA); goto ignore;
373 case 0x43: map_ff_effect(FF_FRICTION); goto ignore;
374 case 0x7e: map_ff(FF_GAIN); break;
375 case 0x83: input->ff_effects_max = field->value[0]; goto ignore;
376 case 0x98: map_ff(FF_AUTOCENTER); break;
377 case 0xa4: map_key_clear(BTN_DEAD); break;
378 default: goto ignore;
379 }
380 break;
381
382 default:
383 unknown:
384 if (field->report_size == 1) {
385 if (field->report->type == HID_OUTPUT_REPORT) {
386 map_led(LED_MISC);
387 break;
388 }
389 map_key(BTN_MISC);
390 break;
391 }
392 if (field->flags & HID_MAIN_ITEM_RELATIVE) {
393 map_rel(REL_MISC);
394 break;
395 }
396 map_abs(ABS_MISC);
397 break;
398 }
399
400 set_bit(usage->type, input->evbit);
401
402 while (usage->code <= max && test_and_set_bit(usage->code, bit))
403 usage->code = find_next_zero_bit(bit, max + 1, usage->code);
404
405 if (usage->code > max)
406 goto ignore;
407
Vojtech Pavlikc58de6d2005-09-05 00:13:15 -0500408 if (((device->quirks & (HID_QUIRK_2WHEEL_POWERMOUSE)) && (usage->hid == 0x00010032)))
409 map_rel(REL_HWHEEL);
410
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) &&
Dmitry Torokhov05f091ab2005-05-29 02:29:01 -0500412 (usage->type == EV_REL) && (usage->code == REL_WHEEL))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 set_bit(REL_HWHEEL, bit);
414
415 if (((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005))
416 || ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007)))
417 goto ignore;
418
419 if (usage->type == EV_ABS) {
420
421 int a = field->logical_minimum;
422 int b = field->logical_maximum;
423
424 if ((device->quirks & HID_QUIRK_BADPAD) && (usage->code == ABS_X || usage->code == ABS_Y)) {
425 a = field->logical_minimum = 0;
426 b = field->logical_maximum = 255;
427 }
Dmitry Torokhov05f091ab2005-05-29 02:29:01 -0500428
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 if (field->application == HID_GD_GAMEPAD || field->application == HID_GD_JOYSTICK)
430 input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4);
431 else input_set_abs_params(input, usage->code, a, b, 0, 0);
Dmitry Torokhov05f091ab2005-05-29 02:29:01 -0500432
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 }
434
435 if (usage->hat_min < usage->hat_max || usage->hat_dir) {
436 int i;
437 for (i = usage->code; i < usage->code + 2 && i <= max; i++) {
438 input_set_abs_params(input, i, -1, 1, 0, 0);
439 set_bit(i, input->absbit);
440 }
441 if (usage->hat_dir && !field->dpad)
442 field->dpad = usage->code;
443 }
444
445#ifdef DEBUG
446 resolv_event(usage->type, usage->code);
447 printk("\n");
448#endif
449 return;
450
451ignore:
452#ifdef DEBUG
453 printk("IGNORED\n");
454#endif
455 return;
456}
457
458void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, struct pt_regs *regs)
459{
Pete Zaitceva9b2e912005-07-29 12:18:34 -0700460 struct input_dev *input;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 int *quirks = &hid->quirks;
462
Pete Zaitceva9b2e912005-07-29 12:18:34 -0700463 if (!field->hidinput)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 return;
Dmitry Torokhovc5b7c7c2005-09-15 02:01:47 -0500465
466 input = field->hidinput->input;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467
468 input_regs(input, regs);
469
470 if (!usage->type)
471 return;
472
473 if (((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005))
474 || ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) {
475 if (value) hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
476 else hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
477 return;
478 }
479
480 if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) {
481 input_event(input, usage->type, REL_HWHEEL, value);
482 return;
483 }
484
Dmitry Torokhov05f091ab2005-05-29 02:29:01 -0500485 if (usage->hat_min < usage->hat_max || usage->hat_dir) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 int hat_dir = usage->hat_dir;
487 if (!hat_dir)
488 hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1;
489 if (hat_dir < 0 || hat_dir > 8) hat_dir = 0;
490 input_event(input, usage->type, usage->code , hid_hat_to_axis[hat_dir].x);
491 input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[hat_dir].y);
492 return;
493 }
494
495 if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */
496 *quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT);
497 return;
498 }
499
500 if (usage->hid == (HID_UP_DIGITIZER | 0x0032)) { /* InRange */
501 if (value) {
502 input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1);
503 return;
504 }
505 input_event(input, usage->type, usage->code, 0);
506 input_event(input, usage->type, BTN_TOOL_RUBBER, 0);
507 return;
508 }
509
510 if (usage->hid == (HID_UP_DIGITIZER | 0x0030) && (*quirks & HID_QUIRK_NOTOUCH)) { /* Pressure */
511 int a = field->logical_minimum;
512 int b = field->logical_maximum;
513 input_event(input, EV_KEY, BTN_TOUCH, value > a + ((b - a) >> 3));
514 }
515
516 if (usage->hid == (HID_UP_PID | 0x83UL)) { /* Simultaneous Effects Max */
517 input->ff_effects_max = value;
518 dbg("Maximum Effects - %d",input->ff_effects_max);
519 return;
520 }
521
522 if (usage->hid == (HID_UP_PID | 0x7fUL)) {
523 dbg("PID Pool Report\n");
524 return;
525 }
526
527 if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
528 return;
529
530 input_event(input, usage->type, usage->code, value);
531
532 if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
533 input_event(input, usage->type, usage->code, 0);
534}
535
536void hidinput_report_event(struct hid_device *hid, struct hid_report *report)
537{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 struct hid_input *hidinput;
539
Dmitry Torokhovc5b7c7c2005-09-15 02:01:47 -0500540 list_for_each_entry(hidinput, &hid->inputs, list)
541 input_sync(hidinput->input);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542}
543
544static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
545{
546 struct hid_report *report;
547 int i, j;
548
549 list_for_each_entry(report, &hid->report_enum[HID_OUTPUT_REPORT].report_list, list) {
550 for (i = 0; i < report->maxfield; i++) {
551 *field = report->field[i];
552 for (j = 0; j < (*field)->maxusage; j++)
553 if ((*field)->usage[j].type == type && (*field)->usage[j].code == code)
554 return j;
555 }
556 }
557 return -1;
558}
559
560static int hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
561{
562 struct hid_device *hid = dev->private;
563 struct hid_field *field;
564 int offset;
565
566 if (type == EV_FF)
567 return hid_ff_event(hid, dev, type, code, value);
568
569 if (type != EV_LED)
570 return -1;
571
572 if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) {
573 warn("event field not found");
574 return -1;
575 }
576
577 hid_set_field(field, offset, value);
578 hid_submit_report(hid, field->report, USB_DIR_OUT);
579
580 return 0;
581}
582
583static int hidinput_open(struct input_dev *dev)
584{
585 struct hid_device *hid = dev->private;
586 return hid_open(hid);
587}
588
589static void hidinput_close(struct input_dev *dev)
590{
591 struct hid_device *hid = dev->private;
592 hid_close(hid);
593}
594
595/*
596 * Register the input device; print a message.
597 * Configure the input layer interface
598 * Read all reports and initialize the absolute field values.
599 */
600
601int hidinput_connect(struct hid_device *hid)
602{
603 struct usb_device *dev = hid->dev;
604 struct hid_report *report;
605 struct hid_input *hidinput = NULL;
Dmitry Torokhovc5b7c7c2005-09-15 02:01:47 -0500606 struct input_dev *input_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 int i, j, k;
608
609 INIT_LIST_HEAD(&hid->inputs);
610
611 for (i = 0; i < hid->maxcollection; i++)
612 if (hid->collection[i].type == HID_COLLECTION_APPLICATION ||
613 hid->collection[i].type == HID_COLLECTION_PHYSICAL)
Dmitry Torokhov05f091ab2005-05-29 02:29:01 -0500614 if (IS_INPUT_APPLICATION(hid->collection[i].usage))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 break;
616
617 if (i == hid->maxcollection)
618 return -1;
619
620 for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++)
621 list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
622
623 if (!report->maxfield)
624 continue;
625
626 if (!hidinput) {
Dmitry Torokhovc5b7c7c2005-09-15 02:01:47 -0500627 hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL);
628 input_dev = input_allocate_device();
629 if (!hidinput || !input_dev) {
630 kfree(hidinput);
631 input_free_device(input_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 err("Out of memory during hid input probe");
633 return -1;
634 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635
Dmitry Torokhovc5b7c7c2005-09-15 02:01:47 -0500636 input_dev->private = hid;
637 input_dev->event = hidinput_input_event;
638 input_dev->open = hidinput_open;
639 input_dev->close = hidinput_close;
640
641 input_dev->name = hid->name;
642 input_dev->phys = hid->phys;
643 input_dev->uniq = hid->uniq;
644 usb_to_input_id(dev, &input_dev->id);
645 input_dev->cdev.dev = &hid->intf->dev;
646
647 hidinput->input = input_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 list_add_tail(&hidinput->list, &hid->inputs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 }
650
651 for (i = 0; i < report->maxfield; i++)
652 for (j = 0; j < report->field[i]->maxusage; j++)
653 hidinput_configure_usage(hidinput, report->field[i],
654 report->field[i]->usage + j);
Dmitry Torokhov05f091ab2005-05-29 02:29:01 -0500655
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 if (hid->quirks & HID_QUIRK_MULTI_INPUT) {
657 /* This will leave hidinput NULL, so that it
658 * allocates another one if we have more inputs on
659 * the same interface. Some devices (e.g. Happ's
660 * UGCI) cram a lot of unrelated inputs into the
661 * same interface. */
662 hidinput->report = report;
Dmitry Torokhovc5b7c7c2005-09-15 02:01:47 -0500663 input_register_device(hidinput->input);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 hidinput = NULL;
665 }
666 }
667
668 /* This only gets called when we are a single-input (most of the
669 * time). IOW, not a HID_QUIRK_MULTI_INPUT. The hid_ff_init() is
670 * only useful in this case, and not for multi-input quirks. */
671 if (hidinput) {
672 hid_ff_init(hid);
Dmitry Torokhovc5b7c7c2005-09-15 02:01:47 -0500673 input_register_device(hidinput->input);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 }
675
676 return 0;
677}
678
679void hidinput_disconnect(struct hid_device *hid)
680{
Dmitry Torokhovc5b7c7c2005-09-15 02:01:47 -0500681 struct hid_input *hidinput, *next;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682
Dmitry Torokhovc5b7c7c2005-09-15 02:01:47 -0500683 list_for_each_entry_safe(hidinput, next, &hid->inputs, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 list_del(&hidinput->list);
Dmitry Torokhovc5b7c7c2005-09-15 02:01:47 -0500685 input_unregister_device(hidinput->input);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 kfree(hidinput);
687 }
688}