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