HID: hid-lg4ff: Export the real wheel model and supported alternate modes
[linux-block.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-ids.h"
34
35 #define to_hid_device(pdev) container_of(pdev, struct hid_device, dev)
36
37 #define LG4FF_MMODE_IS_MULTIMODE 0
38 #define LG4FF_MMODE_SWITCHED 1
39 #define LG4FF_MMODE_NOT_MULTIMODE 2
40
41 #define LG4FF_MODE_NATIVE_IDX 0
42 #define LG4FF_MODE_DFEX_IDX 1
43 #define LG4FF_MODE_DFP_IDX 2
44 #define LG4FF_MODE_G25_IDX 3
45 #define LG4FF_MODE_DFGT_IDX 4
46 #define LG4FF_MODE_G27_IDX 5
47 #define LG4FF_MODE_MAX_IDX 6
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
56 #define LG4FF_DFEX_TAG "DF-EX"
57 #define LG4FF_DFEX_NAME "Driving Force / Formula EX"
58 #define LG4FF_DFP_TAG "DFP"
59 #define LG4FF_DFP_NAME "Driving Force Pro"
60 #define LG4FF_G25_TAG "G25"
61 #define LG4FF_G25_NAME "G25 Racing Wheel"
62 #define LG4FF_G27_TAG "G27"
63 #define LG4FF_G27_NAME "G27 Racing Wheel"
64 #define LG4FF_DFGT_TAG "DFGT"
65 #define LG4FF_DFGT_NAME "Driving Force GT"
66
67 #define LG4FF_FFEX_REV_MAJ 0x21
68 #define LG4FF_FFEX_REV_MIN 0x00
69
70 static void hid_lg4ff_set_range_dfp(struct hid_device *hid, u16 range);
71 static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range);
72
73 struct lg4ff_device_entry {
74         __u32 product_id;
75         __u16 range;
76         __u16 min_range;
77         __u16 max_range;
78 #ifdef CONFIG_LEDS_CLASS
79         __u8  led_state;
80         struct led_classdev *led[5];
81 #endif
82         u32 alternate_modes;
83         const char *real_tag;
84         const char *real_name;
85         u16 real_product_id;
86         struct list_head list;
87         void (*set_range)(struct hid_device *hid, u16 range);
88 };
89
90 static const signed short lg4ff_wheel_effects[] = {
91         FF_CONSTANT,
92         FF_AUTOCENTER,
93         -1
94 };
95
96 struct lg4ff_wheel {
97         const __u32 product_id;
98         const signed short *ff_effects;
99         const __u16 min_range;
100         const __u16 max_range;
101         void (*set_range)(struct hid_device *hid, u16 range);
102 };
103
104 struct lg4ff_compat_mode_switch {
105         const __u8 cmd_count;   /* Number of commands to send */
106         const __u8 cmd[];
107 };
108
109 struct lg4ff_wheel_ident_info {
110         const u16 mask;
111         const u16 result;
112         const u16 real_product_id;
113 };
114
115 struct lg4ff_wheel_ident_checklist {
116         const u32 count;
117         const struct lg4ff_wheel_ident_info *models[];
118 };
119
120 struct lg4ff_multimode_wheel {
121         const u16 product_id;
122         const u32 alternate_modes;
123         const char *real_tag;
124         const char *real_name;
125 };
126
127 struct lg4ff_alternate_mode {
128         const u16 product_id;
129         const char *tag;
130         const char *name;
131 };
132
133 static const struct lg4ff_wheel lg4ff_devices[] = {
134         {USB_DEVICE_ID_LOGITECH_WHEEL,       lg4ff_wheel_effects, 40, 270, NULL},
135         {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL,  lg4ff_wheel_effects, 40, 270, NULL},
136         {USB_DEVICE_ID_LOGITECH_DFP_WHEEL,   lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_dfp},
137         {USB_DEVICE_ID_LOGITECH_G25_WHEEL,   lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25},
138         {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL,  lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25},
139         {USB_DEVICE_ID_LOGITECH_G27_WHEEL,   lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25},
140         {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2, lg4ff_wheel_effects, 40, 270, NULL},
141         {USB_DEVICE_ID_LOGITECH_WII_WHEEL,   lg4ff_wheel_effects, 40, 270, NULL}
142 };
143
144 static const struct lg4ff_multimode_wheel lg4ff_multimode_wheels[] = {
145         {USB_DEVICE_ID_LOGITECH_DFP_WHEEL,
146          LG4FF_MODE_NATIVE | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
147          LG4FF_DFP_TAG, LG4FF_DFP_NAME},
148         {USB_DEVICE_ID_LOGITECH_G25_WHEEL,
149          LG4FF_MODE_NATIVE | LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
150          LG4FF_G25_TAG, LG4FF_G25_NAME},
151         {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL,
152          LG4FF_MODE_NATIVE | LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
153          LG4FF_DFGT_TAG, LG4FF_DFGT_NAME},
154         {USB_DEVICE_ID_LOGITECH_G27_WHEEL,
155          LG4FF_MODE_NATIVE | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
156          LG4FF_G27_TAG, LG4FF_G27_NAME},
157 };
158
159 static const struct lg4ff_alternate_mode lg4ff_alternate_modes[] = {
160         [LG4FF_MODE_NATIVE_IDX] = {0, "native", ""},
161         [LG4FF_MODE_DFEX_IDX] = {USB_DEVICE_ID_LOGITECH_WHEEL, LG4FF_DFEX_TAG, LG4FF_DFEX_NAME},
162         [LG4FF_MODE_DFP_IDX] = {USB_DEVICE_ID_LOGITECH_DFP_WHEEL, LG4FF_DFP_TAG, LG4FF_DFP_NAME},
163         [LG4FF_MODE_G25_IDX] = {USB_DEVICE_ID_LOGITECH_G25_WHEEL, LG4FF_G25_TAG, LG4FF_G25_NAME},
164         [LG4FF_MODE_DFGT_IDX] = {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, LG4FF_DFGT_TAG, LG4FF_DFGT_NAME},
165         [LG4FF_MODE_G27_IDX] = {USB_DEVICE_ID_LOGITECH_G27_WHEEL, LG4FF_G27_TAG, LG4FF_G27_NAME}
166 };
167
168 /* Multimode wheel identificators */
169 static const struct lg4ff_wheel_ident_info lg4ff_dfp_ident_info = {
170         0xf000,
171         0x1000,
172         USB_DEVICE_ID_LOGITECH_DFP_WHEEL
173 };
174
175 static const struct lg4ff_wheel_ident_info lg4ff_g25_ident_info = {
176         0xff00,
177         0x1200,
178         USB_DEVICE_ID_LOGITECH_G25_WHEEL
179 };
180
181 static const struct lg4ff_wheel_ident_info lg4ff_g27_ident_info = {
182         0xfff0,
183         0x1230,
184         USB_DEVICE_ID_LOGITECH_G27_WHEEL
185 };
186
187 static const struct lg4ff_wheel_ident_info lg4ff_dfgt_ident_info = {
188         0xff00,
189         0x1300,
190         USB_DEVICE_ID_LOGITECH_DFGT_WHEEL
191 };
192
193 /* Multimode wheel identification checklists */
194 static const struct lg4ff_wheel_ident_checklist lg4ff_main_checklist = {
195         4,
196         {&lg4ff_dfgt_ident_info,
197          &lg4ff_g27_ident_info,
198          &lg4ff_g25_ident_info,
199          &lg4ff_dfp_ident_info}
200 };
201
202 /* Compatibility mode switching commands */
203 static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_dfp = {
204         1,
205         {0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}
206 };
207
208 static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_dfgt = {
209         2,
210         {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,      /* 1st command */
211          0xf8, 0x09, 0x03, 0x01, 0x00, 0x00, 0x00}      /* 2nd command */
212 };
213
214 static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_g25 = {
215         1,
216         {0xf8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}
217 };
218
219 static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_g27 = {
220         2,
221         {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,      /* 1st command */
222          0xf8, 0x09, 0x04, 0x01, 0x00, 0x00, 0x00}      /* 2nd command */
223 };
224
225 /* Recalculates X axis value accordingly to currently selected range */
226 static __s32 lg4ff_adjust_dfp_x_axis(__s32 value, __u16 range)
227 {
228         __u16 max_range;
229         __s32 new_value;
230
231         if (range == 900)
232                 return value;
233         else if (range == 200)
234                 return value;
235         else if (range < 200)
236                 max_range = 200;
237         else
238                 max_range = 900;
239
240         new_value = 8192 + mult_frac(value - 8192, max_range, range);
241         if (new_value < 0)
242                 return 0;
243         else if (new_value > 16383)
244                 return 16383;
245         else
246                 return new_value;
247 }
248
249 int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field,
250                              struct hid_usage *usage, __s32 value, struct lg_drv_data *drv_data)
251 {
252         struct lg4ff_device_entry *entry = drv_data->device_props;
253         __s32 new_value = 0;
254
255         if (!entry) {
256                 hid_err(hid, "Device properties not found");
257                 return 0;
258         }
259
260         switch (entry->product_id) {
261         case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
262                 switch (usage->code) {
263                 case ABS_X:
264                         new_value = lg4ff_adjust_dfp_x_axis(value, entry->range);
265                         input_event(field->hidinput->input, usage->type, usage->code, new_value);
266                         return 1;
267                 default:
268                         return 0;
269                 }
270         default:
271                 return 0;
272         }
273 }
274
275 static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
276 {
277         struct hid_device *hid = input_get_drvdata(dev);
278         struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
279         struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
280         __s32 *value = report->field[0]->value;
281         int x;
282
283 #define CLAMP(x) do { if (x < 0) x = 0; else if (x > 0xff) x = 0xff; } while (0)
284
285         switch (effect->type) {
286         case FF_CONSTANT:
287                 x = effect->u.ramp.start_level + 0x80;  /* 0x80 is no force */
288                 CLAMP(x);
289
290                 if (x == 0x80) {
291                         /* De-activate force in slot-1*/
292                         value[0] = 0x13;
293                         value[1] = 0x00;
294                         value[2] = 0x00;
295                         value[3] = 0x00;
296                         value[4] = 0x00;
297                         value[5] = 0x00;
298                         value[6] = 0x00;
299
300                         hid_hw_request(hid, report, HID_REQ_SET_REPORT);
301                         return 0;
302                 }
303
304                 value[0] = 0x11;        /* Slot 1 */
305                 value[1] = 0x08;
306                 value[2] = x;
307                 value[3] = 0x80;
308                 value[4] = 0x00;
309                 value[5] = 0x00;
310                 value[6] = 0x00;
311
312                 hid_hw_request(hid, report, HID_REQ_SET_REPORT);
313                 break;
314         }
315         return 0;
316 }
317
318 /* Sends default autocentering command compatible with
319  * all wheels except Formula Force EX */
320 static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude)
321 {
322         struct hid_device *hid = input_get_drvdata(dev);
323         struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
324         struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
325         __s32 *value = report->field[0]->value;
326         __u32 expand_a, expand_b;
327         struct lg4ff_device_entry *entry;
328         struct lg_drv_data *drv_data;
329
330         drv_data = hid_get_drvdata(hid);
331         if (!drv_data) {
332                 hid_err(hid, "Private driver data not found!\n");
333                 return;
334         }
335
336         entry = drv_data->device_props;
337         if (!entry) {
338                 hid_err(hid, "Device properties not found!\n");
339                 return;
340         }
341
342         /* De-activate Auto-Center */
343         if (magnitude == 0) {
344                 value[0] = 0xf5;
345                 value[1] = 0x00;
346                 value[2] = 0x00;
347                 value[3] = 0x00;
348                 value[4] = 0x00;
349                 value[5] = 0x00;
350                 value[6] = 0x00;
351
352                 hid_hw_request(hid, report, HID_REQ_SET_REPORT);
353                 return;
354         }
355
356         if (magnitude <= 0xaaaa) {
357                 expand_a = 0x0c * magnitude;
358                 expand_b = 0x80 * magnitude;
359         } else {
360                 expand_a = (0x0c * 0xaaaa) + 0x06 * (magnitude - 0xaaaa);
361                 expand_b = (0x80 * 0xaaaa) + 0xff * (magnitude - 0xaaaa);
362         }
363
364         /* Adjust for non-MOMO wheels */
365         switch (entry->product_id) {
366         case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
367         case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
368                 break;
369         default:
370                 expand_a = expand_a >> 1;
371                 break;
372         }
373
374         value[0] = 0xfe;
375         value[1] = 0x0d;
376         value[2] = expand_a / 0xaaaa;
377         value[3] = expand_a / 0xaaaa;
378         value[4] = expand_b / 0xaaaa;
379         value[5] = 0x00;
380         value[6] = 0x00;
381
382         hid_hw_request(hid, report, HID_REQ_SET_REPORT);
383
384         /* Activate Auto-Center */
385         value[0] = 0x14;
386         value[1] = 0x00;
387         value[2] = 0x00;
388         value[3] = 0x00;
389         value[4] = 0x00;
390         value[5] = 0x00;
391         value[6] = 0x00;
392
393         hid_hw_request(hid, report, HID_REQ_SET_REPORT);
394 }
395
396 /* Sends autocentering command compatible with Formula Force EX */
397 static void hid_lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude)
398 {
399         struct hid_device *hid = input_get_drvdata(dev);
400         struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
401         struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
402         __s32 *value = report->field[0]->value;
403         magnitude = magnitude * 90 / 65535;
404
405         value[0] = 0xfe;
406         value[1] = 0x03;
407         value[2] = magnitude >> 14;
408         value[3] = magnitude >> 14;
409         value[4] = magnitude;
410         value[5] = 0x00;
411         value[6] = 0x00;
412
413         hid_hw_request(hid, report, HID_REQ_SET_REPORT);
414 }
415
416 /* Sends command to set range compatible with G25/G27/Driving Force GT */
417 static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range)
418 {
419         struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
420         struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
421         __s32 *value = report->field[0]->value;
422
423         dbg_hid("G25/G27/DFGT: setting range to %u\n", range);
424
425         value[0] = 0xf8;
426         value[1] = 0x81;
427         value[2] = range & 0x00ff;
428         value[3] = (range & 0xff00) >> 8;
429         value[4] = 0x00;
430         value[5] = 0x00;
431         value[6] = 0x00;
432
433         hid_hw_request(hid, report, HID_REQ_SET_REPORT);
434 }
435
436 /* Sends commands to set range compatible with Driving Force Pro wheel */
437 static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range)
438 {
439         struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
440         struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
441         int start_left, start_right, full_range;
442         __s32 *value = report->field[0]->value;
443
444         dbg_hid("Driving Force Pro: setting range to %u\n", range);
445
446         /* Prepare "coarse" limit command */
447         value[0] = 0xf8;
448         value[1] = 0x00;        /* Set later */
449         value[2] = 0x00;
450         value[3] = 0x00;
451         value[4] = 0x00;
452         value[5] = 0x00;
453         value[6] = 0x00;
454
455         if (range > 200) {
456                 report->field[0]->value[1] = 0x03;
457                 full_range = 900;
458         } else {
459                 report->field[0]->value[1] = 0x02;
460                 full_range = 200;
461         }
462         hid_hw_request(hid, report, HID_REQ_SET_REPORT);
463
464         /* Prepare "fine" limit command */
465         value[0] = 0x81;
466         value[1] = 0x0b;
467         value[2] = 0x00;
468         value[3] = 0x00;
469         value[4] = 0x00;
470         value[5] = 0x00;
471         value[6] = 0x00;
472
473         if (range == 200 || range == 900) {     /* Do not apply any fine limit */
474                 hid_hw_request(hid, report, HID_REQ_SET_REPORT);
475                 return;
476         }
477
478         /* Construct fine limit command */
479         start_left = (((full_range - range + 1) * 2047) / full_range);
480         start_right = 0xfff - start_left;
481
482         value[2] = start_left >> 4;
483         value[3] = start_right >> 4;
484         value[4] = 0xff;
485         value[5] = (start_right & 0xe) << 4 | (start_left & 0xe);
486         value[6] = 0xff;
487
488         hid_hw_request(hid, report, HID_REQ_SET_REPORT);
489 }
490
491 static int lg4ff_switch_compatibility_mode(struct hid_device *hid, const struct lg4ff_compat_mode_switch *s)
492 {
493         struct usb_device *usbdev = hid_to_usb_dev(hid);
494         struct usbhid_device *usbhid = hid->driver_data;
495         u8 i;
496
497         for (i = 0; i < s->cmd_count; i++) {
498                 int xferd, ret;
499                 u8 data[7];
500
501                 memcpy(data, s->cmd + (7*i), 7);
502                 ret = usb_interrupt_msg(usbdev, usbhid->urbout->pipe, data, 7, &xferd, USB_CTRL_SET_TIMEOUT);
503                 if (ret)
504                         return ret;
505         }
506         return 0;
507 }
508
509 static ssize_t lg4ff_alternate_modes_show(struct device *dev, struct device_attribute *attr, char *buf)
510 {
511         struct hid_device *hid = to_hid_device(dev);
512         struct lg4ff_device_entry *entry;
513         struct lg_drv_data *drv_data;
514         ssize_t count = 0;
515         int i;
516
517         drv_data = hid_get_drvdata(hid);
518         if (!drv_data) {
519                 hid_err(hid, "Private driver data not found!\n");
520                 return 0;
521         }
522
523         entry = drv_data->device_props;
524         if (!entry) {
525                 hid_err(hid, "Device properties not found!\n");
526                 return 0;
527         }
528
529         if (!entry->real_name) {
530                 hid_err(hid, "NULL pointer to string\n");
531                 return 0;
532         }
533
534         for (i = 0; i < LG4FF_MODE_MAX_IDX; i++) {
535                 if (entry->alternate_modes & BIT(i)) {
536                         /* Print tag and full name */
537                         count += scnprintf(buf + count, PAGE_SIZE - count, "%s: %s",
538                                            lg4ff_alternate_modes[i].tag,
539                                            !lg4ff_alternate_modes[i].product_id ? entry->real_name : lg4ff_alternate_modes[i].name);
540                         if (count >= PAGE_SIZE - 1)
541                                 return count;
542
543                         /* Mark the currently active mode with an asterisk */
544                         if (lg4ff_alternate_modes[i].product_id == entry->product_id ||
545                             (lg4ff_alternate_modes[i].product_id == 0 && entry->product_id == entry->real_product_id))
546                                 count += scnprintf(buf + count, PAGE_SIZE - count, " *\n");
547                         else
548                                 count += scnprintf(buf + count, PAGE_SIZE - count, "\n");
549
550                         if (count >= PAGE_SIZE - 1)
551                                 return count;
552                 }
553         }
554
555         return count;
556 }
557
558 static ssize_t lg4ff_alternate_modes_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
559 {
560         return -ENOSYS;
561 }
562 static DEVICE_ATTR(alternate_modes, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, lg4ff_alternate_modes_show, lg4ff_alternate_modes_store);
563
564 /* Read current range and display it in terminal */
565 static ssize_t range_show(struct device *dev, struct device_attribute *attr,
566                           char *buf)
567 {
568         struct hid_device *hid = to_hid_device(dev);
569         struct lg4ff_device_entry *entry;
570         struct lg_drv_data *drv_data;
571         size_t count;
572
573         drv_data = hid_get_drvdata(hid);
574         if (!drv_data) {
575                 hid_err(hid, "Private driver data not found!\n");
576                 return 0;
577         }
578
579         entry = drv_data->device_props;
580         if (!entry) {
581                 hid_err(hid, "Device properties not found!\n");
582                 return 0;
583         }
584
585         count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->range);
586         return count;
587 }
588
589 /* Set range to user specified value, call appropriate function
590  * according to the type of the wheel */
591 static ssize_t range_store(struct device *dev, struct device_attribute *attr,
592                            const char *buf, size_t count)
593 {
594         struct hid_device *hid = to_hid_device(dev);
595         struct lg4ff_device_entry *entry;
596         struct lg_drv_data *drv_data;
597         __u16 range = simple_strtoul(buf, NULL, 10);
598
599         drv_data = hid_get_drvdata(hid);
600         if (!drv_data) {
601                 hid_err(hid, "Private driver data not found!\n");
602                 return -EINVAL;
603         }
604
605         entry = drv_data->device_props;
606         if (!entry) {
607                 hid_err(hid, "Device properties not found!\n");
608                 return -EINVAL;
609         }
610
611         if (range == 0)
612                 range = entry->max_range;
613
614         /* Check if the wheel supports range setting
615          * and that the range is within limits for the wheel */
616         if (entry->set_range != NULL && range >= entry->min_range && range <= entry->max_range) {
617                 entry->set_range(hid, range);
618                 entry->range = range;
619         }
620
621         return count;
622 }
623 static DEVICE_ATTR_RW(range);
624
625 static ssize_t lg4ff_real_id_show(struct device *dev, struct device_attribute *attr, char *buf)
626 {
627         struct hid_device *hid = to_hid_device(dev);
628         struct lg4ff_device_entry *entry;
629         struct lg_drv_data *drv_data;
630         size_t count;
631
632         drv_data = hid_get_drvdata(hid);
633         if (!drv_data) {
634                 hid_err(hid, "Private driver data not found!\n");
635                 return 0;
636         }
637
638         entry = drv_data->device_props;
639         if (!entry) {
640                 hid_err(hid, "Device properties not found!\n");
641                 return 0;
642         }
643
644         if (!entry->real_tag || !entry->real_name) {
645                 hid_err(hid, "NULL pointer to string\n");
646                 return 0;
647         }
648
649         count = scnprintf(buf, PAGE_SIZE, "%s: %s\n", entry->real_tag, entry->real_name);
650         return count;
651 }
652
653 static ssize_t lg4ff_real_id_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
654 {
655         /* Real ID is a read-only value */
656         return -EPERM;
657 }
658 static DEVICE_ATTR(real_id, S_IRUGO, lg4ff_real_id_show, lg4ff_real_id_store);
659
660 #ifdef CONFIG_LEDS_CLASS
661 static void lg4ff_set_leds(struct hid_device *hid, __u8 leds)
662 {
663         struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
664         struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
665         __s32 *value = report->field[0]->value;
666
667         value[0] = 0xf8;
668         value[1] = 0x12;
669         value[2] = leds;
670         value[3] = 0x00;
671         value[4] = 0x00;
672         value[5] = 0x00;
673         value[6] = 0x00;
674         hid_hw_request(hid, report, HID_REQ_SET_REPORT);
675 }
676
677 static void lg4ff_led_set_brightness(struct led_classdev *led_cdev,
678                         enum led_brightness value)
679 {
680         struct device *dev = led_cdev->dev->parent;
681         struct hid_device *hid = container_of(dev, struct hid_device, dev);
682         struct lg_drv_data *drv_data = hid_get_drvdata(hid);
683         struct lg4ff_device_entry *entry;
684         int i, state = 0;
685
686         if (!drv_data) {
687                 hid_err(hid, "Device data not found.");
688                 return;
689         }
690
691         entry = (struct lg4ff_device_entry *)drv_data->device_props;
692
693         if (!entry) {
694                 hid_err(hid, "Device properties not found.");
695                 return;
696         }
697
698         for (i = 0; i < 5; i++) {
699                 if (led_cdev != entry->led[i])
700                         continue;
701                 state = (entry->led_state >> i) & 1;
702                 if (value == LED_OFF && state) {
703                         entry->led_state &= ~(1 << i);
704                         lg4ff_set_leds(hid, entry->led_state);
705                 } else if (value != LED_OFF && !state) {
706                         entry->led_state |= 1 << i;
707                         lg4ff_set_leds(hid, entry->led_state);
708                 }
709                 break;
710         }
711 }
712
713 static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cdev)
714 {
715         struct device *dev = led_cdev->dev->parent;
716         struct hid_device *hid = container_of(dev, struct hid_device, dev);
717         struct lg_drv_data *drv_data = hid_get_drvdata(hid);
718         struct lg4ff_device_entry *entry;
719         int i, value = 0;
720
721         if (!drv_data) {
722                 hid_err(hid, "Device data not found.");
723                 return LED_OFF;
724         }
725
726         entry = (struct lg4ff_device_entry *)drv_data->device_props;
727
728         if (!entry) {
729                 hid_err(hid, "Device properties not found.");
730                 return LED_OFF;
731         }
732
733         for (i = 0; i < 5; i++)
734                 if (led_cdev == entry->led[i]) {
735                         value = (entry->led_state >> i) & 1;
736                         break;
737                 }
738
739         return value ? LED_FULL : LED_OFF;
740 }
741 #endif
742
743 static u16 lg4ff_identify_multimode_wheel(struct hid_device *hid, const u16 reported_product_id, const u16 bcdDevice)
744 {
745         const struct lg4ff_wheel_ident_checklist *checklist;
746         int i, from_idx, to_idx;
747
748         switch (reported_product_id) {
749         case USB_DEVICE_ID_LOGITECH_WHEEL:
750         case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
751                 checklist = &lg4ff_main_checklist;
752                 from_idx = 0;
753                 to_idx = checklist->count - 1;
754                 break;
755         case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
756                 checklist = &lg4ff_main_checklist;
757                 from_idx = 0;
758                 to_idx = checklist->count - 2; /* End identity check at G25 */
759                 break;
760         case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
761                 checklist = &lg4ff_main_checklist;
762                 from_idx = 1; /* Start identity check at G27 */
763                 to_idx = checklist->count - 3; /* End identity check at G27 */
764                 break;
765         case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
766                 checklist = &lg4ff_main_checklist;
767                 from_idx = 0;
768                 to_idx = checklist->count - 4; /* End identity check at DFGT */
769                 break;
770         default:
771                 return 0;
772         }
773
774         for (i = from_idx; i <= to_idx; i++) {
775                 const u16 mask = checklist->models[i]->mask;
776                 const u16 result = checklist->models[i]->result;
777                 const u16 real_product_id = checklist->models[i]->real_product_id;
778
779                 if ((bcdDevice & mask) == result) {
780                         dbg_hid("Found wheel with real PID %X whose reported PID is %X\n", real_product_id, reported_product_id);
781                         return real_product_id;
782                 }
783         }
784
785         /* No match found. This is an unknown wheel model, do not touch it */
786         dbg_hid("Wheel with bcdDevice %X was not recognized as multimode wheel, leaving in its current mode\n", bcdDevice);
787         return 0;
788 }
789
790 static int lg4ff_handle_multimode_wheel(struct hid_device *hid, u16 *real_product_id, const u16 bcdDevice)
791 {
792         const u16 reported_product_id = hid->product;
793         int ret;
794
795         *real_product_id = lg4ff_identify_multimode_wheel(hid, reported_product_id, bcdDevice);
796         /* Probed wheel is not a multimode wheel */
797         if (!*real_product_id) {
798                 *real_product_id = reported_product_id;
799                 dbg_hid("Wheel is not a multimode wheel\n");
800                 return LG4FF_MMODE_NOT_MULTIMODE;
801         }
802
803         /* Switch from "Driving Force" mode to native mode automatically.
804          * Otherwise keep the wheel in its current mode */
805         if (reported_product_id == USB_DEVICE_ID_LOGITECH_WHEEL &&
806             reported_product_id != *real_product_id) {
807                 const struct lg4ff_compat_mode_switch *s;
808
809                 switch (*real_product_id) {
810                 case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
811                         s = &lg4ff_mode_switch_dfp;
812                         break;
813                 case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
814                         s = &lg4ff_mode_switch_g25;
815                         break;
816                 case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
817                         s = &lg4ff_mode_switch_g27;
818                         break;
819                 case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
820                         s = &lg4ff_mode_switch_dfgt;
821                         break;
822                 default:
823                         hid_err(hid, "Invalid product id %X\n", *real_product_id);
824                         return LG4FF_MMODE_NOT_MULTIMODE;
825                 }
826
827                 ret = lg4ff_switch_compatibility_mode(hid, s);
828                 if (ret) {
829                         /* Wheel could not have been switched to native mode,
830                          * leave it in "Driving Force" mode and continue */
831                         hid_err(hid, "Unable to switch wheel mode, errno %d\n", ret);
832                         return LG4FF_MMODE_IS_MULTIMODE;
833                 }
834                 return LG4FF_MMODE_SWITCHED;
835         }
836
837         return LG4FF_MMODE_IS_MULTIMODE;
838 }
839
840
841 int lg4ff_init(struct hid_device *hid)
842 {
843         struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
844         struct input_dev *dev = hidinput->input;
845         const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor);
846         const u16 bcdDevice = le16_to_cpu(udesc->bcdDevice);
847         struct lg4ff_device_entry *entry;
848         struct lg_drv_data *drv_data;
849         int error, i, j;
850         int mmode_ret, mmode_idx = -1;
851         u16 real_product_id;
852
853         /* Check that the report looks ok */
854         if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7))
855                 return -1;
856
857         /* Check if a multimode wheel has been connected and
858          * handle it appropriately */
859         mmode_ret = lg4ff_handle_multimode_wheel(hid, &real_product_id, bcdDevice);
860
861         /* Wheel has been told to switch to native mode. There is no point in going on
862          * with the initialization as the wheel will do a USB reset when it switches mode
863          */
864         if (mmode_ret == LG4FF_MMODE_SWITCHED)
865                 return 0;
866
867         /* Check what wheel has been connected */
868         for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) {
869                 if (hid->product == lg4ff_devices[i].product_id) {
870                         dbg_hid("Found compatible device, product ID %04X\n", lg4ff_devices[i].product_id);
871                         break;
872                 }
873         }
874
875         if (i == ARRAY_SIZE(lg4ff_devices)) {
876                 hid_err(hid, "Device is not supported by lg4ff driver. If you think it should be, consider reporting a bug to"
877                              "LKML, Simon Wood <simon@mungewell.org> or Michal Maly <madcatxster@gmail.com>\n");
878                 return -1;
879         }
880
881         if (mmode_ret == LG4FF_MMODE_IS_MULTIMODE) {
882                 for (mmode_idx = 0; mmode_idx < ARRAY_SIZE(lg4ff_multimode_wheels); mmode_idx++) {
883                         if (real_product_id == lg4ff_multimode_wheels[mmode_idx].product_id)
884                                 break;
885                 }
886
887                 if (mmode_idx == ARRAY_SIZE(lg4ff_multimode_wheels)) {
888                         hid_err(hid, "Device product ID %X is not listed as a multimode wheel", real_product_id);
889                         return -1;
890                 }
891         }
892
893         /* Set supported force feedback capabilities */
894         for (j = 0; lg4ff_devices[i].ff_effects[j] >= 0; j++)
895                 set_bit(lg4ff_devices[i].ff_effects[j], dev->ffbit);
896
897         error = input_ff_create_memless(dev, NULL, hid_lg4ff_play);
898
899         if (error)
900                 return error;
901
902         /* Get private driver data */
903         drv_data = hid_get_drvdata(hid);
904         if (!drv_data) {
905                 hid_err(hid, "Cannot add device, private driver data not allocated\n");
906                 return -1;
907         }
908
909         /* Initialize device properties */
910         entry = kzalloc(sizeof(struct lg4ff_device_entry), GFP_KERNEL);
911         if (!entry) {
912                 hid_err(hid, "Cannot add device, insufficient memory to allocate device properties.\n");
913                 return -ENOMEM;
914         }
915         drv_data->device_props = entry;
916
917         entry->product_id = lg4ff_devices[i].product_id;
918         entry->real_product_id = real_product_id;
919         entry->min_range = lg4ff_devices[i].min_range;
920         entry->max_range = lg4ff_devices[i].max_range;
921         entry->set_range = lg4ff_devices[i].set_range;
922         if (mmode_ret == LG4FF_MMODE_IS_MULTIMODE) {
923                 BUG_ON(mmode_idx == -1);
924                 entry->alternate_modes = lg4ff_multimode_wheels[mmode_idx].alternate_modes;
925                 entry->real_tag = lg4ff_multimode_wheels[mmode_idx].real_tag;
926                 entry->real_name = lg4ff_multimode_wheels[mmode_idx].real_name;
927         }
928
929         /* Check if autocentering is available and
930          * set the centering force to zero by default */
931         if (test_bit(FF_AUTOCENTER, dev->ffbit)) {
932                 /* Formula Force EX expects different autocentering command */
933                 if ((bcdDevice >> 8) == LG4FF_FFEX_REV_MAJ &&
934                     (bcdDevice & 0xff) == LG4FF_FFEX_REV_MIN)
935                         dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex;
936                 else
937                         dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default;
938
939                 dev->ff->set_autocenter(dev, 0);
940         }
941
942         /* Create sysfs interface */
943         error = device_create_file(&hid->dev, &dev_attr_range);
944         if (error)
945                 return error;
946         if (mmode_ret == LG4FF_MMODE_IS_MULTIMODE) {
947                 error = device_create_file(&hid->dev, &dev_attr_real_id);
948                 if (error)
949                         return error;
950                 error = device_create_file(&hid->dev, &dev_attr_alternate_modes);
951                 if (error)
952                         return error;
953         }
954         dbg_hid("sysfs interface created\n");
955
956         /* Set the maximum range to start with */
957         entry->range = entry->max_range;
958         if (entry->set_range != NULL)
959                 entry->set_range(hid, entry->range);
960
961 #ifdef CONFIG_LEDS_CLASS
962         /* register led subsystem - G27 only */
963         entry->led_state = 0;
964         for (j = 0; j < 5; j++)
965                 entry->led[j] = NULL;
966
967         if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_G27_WHEEL) {
968                 struct led_classdev *led;
969                 size_t name_sz;
970                 char *name;
971
972                 lg4ff_set_leds(hid, 0);
973
974                 name_sz = strlen(dev_name(&hid->dev)) + 8;
975
976                 for (j = 0; j < 5; j++) {
977                         led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL);
978                         if (!led) {
979                                 hid_err(hid, "can't allocate memory for LED %d\n", j);
980                                 goto err;
981                         }
982
983                         name = (void *)(&led[1]);
984                         snprintf(name, name_sz, "%s::RPM%d", dev_name(&hid->dev), j+1);
985                         led->name = name;
986                         led->brightness = 0;
987                         led->max_brightness = 1;
988                         led->brightness_get = lg4ff_led_get_brightness;
989                         led->brightness_set = lg4ff_led_set_brightness;
990
991                         entry->led[j] = led;
992                         error = led_classdev_register(&hid->dev, led);
993
994                         if (error) {
995                                 hid_err(hid, "failed to register LED %d. Aborting.\n", j);
996 err:
997                                 /* Deregister LEDs (if any) */
998                                 for (j = 0; j < 5; j++) {
999                                         led = entry->led[j];
1000                                         entry->led[j] = NULL;
1001                                         if (!led)
1002                                                 continue;
1003                                         led_classdev_unregister(led);
1004                                         kfree(led);
1005                                 }
1006                                 goto out;       /* Let the driver continue without LEDs */
1007                         }
1008                 }
1009         }
1010 out:
1011 #endif
1012         hid_info(hid, "Force feedback support for Logitech Gaming Wheels\n");
1013         return 0;
1014 }
1015
1016 int lg4ff_deinit(struct hid_device *hid)
1017 {
1018         struct lg4ff_device_entry *entry;
1019         struct lg_drv_data *drv_data;
1020
1021         drv_data = hid_get_drvdata(hid);
1022         if (!drv_data) {
1023                 hid_err(hid, "Error while deinitializing device, no private driver data.\n");
1024                 return -1;
1025         }
1026         entry = drv_data->device_props;
1027         if (!entry)
1028                 goto out; /* Nothing more to do */
1029
1030         device_remove_file(&hid->dev, &dev_attr_range);
1031
1032         /* Multimode devices will have at least the "MODE_NATIVE" bit set */
1033         if (entry->alternate_modes) {
1034                 device_remove_file(&hid->dev, &dev_attr_real_id);
1035                 device_remove_file(&hid->dev, &dev_attr_alternate_modes);
1036         }
1037
1038 #ifdef CONFIG_LEDS_CLASS
1039         {
1040                 int j;
1041                 struct led_classdev *led;
1042
1043                 /* Deregister LEDs (if any) */
1044                 for (j = 0; j < 5; j++) {
1045
1046                         led = entry->led[j];
1047                         entry->led[j] = NULL;
1048                         if (!led)
1049                                 continue;
1050                         led_classdev_unregister(led);
1051                         kfree(led);
1052                 }
1053         }
1054 #endif
1055
1056         /* Deallocate memory */
1057         kfree(entry);
1058
1059 out:
1060         dbg_hid("Device successfully unregistered\n");
1061         return 0;
1062 }