This source file includes following definitions.
- lg_report_fixup
- lg_ultrax_remote_mapping
- lg_dinovo_mapping
- lg_wireless_mapping
- lg_input_mapping
- lg_input_mapped
- lg_event
- lg_raw_event
- lg_probe
- lg_remove
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 #include <linux/device.h>
17 #include <linux/hid.h>
18 #include <linux/module.h>
19 #include <linux/random.h>
20 #include <linux/sched.h>
21 #include <linux/usb.h>
22 #include <linux/wait.h>
23
24 #include "usbhid/usbhid.h"
25 #include "hid-ids.h"
26 #include "hid-lg.h"
27 #include "hid-lg4ff.h"
28
29 #define LG_RDESC 0x001
30 #define LG_BAD_RELATIVE_KEYS 0x002
31 #define LG_DUPLICATE_USAGES 0x004
32 #define LG_EXPANDED_KEYMAP 0x010
33 #define LG_IGNORE_DOUBLED_WHEEL 0x020
34 #define LG_WIRELESS 0x040
35 #define LG_INVERT_HWHEEL 0x080
36 #define LG_NOGET 0x100
37 #define LG_FF 0x200
38 #define LG_FF2 0x400
39 #define LG_RDESC_REL_ABS 0x800
40 #define LG_FF3 0x1000
41 #define LG_FF4 0x2000
42
43
44 #define DF_RDESC_ORIG_SIZE 130
45 #define DFP_RDESC_ORIG_SIZE 97
46 #define FV_RDESC_ORIG_SIZE 130
47 #define MOMO_RDESC_ORIG_SIZE 87
48 #define MOMO2_RDESC_ORIG_SIZE 87
49 #define FFG_RDESC_ORIG_SIZE 85
50 #define FG_RDESC_ORIG_SIZE 82
51
52
53
54
55
56
57
58
59
60
61 static __u8 df_rdesc_fixed[] = {
62 0x05, 0x01,
63 0x09, 0x04,
64 0xA1, 0x01,
65 0xA1, 0x02,
66 0x95, 0x01,
67 0x75, 0x0A,
68 0x14,
69 0x26, 0xFF, 0x03,
70 0x34,
71 0x46, 0xFF, 0x03,
72 0x09, 0x30,
73 0x81, 0x02,
74 0x95, 0x0C,
75 0x75, 0x01,
76 0x25, 0x01,
77 0x45, 0x01,
78 0x05, 0x09,
79 0x19, 0x01,
80 0x29, 0x0c,
81 0x81, 0x02,
82 0x95, 0x02,
83 0x06, 0x00, 0xFF,
84 0x09, 0x01,
85 0x81, 0x02,
86 0x05, 0x01,
87 0x26, 0xFF, 0x00,
88 0x46, 0xFF, 0x00,
89 0x95, 0x01,
90 0x75, 0x08,
91 0x81, 0x02,
92 0x25, 0x07,
93 0x46, 0x3B, 0x01,
94 0x75, 0x04,
95 0x65, 0x14,
96 0x09, 0x39,
97 0x81, 0x42,
98 0x75, 0x01,
99 0x95, 0x04,
100 0x65, 0x00,
101 0x06, 0x00, 0xFF,
102 0x09, 0x01,
103 0x25, 0x01,
104 0x45, 0x01,
105 0x81, 0x02,
106 0x05, 0x01,
107 0x95, 0x01,
108 0x75, 0x08,
109 0x26, 0xFF, 0x00,
110 0x46, 0xFF, 0x00,
111 0x09, 0x31,
112 0x81, 0x02,
113 0x09, 0x35,
114 0x81, 0x02,
115 0xC0,
116 0xA1, 0x02,
117 0x26, 0xFF, 0x00,
118 0x46, 0xFF, 0x00,
119 0x95, 0x07,
120 0x75, 0x08,
121 0x09, 0x03,
122 0x91, 0x02,
123 0xC0,
124 0xC0
125 };
126
127 static __u8 dfp_rdesc_fixed[] = {
128 0x05, 0x01,
129 0x09, 0x04,
130 0xA1, 0x01,
131 0xA1, 0x02,
132 0x95, 0x01,
133 0x75, 0x0E,
134 0x14,
135 0x26, 0xFF, 0x3F,
136 0x34,
137 0x46, 0xFF, 0x3F,
138 0x09, 0x30,
139 0x81, 0x02,
140 0x95, 0x0E,
141 0x75, 0x01,
142 0x25, 0x01,
143 0x45, 0x01,
144 0x05, 0x09,
145 0x19, 0x01,
146 0x29, 0x0E,
147 0x81, 0x02,
148 0x05, 0x01,
149 0x95, 0x01,
150 0x75, 0x04,
151 0x25, 0x07,
152 0x46, 0x3B, 0x01,
153 0x65, 0x14,
154 0x09, 0x39,
155 0x81, 0x42,
156 0x65, 0x00,
157 0x26, 0xFF, 0x00,
158 0x46, 0xFF, 0x00,
159 0x75, 0x08,
160 0x81, 0x01,
161 0x09, 0x31,
162 0x81, 0x02,
163 0x09, 0x35,
164 0x81, 0x02,
165 0x81, 0x01,
166 0xC0,
167 0xA1, 0x02,
168 0x09, 0x02,
169 0x95, 0x07,
170 0x91, 0x02,
171 0xC0,
172 0xC0
173 };
174
175 static __u8 fv_rdesc_fixed[] = {
176 0x05, 0x01,
177 0x09, 0x04,
178 0xA1, 0x01,
179 0xA1, 0x02,
180 0x95, 0x01,
181 0x75, 0x0A,
182 0x15, 0x00,
183 0x26, 0xFF, 0x03,
184 0x35, 0x00,
185 0x46, 0xFF, 0x03,
186 0x09, 0x30,
187 0x81, 0x02,
188 0x95, 0x0C,
189 0x75, 0x01,
190 0x25, 0x01,
191 0x45, 0x01,
192 0x05, 0x09,
193 0x19, 0x01,
194 0x29, 0x0C,
195 0x81, 0x02,
196 0x95, 0x02,
197 0x06, 0x00, 0xFF,
198 0x09, 0x01,
199 0x81, 0x02,
200 0x09, 0x02,
201 0x26, 0xFF, 0x00,
202 0x46, 0xFF, 0x00,
203 0x95, 0x01,
204 0x75, 0x08,
205 0x81, 0x02,
206 0x05, 0x01,
207 0x25, 0x07,
208 0x46, 0x3B, 0x01,
209 0x75, 0x04,
210 0x65, 0x14,
211 0x09, 0x39,
212 0x81, 0x42,
213 0x75, 0x01,
214 0x95, 0x04,
215 0x65, 0x00,
216 0x06, 0x00, 0xFF,
217 0x09, 0x01,
218 0x25, 0x01,
219 0x45, 0x01,
220 0x81, 0x02,
221 0x05, 0x01,
222 0x95, 0x01,
223 0x75, 0x08,
224 0x26, 0xFF, 0x00,
225 0x46, 0xFF, 0x00,
226 0x09, 0x31,
227 0x81, 0x02,
228 0x09, 0x32,
229 0x81, 0x02,
230 0xC0,
231 0xA1, 0x02,
232 0x26, 0xFF, 0x00,
233 0x46, 0xFF, 0x00,
234 0x95, 0x07,
235 0x75, 0x08,
236 0x09, 0x03,
237 0x91, 0x02,
238 0xC0,
239 0xC0
240 };
241
242 static __u8 momo_rdesc_fixed[] = {
243 0x05, 0x01,
244 0x09, 0x04,
245 0xA1, 0x01,
246 0xA1, 0x02,
247 0x95, 0x01,
248 0x75, 0x0A,
249 0x15, 0x00,
250 0x26, 0xFF, 0x03,
251 0x35, 0x00,
252 0x46, 0xFF, 0x03,
253 0x09, 0x30,
254 0x81, 0x02,
255 0x95, 0x08,
256 0x75, 0x01,
257 0x25, 0x01,
258 0x45, 0x01,
259 0x05, 0x09,
260 0x19, 0x01,
261 0x29, 0x08,
262 0x81, 0x02,
263 0x06, 0x00, 0xFF,
264 0x75, 0x0E,
265 0x95, 0x01,
266 0x26, 0xFF, 0x00,
267 0x46, 0xFF, 0x00,
268 0x09, 0x00,
269 0x81, 0x02,
270 0x05, 0x01,
271 0x75, 0x08,
272 0x09, 0x31,
273 0x81, 0x02,
274 0x09, 0x32,
275 0x81, 0x02,
276 0x06, 0x00, 0xFF,
277 0x09, 0x01,
278 0x81, 0x02,
279 0xC0,
280 0xA1, 0x02,
281 0x09, 0x02,
282 0x95, 0x07,
283 0x91, 0x02,
284 0xC0,
285 0xC0
286 };
287
288 static __u8 momo2_rdesc_fixed[] = {
289 0x05, 0x01,
290 0x09, 0x04,
291 0xA1, 0x01,
292 0xA1, 0x02,
293 0x95, 0x01,
294 0x75, 0x0A,
295 0x15, 0x00,
296 0x26, 0xFF, 0x03,
297 0x35, 0x00,
298 0x46, 0xFF, 0x03,
299 0x09, 0x30,
300 0x81, 0x02,
301 0x95, 0x0A,
302 0x75, 0x01,
303 0x25, 0x01,
304 0x45, 0x01,
305 0x05, 0x09,
306 0x19, 0x01,
307 0x29, 0x0A,
308 0x81, 0x02,
309 0x06, 0x00, 0xFF,
310 0x09, 0x00,
311 0x95, 0x04,
312 0x81, 0x02,
313 0x95, 0x01,
314 0x75, 0x08,
315 0x26, 0xFF, 0x00,
316 0x46, 0xFF, 0x00,
317 0x09, 0x01,
318 0x81, 0x02,
319 0x05, 0x01,
320 0x09, 0x31,
321 0x81, 0x02,
322 0x09, 0x32,
323 0x81, 0x02,
324 0x06, 0x00, 0xFF,
325 0x09, 0x00,
326 0x81, 0x02,
327 0xC0,
328 0xA1, 0x02,
329 0x09, 0x02,
330 0x95, 0x07,
331 0x91, 0x02,
332 0xC0,
333 0xC0
334 };
335
336 static __u8 ffg_rdesc_fixed[] = {
337 0x05, 0x01,
338 0x09, 0x04,
339 0xA1, 0x01,
340 0xA1, 0x02,
341 0x95, 0x01,
342 0x75, 0x0A,
343 0x15, 0x00,
344 0x26, 0xFF, 0x03,
345 0x35, 0x00,
346 0x46, 0xFF, 0x03,
347 0x09, 0x30,
348 0x81, 0x02,
349 0x95, 0x06,
350 0x75, 0x01,
351 0x25, 0x01,
352 0x45, 0x01,
353 0x05, 0x09,
354 0x19, 0x01,
355 0x29, 0x06,
356 0x81, 0x02,
357 0x95, 0x01,
358 0x75, 0x08,
359 0x26, 0xFF, 0x00,
360 0x46, 0xFF, 0x00,
361 0x06, 0x00, 0xFF,
362 0x09, 0x01,
363 0x81, 0x02,
364 0x05, 0x01,
365 0x81, 0x01,
366 0x09, 0x31,
367 0x81, 0x02,
368 0x09, 0x32,
369 0x81, 0x02,
370 0x06, 0x00, 0xFF,
371 0x09, 0x01,
372 0x81, 0x02,
373 0xC0,
374 0xA1, 0x02,
375 0x09, 0x02,
376 0x95, 0x07,
377 0x91, 0x02,
378 0xC0,
379 0xC0
380 };
381
382 static __u8 fg_rdesc_fixed[] = {
383 0x05, 0x01,
384 0x09, 0x04,
385 0xA1, 0x01,
386 0xA1, 0x02,
387 0x15, 0x00,
388 0x26, 0xFF, 0x00,
389 0x35, 0x00,
390 0x46, 0xFF, 0x00,
391 0x75, 0x08,
392 0x95, 0x01,
393 0x09, 0x30,
394 0x81, 0x02,
395 0xA4,
396 0x25, 0x01,
397 0x45, 0x01,
398 0x75, 0x01,
399 0x95, 0x02,
400 0x81, 0x01,
401 0x95, 0x06,
402 0x05, 0x09,
403 0x19, 0x01,
404 0x29, 0x06,
405 0x81, 0x02,
406 0x05, 0x01,
407 0xB4,
408 0x81, 0x02,
409 0x09, 0x31,
410 0x81, 0x02,
411 0x09, 0x32,
412 0x81, 0x02,
413 0xC0,
414 0xA1, 0x02,
415 0x26, 0xFF, 0x00,
416 0x46, 0xFF, 0x00,
417 0x75, 0x08,
418 0x95, 0x04,
419 0x09, 0x02,
420 0xB1, 0x02,
421 0xC0,
422 0xC0
423 };
424
425
426
427
428
429
430 static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
431 unsigned int *rsize)
432 {
433 struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
434
435 if ((drv_data->quirks & LG_RDESC) && *rsize >= 91 && rdesc[83] == 0x26 &&
436 rdesc[84] == 0x8c && rdesc[85] == 0x02) {
437 hid_info(hdev,
438 "fixing up Logitech keyboard report descriptor\n");
439 rdesc[84] = rdesc[89] = 0x4d;
440 rdesc[85] = rdesc[90] = 0x10;
441 }
442 if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 51 &&
443 rdesc[32] == 0x81 && rdesc[33] == 0x06 &&
444 rdesc[49] == 0x81 && rdesc[50] == 0x06) {
445 hid_info(hdev,
446 "fixing up rel/abs in Logitech report descriptor\n");
447 rdesc[33] = rdesc[50] = 0x02;
448 }
449
450 switch (hdev->product) {
451
452 case USB_DEVICE_ID_LOGITECH_WINGMAN_FG:
453 if (*rsize == FG_RDESC_ORIG_SIZE) {
454 hid_info(hdev,
455 "fixing up Logitech Wingman Formula GP report descriptor\n");
456 rdesc = fg_rdesc_fixed;
457 *rsize = sizeof(fg_rdesc_fixed);
458 } else {
459 hid_info(hdev,
460 "rdesc size test failed for formula gp\n");
461 }
462 break;
463
464
465 case USB_DEVICE_ID_LOGITECH_WINGMAN_FFG:
466 if (*rsize == FFG_RDESC_ORIG_SIZE) {
467 hid_info(hdev,
468 "fixing up Logitech Wingman Formula Force GP report descriptor\n");
469 rdesc = ffg_rdesc_fixed;
470 *rsize = sizeof(ffg_rdesc_fixed);
471 }
472 break;
473
474
475 case USB_DEVICE_ID_LOGITECH_WHEEL:
476 if (*rsize == DF_RDESC_ORIG_SIZE) {
477 hid_info(hdev,
478 "fixing up Logitech Driving Force report descriptor\n");
479 rdesc = df_rdesc_fixed;
480 *rsize = sizeof(df_rdesc_fixed);
481 }
482 break;
483
484 case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
485 if (*rsize == MOMO_RDESC_ORIG_SIZE) {
486 hid_info(hdev,
487 "fixing up Logitech Momo Force (Red) report descriptor\n");
488 rdesc = momo_rdesc_fixed;
489 *rsize = sizeof(momo_rdesc_fixed);
490 }
491 break;
492
493 case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
494 if (*rsize == MOMO2_RDESC_ORIG_SIZE) {
495 hid_info(hdev,
496 "fixing up Logitech Momo Racing Force (Black) report descriptor\n");
497 rdesc = momo2_rdesc_fixed;
498 *rsize = sizeof(momo2_rdesc_fixed);
499 }
500 break;
501
502 case USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL:
503 if (*rsize == FV_RDESC_ORIG_SIZE) {
504 hid_info(hdev,
505 "fixing up Logitech Formula Vibration report descriptor\n");
506 rdesc = fv_rdesc_fixed;
507 *rsize = sizeof(fv_rdesc_fixed);
508 }
509 break;
510
511 case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
512 if (*rsize == DFP_RDESC_ORIG_SIZE) {
513 hid_info(hdev,
514 "fixing up Logitech Driving Force Pro report descriptor\n");
515 rdesc = dfp_rdesc_fixed;
516 *rsize = sizeof(dfp_rdesc_fixed);
517 }
518 break;
519
520 case USB_DEVICE_ID_LOGITECH_WII_WHEEL:
521 if (*rsize >= 101 && rdesc[41] == 0x95 && rdesc[42] == 0x0B &&
522 rdesc[47] == 0x05 && rdesc[48] == 0x09) {
523 hid_info(hdev, "fixing up Logitech Speed Force Wireless report descriptor\n");
524 rdesc[41] = 0x05;
525 rdesc[42] = 0x09;
526 rdesc[47] = 0x95;
527 rdesc[48] = 0x0B;
528 }
529 break;
530 }
531
532 return rdesc;
533 }
534
535 #define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
536 EV_KEY, (c))
537
538 static int lg_ultrax_remote_mapping(struct hid_input *hi,
539 struct hid_usage *usage, unsigned long **bit, int *max)
540 {
541 if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
542 return 0;
543
544 set_bit(EV_REP, hi->input->evbit);
545 switch (usage->hid & HID_USAGE) {
546
547 case 0x004: lg_map_key_clear(KEY_AGAIN); break;
548 case 0x00d: lg_map_key_clear(KEY_HOME); break;
549 case 0x024: lg_map_key_clear(KEY_SHUFFLE); break;
550 case 0x025: lg_map_key_clear(KEY_TV); break;
551 case 0x026: lg_map_key_clear(KEY_MENU); break;
552 case 0x031: lg_map_key_clear(KEY_AUDIO); break;
553 case 0x032: lg_map_key_clear(KEY_TEXT); break;
554 case 0x033: lg_map_key_clear(KEY_LAST); break;
555 case 0x047: lg_map_key_clear(KEY_MP3); break;
556 case 0x048: lg_map_key_clear(KEY_DVD); break;
557 case 0x049: lg_map_key_clear(KEY_MEDIA); break;
558 case 0x04a: lg_map_key_clear(KEY_VIDEO); break;
559 case 0x04b: lg_map_key_clear(KEY_ANGLE); break;
560 case 0x04c: lg_map_key_clear(KEY_LANGUAGE); break;
561 case 0x04d: lg_map_key_clear(KEY_SUBTITLE); break;
562 case 0x051: lg_map_key_clear(KEY_RED); break;
563 case 0x052: lg_map_key_clear(KEY_CLOSE); break;
564
565 default:
566 return 0;
567 }
568 return 1;
569 }
570
571 static int lg_dinovo_mapping(struct hid_input *hi, struct hid_usage *usage,
572 unsigned long **bit, int *max)
573 {
574 if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
575 return 0;
576
577 switch (usage->hid & HID_USAGE) {
578
579 case 0x00d: lg_map_key_clear(KEY_MEDIA); break;
580 default:
581 return 0;
582
583 }
584 return 1;
585 }
586
587 static int lg_wireless_mapping(struct hid_input *hi, struct hid_usage *usage,
588 unsigned long **bit, int *max)
589 {
590 if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
591 return 0;
592
593 switch (usage->hid & HID_USAGE) {
594 case 0x1001: lg_map_key_clear(KEY_MESSENGER); break;
595 case 0x1003: lg_map_key_clear(KEY_SOUND); break;
596 case 0x1004: lg_map_key_clear(KEY_VIDEO); break;
597 case 0x1005: lg_map_key_clear(KEY_AUDIO); break;
598 case 0x100a: lg_map_key_clear(KEY_DOCUMENTS); break;
599
600 case 0x100f: lg_map_key_clear(KEY_FN_1); break;
601 case 0x1010: lg_map_key_clear(KEY_FN_2); break;
602 case 0x1011: lg_map_key_clear(KEY_PREVIOUSSONG); break;
603 case 0x1012: lg_map_key_clear(KEY_NEXTSONG); break;
604 case 0x1013: lg_map_key_clear(KEY_CAMERA); break;
605 case 0x1014: lg_map_key_clear(KEY_MESSENGER); break;
606 case 0x1015: lg_map_key_clear(KEY_RECORD); break;
607 case 0x1016: lg_map_key_clear(KEY_PLAYER); break;
608 case 0x1017: lg_map_key_clear(KEY_EJECTCD); break;
609 case 0x1018: lg_map_key_clear(KEY_MEDIA); break;
610 case 0x1019: lg_map_key_clear(KEY_PROG1); break;
611 case 0x101a: lg_map_key_clear(KEY_PROG2); break;
612 case 0x101b: lg_map_key_clear(KEY_PROG3); break;
613 case 0x101c: lg_map_key_clear(KEY_CYCLEWINDOWS); break;
614 case 0x101f: lg_map_key_clear(KEY_ZOOMIN); break;
615 case 0x1020: lg_map_key_clear(KEY_ZOOMOUT); break;
616 case 0x1021: lg_map_key_clear(KEY_ZOOMRESET); break;
617 case 0x1023: lg_map_key_clear(KEY_CLOSE); break;
618 case 0x1027: lg_map_key_clear(KEY_MENU); break;
619
620 case 0x1028: lg_map_key_clear(KEY_ANGLE); break;
621 case 0x1029: lg_map_key_clear(KEY_SHUFFLE); break;
622 case 0x102a: lg_map_key_clear(KEY_BACK); break;
623 case 0x102b: lg_map_key_clear(KEY_CYCLEWINDOWS); break;
624 case 0x102d: lg_map_key_clear(KEY_WWW); break;
625
626
627 case 0x1031: lg_map_key_clear(KEY_OK); break;
628 case 0x1032: lg_map_key_clear(KEY_CANCEL); break;
629 case 0x1041: lg_map_key_clear(KEY_BATTERY); break;
630 case 0x1042: lg_map_key_clear(KEY_WORDPROCESSOR); break;
631 case 0x1043: lg_map_key_clear(KEY_SPREADSHEET); break;
632 case 0x1044: lg_map_key_clear(KEY_PRESENTATION); break;
633 case 0x1045: lg_map_key_clear(KEY_UNDO); break;
634 case 0x1046: lg_map_key_clear(KEY_REDO); break;
635 case 0x1047: lg_map_key_clear(KEY_PRINT); break;
636 case 0x1048: lg_map_key_clear(KEY_SAVE); break;
637 case 0x1049: lg_map_key_clear(KEY_PROG1); break;
638 case 0x104a: lg_map_key_clear(KEY_PROG2); break;
639 case 0x104b: lg_map_key_clear(KEY_PROG3); break;
640 case 0x104c: lg_map_key_clear(KEY_PROG4); break;
641
642 default:
643 return 0;
644 }
645 return 1;
646 }
647
648 static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
649 struct hid_field *field, struct hid_usage *usage,
650 unsigned long **bit, int *max)
651 {
652
653
654 static const u8 e_keymap[] = {
655 0,216, 0,213,175,156, 0, 0, 0, 0,
656 144, 0, 0, 0, 0, 0, 0, 0, 0,212,
657 174,167,152,161,112, 0, 0, 0,154, 0,
658 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
659 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
660 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
661 0, 0, 0, 0, 0,183,184,185,186,187,
662 188,189,190,191,192,193,194, 0, 0, 0
663 };
664 struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
665 unsigned int hid = usage->hid;
666
667 if (hdev->product == USB_DEVICE_ID_LOGITECH_RECEIVER &&
668 lg_ultrax_remote_mapping(hi, usage, bit, max))
669 return 1;
670
671 if (hdev->product == USB_DEVICE_ID_DINOVO_MINI &&
672 lg_dinovo_mapping(hi, usage, bit, max))
673 return 1;
674
675 if ((drv_data->quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max))
676 return 1;
677
678 if ((hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
679 return 0;
680
681 hid &= HID_USAGE;
682
683
684 if (field->application == HID_GD_MOUSE) {
685 if ((drv_data->quirks & LG_IGNORE_DOUBLED_WHEEL) &&
686 (hid == 7 || hid == 8))
687 return -1;
688 } else {
689 if ((drv_data->quirks & LG_EXPANDED_KEYMAP) &&
690 hid < ARRAY_SIZE(e_keymap) &&
691 e_keymap[hid] != 0) {
692 hid_map_usage(hi, usage, bit, max, EV_KEY,
693 e_keymap[hid]);
694 return 1;
695 }
696 }
697
698 return 0;
699 }
700
701 static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
702 struct hid_field *field, struct hid_usage *usage,
703 unsigned long **bit, int *max)
704 {
705 struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
706
707 if ((drv_data->quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY &&
708 (field->flags & HID_MAIN_ITEM_RELATIVE))
709 field->flags &= ~HID_MAIN_ITEM_RELATIVE;
710
711 if ((drv_data->quirks & LG_DUPLICATE_USAGES) && (usage->type == EV_KEY ||
712 usage->type == EV_REL || usage->type == EV_ABS))
713 clear_bit(usage->code, *bit);
714
715
716 if (usage->type == EV_ABS && (usage->code == ABS_X ||
717 usage->code == ABS_Y || usage->code == ABS_Z ||
718 usage->code == ABS_RZ)) {
719 switch (hdev->product) {
720 case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
721 case USB_DEVICE_ID_LOGITECH_WINGMAN_FG:
722 case USB_DEVICE_ID_LOGITECH_WINGMAN_FFG:
723 case USB_DEVICE_ID_LOGITECH_WHEEL:
724 case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
725 case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
726 case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
727 case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
728 case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
729 case USB_DEVICE_ID_LOGITECH_WII_WHEEL:
730 case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
731 case USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL:
732 field->application = HID_GD_MULTIAXIS;
733 break;
734 default:
735 break;
736 }
737 }
738
739 return 0;
740 }
741
742 static int lg_event(struct hid_device *hdev, struct hid_field *field,
743 struct hid_usage *usage, __s32 value)
744 {
745 struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
746
747 if ((drv_data->quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) {
748 input_event(field->hidinput->input, usage->type, usage->code,
749 -value);
750 return 1;
751 }
752 if (drv_data->quirks & LG_FF4) {
753 return lg4ff_adjust_input_event(hdev, field, usage, value, drv_data);
754 }
755
756 return 0;
757 }
758
759 static int lg_raw_event(struct hid_device *hdev, struct hid_report *report,
760 u8 *rd, int size)
761 {
762 struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
763
764 if (drv_data->quirks & LG_FF4)
765 return lg4ff_raw_event(hdev, report, rd, size, drv_data);
766
767 return 0;
768 }
769
770 static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
771 {
772 struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
773 __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
774 unsigned int connect_mask = HID_CONNECT_DEFAULT;
775 struct lg_drv_data *drv_data;
776 int ret;
777
778
779 if ((hdev->product == USB_DEVICE_ID_LOGITECH_G29_WHEEL) &&
780 (iface_num != 0)) {
781 dbg_hid("%s: ignoring ifnum %d\n", __func__, iface_num);
782 return -ENODEV;
783 }
784
785 drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL);
786 if (!drv_data) {
787 hid_err(hdev, "Insufficient memory, cannot allocate driver data\n");
788 return -ENOMEM;
789 }
790 drv_data->quirks = id->driver_data;
791
792 hid_set_drvdata(hdev, (void *)drv_data);
793
794 if (drv_data->quirks & LG_NOGET)
795 hdev->quirks |= HID_QUIRK_NOGET;
796
797 ret = hid_parse(hdev);
798 if (ret) {
799 hid_err(hdev, "parse failed\n");
800 goto err_free;
801 }
802
803 if (drv_data->quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4))
804 connect_mask &= ~HID_CONNECT_FF;
805
806 ret = hid_hw_start(hdev, connect_mask);
807 if (ret) {
808 hid_err(hdev, "hw start failed\n");
809 goto err_free;
810 }
811
812
813 if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
814 static const unsigned char cbuf[] = {
815 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
816 };
817 u8 *buf = kmemdup(cbuf, sizeof(cbuf), GFP_KERNEL);
818
819 if (!buf) {
820 ret = -ENOMEM;
821 goto err_stop;
822 }
823
824 ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(cbuf),
825 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
826 if (ret >= 0) {
827
828 wait_queue_head_t wait;
829 init_waitqueue_head (&wait);
830 wait_event_interruptible_timeout(wait, 0,
831 msecs_to_jiffies(40));
832
833
834 buf[1] = 0xB2;
835 get_random_bytes(&buf[2], 2);
836
837 ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(cbuf),
838 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
839 }
840 kfree(buf);
841 }
842
843 if (drv_data->quirks & LG_FF)
844 ret = lgff_init(hdev);
845 else if (drv_data->quirks & LG_FF2)
846 ret = lg2ff_init(hdev);
847 else if (drv_data->quirks & LG_FF3)
848 ret = lg3ff_init(hdev);
849 else if (drv_data->quirks & LG_FF4)
850 ret = lg4ff_init(hdev);
851
852 if (ret)
853 goto err_stop;
854
855 return 0;
856
857 err_stop:
858 hid_hw_stop(hdev);
859 err_free:
860 kfree(drv_data);
861 return ret;
862 }
863
864 static void lg_remove(struct hid_device *hdev)
865 {
866 struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
867 if (drv_data->quirks & LG_FF4)
868 lg4ff_deinit(hdev);
869 hid_hw_stop(hdev);
870 kfree(drv_data);
871 }
872
873 static const struct hid_device_id lg_devices[] = {
874 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER),
875 .driver_data = LG_RDESC | LG_WIRELESS },
876
877 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER),
878 .driver_data = LG_BAD_RELATIVE_KEYS },
879
880 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP),
881 .driver_data = LG_DUPLICATE_USAGES },
882 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE),
883 .driver_data = LG_DUPLICATE_USAGES },
884 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI),
885 .driver_data = LG_DUPLICATE_USAGES },
886
887 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD),
888 .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
889 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500),
890 .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
891
892 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D),
893 .driver_data = LG_NOGET },
894 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DUAL_ACTION),
895 .driver_data = LG_NOGET },
896 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL),
897 .driver_data = LG_NOGET | LG_FF4 },
898
899 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD),
900 .driver_data = LG_FF2 },
901 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD),
902 .driver_data = LG_FF },
903 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2),
904 .driver_data = LG_FF },
905 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G29_WHEEL),
906 .driver_data = LG_FF4 },
907 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D),
908 .driver_data = LG_FF },
909 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO),
910 .driver_data = LG_FF },
911 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL),
912 .driver_data = LG_NOGET | LG_FF4 },
913 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2),
914 .driver_data = LG_FF4 },
915 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL),
916 .driver_data = LG_FF2 },
917 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
918 .driver_data = LG_FF4 },
919 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL),
920 .driver_data = LG_FF4 },
921 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL),
922 .driver_data = LG_FF4 },
923 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL),
924 .driver_data = LG_NOGET | LG_FF4 },
925 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL),
926 .driver_data = LG_FF4 },
927 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FG),
928 .driver_data = LG_NOGET },
929 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG),
930 .driver_data = LG_NOGET | LG_FF4 },
931 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
932 .driver_data = LG_NOGET | LG_FF2 },
933 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940),
934 .driver_data = LG_FF3 },
935 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR),
936 .driver_data = LG_RDESC_REL_ABS },
937 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER),
938 .driver_data = LG_RDESC_REL_ABS },
939 { }
940 };
941
942 MODULE_DEVICE_TABLE(hid, lg_devices);
943
944 static struct hid_driver lg_driver = {
945 .name = "logitech",
946 .id_table = lg_devices,
947 .report_fixup = lg_report_fixup,
948 .input_mapping = lg_input_mapping,
949 .input_mapped = lg_input_mapped,
950 .event = lg_event,
951 .raw_event = lg_raw_event,
952 .probe = lg_probe,
953 .remove = lg_remove,
954 };
955 module_hid_driver(lg_driver);
956
957 #ifdef CONFIG_LOGIWHEELS_FF
958 int lg4ff_no_autoswitch = 0;
959 module_param_named(lg4ff_no_autoswitch, lg4ff_no_autoswitch, int, S_IRUGO);
960 MODULE_PARM_DESC(lg4ff_no_autoswitch, "Do not switch multimode wheels to their native mode automatically");
961 #endif
962
963 MODULE_LICENSE("GPL");