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