xref: /openbmc/linux/drivers/hid/hid-lg4ff.c (revision 84c43674)
1 /*
2  *  Force feedback support for Logitech Gaming Wheels
3  *
4  *  Including G27, G25, DFP, DFGT, FFEX, Momo, Momo2 &
5  *  Speed Force Wireless (WiiWheel)
6  *
7  *  Copyright (c) 2010 Simon Wood <simon@mungewell.org>
8  */
9 
10 /*
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24  */
25 
26 
27 #include <linux/input.h>
28 #include <linux/usb.h>
29 #include <linux/hid.h>
30 
31 #include "usbhid/usbhid.h"
32 #include "hid-lg.h"
33 #include "hid-lg4ff.h"
34 #include "hid-ids.h"
35 
36 #define LG4FF_MMODE_IS_MULTIMODE 0
37 #define LG4FF_MMODE_SWITCHED 1
38 #define LG4FF_MMODE_NOT_MULTIMODE 2
39 
40 #define LG4FF_MODE_NATIVE_IDX 0
41 #define LG4FF_MODE_DFEX_IDX 1
42 #define LG4FF_MODE_DFP_IDX 2
43 #define LG4FF_MODE_G25_IDX 3
44 #define LG4FF_MODE_DFGT_IDX 4
45 #define LG4FF_MODE_G27_IDX 5
46 #define LG4FF_MODE_G29_IDX 6
47 #define LG4FF_MODE_MAX_IDX 7
48 
49 #define LG4FF_MODE_NATIVE BIT(LG4FF_MODE_NATIVE_IDX)
50 #define LG4FF_MODE_DFEX BIT(LG4FF_MODE_DFEX_IDX)
51 #define LG4FF_MODE_DFP BIT(LG4FF_MODE_DFP_IDX)
52 #define LG4FF_MODE_G25 BIT(LG4FF_MODE_G25_IDX)
53 #define LG4FF_MODE_DFGT BIT(LG4FF_MODE_DFGT_IDX)
54 #define LG4FF_MODE_G27 BIT(LG4FF_MODE_G27_IDX)
55 #define LG4FF_MODE_G29 BIT(LG4FF_MODE_G29_IDX)
56 
57 #define LG4FF_DFEX_TAG "DF-EX"
58 #define LG4FF_DFEX_NAME "Driving Force / Formula EX"
59 #define LG4FF_DFP_TAG "DFP"
60 #define LG4FF_DFP_NAME "Driving Force Pro"
61 #define LG4FF_G25_TAG "G25"
62 #define LG4FF_G25_NAME "G25 Racing Wheel"
63 #define LG4FF_G27_TAG "G27"
64 #define LG4FF_G27_NAME "G27 Racing Wheel"
65 #define LG4FF_G29_TAG "G29"
66 #define LG4FF_G29_NAME "G29 Racing Wheel"
67 #define LG4FF_DFGT_TAG "DFGT"
68 #define LG4FF_DFGT_NAME "Driving Force GT"
69 
70 #define LG4FF_FFEX_REV_MAJ 0x21
71 #define LG4FF_FFEX_REV_MIN 0x00
72 
73 static void lg4ff_set_range_dfp(struct hid_device *hid, u16 range);
74 static void lg4ff_set_range_g25(struct hid_device *hid, u16 range);
75 
76 struct lg4ff_wheel_data {
77 	const u32 product_id;
78 	u16 combine;
79 	u16 range;
80 	const u16 min_range;
81 	const u16 max_range;
82 #ifdef CONFIG_LEDS_CLASS
83 	u8  led_state;
84 	struct led_classdev *led[5];
85 #endif
86 	const u32 alternate_modes;
87 	const char * const real_tag;
88 	const char * const real_name;
89 	const u16 real_product_id;
90 
91 	void (*set_range)(struct hid_device *hid, u16 range);
92 };
93 
94 struct lg4ff_device_entry {
95 	spinlock_t report_lock; /* Protect output HID report */
96 	struct hid_report *report;
97 	struct lg4ff_wheel_data wdata;
98 };
99 
100 static const signed short lg4ff_wheel_effects[] = {
101 	FF_CONSTANT,
102 	FF_AUTOCENTER,
103 	-1
104 };
105 
106 struct lg4ff_wheel {
107 	const u32 product_id;
108 	const signed short *ff_effects;
109 	const u16 min_range;
110 	const u16 max_range;
111 	void (*set_range)(struct hid_device *hid, u16 range);
112 };
113 
114 struct lg4ff_compat_mode_switch {
115 	const u8 cmd_count;	/* Number of commands to send */
116 	const u8 cmd[];
117 };
118 
119 struct lg4ff_wheel_ident_info {
120 	const u32 modes;
121 	const u16 mask;
122 	const u16 result;
123 	const u16 real_product_id;
124 };
125 
126 struct lg4ff_multimode_wheel {
127 	const u16 product_id;
128 	const u32 alternate_modes;
129 	const char *real_tag;
130 	const char *real_name;
131 };
132 
133 struct lg4ff_alternate_mode {
134 	const u16 product_id;
135 	const char *tag;
136 	const char *name;
137 };
138 
139 static const struct lg4ff_wheel lg4ff_devices[] = {
140 	{USB_DEVICE_ID_LOGITECH_WINGMAN_FFG, lg4ff_wheel_effects, 40, 180, NULL},
141 	{USB_DEVICE_ID_LOGITECH_WHEEL,       lg4ff_wheel_effects, 40, 270, NULL},
142 	{USB_DEVICE_ID_LOGITECH_MOMO_WHEEL,  lg4ff_wheel_effects, 40, 270, NULL},
143 	{USB_DEVICE_ID_LOGITECH_DFP_WHEEL,   lg4ff_wheel_effects, 40, 900, lg4ff_set_range_dfp},
144 	{USB_DEVICE_ID_LOGITECH_G25_WHEEL,   lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25},
145 	{USB_DEVICE_ID_LOGITECH_DFGT_WHEEL,  lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25},
146 	{USB_DEVICE_ID_LOGITECH_G27_WHEEL,   lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25},
147 	{USB_DEVICE_ID_LOGITECH_G29_WHEEL,   lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25},
148 	{USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2, lg4ff_wheel_effects, 40, 270, NULL},
149 	{USB_DEVICE_ID_LOGITECH_WII_WHEEL,   lg4ff_wheel_effects, 40, 270, NULL}
150 };
151 
152 static const struct lg4ff_multimode_wheel lg4ff_multimode_wheels[] = {
153 	{USB_DEVICE_ID_LOGITECH_DFP_WHEEL,
154 	 LG4FF_MODE_NATIVE | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
155 	 LG4FF_DFP_TAG, LG4FF_DFP_NAME},
156 	{USB_DEVICE_ID_LOGITECH_G25_WHEEL,
157 	 LG4FF_MODE_NATIVE | LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
158 	 LG4FF_G25_TAG, LG4FF_G25_NAME},
159 	{USB_DEVICE_ID_LOGITECH_DFGT_WHEEL,
160 	 LG4FF_MODE_NATIVE | LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
161 	 LG4FF_DFGT_TAG, LG4FF_DFGT_NAME},
162 	{USB_DEVICE_ID_LOGITECH_G27_WHEEL,
163 	 LG4FF_MODE_NATIVE | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
164 	 LG4FF_G27_TAG, LG4FF_G27_NAME},
165 	{USB_DEVICE_ID_LOGITECH_G29_WHEEL,
166 	 LG4FF_MODE_NATIVE | LG4FF_MODE_G29 | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
167 	 LG4FF_G29_TAG, LG4FF_G29_NAME},
168 };
169 
170 static const struct lg4ff_alternate_mode lg4ff_alternate_modes[] = {
171 	[LG4FF_MODE_NATIVE_IDX] = {0, "native", ""},
172 	[LG4FF_MODE_DFEX_IDX] = {USB_DEVICE_ID_LOGITECH_WHEEL, LG4FF_DFEX_TAG, LG4FF_DFEX_NAME},
173 	[LG4FF_MODE_DFP_IDX] = {USB_DEVICE_ID_LOGITECH_DFP_WHEEL, LG4FF_DFP_TAG, LG4FF_DFP_NAME},
174 	[LG4FF_MODE_G25_IDX] = {USB_DEVICE_ID_LOGITECH_G25_WHEEL, LG4FF_G25_TAG, LG4FF_G25_NAME},
175 	[LG4FF_MODE_DFGT_IDX] = {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, LG4FF_DFGT_TAG, LG4FF_DFGT_NAME},
176 	[LG4FF_MODE_G27_IDX] = {USB_DEVICE_ID_LOGITECH_G27_WHEEL, LG4FF_G27_TAG, LG4FF_G27_NAME},
177 	[LG4FF_MODE_G29_IDX] = {USB_DEVICE_ID_LOGITECH_G29_WHEEL, LG4FF_G29_TAG, LG4FF_G29_NAME},
178 };
179 
180 /* Multimode wheel identificators */
181 static const struct lg4ff_wheel_ident_info lg4ff_dfp_ident_info = {
182 	LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
183 	0xf000,
184 	0x1000,
185 	USB_DEVICE_ID_LOGITECH_DFP_WHEEL
186 };
187 
188 static const struct lg4ff_wheel_ident_info lg4ff_g25_ident_info = {
189 	LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
190 	0xff00,
191 	0x1200,
192 	USB_DEVICE_ID_LOGITECH_G25_WHEEL
193 };
194 
195 static const struct lg4ff_wheel_ident_info lg4ff_g27_ident_info = {
196 	LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
197 	0xfff0,
198 	0x1230,
199 	USB_DEVICE_ID_LOGITECH_G27_WHEEL
200 };
201 
202 static const struct lg4ff_wheel_ident_info lg4ff_dfgt_ident_info = {
203 	LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
204 	0xff00,
205 	0x1300,
206 	USB_DEVICE_ID_LOGITECH_DFGT_WHEEL
207 };
208 
209 static const struct lg4ff_wheel_ident_info lg4ff_g29_ident_info = {
210 	LG4FF_MODE_G29 | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
211 	0xfff8,
212 	0x1350,
213 	USB_DEVICE_ID_LOGITECH_G29_WHEEL
214 };
215 
216 static const struct lg4ff_wheel_ident_info lg4ff_g29_ident_info2 = {
217 	LG4FF_MODE_G29 | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
218 	0xff00,
219 	0x8900,
220 	USB_DEVICE_ID_LOGITECH_G29_WHEEL
221 };
222 
223 /* Multimode wheel identification checklists */
224 static const struct lg4ff_wheel_ident_info *lg4ff_main_checklist[] = {
225 	&lg4ff_g29_ident_info,
226 	&lg4ff_g29_ident_info2,
227 	&lg4ff_dfgt_ident_info,
228 	&lg4ff_g27_ident_info,
229 	&lg4ff_g25_ident_info,
230 	&lg4ff_dfp_ident_info
231 };
232 
233 /* Compatibility mode switching commands */
234 /* EXT_CMD9 - Understood by G27 and DFGT */
235 static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_dfex = {
236 	2,
237 	{0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,	/* Revert mode upon USB reset */
238 	 0xf8, 0x09, 0x00, 0x01, 0x00, 0x00, 0x00}	/* Switch mode to DF-EX with detach */
239 };
240 
241 static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_dfp = {
242 	2,
243 	{0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,	/* Revert mode upon USB reset */
244 	 0xf8, 0x09, 0x01, 0x01, 0x00, 0x00, 0x00}	/* Switch mode to DFP with detach */
245 };
246 
247 static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_g25 = {
248 	2,
249 	{0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,	/* Revert mode upon USB reset */
250 	 0xf8, 0x09, 0x02, 0x01, 0x00, 0x00, 0x00}	/* Switch mode to G25 with detach */
251 };
252 
253 static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_dfgt = {
254 	2,
255 	{0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,	/* Revert mode upon USB reset */
256 	 0xf8, 0x09, 0x03, 0x01, 0x00, 0x00, 0x00}	/* Switch mode to DFGT with detach */
257 };
258 
259 static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_g27 = {
260 	2,
261 	{0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,	/* Revert mode upon USB reset */
262 	 0xf8, 0x09, 0x04, 0x01, 0x00, 0x00, 0x00}	/* Switch mode to G27 with detach */
263 };
264 
265 static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_g29 = {
266 	2,
267 	{0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,	/* Revert mode upon USB reset */
268 	 0xf8, 0x09, 0x05, 0x01, 0x01, 0x00, 0x00}	/* Switch mode to G29 with detach */
269 };
270 
271 /* EXT_CMD1 - Understood by DFP, G25, G27 and DFGT */
272 static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext01_dfp = {
273 	1,
274 	{0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}
275 };
276 
277 /* EXT_CMD16 - Understood by G25 and G27 */
278 static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext16_g25 = {
279 	1,
280 	{0xf8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}
281 };
282 
283 /* Recalculates X axis value accordingly to currently selected range */
284 static s32 lg4ff_adjust_dfp_x_axis(s32 value, u16 range)
285 {
286 	u16 max_range;
287 	s32 new_value;
288 
289 	if (range == 900)
290 		return value;
291 	else if (range == 200)
292 		return value;
293 	else if (range < 200)
294 		max_range = 200;
295 	else
296 		max_range = 900;
297 
298 	new_value = 8192 + mult_frac(value - 8192, max_range, range);
299 	if (new_value < 0)
300 		return 0;
301 	else if (new_value > 16383)
302 		return 16383;
303 	else
304 		return new_value;
305 }
306 
307 int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field,
308 			     struct hid_usage *usage, s32 value, struct lg_drv_data *drv_data)
309 {
310 	struct lg4ff_device_entry *entry = drv_data->device_props;
311 	s32 new_value = 0;
312 
313 	if (!entry) {
314 		hid_err(hid, "Device properties not found");
315 		return 0;
316 	}
317 
318 	switch (entry->wdata.product_id) {
319 	case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
320 		switch (usage->code) {
321 		case ABS_X:
322 			new_value = lg4ff_adjust_dfp_x_axis(value, entry->wdata.range);
323 			input_event(field->hidinput->input, usage->type, usage->code, new_value);
324 			return 1;
325 		default:
326 			return 0;
327 		}
328 	default:
329 		return 0;
330 	}
331 }
332 
333 int lg4ff_raw_event(struct hid_device *hdev, struct hid_report *report,
334 		u8 *rd, int size, struct lg_drv_data *drv_data)
335 {
336 	int offset;
337 	struct lg4ff_device_entry *entry = drv_data->device_props;
338 
339 	if (!entry)
340 		return 0;
341 
342 	/* adjust HID report present combined pedals data */
343 	if (entry->wdata.combine) {
344 		switch (entry->wdata.product_id) {
345 		case USB_DEVICE_ID_LOGITECH_WHEEL:
346 			rd[5] = rd[3];
347 			rd[6] = 0x7F;
348 			return 1;
349 		case USB_DEVICE_ID_LOGITECH_WINGMAN_FFG:
350 		case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
351 		case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
352 			rd[4] = rd[3];
353 			rd[5] = 0x7F;
354 			return 1;
355 		case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
356 			rd[5] = rd[4];
357 			rd[6] = 0x7F;
358 			return 1;
359 		case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
360 		case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
361 			offset = 5;
362 			break;
363 		case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
364 		case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
365 			offset = 6;
366 			break;
367 		case USB_DEVICE_ID_LOGITECH_WII_WHEEL:
368 			offset = 3;
369 			break;
370 		default:
371 			return 0;
372 		}
373 
374 		/* Compute a combined axis when wheel does not supply it */
375 		rd[offset] = (0xFF + rd[offset] - rd[offset+1]) >> 1;
376 		rd[offset+1] = 0x7F;
377 		return 1;
378 	}
379 
380 	return 0;
381 }
382 
383 static void lg4ff_init_wheel_data(struct lg4ff_wheel_data * const wdata, const struct lg4ff_wheel *wheel,
384 				  const struct lg4ff_multimode_wheel *mmode_wheel,
385 				  const u16 real_product_id)
386 {
387 	u32 alternate_modes = 0;
388 	const char *real_tag = NULL;
389 	const char *real_name = NULL;
390 
391 	if (mmode_wheel) {
392 		alternate_modes = mmode_wheel->alternate_modes;
393 		real_tag = mmode_wheel->real_tag;
394 		real_name = mmode_wheel->real_name;
395 	}
396 
397 	{
398 		struct lg4ff_wheel_data t_wdata =  { .product_id = wheel->product_id,
399 						     .real_product_id = real_product_id,
400 						     .combine = 0,
401 						     .min_range = wheel->min_range,
402 						     .max_range = wheel->max_range,
403 						     .set_range = wheel->set_range,
404 						     .alternate_modes = alternate_modes,
405 						     .real_tag = real_tag,
406 						     .real_name = real_name };
407 
408 		memcpy(wdata, &t_wdata, sizeof(t_wdata));
409 	}
410 }
411 
412 static int lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
413 {
414 	struct hid_device *hid = input_get_drvdata(dev);
415 	struct lg4ff_device_entry *entry;
416 	struct lg_drv_data *drv_data;
417 	unsigned long flags;
418 	s32 *value;
419 	int x;
420 
421 	drv_data = hid_get_drvdata(hid);
422 	if (!drv_data) {
423 		hid_err(hid, "Private driver data not found!\n");
424 		return -EINVAL;
425 	}
426 
427 	entry = drv_data->device_props;
428 	if (!entry) {
429 		hid_err(hid, "Device properties not found!\n");
430 		return -EINVAL;
431 	}
432 	value = entry->report->field[0]->value;
433 
434 #define CLAMP(x) do { if (x < 0) x = 0; else if (x > 0xff) x = 0xff; } while (0)
435 
436 	switch (effect->type) {
437 	case FF_CONSTANT:
438 		x = effect->u.ramp.start_level + 0x80;	/* 0x80 is no force */
439 		CLAMP(x);
440 
441 		spin_lock_irqsave(&entry->report_lock, flags);
442 		if (x == 0x80) {
443 			/* De-activate force in slot-1*/
444 			value[0] = 0x13;
445 			value[1] = 0x00;
446 			value[2] = 0x00;
447 			value[3] = 0x00;
448 			value[4] = 0x00;
449 			value[5] = 0x00;
450 			value[6] = 0x00;
451 
452 			hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT);
453 			spin_unlock_irqrestore(&entry->report_lock, flags);
454 			return 0;
455 		}
456 
457 		value[0] = 0x11;	/* Slot 1 */
458 		value[1] = 0x08;
459 		value[2] = x;
460 		value[3] = 0x80;
461 		value[4] = 0x00;
462 		value[5] = 0x00;
463 		value[6] = 0x00;
464 
465 		hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT);
466 		spin_unlock_irqrestore(&entry->report_lock, flags);
467 		break;
468 	}
469 	return 0;
470 }
471 
472 /* Sends default autocentering command compatible with
473  * all wheels except Formula Force EX */
474 static void lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude)
475 {
476 	struct hid_device *hid = input_get_drvdata(dev);
477 	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
478 	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
479 	s32 *value = report->field[0]->value;
480 	u32 expand_a, expand_b;
481 	struct lg4ff_device_entry *entry;
482 	struct lg_drv_data *drv_data;
483 	unsigned long flags;
484 
485 	drv_data = hid_get_drvdata(hid);
486 	if (!drv_data) {
487 		hid_err(hid, "Private driver data not found!\n");
488 		return;
489 	}
490 
491 	entry = drv_data->device_props;
492 	if (!entry) {
493 		hid_err(hid, "Device properties not found!\n");
494 		return;
495 	}
496 	value = entry->report->field[0]->value;
497 
498 	/* De-activate Auto-Center */
499 	spin_lock_irqsave(&entry->report_lock, flags);
500 	if (magnitude == 0) {
501 		value[0] = 0xf5;
502 		value[1] = 0x00;
503 		value[2] = 0x00;
504 		value[3] = 0x00;
505 		value[4] = 0x00;
506 		value[5] = 0x00;
507 		value[6] = 0x00;
508 
509 		hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT);
510 		spin_unlock_irqrestore(&entry->report_lock, flags);
511 		return;
512 	}
513 
514 	if (magnitude <= 0xaaaa) {
515 		expand_a = 0x0c * magnitude;
516 		expand_b = 0x80 * magnitude;
517 	} else {
518 		expand_a = (0x0c * 0xaaaa) + 0x06 * (magnitude - 0xaaaa);
519 		expand_b = (0x80 * 0xaaaa) + 0xff * (magnitude - 0xaaaa);
520 	}
521 
522 	/* Adjust for non-MOMO wheels */
523 	switch (entry->wdata.product_id) {
524 	case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
525 	case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
526 		break;
527 	default:
528 		expand_a = expand_a >> 1;
529 		break;
530 	}
531 
532 	value[0] = 0xfe;
533 	value[1] = 0x0d;
534 	value[2] = expand_a / 0xaaaa;
535 	value[3] = expand_a / 0xaaaa;
536 	value[4] = expand_b / 0xaaaa;
537 	value[5] = 0x00;
538 	value[6] = 0x00;
539 
540 	hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT);
541 
542 	/* Activate Auto-Center */
543 	value[0] = 0x14;
544 	value[1] = 0x00;
545 	value[2] = 0x00;
546 	value[3] = 0x00;
547 	value[4] = 0x00;
548 	value[5] = 0x00;
549 	value[6] = 0x00;
550 
551 	hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT);
552 	spin_unlock_irqrestore(&entry->report_lock, flags);
553 }
554 
555 /* Sends autocentering command compatible with Formula Force EX */
556 static void lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude)
557 {
558 	struct hid_device *hid = input_get_drvdata(dev);
559 	struct lg4ff_device_entry *entry;
560 	struct lg_drv_data *drv_data;
561 	unsigned long flags;
562 	s32 *value;
563 	magnitude = magnitude * 90 / 65535;
564 
565 	drv_data = hid_get_drvdata(hid);
566 	if (!drv_data) {
567 		hid_err(hid, "Private driver data not found!\n");
568 		return;
569 	}
570 
571 	entry = drv_data->device_props;
572 	if (!entry) {
573 		hid_err(hid, "Device properties not found!\n");
574 		return;
575 	}
576 	value = entry->report->field[0]->value;
577 
578 	spin_lock_irqsave(&entry->report_lock, flags);
579 	value[0] = 0xfe;
580 	value[1] = 0x03;
581 	value[2] = magnitude >> 14;
582 	value[3] = magnitude >> 14;
583 	value[4] = magnitude;
584 	value[5] = 0x00;
585 	value[6] = 0x00;
586 
587 	hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT);
588 	spin_unlock_irqrestore(&entry->report_lock, flags);
589 }
590 
591 /* Sends command to set range compatible with G25/G27/Driving Force GT */
592 static void lg4ff_set_range_g25(struct hid_device *hid, u16 range)
593 {
594 	struct lg4ff_device_entry *entry;
595 	struct lg_drv_data *drv_data;
596 	unsigned long flags;
597 	s32 *value;
598 
599 	drv_data = hid_get_drvdata(hid);
600 	if (!drv_data) {
601 		hid_err(hid, "Private driver data not found!\n");
602 		return;
603 	}
604 
605 	entry = drv_data->device_props;
606 	if (!entry) {
607 		hid_err(hid, "Device properties not found!\n");
608 		return;
609 	}
610 	value = entry->report->field[0]->value;
611 	dbg_hid("G25/G27/DFGT: setting range to %u\n", range);
612 
613 	spin_lock_irqsave(&entry->report_lock, flags);
614 	value[0] = 0xf8;
615 	value[1] = 0x81;
616 	value[2] = range & 0x00ff;
617 	value[3] = (range & 0xff00) >> 8;
618 	value[4] = 0x00;
619 	value[5] = 0x00;
620 	value[6] = 0x00;
621 
622 	hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT);
623 	spin_unlock_irqrestore(&entry->report_lock, flags);
624 }
625 
626 /* Sends commands to set range compatible with Driving Force Pro wheel */
627 static void lg4ff_set_range_dfp(struct hid_device *hid, u16 range)
628 {
629 	struct lg4ff_device_entry *entry;
630 	struct lg_drv_data *drv_data;
631 	unsigned long flags;
632 	int start_left, start_right, full_range;
633 	s32 *value;
634 
635 	drv_data = hid_get_drvdata(hid);
636 	if (!drv_data) {
637 		hid_err(hid, "Private driver data not found!\n");
638 		return;
639 	}
640 
641 	entry = drv_data->device_props;
642 	if (!entry) {
643 		hid_err(hid, "Device properties not found!\n");
644 		return;
645 	}
646 	value = entry->report->field[0]->value;
647 	dbg_hid("Driving Force Pro: setting range to %u\n", range);
648 
649 	/* Prepare "coarse" limit command */
650 	spin_lock_irqsave(&entry->report_lock, flags);
651 	value[0] = 0xf8;
652 	value[1] = 0x00;	/* Set later */
653 	value[2] = 0x00;
654 	value[3] = 0x00;
655 	value[4] = 0x00;
656 	value[5] = 0x00;
657 	value[6] = 0x00;
658 
659 	if (range > 200) {
660 		value[1] = 0x03;
661 		full_range = 900;
662 	} else {
663 		value[1] = 0x02;
664 		full_range = 200;
665 	}
666 	hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT);
667 
668 	/* Prepare "fine" limit command */
669 	value[0] = 0x81;
670 	value[1] = 0x0b;
671 	value[2] = 0x00;
672 	value[3] = 0x00;
673 	value[4] = 0x00;
674 	value[5] = 0x00;
675 	value[6] = 0x00;
676 
677 	if (range == 200 || range == 900) {	/* Do not apply any fine limit */
678 		hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT);
679 		spin_unlock_irqrestore(&entry->report_lock, flags);
680 		return;
681 	}
682 
683 	/* Construct fine limit command */
684 	start_left = (((full_range - range + 1) * 2047) / full_range);
685 	start_right = 0xfff - start_left;
686 
687 	value[2] = start_left >> 4;
688 	value[3] = start_right >> 4;
689 	value[4] = 0xff;
690 	value[5] = (start_right & 0xe) << 4 | (start_left & 0xe);
691 	value[6] = 0xff;
692 
693 	hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT);
694 	spin_unlock_irqrestore(&entry->report_lock, flags);
695 }
696 
697 static const struct lg4ff_compat_mode_switch *lg4ff_get_mode_switch_command(const u16 real_product_id, const u16 target_product_id)
698 {
699 	switch (real_product_id) {
700 	case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
701 		switch (target_product_id) {
702 		case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
703 			return &lg4ff_mode_switch_ext01_dfp;
704 		/* DFP can only be switched to its native mode */
705 		default:
706 			return NULL;
707 		}
708 		break;
709 	case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
710 		switch (target_product_id) {
711 		case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
712 			return &lg4ff_mode_switch_ext01_dfp;
713 		case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
714 			return &lg4ff_mode_switch_ext16_g25;
715 		/* G25 can only be switched to DFP mode or its native mode */
716 		default:
717 			return NULL;
718 		}
719 		break;
720 	case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
721 		switch (target_product_id) {
722 		case USB_DEVICE_ID_LOGITECH_WHEEL:
723 			return &lg4ff_mode_switch_ext09_dfex;
724 		case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
725 			return &lg4ff_mode_switch_ext09_dfp;
726 		case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
727 			return &lg4ff_mode_switch_ext09_g25;
728 		case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
729 			return &lg4ff_mode_switch_ext09_g27;
730 		/* G27 can only be switched to DF-EX, DFP, G25 or its native mode */
731 		default:
732 			return NULL;
733 		}
734 		break;
735 	case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
736 		switch (target_product_id) {
737 		case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
738 			return &lg4ff_mode_switch_ext09_dfp;
739 		case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
740 			return &lg4ff_mode_switch_ext09_dfgt;
741 		case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
742 			return &lg4ff_mode_switch_ext09_g25;
743 		case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
744 			return &lg4ff_mode_switch_ext09_g27;
745 		case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
746 			return &lg4ff_mode_switch_ext09_g29;
747 		/* G29 can only be switched to DF-EX, DFP, DFGT, G25, G27 or its native mode */
748 		default:
749 			return NULL;
750 		}
751 		break;
752 	case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
753 		switch (target_product_id) {
754 		case USB_DEVICE_ID_LOGITECH_WHEEL:
755 			return &lg4ff_mode_switch_ext09_dfex;
756 		case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
757 			return &lg4ff_mode_switch_ext09_dfp;
758 		case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
759 			return &lg4ff_mode_switch_ext09_dfgt;
760 		/* DFGT can only be switched to DF-EX, DFP or its native mode */
761 		default:
762 			return NULL;
763 		}
764 		break;
765 	/* No other wheels have multiple modes */
766 	default:
767 		return NULL;
768 	}
769 }
770 
771 static int lg4ff_switch_compatibility_mode(struct hid_device *hid, const struct lg4ff_compat_mode_switch *s)
772 {
773 	struct lg4ff_device_entry *entry;
774 	struct lg_drv_data *drv_data;
775 	unsigned long flags;
776 	s32 *value;
777 	u8 i;
778 
779 	drv_data = hid_get_drvdata(hid);
780 	if (!drv_data) {
781 		hid_err(hid, "Private driver data not found!\n");
782 		return -EINVAL;
783 	}
784 
785 	entry = drv_data->device_props;
786 	if (!entry) {
787 		hid_err(hid, "Device properties not found!\n");
788 		return -EINVAL;
789 	}
790 	value = entry->report->field[0]->value;
791 
792 	spin_lock_irqsave(&entry->report_lock, flags);
793 	for (i = 0; i < s->cmd_count; i++) {
794 		u8 j;
795 
796 		for (j = 0; j < 7; j++)
797 			value[j] = s->cmd[j + (7*i)];
798 
799 		hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT);
800 	}
801 	spin_unlock_irqrestore(&entry->report_lock, flags);
802 	hid_hw_wait(hid);
803 	return 0;
804 }
805 
806 static ssize_t lg4ff_alternate_modes_show(struct device *dev, struct device_attribute *attr, char *buf)
807 {
808 	struct hid_device *hid = to_hid_device(dev);
809 	struct lg4ff_device_entry *entry;
810 	struct lg_drv_data *drv_data;
811 	ssize_t count = 0;
812 	int i;
813 
814 	drv_data = hid_get_drvdata(hid);
815 	if (!drv_data) {
816 		hid_err(hid, "Private driver data not found!\n");
817 		return 0;
818 	}
819 
820 	entry = drv_data->device_props;
821 	if (!entry) {
822 		hid_err(hid, "Device properties not found!\n");
823 		return 0;
824 	}
825 
826 	if (!entry->wdata.real_name) {
827 		hid_err(hid, "NULL pointer to string\n");
828 		return 0;
829 	}
830 
831 	for (i = 0; i < LG4FF_MODE_MAX_IDX; i++) {
832 		if (entry->wdata.alternate_modes & BIT(i)) {
833 			/* Print tag and full name */
834 			count += scnprintf(buf + count, PAGE_SIZE - count, "%s: %s",
835 					   lg4ff_alternate_modes[i].tag,
836 					   !lg4ff_alternate_modes[i].product_id ? entry->wdata.real_name : lg4ff_alternate_modes[i].name);
837 			if (count >= PAGE_SIZE - 1)
838 				return count;
839 
840 			/* Mark the currently active mode with an asterisk */
841 			if (lg4ff_alternate_modes[i].product_id == entry->wdata.product_id ||
842 			    (lg4ff_alternate_modes[i].product_id == 0 && entry->wdata.product_id == entry->wdata.real_product_id))
843 				count += scnprintf(buf + count, PAGE_SIZE - count, " *\n");
844 			else
845 				count += scnprintf(buf + count, PAGE_SIZE - count, "\n");
846 
847 			if (count >= PAGE_SIZE - 1)
848 				return count;
849 		}
850 	}
851 
852 	return count;
853 }
854 
855 static ssize_t lg4ff_alternate_modes_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
856 {
857 	struct hid_device *hid = to_hid_device(dev);
858 	struct lg4ff_device_entry *entry;
859 	struct lg_drv_data *drv_data;
860 	const struct lg4ff_compat_mode_switch *s;
861 	u16 target_product_id = 0;
862 	int i, ret;
863 	char *lbuf;
864 
865 	drv_data = hid_get_drvdata(hid);
866 	if (!drv_data) {
867 		hid_err(hid, "Private driver data not found!\n");
868 		return -EINVAL;
869 	}
870 
871 	entry = drv_data->device_props;
872 	if (!entry) {
873 		hid_err(hid, "Device properties not found!\n");
874 		return -EINVAL;
875 	}
876 
877 	/* Allow \n at the end of the input parameter */
878 	lbuf = kasprintf(GFP_KERNEL, "%s", buf);
879 	if (!lbuf)
880 		return -ENOMEM;
881 
882 	i = strlen(lbuf);
883 	if (lbuf[i-1] == '\n') {
884 		if (i == 1) {
885 			kfree(lbuf);
886 			return -EINVAL;
887 		}
888 		lbuf[i-1] = '\0';
889 	}
890 
891 	for (i = 0; i < LG4FF_MODE_MAX_IDX; i++) {
892 		const u16 mode_product_id = lg4ff_alternate_modes[i].product_id;
893 		const char *tag = lg4ff_alternate_modes[i].tag;
894 
895 		if (entry->wdata.alternate_modes & BIT(i)) {
896 			if (!strcmp(tag, lbuf)) {
897 				if (!mode_product_id)
898 					target_product_id = entry->wdata.real_product_id;
899 				else
900 					target_product_id = mode_product_id;
901 				break;
902 			}
903 		}
904 	}
905 
906 	if (i == LG4FF_MODE_MAX_IDX) {
907 		hid_info(hid, "Requested mode \"%s\" is not supported by the device\n", lbuf);
908 		kfree(lbuf);
909 		return -EINVAL;
910 	}
911 	kfree(lbuf); /* Not needed anymore */
912 
913 	if (target_product_id == entry->wdata.product_id) /* Nothing to do */
914 		return count;
915 
916 	/* Automatic switching has to be disabled for the switch to DF-EX mode to work correctly */
917 	if (target_product_id == USB_DEVICE_ID_LOGITECH_WHEEL && !lg4ff_no_autoswitch) {
918 		hid_info(hid, "\"%s\" cannot be switched to \"DF-EX\" mode. Load the \"hid_logitech\" module with \"lg4ff_no_autoswitch=1\" parameter set and try again\n",
919 			 entry->wdata.real_name);
920 		return -EINVAL;
921 	}
922 
923 	/* Take care of hardware limitations */
924 	if ((entry->wdata.real_product_id == USB_DEVICE_ID_LOGITECH_DFP_WHEEL || entry->wdata.real_product_id == USB_DEVICE_ID_LOGITECH_G25_WHEEL) &&
925 	    entry->wdata.product_id > target_product_id) {
926 		hid_info(hid, "\"%s\" cannot be switched back into \"%s\" mode\n", entry->wdata.real_name, lg4ff_alternate_modes[i].name);
927 		return -EINVAL;
928 	}
929 
930 	s = lg4ff_get_mode_switch_command(entry->wdata.real_product_id, target_product_id);
931 	if (!s) {
932 		hid_err(hid, "Invalid target product ID %X\n", target_product_id);
933 		return -EINVAL;
934 	}
935 
936 	ret = lg4ff_switch_compatibility_mode(hid, s);
937 	return (ret == 0 ? count : ret);
938 }
939 static DEVICE_ATTR(alternate_modes, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, lg4ff_alternate_modes_show, lg4ff_alternate_modes_store);
940 
941 static ssize_t lg4ff_combine_show(struct device *dev, struct device_attribute *attr,
942 				char *buf)
943 {
944 	struct hid_device *hid = to_hid_device(dev);
945 	struct lg4ff_device_entry *entry;
946 	struct lg_drv_data *drv_data;
947 	size_t count;
948 
949 	drv_data = hid_get_drvdata(hid);
950 	if (!drv_data) {
951 		hid_err(hid, "Private driver data not found!\n");
952 		return 0;
953 	}
954 
955 	entry = drv_data->device_props;
956 	if (!entry) {
957 		hid_err(hid, "Device properties not found!\n");
958 		return 0;
959 	}
960 
961 	count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->wdata.combine);
962 	return count;
963 }
964 
965 static ssize_t lg4ff_combine_store(struct device *dev, struct device_attribute *attr,
966 				 const char *buf, size_t count)
967 {
968 	struct hid_device *hid = to_hid_device(dev);
969 	struct lg4ff_device_entry *entry;
970 	struct lg_drv_data *drv_data;
971 	u16 combine = simple_strtoul(buf, NULL, 10);
972 
973 	drv_data = hid_get_drvdata(hid);
974 	if (!drv_data) {
975 		hid_err(hid, "Private driver data not found!\n");
976 		return -EINVAL;
977 	}
978 
979 	entry = drv_data->device_props;
980 	if (!entry) {
981 		hid_err(hid, "Device properties not found!\n");
982 		return -EINVAL;
983 	}
984 
985 	if (combine > 1)
986 		combine = 1;
987 
988 	entry->wdata.combine = combine;
989 	return count;
990 }
991 static DEVICE_ATTR(combine_pedals, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, lg4ff_combine_show, lg4ff_combine_store);
992 
993 /* Export the currently set range of the wheel */
994 static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr,
995 				char *buf)
996 {
997 	struct hid_device *hid = to_hid_device(dev);
998 	struct lg4ff_device_entry *entry;
999 	struct lg_drv_data *drv_data;
1000 	size_t count;
1001 
1002 	drv_data = hid_get_drvdata(hid);
1003 	if (!drv_data) {
1004 		hid_err(hid, "Private driver data not found!\n");
1005 		return 0;
1006 	}
1007 
1008 	entry = drv_data->device_props;
1009 	if (!entry) {
1010 		hid_err(hid, "Device properties not found!\n");
1011 		return 0;
1012 	}
1013 
1014 	count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->wdata.range);
1015 	return count;
1016 }
1017 
1018 /* Set range to user specified value, call appropriate function
1019  * according to the type of the wheel */
1020 static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *attr,
1021 				 const char *buf, size_t count)
1022 {
1023 	struct hid_device *hid = to_hid_device(dev);
1024 	struct lg4ff_device_entry *entry;
1025 	struct lg_drv_data *drv_data;
1026 	u16 range = simple_strtoul(buf, NULL, 10);
1027 
1028 	drv_data = hid_get_drvdata(hid);
1029 	if (!drv_data) {
1030 		hid_err(hid, "Private driver data not found!\n");
1031 		return -EINVAL;
1032 	}
1033 
1034 	entry = drv_data->device_props;
1035 	if (!entry) {
1036 		hid_err(hid, "Device properties not found!\n");
1037 		return -EINVAL;
1038 	}
1039 
1040 	if (range == 0)
1041 		range = entry->wdata.max_range;
1042 
1043 	/* Check if the wheel supports range setting
1044 	 * and that the range is within limits for the wheel */
1045 	if (entry->wdata.set_range && range >= entry->wdata.min_range && range <= entry->wdata.max_range) {
1046 		entry->wdata.set_range(hid, range);
1047 		entry->wdata.range = range;
1048 	}
1049 
1050 	return count;
1051 }
1052 static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, lg4ff_range_show, lg4ff_range_store);
1053 
1054 static ssize_t lg4ff_real_id_show(struct device *dev, struct device_attribute *attr, char *buf)
1055 {
1056 	struct hid_device *hid = to_hid_device(dev);
1057 	struct lg4ff_device_entry *entry;
1058 	struct lg_drv_data *drv_data;
1059 	size_t count;
1060 
1061 	drv_data = hid_get_drvdata(hid);
1062 	if (!drv_data) {
1063 		hid_err(hid, "Private driver data not found!\n");
1064 		return 0;
1065 	}
1066 
1067 	entry = drv_data->device_props;
1068 	if (!entry) {
1069 		hid_err(hid, "Device properties not found!\n");
1070 		return 0;
1071 	}
1072 
1073 	if (!entry->wdata.real_tag || !entry->wdata.real_name) {
1074 		hid_err(hid, "NULL pointer to string\n");
1075 		return 0;
1076 	}
1077 
1078 	count = scnprintf(buf, PAGE_SIZE, "%s: %s\n", entry->wdata.real_tag, entry->wdata.real_name);
1079 	return count;
1080 }
1081 
1082 static ssize_t lg4ff_real_id_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
1083 {
1084 	/* Real ID is a read-only value */
1085 	return -EPERM;
1086 }
1087 static DEVICE_ATTR(real_id, S_IRUGO, lg4ff_real_id_show, lg4ff_real_id_store);
1088 
1089 #ifdef CONFIG_LEDS_CLASS
1090 static void lg4ff_set_leds(struct hid_device *hid, u8 leds)
1091 {
1092 	struct lg_drv_data *drv_data;
1093 	struct lg4ff_device_entry *entry;
1094 	unsigned long flags;
1095 	s32 *value;
1096 
1097 	drv_data = hid_get_drvdata(hid);
1098 	if (!drv_data) {
1099 		hid_err(hid, "Private driver data not found!\n");
1100 		return;
1101 	}
1102 
1103 	entry = drv_data->device_props;
1104 	if (!entry) {
1105 		hid_err(hid, "Device properties not found!\n");
1106 		return;
1107 	}
1108 	value = entry->report->field[0]->value;
1109 
1110 	spin_lock_irqsave(&entry->report_lock, flags);
1111 	value[0] = 0xf8;
1112 	value[1] = 0x12;
1113 	value[2] = leds;
1114 	value[3] = 0x00;
1115 	value[4] = 0x00;
1116 	value[5] = 0x00;
1117 	value[6] = 0x00;
1118 	hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT);
1119 	spin_unlock_irqrestore(&entry->report_lock, flags);
1120 }
1121 
1122 static void lg4ff_led_set_brightness(struct led_classdev *led_cdev,
1123 			enum led_brightness value)
1124 {
1125 	struct device *dev = led_cdev->dev->parent;
1126 	struct hid_device *hid = to_hid_device(dev);
1127 	struct lg_drv_data *drv_data = hid_get_drvdata(hid);
1128 	struct lg4ff_device_entry *entry;
1129 	int i, state = 0;
1130 
1131 	if (!drv_data) {
1132 		hid_err(hid, "Device data not found.");
1133 		return;
1134 	}
1135 
1136 	entry = drv_data->device_props;
1137 
1138 	if (!entry) {
1139 		hid_err(hid, "Device properties not found.");
1140 		return;
1141 	}
1142 
1143 	for (i = 0; i < 5; i++) {
1144 		if (led_cdev != entry->wdata.led[i])
1145 			continue;
1146 		state = (entry->wdata.led_state >> i) & 1;
1147 		if (value == LED_OFF && state) {
1148 			entry->wdata.led_state &= ~(1 << i);
1149 			lg4ff_set_leds(hid, entry->wdata.led_state);
1150 		} else if (value != LED_OFF && !state) {
1151 			entry->wdata.led_state |= 1 << i;
1152 			lg4ff_set_leds(hid, entry->wdata.led_state);
1153 		}
1154 		break;
1155 	}
1156 }
1157 
1158 static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cdev)
1159 {
1160 	struct device *dev = led_cdev->dev->parent;
1161 	struct hid_device *hid = to_hid_device(dev);
1162 	struct lg_drv_data *drv_data = hid_get_drvdata(hid);
1163 	struct lg4ff_device_entry *entry;
1164 	int i, value = 0;
1165 
1166 	if (!drv_data) {
1167 		hid_err(hid, "Device data not found.");
1168 		return LED_OFF;
1169 	}
1170 
1171 	entry = drv_data->device_props;
1172 
1173 	if (!entry) {
1174 		hid_err(hid, "Device properties not found.");
1175 		return LED_OFF;
1176 	}
1177 
1178 	for (i = 0; i < 5; i++)
1179 		if (led_cdev == entry->wdata.led[i]) {
1180 			value = (entry->wdata.led_state >> i) & 1;
1181 			break;
1182 		}
1183 
1184 	return value ? LED_FULL : LED_OFF;
1185 }
1186 #endif
1187 
1188 static u16 lg4ff_identify_multimode_wheel(struct hid_device *hid, const u16 reported_product_id, const u16 bcdDevice)
1189 {
1190 	u32 current_mode;
1191 	int i;
1192 
1193 	/* identify current mode from USB PID */
1194 	for (i = 1; i < ARRAY_SIZE(lg4ff_alternate_modes); i++) {
1195 		dbg_hid("Testing whether PID is %X\n", lg4ff_alternate_modes[i].product_id);
1196 		if (reported_product_id == lg4ff_alternate_modes[i].product_id)
1197 			break;
1198 	}
1199 
1200 	if (i == ARRAY_SIZE(lg4ff_alternate_modes))
1201 		return 0;
1202 
1203 	current_mode = BIT(i);
1204 
1205 	for (i = 0; i < ARRAY_SIZE(lg4ff_main_checklist); i++) {
1206 		const u16 mask = lg4ff_main_checklist[i]->mask;
1207 		const u16 result = lg4ff_main_checklist[i]->result;
1208 		const u16 real_product_id = lg4ff_main_checklist[i]->real_product_id;
1209 
1210 		if ((current_mode & lg4ff_main_checklist[i]->modes) && \
1211 				(bcdDevice & mask) == result) {
1212 			dbg_hid("Found wheel with real PID %X whose reported PID is %X\n", real_product_id, reported_product_id);
1213 			return real_product_id;
1214 		}
1215 	}
1216 
1217 	/* No match found. This is either Driving Force or an unknown
1218 	 * wheel model, do not touch it */
1219 	dbg_hid("Wheel with bcdDevice %X was not recognized as multimode wheel, leaving in its current mode\n", bcdDevice);
1220 	return 0;
1221 }
1222 
1223 static int lg4ff_handle_multimode_wheel(struct hid_device *hid, u16 *real_product_id, const u16 bcdDevice)
1224 {
1225 	const u16 reported_product_id = hid->product;
1226 	int ret;
1227 
1228 	*real_product_id = lg4ff_identify_multimode_wheel(hid, reported_product_id, bcdDevice);
1229 	/* Probed wheel is not a multimode wheel */
1230 	if (!*real_product_id) {
1231 		*real_product_id = reported_product_id;
1232 		dbg_hid("Wheel is not a multimode wheel\n");
1233 		return LG4FF_MMODE_NOT_MULTIMODE;
1234 	}
1235 
1236 	/* Switch from "Driving Force" mode to native mode automatically.
1237 	 * Otherwise keep the wheel in its current mode */
1238 	if (reported_product_id == USB_DEVICE_ID_LOGITECH_WHEEL &&
1239 	    reported_product_id != *real_product_id &&
1240 	    !lg4ff_no_autoswitch) {
1241 		const struct lg4ff_compat_mode_switch *s = lg4ff_get_mode_switch_command(*real_product_id, *real_product_id);
1242 
1243 		if (!s) {
1244 			hid_err(hid, "Invalid product id %X\n", *real_product_id);
1245 			return LG4FF_MMODE_NOT_MULTIMODE;
1246 		}
1247 
1248 		ret = lg4ff_switch_compatibility_mode(hid, s);
1249 		if (ret) {
1250 			/* Wheel could not have been switched to native mode,
1251 			 * leave it in "Driving Force" mode and continue */
1252 			hid_err(hid, "Unable to switch wheel mode, errno %d\n", ret);
1253 			return LG4FF_MMODE_IS_MULTIMODE;
1254 		}
1255 		return LG4FF_MMODE_SWITCHED;
1256 	}
1257 
1258 	return LG4FF_MMODE_IS_MULTIMODE;
1259 }
1260 
1261 
1262 int lg4ff_init(struct hid_device *hid)
1263 {
1264 	struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
1265 	struct input_dev *dev = hidinput->input;
1266 	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
1267 	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
1268 	const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor);
1269 	const u16 bcdDevice = le16_to_cpu(udesc->bcdDevice);
1270 	const struct lg4ff_multimode_wheel *mmode_wheel = NULL;
1271 	struct lg4ff_device_entry *entry;
1272 	struct lg_drv_data *drv_data;
1273 	int error, i, j;
1274 	int mmode_ret, mmode_idx = -1;
1275 	u16 real_product_id;
1276 
1277 	/* Check that the report looks ok */
1278 	if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7))
1279 		return -1;
1280 
1281 	drv_data = hid_get_drvdata(hid);
1282 	if (!drv_data) {
1283 		hid_err(hid, "Cannot add device, private driver data not allocated\n");
1284 		return -1;
1285 	}
1286 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
1287 	if (!entry)
1288 		return -ENOMEM;
1289 	spin_lock_init(&entry->report_lock);
1290 	entry->report = report;
1291 	drv_data->device_props = entry;
1292 
1293 	/* Check if a multimode wheel has been connected and
1294 	 * handle it appropriately */
1295 	mmode_ret = lg4ff_handle_multimode_wheel(hid, &real_product_id, bcdDevice);
1296 
1297 	/* Wheel has been told to switch to native mode. There is no point in going on
1298 	 * with the initialization as the wheel will do a USB reset when it switches mode
1299 	 */
1300 	if (mmode_ret == LG4FF_MMODE_SWITCHED)
1301 		return 0;
1302 	else if (mmode_ret < 0) {
1303 		hid_err(hid, "Unable to switch device mode during initialization, errno %d\n", mmode_ret);
1304 		error = mmode_ret;
1305 		goto err_init;
1306 	}
1307 
1308 	/* Check what wheel has been connected */
1309 	for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) {
1310 		if (hid->product == lg4ff_devices[i].product_id) {
1311 			dbg_hid("Found compatible device, product ID %04X\n", lg4ff_devices[i].product_id);
1312 			break;
1313 		}
1314 	}
1315 
1316 	if (i == ARRAY_SIZE(lg4ff_devices)) {
1317 		hid_err(hid, "This device is flagged to be handled by the lg4ff module but this module does not know how to handle it. "
1318 			     "Please report this as a bug to LKML, Simon Wood <simon@mungewell.org> or "
1319 			     "Michal Maly <madcatxster@devoid-pointer.net>\n");
1320 		error = -1;
1321 		goto err_init;
1322 	}
1323 
1324 	if (mmode_ret == LG4FF_MMODE_IS_MULTIMODE) {
1325 		for (mmode_idx = 0; mmode_idx < ARRAY_SIZE(lg4ff_multimode_wheels); mmode_idx++) {
1326 			if (real_product_id == lg4ff_multimode_wheels[mmode_idx].product_id)
1327 				break;
1328 		}
1329 
1330 		if (mmode_idx == ARRAY_SIZE(lg4ff_multimode_wheels)) {
1331 			hid_err(hid, "Device product ID %X is not listed as a multimode wheel", real_product_id);
1332 			error = -1;
1333 			goto err_init;
1334 		}
1335 	}
1336 
1337 	/* Set supported force feedback capabilities */
1338 	for (j = 0; lg4ff_devices[i].ff_effects[j] >= 0; j++)
1339 		set_bit(lg4ff_devices[i].ff_effects[j], dev->ffbit);
1340 
1341 	error = input_ff_create_memless(dev, NULL, lg4ff_play);
1342 
1343 	if (error)
1344 		goto err_init;
1345 
1346 	/* Initialize device properties */
1347 	if (mmode_ret == LG4FF_MMODE_IS_MULTIMODE) {
1348 		BUG_ON(mmode_idx == -1);
1349 		mmode_wheel = &lg4ff_multimode_wheels[mmode_idx];
1350 	}
1351 	lg4ff_init_wheel_data(&entry->wdata, &lg4ff_devices[i], mmode_wheel, real_product_id);
1352 
1353 	/* Check if autocentering is available and
1354 	 * set the centering force to zero by default */
1355 	if (test_bit(FF_AUTOCENTER, dev->ffbit)) {
1356 		/* Formula Force EX expects different autocentering command */
1357 		if ((bcdDevice >> 8) == LG4FF_FFEX_REV_MAJ &&
1358 		    (bcdDevice & 0xff) == LG4FF_FFEX_REV_MIN)
1359 			dev->ff->set_autocenter = lg4ff_set_autocenter_ffex;
1360 		else
1361 			dev->ff->set_autocenter = lg4ff_set_autocenter_default;
1362 
1363 		dev->ff->set_autocenter(dev, 0);
1364 	}
1365 
1366 	/* Create sysfs interface */
1367 	error = device_create_file(&hid->dev, &dev_attr_combine_pedals);
1368 	if (error)
1369 		hid_warn(hid, "Unable to create sysfs interface for \"combine\", errno %d\n", error);
1370 	error = device_create_file(&hid->dev, &dev_attr_range);
1371 	if (error)
1372 		hid_warn(hid, "Unable to create sysfs interface for \"range\", errno %d\n", error);
1373 	if (mmode_ret == LG4FF_MMODE_IS_MULTIMODE) {
1374 		error = device_create_file(&hid->dev, &dev_attr_real_id);
1375 		if (error)
1376 			hid_warn(hid, "Unable to create sysfs interface for \"real_id\", errno %d\n", error);
1377 		error = device_create_file(&hid->dev, &dev_attr_alternate_modes);
1378 		if (error)
1379 			hid_warn(hid, "Unable to create sysfs interface for \"alternate_modes\", errno %d\n", error);
1380 	}
1381 	dbg_hid("sysfs interface created\n");
1382 
1383 	/* Set the maximum range to start with */
1384 	entry->wdata.range = entry->wdata.max_range;
1385 	if (entry->wdata.set_range)
1386 		entry->wdata.set_range(hid, entry->wdata.range);
1387 
1388 #ifdef CONFIG_LEDS_CLASS
1389 	/* register led subsystem - G27/G29 only */
1390 	entry->wdata.led_state = 0;
1391 	for (j = 0; j < 5; j++)
1392 		entry->wdata.led[j] = NULL;
1393 
1394 	if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_G27_WHEEL ||
1395 			lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_G29_WHEEL) {
1396 		struct led_classdev *led;
1397 		size_t name_sz;
1398 		char *name;
1399 
1400 		lg4ff_set_leds(hid, 0);
1401 
1402 		name_sz = strlen(dev_name(&hid->dev)) + 8;
1403 
1404 		for (j = 0; j < 5; j++) {
1405 			led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL);
1406 			if (!led) {
1407 				hid_err(hid, "can't allocate memory for LED %d\n", j);
1408 				goto err_leds;
1409 			}
1410 
1411 			name = (void *)(&led[1]);
1412 			snprintf(name, name_sz, "%s::RPM%d", dev_name(&hid->dev), j+1);
1413 			led->name = name;
1414 			led->brightness = 0;
1415 			led->max_brightness = 1;
1416 			led->brightness_get = lg4ff_led_get_brightness;
1417 			led->brightness_set = lg4ff_led_set_brightness;
1418 
1419 			entry->wdata.led[j] = led;
1420 			error = led_classdev_register(&hid->dev, led);
1421 
1422 			if (error) {
1423 				hid_err(hid, "failed to register LED %d. Aborting.\n", j);
1424 err_leds:
1425 				/* Deregister LEDs (if any) */
1426 				for (j = 0; j < 5; j++) {
1427 					led = entry->wdata.led[j];
1428 					entry->wdata.led[j] = NULL;
1429 					if (!led)
1430 						continue;
1431 					led_classdev_unregister(led);
1432 					kfree(led);
1433 				}
1434 				goto out;	/* Let the driver continue without LEDs */
1435 			}
1436 		}
1437 	}
1438 out:
1439 #endif
1440 	hid_info(hid, "Force feedback support for Logitech Gaming Wheels\n");
1441 	return 0;
1442 
1443 err_init:
1444 	drv_data->device_props = NULL;
1445 	kfree(entry);
1446 	return error;
1447 }
1448 
1449 int lg4ff_deinit(struct hid_device *hid)
1450 {
1451 	struct lg4ff_device_entry *entry;
1452 	struct lg_drv_data *drv_data;
1453 
1454 	drv_data = hid_get_drvdata(hid);
1455 	if (!drv_data) {
1456 		hid_err(hid, "Error while deinitializing device, no private driver data.\n");
1457 		return -1;
1458 	}
1459 	entry = drv_data->device_props;
1460 	if (!entry)
1461 		goto out; /* Nothing more to do */
1462 
1463 	/* Multimode devices will have at least the "MODE_NATIVE" bit set */
1464 	if (entry->wdata.alternate_modes) {
1465 		device_remove_file(&hid->dev, &dev_attr_real_id);
1466 		device_remove_file(&hid->dev, &dev_attr_alternate_modes);
1467 	}
1468 
1469 	device_remove_file(&hid->dev, &dev_attr_combine_pedals);
1470 	device_remove_file(&hid->dev, &dev_attr_range);
1471 #ifdef CONFIG_LEDS_CLASS
1472 	{
1473 		int j;
1474 		struct led_classdev *led;
1475 
1476 		/* Deregister LEDs (if any) */
1477 		for (j = 0; j < 5; j++) {
1478 
1479 			led = entry->wdata.led[j];
1480 			entry->wdata.led[j] = NULL;
1481 			if (!led)
1482 				continue;
1483 			led_classdev_unregister(led);
1484 			kfree(led);
1485 		}
1486 	}
1487 #endif
1488 	hid_hw_stop(hid);
1489 	drv_data->device_props = NULL;
1490 
1491 	kfree(entry);
1492 out:
1493 	dbg_hid("Device successfully unregistered\n");
1494 	return 0;
1495 }
1496