xref: /linux/drivers/hid/hid-lg.c (revision 148f9bb87745ed45f7a11b2cbd3bc0f017d5d257)
1 /*
2  *  HID driver for some logitech "special" devices
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) 2008 Jiri Slaby
9  *  Copyright (c) 2010 Hendrik Iben
10  */
11 
12 /*
13  * This program is free software; you can redistribute it and/or modify it
14  * under the terms of the GNU General Public License as published by the Free
15  * Software Foundation; either version 2 of the License, or (at your option)
16  * any later version.
17  */
18 
19 #include <linux/device.h>
20 #include <linux/hid.h>
21 #include <linux/module.h>
22 #include <linux/random.h>
23 #include <linux/sched.h>
24 #include <linux/usb.h>
25 #include <linux/wait.h>
26 
27 #include "usbhid/usbhid.h"
28 #include "hid-ids.h"
29 #include "hid-lg.h"
30 
31 #define LG_RDESC		0x001
32 #define LG_BAD_RELATIVE_KEYS	0x002
33 #define LG_DUPLICATE_USAGES	0x004
34 #define LG_EXPANDED_KEYMAP	0x010
35 #define LG_IGNORE_DOUBLED_WHEEL	0x020
36 #define LG_WIRELESS		0x040
37 #define LG_INVERT_HWHEEL	0x080
38 #define LG_NOGET		0x100
39 #define LG_FF			0x200
40 #define LG_FF2			0x400
41 #define LG_RDESC_REL_ABS	0x800
42 #define LG_FF3			0x1000
43 #define LG_FF4			0x2000
44 
45 /* Size of the original descriptors of the Driving Force (and Pro) wheels */
46 #define DF_RDESC_ORIG_SIZE	130
47 #define DFP_RDESC_ORIG_SIZE	97
48 #define MOMO_RDESC_ORIG_SIZE	87
49 
50 /* Fixed report descriptors for Logitech Driving Force (and Pro)
51  * wheel controllers
52  *
53  * The original descriptors hide the separate throttle and brake axes in
54  * a custom vendor usage page, providing only a combined value as
55  * GenericDesktop.Y.
56  * These descriptors remove the combined Y axis and instead report
57  * separate throttle (Y) and brake (RZ).
58  */
59 static __u8 df_rdesc_fixed[] = {
60 0x05, 0x01,         /*  Usage Page (Desktop),                   */
61 0x09, 0x04,         /*  Usage (Joystik),                        */
62 0xA1, 0x01,         /*  Collection (Application),               */
63 0xA1, 0x02,         /*      Collection (Logical),               */
64 0x95, 0x01,         /*          Report Count (1),               */
65 0x75, 0x0A,         /*          Report Size (10),               */
66 0x14,               /*          Logical Minimum (0),            */
67 0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),         */
68 0x34,               /*          Physical Minimum (0),           */
69 0x46, 0xFF, 0x03,   /*          Physical Maximum (1023),        */
70 0x09, 0x30,         /*          Usage (X),                      */
71 0x81, 0x02,         /*          Input (Variable),               */
72 0x95, 0x0C,         /*          Report Count (12),              */
73 0x75, 0x01,         /*          Report Size (1),                */
74 0x25, 0x01,         /*          Logical Maximum (1),            */
75 0x45, 0x01,         /*          Physical Maximum (1),           */
76 0x05, 0x09,         /*          Usage (Buttons),                */
77 0x19, 0x01,         /*          Usage Minimum (1),              */
78 0x29, 0x0c,         /*          Usage Maximum (12),             */
79 0x81, 0x02,         /*          Input (Variable),               */
80 0x95, 0x02,         /*          Report Count (2),               */
81 0x06, 0x00, 0xFF,   /*          Usage Page (Vendor: 65280),     */
82 0x09, 0x01,         /*          Usage (?: 1),                   */
83 0x81, 0x02,         /*          Input (Variable),               */
84 0x05, 0x01,         /*          Usage Page (Desktop),           */
85 0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
86 0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
87 0x95, 0x01,         /*          Report Count (1),               */
88 0x75, 0x08,         /*          Report Size (8),                */
89 0x81, 0x02,         /*          Input (Variable),               */
90 0x25, 0x07,         /*          Logical Maximum (7),            */
91 0x46, 0x3B, 0x01,   /*          Physical Maximum (315),         */
92 0x75, 0x04,         /*          Report Size (4),                */
93 0x65, 0x14,         /*          Unit (Degrees),                 */
94 0x09, 0x39,         /*          Usage (Hat Switch),             */
95 0x81, 0x42,         /*          Input (Variable, Null State),   */
96 0x75, 0x01,         /*          Report Size (1),                */
97 0x95, 0x04,         /*          Report Count (4),               */
98 0x65, 0x00,         /*          Unit (none),                    */
99 0x06, 0x00, 0xFF,   /*          Usage Page (Vendor: 65280),     */
100 0x09, 0x01,         /*          Usage (?: 1),                   */
101 0x25, 0x01,         /*          Logical Maximum (1),            */
102 0x45, 0x01,         /*          Physical Maximum (1),           */
103 0x81, 0x02,         /*          Input (Variable),               */
104 0x05, 0x01,         /*          Usage Page (Desktop),           */
105 0x95, 0x01,         /*          Report Count (1),               */
106 0x75, 0x08,         /*          Report Size (8),                */
107 0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
108 0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
109 0x09, 0x31,         /*          Usage (Y),                      */
110 0x81, 0x02,         /*          Input (Variable),               */
111 0x09, 0x35,         /*          Usage (Rz),                     */
112 0x81, 0x02,         /*          Input (Variable),               */
113 0xC0,               /*      End Collection,                     */
114 0xA1, 0x02,         /*      Collection (Logical),               */
115 0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
116 0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
117 0x95, 0x07,         /*          Report Count (7),               */
118 0x75, 0x08,         /*          Report Size (8),                */
119 0x09, 0x03,         /*          Usage (?: 3),                   */
120 0x91, 0x02,         /*          Output (Variable),              */
121 0xC0,               /*      End Collection,                     */
122 0xC0                /*  End Collection                          */
123 };
124 
125 static __u8 dfp_rdesc_fixed[] = {
126 0x05, 0x01,         /*  Usage Page (Desktop),                   */
127 0x09, 0x04,         /*  Usage (Joystik),                        */
128 0xA1, 0x01,         /*  Collection (Application),               */
129 0xA1, 0x02,         /*      Collection (Logical),               */
130 0x95, 0x01,         /*          Report Count (1),               */
131 0x75, 0x0E,         /*          Report Size (14),               */
132 0x14,               /*          Logical Minimum (0),            */
133 0x26, 0xFF, 0x3F,   /*          Logical Maximum (16383),        */
134 0x34,               /*          Physical Minimum (0),           */
135 0x46, 0xFF, 0x3F,   /*          Physical Maximum (16383),       */
136 0x09, 0x30,         /*          Usage (X),                      */
137 0x81, 0x02,         /*          Input (Variable),               */
138 0x95, 0x0E,         /*          Report Count (14),              */
139 0x75, 0x01,         /*          Report Size (1),                */
140 0x25, 0x01,         /*          Logical Maximum (1),            */
141 0x45, 0x01,         /*          Physical Maximum (1),           */
142 0x05, 0x09,         /*          Usage Page (Button),            */
143 0x19, 0x01,         /*          Usage Minimum (01h),            */
144 0x29, 0x0E,         /*          Usage Maximum (0Eh),            */
145 0x81, 0x02,         /*          Input (Variable),               */
146 0x05, 0x01,         /*          Usage Page (Desktop),           */
147 0x95, 0x01,         /*          Report Count (1),               */
148 0x75, 0x04,         /*          Report Size (4),                */
149 0x25, 0x07,         /*          Logical Maximum (7),            */
150 0x46, 0x3B, 0x01,   /*          Physical Maximum (315),         */
151 0x65, 0x14,         /*          Unit (Degrees),                 */
152 0x09, 0x39,         /*          Usage (Hat Switch),             */
153 0x81, 0x42,         /*          Input (Variable, Nullstate),    */
154 0x65, 0x00,         /*          Unit,                           */
155 0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
156 0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
157 0x75, 0x08,         /*          Report Size (8),                */
158 0x81, 0x01,         /*          Input (Constant),               */
159 0x09, 0x31,         /*          Usage (Y),                      */
160 0x81, 0x02,         /*          Input (Variable),               */
161 0x09, 0x35,         /*          Usage (Rz),                     */
162 0x81, 0x02,         /*          Input (Variable),               */
163 0x81, 0x01,         /*          Input (Constant),               */
164 0xC0,               /*      End Collection,                     */
165 0xA1, 0x02,         /*      Collection (Logical),               */
166 0x09, 0x02,         /*          Usage (02h),                    */
167 0x95, 0x07,         /*          Report Count (7),               */
168 0x91, 0x02,         /*          Output (Variable),              */
169 0xC0,               /*      End Collection,                     */
170 0xC0                /*  End Collection                          */
171 };
172 
173 static __u8 momo_rdesc_fixed[] = {
174 0x05, 0x01,         /*  Usage Page (Desktop),               */
175 0x09, 0x04,         /*  Usage (Joystik),                    */
176 0xA1, 0x01,         /*  Collection (Application),           */
177 0xA1, 0x02,         /*      Collection (Logical),           */
178 0x95, 0x01,         /*          Report Count (1),           */
179 0x75, 0x0A,         /*          Report Size (10),           */
180 0x15, 0x00,         /*          Logical Minimum (0),        */
181 0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
182 0x35, 0x00,         /*          Physical Minimum (0),       */
183 0x46, 0xFF, 0x03,   /*          Physical Maximum (1023),    */
184 0x09, 0x30,         /*          Usage (X),                  */
185 0x81, 0x02,         /*          Input (Variable),           */
186 0x95, 0x08,         /*          Report Count (8),           */
187 0x75, 0x01,         /*          Report Size (1),            */
188 0x25, 0x01,         /*          Logical Maximum (1),        */
189 0x45, 0x01,         /*          Physical Maximum (1),       */
190 0x05, 0x09,         /*          Usage Page (Button),        */
191 0x19, 0x01,         /*          Usage Minimum (01h),        */
192 0x29, 0x08,         /*          Usage Maximum (08h),        */
193 0x81, 0x02,         /*          Input (Variable),           */
194 0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
195 0x75, 0x0E,         /*          Report Size (14),           */
196 0x95, 0x01,         /*          Report Count (1),           */
197 0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
198 0x46, 0xFF, 0x00,   /*          Physical Maximum (255),     */
199 0x09, 0x00,         /*          Usage (00h),                */
200 0x81, 0x02,         /*          Input (Variable),           */
201 0x05, 0x01,         /*          Usage Page (Desktop),       */
202 0x75, 0x08,         /*          Report Size (8),            */
203 0x09, 0x31,         /*          Usage (Y),                  */
204 0x81, 0x02,         /*          Input (Variable),           */
205 0x09, 0x32,         /*          Usage (Z),                  */
206 0x81, 0x02,         /*          Input (Variable),           */
207 0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
208 0x09, 0x01,         /*          Usage (01h),                */
209 0x81, 0x02,         /*          Input (Variable),           */
210 0xC0,               /*      End Collection,                 */
211 0xA1, 0x02,         /*      Collection (Logical),           */
212 0x09, 0x02,         /*          Usage (02h),                */
213 0x95, 0x07,         /*          Report Count (7),           */
214 0x91, 0x02,         /*          Output (Variable),          */
215 0xC0,               /*      End Collection,                 */
216 0xC0                /*  End Collection                      */
217 };
218 
219 /*
220  * Certain Logitech keyboards send in report #3 keys which are far
221  * above the logical maximum described in descriptor. This extends
222  * the original value of 0x28c of logical maximum to 0x104d
223  */
224 static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
225 		unsigned int *rsize)
226 {
227 	struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
228 	struct usb_device_descriptor *udesc;
229 	__u16 bcdDevice, rev_maj, rev_min;
230 
231 	if ((drv_data->quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 &&
232 			rdesc[84] == 0x8c && rdesc[85] == 0x02) {
233 		hid_info(hdev,
234 			 "fixing up Logitech keyboard report descriptor\n");
235 		rdesc[84] = rdesc[89] = 0x4d;
236 		rdesc[85] = rdesc[90] = 0x10;
237 	}
238 	if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 50 &&
239 			rdesc[32] == 0x81 && rdesc[33] == 0x06 &&
240 			rdesc[49] == 0x81 && rdesc[50] == 0x06) {
241 		hid_info(hdev,
242 			 "fixing up rel/abs in Logitech report descriptor\n");
243 		rdesc[33] = rdesc[50] = 0x02;
244 	}
245 
246 	switch (hdev->product) {
247 
248 	/* Several wheels report as this id when operating in emulation mode. */
249 	case USB_DEVICE_ID_LOGITECH_WHEEL:
250 		udesc = &(hid_to_usb_dev(hdev)->descriptor);
251 		if (!udesc) {
252 			hid_err(hdev, "NULL USB device descriptor\n");
253 			break;
254 		}
255 		bcdDevice = le16_to_cpu(udesc->bcdDevice);
256 		rev_maj = bcdDevice >> 8;
257 		rev_min = bcdDevice & 0xff;
258 
259 		/* Update the report descriptor for only the Driving Force wheel */
260 		if (rev_maj == 1 && rev_min == 2 &&
261 				*rsize == DF_RDESC_ORIG_SIZE) {
262 			hid_info(hdev,
263 				"fixing up Logitech Driving Force report descriptor\n");
264 			rdesc = df_rdesc_fixed;
265 			*rsize = sizeof(df_rdesc_fixed);
266 		}
267 		break;
268 
269 	case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
270 		if (*rsize == MOMO_RDESC_ORIG_SIZE) {
271 			hid_info(hdev,
272 				"fixing up Logitech Momo Force (Red) report descriptor\n");
273 			rdesc = momo_rdesc_fixed;
274 			*rsize = sizeof(momo_rdesc_fixed);
275 		}
276 		break;
277 
278 	case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
279 		if (*rsize == DFP_RDESC_ORIG_SIZE) {
280 			hid_info(hdev,
281 				"fixing up Logitech Driving Force Pro report descriptor\n");
282 			rdesc = dfp_rdesc_fixed;
283 			*rsize = sizeof(dfp_rdesc_fixed);
284 		}
285 		break;
286 
287 	case USB_DEVICE_ID_LOGITECH_WII_WHEEL:
288 		if (*rsize >= 101 && rdesc[41] == 0x95 && rdesc[42] == 0x0B &&
289 				rdesc[47] == 0x05 && rdesc[48] == 0x09) {
290 			hid_info(hdev, "fixing up Logitech Speed Force Wireless report descriptor\n");
291 			rdesc[41] = 0x05;
292 			rdesc[42] = 0x09;
293 			rdesc[47] = 0x95;
294 			rdesc[48] = 0x0B;
295 		}
296 		break;
297 	}
298 
299 	return rdesc;
300 }
301 
302 #define lg_map_key_clear(c)	hid_map_usage_clear(hi, usage, bit, max, \
303 		EV_KEY, (c))
304 
305 static int lg_ultrax_remote_mapping(struct hid_input *hi,
306 		struct hid_usage *usage, unsigned long **bit, int *max)
307 {
308 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
309 		return 0;
310 
311 	set_bit(EV_REP, hi->input->evbit);
312 	switch (usage->hid & HID_USAGE) {
313 	/* Reported on Logitech Ultra X Media Remote */
314 	case 0x004: lg_map_key_clear(KEY_AGAIN);	break;
315 	case 0x00d: lg_map_key_clear(KEY_HOME);		break;
316 	case 0x024: lg_map_key_clear(KEY_SHUFFLE);	break;
317 	case 0x025: lg_map_key_clear(KEY_TV);		break;
318 	case 0x026: lg_map_key_clear(KEY_MENU);		break;
319 	case 0x031: lg_map_key_clear(KEY_AUDIO);	break;
320 	case 0x032: lg_map_key_clear(KEY_TEXT);		break;
321 	case 0x033: lg_map_key_clear(KEY_LAST);		break;
322 	case 0x047: lg_map_key_clear(KEY_MP3);		break;
323 	case 0x048: lg_map_key_clear(KEY_DVD);		break;
324 	case 0x049: lg_map_key_clear(KEY_MEDIA);	break;
325 	case 0x04a: lg_map_key_clear(KEY_VIDEO);	break;
326 	case 0x04b: lg_map_key_clear(KEY_ANGLE);	break;
327 	case 0x04c: lg_map_key_clear(KEY_LANGUAGE);	break;
328 	case 0x04d: lg_map_key_clear(KEY_SUBTITLE);	break;
329 	case 0x051: lg_map_key_clear(KEY_RED);		break;
330 	case 0x052: lg_map_key_clear(KEY_CLOSE);	break;
331 
332 	default:
333 		return 0;
334 	}
335 	return 1;
336 }
337 
338 static int lg_dinovo_mapping(struct hid_input *hi, struct hid_usage *usage,
339 		unsigned long **bit, int *max)
340 {
341 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
342 		return 0;
343 
344 	switch (usage->hid & HID_USAGE) {
345 
346 	case 0x00d: lg_map_key_clear(KEY_MEDIA);	break;
347 	default:
348 		return 0;
349 
350 	}
351 	return 1;
352 }
353 
354 static int lg_wireless_mapping(struct hid_input *hi, struct hid_usage *usage,
355 		unsigned long **bit, int *max)
356 {
357 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
358 		return 0;
359 
360 	switch (usage->hid & HID_USAGE) {
361 	case 0x1001: lg_map_key_clear(KEY_MESSENGER);		break;
362 	case 0x1003: lg_map_key_clear(KEY_SOUND);		break;
363 	case 0x1004: lg_map_key_clear(KEY_VIDEO);		break;
364 	case 0x1005: lg_map_key_clear(KEY_AUDIO);		break;
365 	case 0x100a: lg_map_key_clear(KEY_DOCUMENTS);		break;
366 	/* The following two entries are Playlist 1 and 2 on the MX3200 */
367 	case 0x100f: lg_map_key_clear(KEY_FN_1);		break;
368 	case 0x1010: lg_map_key_clear(KEY_FN_2);		break;
369 	case 0x1011: lg_map_key_clear(KEY_PREVIOUSSONG);	break;
370 	case 0x1012: lg_map_key_clear(KEY_NEXTSONG);		break;
371 	case 0x1013: lg_map_key_clear(KEY_CAMERA);		break;
372 	case 0x1014: lg_map_key_clear(KEY_MESSENGER);		break;
373 	case 0x1015: lg_map_key_clear(KEY_RECORD);		break;
374 	case 0x1016: lg_map_key_clear(KEY_PLAYER);		break;
375 	case 0x1017: lg_map_key_clear(KEY_EJECTCD);		break;
376 	case 0x1018: lg_map_key_clear(KEY_MEDIA);		break;
377 	case 0x1019: lg_map_key_clear(KEY_PROG1);		break;
378 	case 0x101a: lg_map_key_clear(KEY_PROG2);		break;
379 	case 0x101b: lg_map_key_clear(KEY_PROG3);		break;
380 	case 0x101c: lg_map_key_clear(KEY_CYCLEWINDOWS);	break;
381 	case 0x101f: lg_map_key_clear(KEY_ZOOMIN);		break;
382 	case 0x1020: lg_map_key_clear(KEY_ZOOMOUT);		break;
383 	case 0x1021: lg_map_key_clear(KEY_ZOOMRESET);		break;
384 	case 0x1023: lg_map_key_clear(KEY_CLOSE);		break;
385 	case 0x1027: lg_map_key_clear(KEY_MENU);		break;
386 	/* this one is marked as 'Rotate' */
387 	case 0x1028: lg_map_key_clear(KEY_ANGLE);		break;
388 	case 0x1029: lg_map_key_clear(KEY_SHUFFLE);		break;
389 	case 0x102a: lg_map_key_clear(KEY_BACK);		break;
390 	case 0x102b: lg_map_key_clear(KEY_CYCLEWINDOWS);	break;
391 	case 0x102d: lg_map_key_clear(KEY_WWW);			break;
392 	/* The following two are 'Start/answer call' and 'End/reject call'
393 	   on the MX3200 */
394 	case 0x1031: lg_map_key_clear(KEY_OK);			break;
395 	case 0x1032: lg_map_key_clear(KEY_CANCEL);		break;
396 	case 0x1041: lg_map_key_clear(KEY_BATTERY);		break;
397 	case 0x1042: lg_map_key_clear(KEY_WORDPROCESSOR);	break;
398 	case 0x1043: lg_map_key_clear(KEY_SPREADSHEET);		break;
399 	case 0x1044: lg_map_key_clear(KEY_PRESENTATION);	break;
400 	case 0x1045: lg_map_key_clear(KEY_UNDO);		break;
401 	case 0x1046: lg_map_key_clear(KEY_REDO);		break;
402 	case 0x1047: lg_map_key_clear(KEY_PRINT);		break;
403 	case 0x1048: lg_map_key_clear(KEY_SAVE);		break;
404 	case 0x1049: lg_map_key_clear(KEY_PROG1);		break;
405 	case 0x104a: lg_map_key_clear(KEY_PROG2);		break;
406 	case 0x104b: lg_map_key_clear(KEY_PROG3);		break;
407 	case 0x104c: lg_map_key_clear(KEY_PROG4);		break;
408 
409 	default:
410 		return 0;
411 	}
412 	return 1;
413 }
414 
415 static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
416 		struct hid_field *field, struct hid_usage *usage,
417 		unsigned long **bit, int *max)
418 {
419 	/* extended mapping for certain Logitech hardware (Logitech cordless
420 	   desktop LX500) */
421 	static const u8 e_keymap[] = {
422 		  0,216,  0,213,175,156,  0,  0,  0,  0,
423 		144,  0,  0,  0,  0,  0,  0,  0,  0,212,
424 		174,167,152,161,112,  0,  0,  0,154,  0,
425 		  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
426 		  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
427 		  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
428 		  0,  0,  0,  0,  0,183,184,185,186,187,
429 		188,189,190,191,192,193,194,  0,  0,  0
430 	};
431 	struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
432 	unsigned int hid = usage->hid;
433 
434 	if (hdev->product == USB_DEVICE_ID_LOGITECH_RECEIVER &&
435 			lg_ultrax_remote_mapping(hi, usage, bit, max))
436 		return 1;
437 
438 	if (hdev->product == USB_DEVICE_ID_DINOVO_MINI &&
439 			lg_dinovo_mapping(hi, usage, bit, max))
440 		return 1;
441 
442 	if ((drv_data->quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max))
443 		return 1;
444 
445 	if ((hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
446 		return 0;
447 
448 	hid &= HID_USAGE;
449 
450 	/* Special handling for Logitech Cordless Desktop */
451 	if (field->application == HID_GD_MOUSE) {
452 		if ((drv_data->quirks & LG_IGNORE_DOUBLED_WHEEL) &&
453 				(hid == 7 || hid == 8))
454 			return -1;
455 	} else {
456 		if ((drv_data->quirks & LG_EXPANDED_KEYMAP) &&
457 				hid < ARRAY_SIZE(e_keymap) &&
458 				e_keymap[hid] != 0) {
459 			hid_map_usage(hi, usage, bit, max, EV_KEY,
460 					e_keymap[hid]);
461 			return 1;
462 		}
463 	}
464 
465 	return 0;
466 }
467 
468 static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
469 		struct hid_field *field, struct hid_usage *usage,
470 		unsigned long **bit, int *max)
471 {
472 	struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
473 
474 	if ((drv_data->quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY &&
475 			(field->flags & HID_MAIN_ITEM_RELATIVE))
476 		field->flags &= ~HID_MAIN_ITEM_RELATIVE;
477 
478 	if ((drv_data->quirks & LG_DUPLICATE_USAGES) && (usage->type == EV_KEY ||
479 			 usage->type == EV_REL || usage->type == EV_ABS))
480 		clear_bit(usage->code, *bit);
481 
482 	/* Ensure that Logitech wheels are not given a default fuzz/flat value */
483 	if (usage->type == EV_ABS && (usage->code == ABS_X ||
484 			usage->code == ABS_Y || usage->code == ABS_Z ||
485 			usage->code == ABS_RZ)) {
486 		switch (hdev->product) {
487 		case USB_DEVICE_ID_LOGITECH_WHEEL:
488 		case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
489 		case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
490 		case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
491 		case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
492 		case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
493 		case USB_DEVICE_ID_LOGITECH_WII_WHEEL:
494 		case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
495 			field->application = HID_GD_MULTIAXIS;
496 			break;
497 		default:
498 			break;
499 		}
500 	}
501 
502 	return 0;
503 }
504 
505 static int lg_event(struct hid_device *hdev, struct hid_field *field,
506 		struct hid_usage *usage, __s32 value)
507 {
508 	struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
509 
510 	if ((drv_data->quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) {
511 		input_event(field->hidinput->input, usage->type, usage->code,
512 				-value);
513 		return 1;
514 	}
515 	if (drv_data->quirks & LG_FF4) {
516 		return lg4ff_adjust_input_event(hdev, field, usage, value, drv_data);
517 	}
518 
519 	return 0;
520 }
521 
522 static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
523 {
524 	unsigned int connect_mask = HID_CONNECT_DEFAULT;
525 	struct lg_drv_data *drv_data;
526 	int ret;
527 
528 	drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL);
529 	if (!drv_data) {
530 		hid_err(hdev, "Insufficient memory, cannot allocate driver data\n");
531 		return -ENOMEM;
532 	}
533 	drv_data->quirks = id->driver_data;
534 
535 	hid_set_drvdata(hdev, (void *)drv_data);
536 
537 	if (drv_data->quirks & LG_NOGET)
538 		hdev->quirks |= HID_QUIRK_NOGET;
539 
540 	ret = hid_parse(hdev);
541 	if (ret) {
542 		hid_err(hdev, "parse failed\n");
543 		goto err_free;
544 	}
545 
546 	if (drv_data->quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4))
547 		connect_mask &= ~HID_CONNECT_FF;
548 
549 	ret = hid_hw_start(hdev, connect_mask);
550 	if (ret) {
551 		hid_err(hdev, "hw start failed\n");
552 		goto err_free;
553 	}
554 
555 	/* Setup wireless link with Logitech Wii wheel */
556 	if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
557 		unsigned char buf[] = { 0x00, 0xAF,  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
558 
559 		ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
560 
561 		if (ret >= 0) {
562 			/* insert a little delay of 10 jiffies ~ 40ms */
563 			wait_queue_head_t wait;
564 			init_waitqueue_head (&wait);
565 			wait_event_interruptible_timeout(wait, 0, 10);
566 
567 			/* Select random Address */
568 			buf[1] = 0xB2;
569 			get_random_bytes(&buf[2], 2);
570 
571 			ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
572 		}
573 	}
574 
575 	if (drv_data->quirks & LG_FF)
576 		lgff_init(hdev);
577 	if (drv_data->quirks & LG_FF2)
578 		lg2ff_init(hdev);
579 	if (drv_data->quirks & LG_FF3)
580 		lg3ff_init(hdev);
581 	if (drv_data->quirks & LG_FF4)
582 		lg4ff_init(hdev);
583 
584 	return 0;
585 err_free:
586 	kfree(drv_data);
587 	return ret;
588 }
589 
590 static void lg_remove(struct hid_device *hdev)
591 {
592 	struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
593 	if (drv_data->quirks & LG_FF4)
594 		lg4ff_deinit(hdev);
595 
596 	hid_hw_stop(hdev);
597 	kfree(drv_data);
598 }
599 
600 static const struct hid_device_id lg_devices[] = {
601 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
602 		.driver_data = LG_RDESC | LG_WIRELESS },
603 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER),
604 		.driver_data = LG_RDESC | LG_WIRELESS },
605 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2),
606 		.driver_data = LG_RDESC | LG_WIRELESS },
607 
608 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER),
609 		.driver_data = LG_BAD_RELATIVE_KEYS },
610 
611 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP),
612 		.driver_data = LG_DUPLICATE_USAGES },
613 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE),
614 		.driver_data = LG_DUPLICATE_USAGES },
615 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI),
616 		.driver_data = LG_DUPLICATE_USAGES },
617 
618 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD),
619 		.driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
620 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500),
621 		.driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
622 
623 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D),
624 		.driver_data = LG_NOGET },
625 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL),
626 		.driver_data = LG_NOGET | LG_FF4 },
627 
628 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD),
629 		.driver_data = LG_FF2 },
630 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD),
631 		.driver_data = LG_FF },
632 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2),
633 		.driver_data = LG_FF },
634 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D),
635 		.driver_data = LG_FF },
636 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO),
637 		.driver_data = LG_FF },
638 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL),
639 		.driver_data = LG_NOGET | LG_FF4 },
640 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2),
641 		.driver_data = LG_FF4 },
642 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
643 		.driver_data = LG_FF4 },
644 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL),
645 		.driver_data = LG_FF4 },
646 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL),
647 		.driver_data = LG_FF4 },
648 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL),
649 		.driver_data = LG_NOGET | LG_FF4 },
650 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL),
651 		.driver_data = LG_FF4 },
652 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG),
653 		.driver_data = LG_FF },
654 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
655 		.driver_data = LG_FF2 },
656 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940),
657 		.driver_data = LG_FF3 },
658 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR),
659 		.driver_data = LG_RDESC_REL_ABS },
660 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER),
661 		.driver_data = LG_RDESC_REL_ABS },
662 	{ }
663 };
664 
665 MODULE_DEVICE_TABLE(hid, lg_devices);
666 
667 static struct hid_driver lg_driver = {
668 	.name = "logitech",
669 	.id_table = lg_devices,
670 	.report_fixup = lg_report_fixup,
671 	.input_mapping = lg_input_mapping,
672 	.input_mapped = lg_input_mapped,
673 	.event = lg_event,
674 	.probe = lg_probe,
675 	.remove = lg_remove,
676 };
677 module_hid_driver(lg_driver);
678 
679 MODULE_LICENSE("GPL");
680