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