GNU Linux-libre 4.4.289-gnu1
[releases.git] / drivers / hid / hid-lg.c
1 /*
2  *  HID driver for some logitech "special" devices
3  *
4  *  Copyright (c) 1999 Andreas Gal
5  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
6  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
7  *  Copyright (c) 2006-2007 Jiri Kosina
8  *  Copyright (c) 2008 Jiri Slaby
9  *  Copyright (c) 2010 Hendrik Iben
10  */
11
12 /*
13  * This program is free software; you can redistribute it and/or modify it
14  * under the terms of the GNU General Public License as published by the Free
15  * Software Foundation; either version 2 of the License, or (at your option)
16  * any later version.
17  */
18
19 #include <linux/device.h>
20 #include <linux/hid.h>
21 #include <linux/module.h>
22 #include <linux/random.h>
23 #include <linux/sched.h>
24 #include <linux/usb.h>
25 #include <linux/wait.h>
26
27 #include "usbhid/usbhid.h"
28 #include "hid-ids.h"
29 #include "hid-lg.h"
30 #include "hid-lg4ff.h"
31
32 #define LG_RDESC                0x001
33 #define LG_BAD_RELATIVE_KEYS    0x002
34 #define LG_DUPLICATE_USAGES     0x004
35 #define LG_EXPANDED_KEYMAP      0x010
36 #define LG_IGNORE_DOUBLED_WHEEL 0x020
37 #define LG_WIRELESS             0x040
38 #define LG_INVERT_HWHEEL        0x080
39 #define LG_NOGET                0x100
40 #define LG_FF                   0x200
41 #define LG_FF2                  0x400
42 #define LG_RDESC_REL_ABS        0x800
43 #define LG_FF3                  0x1000
44 #define LG_FF4                  0x2000
45
46 /* Size of the original descriptors of the Driving Force (and Pro) wheels */
47 #define DF_RDESC_ORIG_SIZE      130
48 #define DFP_RDESC_ORIG_SIZE     97
49 #define FV_RDESC_ORIG_SIZE      130
50 #define MOMO_RDESC_ORIG_SIZE    87
51 #define MOMO2_RDESC_ORIG_SIZE   87
52
53 /* Fixed report descriptors for Logitech Driving Force (and Pro)
54  * wheel controllers
55  *
56  * The original descriptors hide the separate throttle and brake axes in
57  * a custom vendor usage page, providing only a combined value as
58  * GenericDesktop.Y.
59  * These descriptors remove the combined Y axis and instead report
60  * separate throttle (Y) and brake (RZ).
61  */
62 static __u8 df_rdesc_fixed[] = {
63 0x05, 0x01,         /*  Usage Page (Desktop),                   */
64 0x09, 0x04,         /*  Usage (Joystik),                        */
65 0xA1, 0x01,         /*  Collection (Application),               */
66 0xA1, 0x02,         /*      Collection (Logical),               */
67 0x95, 0x01,         /*          Report Count (1),               */
68 0x75, 0x0A,         /*          Report Size (10),               */
69 0x14,               /*          Logical Minimum (0),            */
70 0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),         */
71 0x34,               /*          Physical Minimum (0),           */
72 0x46, 0xFF, 0x03,   /*          Physical Maximum (1023),        */
73 0x09, 0x30,         /*          Usage (X),                      */
74 0x81, 0x02,         /*          Input (Variable),               */
75 0x95, 0x0C,         /*          Report Count (12),              */
76 0x75, 0x01,         /*          Report Size (1),                */
77 0x25, 0x01,         /*          Logical Maximum (1),            */
78 0x45, 0x01,         /*          Physical Maximum (1),           */
79 0x05, 0x09,         /*          Usage (Buttons),                */
80 0x19, 0x01,         /*          Usage Minimum (1),              */
81 0x29, 0x0c,         /*          Usage Maximum (12),             */
82 0x81, 0x02,         /*          Input (Variable),               */
83 0x95, 0x02,         /*          Report Count (2),               */
84 0x06, 0x00, 0xFF,   /*          Usage Page (Vendor: 65280),     */
85 0x09, 0x01,         /*          Usage (?: 1),                   */
86 0x81, 0x02,         /*          Input (Variable),               */
87 0x05, 0x01,         /*          Usage Page (Desktop),           */
88 0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
89 0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
90 0x95, 0x01,         /*          Report Count (1),               */
91 0x75, 0x08,         /*          Report Size (8),                */
92 0x81, 0x02,         /*          Input (Variable),               */
93 0x25, 0x07,         /*          Logical Maximum (7),            */
94 0x46, 0x3B, 0x01,   /*          Physical Maximum (315),         */
95 0x75, 0x04,         /*          Report Size (4),                */
96 0x65, 0x14,         /*          Unit (Degrees),                 */
97 0x09, 0x39,         /*          Usage (Hat Switch),             */
98 0x81, 0x42,         /*          Input (Variable, Null State),   */
99 0x75, 0x01,         /*          Report Size (1),                */
100 0x95, 0x04,         /*          Report Count (4),               */
101 0x65, 0x00,         /*          Unit (none),                    */
102 0x06, 0x00, 0xFF,   /*          Usage Page (Vendor: 65280),     */
103 0x09, 0x01,         /*          Usage (?: 1),                   */
104 0x25, 0x01,         /*          Logical Maximum (1),            */
105 0x45, 0x01,         /*          Physical Maximum (1),           */
106 0x81, 0x02,         /*          Input (Variable),               */
107 0x05, 0x01,         /*          Usage Page (Desktop),           */
108 0x95, 0x01,         /*          Report Count (1),               */
109 0x75, 0x08,         /*          Report Size (8),                */
110 0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
111 0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
112 0x09, 0x31,         /*          Usage (Y),                      */
113 0x81, 0x02,         /*          Input (Variable),               */
114 0x09, 0x35,         /*          Usage (Rz),                     */
115 0x81, 0x02,         /*          Input (Variable),               */
116 0xC0,               /*      End Collection,                     */
117 0xA1, 0x02,         /*      Collection (Logical),               */
118 0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
119 0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
120 0x95, 0x07,         /*          Report Count (7),               */
121 0x75, 0x08,         /*          Report Size (8),                */
122 0x09, 0x03,         /*          Usage (?: 3),                   */
123 0x91, 0x02,         /*          Output (Variable),              */
124 0xC0,               /*      End Collection,                     */
125 0xC0                /*  End Collection                          */
126 };
127
128 static __u8 dfp_rdesc_fixed[] = {
129 0x05, 0x01,         /*  Usage Page (Desktop),                   */
130 0x09, 0x04,         /*  Usage (Joystik),                        */
131 0xA1, 0x01,         /*  Collection (Application),               */
132 0xA1, 0x02,         /*      Collection (Logical),               */
133 0x95, 0x01,         /*          Report Count (1),               */
134 0x75, 0x0E,         /*          Report Size (14),               */
135 0x14,               /*          Logical Minimum (0),            */
136 0x26, 0xFF, 0x3F,   /*          Logical Maximum (16383),        */
137 0x34,               /*          Physical Minimum (0),           */
138 0x46, 0xFF, 0x3F,   /*          Physical Maximum (16383),       */
139 0x09, 0x30,         /*          Usage (X),                      */
140 0x81, 0x02,         /*          Input (Variable),               */
141 0x95, 0x0E,         /*          Report Count (14),              */
142 0x75, 0x01,         /*          Report Size (1),                */
143 0x25, 0x01,         /*          Logical Maximum (1),            */
144 0x45, 0x01,         /*          Physical Maximum (1),           */
145 0x05, 0x09,         /*          Usage Page (Button),            */
146 0x19, 0x01,         /*          Usage Minimum (01h),            */
147 0x29, 0x0E,         /*          Usage Maximum (0Eh),            */
148 0x81, 0x02,         /*          Input (Variable),               */
149 0x05, 0x01,         /*          Usage Page (Desktop),           */
150 0x95, 0x01,         /*          Report Count (1),               */
151 0x75, 0x04,         /*          Report Size (4),                */
152 0x25, 0x07,         /*          Logical Maximum (7),            */
153 0x46, 0x3B, 0x01,   /*          Physical Maximum (315),         */
154 0x65, 0x14,         /*          Unit (Degrees),                 */
155 0x09, 0x39,         /*          Usage (Hat Switch),             */
156 0x81, 0x42,         /*          Input (Variable, Nullstate),    */
157 0x65, 0x00,         /*          Unit,                           */
158 0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
159 0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
160 0x75, 0x08,         /*          Report Size (8),                */
161 0x81, 0x01,         /*          Input (Constant),               */
162 0x09, 0x31,         /*          Usage (Y),                      */
163 0x81, 0x02,         /*          Input (Variable),               */
164 0x09, 0x35,         /*          Usage (Rz),                     */
165 0x81, 0x02,         /*          Input (Variable),               */
166 0x81, 0x01,         /*          Input (Constant),               */
167 0xC0,               /*      End Collection,                     */
168 0xA1, 0x02,         /*      Collection (Logical),               */
169 0x09, 0x02,         /*          Usage (02h),                    */
170 0x95, 0x07,         /*          Report Count (7),               */
171 0x91, 0x02,         /*          Output (Variable),              */
172 0xC0,               /*      End Collection,                     */
173 0xC0                /*  End Collection                          */
174 };
175
176 static __u8 fv_rdesc_fixed[] = {
177 0x05, 0x01,         /*  Usage Page (Desktop),                   */
178 0x09, 0x04,         /*  Usage (Joystik),                        */
179 0xA1, 0x01,         /*  Collection (Application),               */
180 0xA1, 0x02,         /*      Collection (Logical),               */
181 0x95, 0x01,         /*          Report Count (1),               */
182 0x75, 0x0A,         /*          Report Size (10),               */
183 0x15, 0x00,         /*          Logical Minimum (0),            */
184 0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),         */
185 0x35, 0x00,         /*          Physical Minimum (0),           */
186 0x46, 0xFF, 0x03,   /*          Physical Maximum (1023),        */
187 0x09, 0x30,         /*          Usage (X),                      */
188 0x81, 0x02,         /*          Input (Variable),               */
189 0x95, 0x0C,         /*          Report Count (12),              */
190 0x75, 0x01,         /*          Report Size (1),                */
191 0x25, 0x01,         /*          Logical Maximum (1),            */
192 0x45, 0x01,         /*          Physical Maximum (1),           */
193 0x05, 0x09,         /*          Usage Page (Button),            */
194 0x19, 0x01,         /*          Usage Minimum (01h),            */
195 0x29, 0x0C,         /*          Usage Maximum (0Ch),            */
196 0x81, 0x02,         /*          Input (Variable),               */
197 0x95, 0x02,         /*          Report Count (2),               */
198 0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),             */
199 0x09, 0x01,         /*          Usage (01h),                    */
200 0x81, 0x02,         /*          Input (Variable),               */
201 0x09, 0x02,         /*          Usage (02h),                    */
202 0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
203 0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
204 0x95, 0x01,         /*          Report Count (1),               */
205 0x75, 0x08,         /*          Report Size (8),                */
206 0x81, 0x02,         /*          Input (Variable),               */
207 0x05, 0x01,         /*          Usage Page (Desktop),           */
208 0x25, 0x07,         /*          Logical Maximum (7),            */
209 0x46, 0x3B, 0x01,   /*          Physical Maximum (315),         */
210 0x75, 0x04,         /*          Report Size (4),                */
211 0x65, 0x14,         /*          Unit (Degrees),                 */
212 0x09, 0x39,         /*          Usage (Hat Switch),             */
213 0x81, 0x42,         /*          Input (Variable, Null State),   */
214 0x75, 0x01,         /*          Report Size (1),                */
215 0x95, 0x04,         /*          Report Count (4),               */
216 0x65, 0x00,         /*          Unit,                           */
217 0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),             */
218 0x09, 0x01,         /*          Usage (01h),                    */
219 0x25, 0x01,         /*          Logical Maximum (1),            */
220 0x45, 0x01,         /*          Physical Maximum (1),           */
221 0x81, 0x02,         /*          Input (Variable),               */
222 0x05, 0x01,         /*          Usage Page (Desktop),           */
223 0x95, 0x01,         /*          Report Count (1),               */
224 0x75, 0x08,         /*          Report Size (8),                */
225 0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
226 0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
227 0x09, 0x31,         /*          Usage (Y),                      */
228 0x81, 0x02,         /*          Input (Variable),               */
229 0x09, 0x32,         /*          Usage (Z),                      */
230 0x81, 0x02,         /*          Input (Variable),               */
231 0xC0,               /*      End Collection,                     */
232 0xA1, 0x02,         /*      Collection (Logical),               */
233 0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
234 0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
235 0x95, 0x07,         /*          Report Count (7),               */
236 0x75, 0x08,         /*          Report Size (8),                */
237 0x09, 0x03,         /*          Usage (03h),                    */
238 0x91, 0x02,         /*          Output (Variable),              */
239 0xC0,               /*      End Collection,                     */
240 0xC0                /*  End Collection                          */
241 };
242
243 static __u8 momo_rdesc_fixed[] = {
244 0x05, 0x01,         /*  Usage Page (Desktop),               */
245 0x09, 0x04,         /*  Usage (Joystik),                    */
246 0xA1, 0x01,         /*  Collection (Application),           */
247 0xA1, 0x02,         /*      Collection (Logical),           */
248 0x95, 0x01,         /*          Report Count (1),           */
249 0x75, 0x0A,         /*          Report Size (10),           */
250 0x15, 0x00,         /*          Logical Minimum (0),        */
251 0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
252 0x35, 0x00,         /*          Physical Minimum (0),       */
253 0x46, 0xFF, 0x03,   /*          Physical Maximum (1023),    */
254 0x09, 0x30,         /*          Usage (X),                  */
255 0x81, 0x02,         /*          Input (Variable),           */
256 0x95, 0x08,         /*          Report Count (8),           */
257 0x75, 0x01,         /*          Report Size (1),            */
258 0x25, 0x01,         /*          Logical Maximum (1),        */
259 0x45, 0x01,         /*          Physical Maximum (1),       */
260 0x05, 0x09,         /*          Usage Page (Button),        */
261 0x19, 0x01,         /*          Usage Minimum (01h),        */
262 0x29, 0x08,         /*          Usage Maximum (08h),        */
263 0x81, 0x02,         /*          Input (Variable),           */
264 0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
265 0x75, 0x0E,         /*          Report Size (14),           */
266 0x95, 0x01,         /*          Report Count (1),           */
267 0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
268 0x46, 0xFF, 0x00,   /*          Physical Maximum (255),     */
269 0x09, 0x00,         /*          Usage (00h),                */
270 0x81, 0x02,         /*          Input (Variable),           */
271 0x05, 0x01,         /*          Usage Page (Desktop),       */
272 0x75, 0x08,         /*          Report Size (8),            */
273 0x09, 0x31,         /*          Usage (Y),                  */
274 0x81, 0x02,         /*          Input (Variable),           */
275 0x09, 0x32,         /*          Usage (Z),                  */
276 0x81, 0x02,         /*          Input (Variable),           */
277 0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
278 0x09, 0x01,         /*          Usage (01h),                */
279 0x81, 0x02,         /*          Input (Variable),           */
280 0xC0,               /*      End Collection,                 */
281 0xA1, 0x02,         /*      Collection (Logical),           */
282 0x09, 0x02,         /*          Usage (02h),                */
283 0x95, 0x07,         /*          Report Count (7),           */
284 0x91, 0x02,         /*          Output (Variable),          */
285 0xC0,               /*      End Collection,                 */
286 0xC0                /*  End Collection                      */
287 };
288
289 static __u8 momo2_rdesc_fixed[] = {
290 0x05, 0x01,         /*  Usage Page (Desktop),               */
291 0x09, 0x04,         /*  Usage (Joystik),                    */
292 0xA1, 0x01,         /*  Collection (Application),           */
293 0xA1, 0x02,         /*      Collection (Logical),           */
294 0x95, 0x01,         /*          Report Count (1),           */
295 0x75, 0x0A,         /*          Report Size (10),           */
296 0x15, 0x00,         /*          Logical Minimum (0),        */
297 0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
298 0x35, 0x00,         /*          Physical Minimum (0),       */
299 0x46, 0xFF, 0x03,   /*          Physical Maximum (1023),    */
300 0x09, 0x30,         /*          Usage (X),                  */
301 0x81, 0x02,         /*          Input (Variable),           */
302 0x95, 0x0A,         /*          Report Count (10),          */
303 0x75, 0x01,         /*          Report Size (1),            */
304 0x25, 0x01,         /*          Logical Maximum (1),        */
305 0x45, 0x01,         /*          Physical Maximum (1),       */
306 0x05, 0x09,         /*          Usage Page (Button),        */
307 0x19, 0x01,         /*          Usage Minimum (01h),        */
308 0x29, 0x0A,         /*          Usage Maximum (0Ah),        */
309 0x81, 0x02,         /*          Input (Variable),           */
310 0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
311 0x09, 0x00,         /*          Usage (00h),                */
312 0x95, 0x04,         /*          Report Count (4),           */
313 0x81, 0x02,         /*          Input (Variable),           */
314 0x95, 0x01,         /*          Report Count (1),           */
315 0x75, 0x08,         /*          Report Size (8),            */
316 0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
317 0x46, 0xFF, 0x00,   /*          Physical Maximum (255),     */
318 0x09, 0x01,         /*          Usage (01h),                */
319 0x81, 0x02,         /*          Input (Variable),           */
320 0x05, 0x01,         /*          Usage Page (Desktop),       */
321 0x09, 0x31,         /*          Usage (Y),                  */
322 0x81, 0x02,         /*          Input (Variable),           */
323 0x09, 0x32,         /*          Usage (Z),                  */
324 0x81, 0x02,         /*          Input (Variable),           */
325 0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
326 0x09, 0x00,         /*          Usage (00h),                */
327 0x81, 0x02,         /*          Input (Variable),           */
328 0xC0,               /*      End Collection,                 */
329 0xA1, 0x02,         /*      Collection (Logical),           */
330 0x09, 0x02,         /*          Usage (02h),                */
331 0x95, 0x07,         /*          Report Count (7),           */
332 0x91, 0x02,         /*          Output (Variable),          */
333 0xC0,               /*      End Collection,                 */
334 0xC0                /*  End Collection                      */
335 };
336
337 /*
338  * Certain Logitech keyboards send in report #3 keys which are far
339  * above the logical maximum described in descriptor. This extends
340  * the original value of 0x28c of logical maximum to 0x104d
341  */
342 static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
343                 unsigned int *rsize)
344 {
345         struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
346         struct usb_device_descriptor *udesc;
347         __u16 bcdDevice, rev_maj, rev_min;
348
349         if ((drv_data->quirks & LG_RDESC) && *rsize >= 91 && rdesc[83] == 0x26 &&
350                         rdesc[84] == 0x8c && rdesc[85] == 0x02) {
351                 hid_info(hdev,
352                          "fixing up Logitech keyboard report descriptor\n");
353                 rdesc[84] = rdesc[89] = 0x4d;
354                 rdesc[85] = rdesc[90] = 0x10;
355         }
356         if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 51 &&
357                         rdesc[32] == 0x81 && rdesc[33] == 0x06 &&
358                         rdesc[49] == 0x81 && rdesc[50] == 0x06) {
359                 hid_info(hdev,
360                          "fixing up rel/abs in Logitech report descriptor\n");
361                 rdesc[33] = rdesc[50] = 0x02;
362         }
363
364         switch (hdev->product) {
365
366         /* Several wheels report as this id when operating in emulation mode. */
367         case USB_DEVICE_ID_LOGITECH_WHEEL:
368                 udesc = &(hid_to_usb_dev(hdev)->descriptor);
369                 if (!udesc) {
370                         hid_err(hdev, "NULL USB device descriptor\n");
371                         break;
372                 }
373                 bcdDevice = le16_to_cpu(udesc->bcdDevice);
374                 rev_maj = bcdDevice >> 8;
375                 rev_min = bcdDevice & 0xff;
376
377                 /* Update the report descriptor for only the Driving Force wheel */
378                 if (rev_maj == 1 && rev_min == 2 &&
379                                 *rsize == DF_RDESC_ORIG_SIZE) {
380                         hid_info(hdev,
381                                 "fixing up Logitech Driving Force report descriptor\n");
382                         rdesc = df_rdesc_fixed;
383                         *rsize = sizeof(df_rdesc_fixed);
384                 }
385                 break;
386
387         case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
388                 if (*rsize == MOMO_RDESC_ORIG_SIZE) {
389                         hid_info(hdev,
390                                 "fixing up Logitech Momo Force (Red) report descriptor\n");
391                         rdesc = momo_rdesc_fixed;
392                         *rsize = sizeof(momo_rdesc_fixed);
393                 }
394                 break;
395
396         case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
397                 if (*rsize == MOMO2_RDESC_ORIG_SIZE) {
398                         hid_info(hdev,
399                                 "fixing up Logitech Momo Racing Force (Black) report descriptor\n");
400                         rdesc = momo2_rdesc_fixed;
401                         *rsize = sizeof(momo2_rdesc_fixed);
402                 }
403                 break;
404
405         case USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL:
406                 if (*rsize == FV_RDESC_ORIG_SIZE) {
407                         hid_info(hdev,
408                                 "fixing up Logitech Formula Vibration report descriptor\n");
409                         rdesc = fv_rdesc_fixed;
410                         *rsize = sizeof(fv_rdesc_fixed);
411                 }
412                 break;
413
414         case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
415                 if (*rsize == DFP_RDESC_ORIG_SIZE) {
416                         hid_info(hdev,
417                                 "fixing up Logitech Driving Force Pro report descriptor\n");
418                         rdesc = dfp_rdesc_fixed;
419                         *rsize = sizeof(dfp_rdesc_fixed);
420                 }
421                 break;
422
423         case USB_DEVICE_ID_LOGITECH_WII_WHEEL:
424                 if (*rsize >= 101 && rdesc[41] == 0x95 && rdesc[42] == 0x0B &&
425                                 rdesc[47] == 0x05 && rdesc[48] == 0x09) {
426                         hid_info(hdev, "fixing up Logitech Speed Force Wireless report descriptor\n");
427                         rdesc[41] = 0x05;
428                         rdesc[42] = 0x09;
429                         rdesc[47] = 0x95;
430                         rdesc[48] = 0x0B;
431                 }
432                 break;
433         }
434
435         return rdesc;
436 }
437
438 #define lg_map_key_clear(c)     hid_map_usage_clear(hi, usage, bit, max, \
439                 EV_KEY, (c))
440
441 static int lg_ultrax_remote_mapping(struct hid_input *hi,
442                 struct hid_usage *usage, unsigned long **bit, int *max)
443 {
444         if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
445                 return 0;
446
447         set_bit(EV_REP, hi->input->evbit);
448         switch (usage->hid & HID_USAGE) {
449         /* Reported on Logitech Ultra X Media Remote */
450         case 0x004: lg_map_key_clear(KEY_AGAIN);        break;
451         case 0x00d: lg_map_key_clear(KEY_HOME);         break;
452         case 0x024: lg_map_key_clear(KEY_SHUFFLE);      break;
453         case 0x025: lg_map_key_clear(KEY_TV);           break;
454         case 0x026: lg_map_key_clear(KEY_MENU);         break;
455         case 0x031: lg_map_key_clear(KEY_AUDIO);        break;
456         case 0x032: lg_map_key_clear(KEY_TEXT);         break;
457         case 0x033: lg_map_key_clear(KEY_LAST);         break;
458         case 0x047: lg_map_key_clear(KEY_MP3);          break;
459         case 0x048: lg_map_key_clear(KEY_DVD);          break;
460         case 0x049: lg_map_key_clear(KEY_MEDIA);        break;
461         case 0x04a: lg_map_key_clear(KEY_VIDEO);        break;
462         case 0x04b: lg_map_key_clear(KEY_ANGLE);        break;
463         case 0x04c: lg_map_key_clear(KEY_LANGUAGE);     break;
464         case 0x04d: lg_map_key_clear(KEY_SUBTITLE);     break;
465         case 0x051: lg_map_key_clear(KEY_RED);          break;
466         case 0x052: lg_map_key_clear(KEY_CLOSE);        break;
467
468         default:
469                 return 0;
470         }
471         return 1;
472 }
473
474 static int lg_dinovo_mapping(struct hid_input *hi, struct hid_usage *usage,
475                 unsigned long **bit, int *max)
476 {
477         if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
478                 return 0;
479
480         switch (usage->hid & HID_USAGE) {
481
482         case 0x00d: lg_map_key_clear(KEY_MEDIA);        break;
483         default:
484                 return 0;
485
486         }
487         return 1;
488 }
489
490 static int lg_wireless_mapping(struct hid_input *hi, struct hid_usage *usage,
491                 unsigned long **bit, int *max)
492 {
493         if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
494                 return 0;
495
496         switch (usage->hid & HID_USAGE) {
497         case 0x1001: lg_map_key_clear(KEY_MESSENGER);           break;
498         case 0x1003: lg_map_key_clear(KEY_SOUND);               break;
499         case 0x1004: lg_map_key_clear(KEY_VIDEO);               break;
500         case 0x1005: lg_map_key_clear(KEY_AUDIO);               break;
501         case 0x100a: lg_map_key_clear(KEY_DOCUMENTS);           break;
502         /* The following two entries are Playlist 1 and 2 on the MX3200 */
503         case 0x100f: lg_map_key_clear(KEY_FN_1);                break;
504         case 0x1010: lg_map_key_clear(KEY_FN_2);                break;
505         case 0x1011: lg_map_key_clear(KEY_PREVIOUSSONG);        break;
506         case 0x1012: lg_map_key_clear(KEY_NEXTSONG);            break;
507         case 0x1013: lg_map_key_clear(KEY_CAMERA);              break;
508         case 0x1014: lg_map_key_clear(KEY_MESSENGER);           break;
509         case 0x1015: lg_map_key_clear(KEY_RECORD);              break;
510         case 0x1016: lg_map_key_clear(KEY_PLAYER);              break;
511         case 0x1017: lg_map_key_clear(KEY_EJECTCD);             break;
512         case 0x1018: lg_map_key_clear(KEY_MEDIA);               break;
513         case 0x1019: lg_map_key_clear(KEY_PROG1);               break;
514         case 0x101a: lg_map_key_clear(KEY_PROG2);               break;
515         case 0x101b: lg_map_key_clear(KEY_PROG3);               break;
516         case 0x101c: lg_map_key_clear(KEY_CYCLEWINDOWS);        break;
517         case 0x101f: lg_map_key_clear(KEY_ZOOMIN);              break;
518         case 0x1020: lg_map_key_clear(KEY_ZOOMOUT);             break;
519         case 0x1021: lg_map_key_clear(KEY_ZOOMRESET);           break;
520         case 0x1023: lg_map_key_clear(KEY_CLOSE);               break;
521         case 0x1027: lg_map_key_clear(KEY_MENU);                break;
522         /* this one is marked as 'Rotate' */
523         case 0x1028: lg_map_key_clear(KEY_ANGLE);               break;
524         case 0x1029: lg_map_key_clear(KEY_SHUFFLE);             break;
525         case 0x102a: lg_map_key_clear(KEY_BACK);                break;
526         case 0x102b: lg_map_key_clear(KEY_CYCLEWINDOWS);        break;
527         case 0x102d: lg_map_key_clear(KEY_WWW);                 break;
528         /* The following two are 'Start/answer call' and 'End/reject call'
529            on the MX3200 */
530         case 0x1031: lg_map_key_clear(KEY_OK);                  break;
531         case 0x1032: lg_map_key_clear(KEY_CANCEL);              break;
532         case 0x1041: lg_map_key_clear(KEY_BATTERY);             break;
533         case 0x1042: lg_map_key_clear(KEY_WORDPROCESSOR);       break;
534         case 0x1043: lg_map_key_clear(KEY_SPREADSHEET);         break;
535         case 0x1044: lg_map_key_clear(KEY_PRESENTATION);        break;
536         case 0x1045: lg_map_key_clear(KEY_UNDO);                break;
537         case 0x1046: lg_map_key_clear(KEY_REDO);                break;
538         case 0x1047: lg_map_key_clear(KEY_PRINT);               break;
539         case 0x1048: lg_map_key_clear(KEY_SAVE);                break;
540         case 0x1049: lg_map_key_clear(KEY_PROG1);               break;
541         case 0x104a: lg_map_key_clear(KEY_PROG2);               break;
542         case 0x104b: lg_map_key_clear(KEY_PROG3);               break;
543         case 0x104c: lg_map_key_clear(KEY_PROG4);               break;
544
545         default:
546                 return 0;
547         }
548         return 1;
549 }
550
551 static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
552                 struct hid_field *field, struct hid_usage *usage,
553                 unsigned long **bit, int *max)
554 {
555         /* extended mapping for certain Logitech hardware (Logitech cordless
556            desktop LX500) */
557         static const u8 e_keymap[] = {
558                   0,216,  0,213,175,156,  0,  0,  0,  0,
559                 144,  0,  0,  0,  0,  0,  0,  0,  0,212,
560                 174,167,152,161,112,  0,  0,  0,154,  0,
561                   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
562                   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
563                   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
564                   0,  0,  0,  0,  0,183,184,185,186,187,
565                 188,189,190,191,192,193,194,  0,  0,  0
566         };
567         struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
568         unsigned int hid = usage->hid;
569
570         if (hdev->product == USB_DEVICE_ID_LOGITECH_RECEIVER &&
571                         lg_ultrax_remote_mapping(hi, usage, bit, max))
572                 return 1;
573
574         if (hdev->product == USB_DEVICE_ID_DINOVO_MINI &&
575                         lg_dinovo_mapping(hi, usage, bit, max))
576                 return 1;
577
578         if ((drv_data->quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max))
579                 return 1;
580
581         if ((hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
582                 return 0;
583
584         hid &= HID_USAGE;
585
586         /* Special handling for Logitech Cordless Desktop */
587         if (field->application == HID_GD_MOUSE) {
588                 if ((drv_data->quirks & LG_IGNORE_DOUBLED_WHEEL) &&
589                                 (hid == 7 || hid == 8))
590                         return -1;
591         } else {
592                 if ((drv_data->quirks & LG_EXPANDED_KEYMAP) &&
593                                 hid < ARRAY_SIZE(e_keymap) &&
594                                 e_keymap[hid] != 0) {
595                         hid_map_usage(hi, usage, bit, max, EV_KEY,
596                                         e_keymap[hid]);
597                         return 1;
598                 }
599         }
600
601         return 0;
602 }
603
604 static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
605                 struct hid_field *field, struct hid_usage *usage,
606                 unsigned long **bit, int *max)
607 {
608         struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
609
610         if ((drv_data->quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY &&
611                         (field->flags & HID_MAIN_ITEM_RELATIVE))
612                 field->flags &= ~HID_MAIN_ITEM_RELATIVE;
613
614         if ((drv_data->quirks & LG_DUPLICATE_USAGES) && (usage->type == EV_KEY ||
615                          usage->type == EV_REL || usage->type == EV_ABS))
616                 clear_bit(usage->code, *bit);
617
618         /* Ensure that Logitech wheels are not given a default fuzz/flat value */
619         if (usage->type == EV_ABS && (usage->code == ABS_X ||
620                         usage->code == ABS_Y || usage->code == ABS_Z ||
621                         usage->code == ABS_RZ)) {
622                 switch (hdev->product) {
623                 case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
624                 case USB_DEVICE_ID_LOGITECH_WHEEL:
625                 case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
626                 case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
627                 case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
628                 case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
629                 case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
630                 case USB_DEVICE_ID_LOGITECH_WII_WHEEL:
631                 case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
632                 case USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL:
633                         field->application = HID_GD_MULTIAXIS;
634                         break;
635                 default:
636                         break;
637                 }
638         }
639
640         return 0;
641 }
642
643 static int lg_event(struct hid_device *hdev, struct hid_field *field,
644                 struct hid_usage *usage, __s32 value)
645 {
646         struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
647
648         if ((drv_data->quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) {
649                 input_event(field->hidinput->input, usage->type, usage->code,
650                                 -value);
651                 return 1;
652         }
653         if (drv_data->quirks & LG_FF4) {
654                 return lg4ff_adjust_input_event(hdev, field, usage, value, drv_data);
655         }
656
657         return 0;
658 }
659
660 static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
661 {
662         struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
663         __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
664         unsigned int connect_mask = HID_CONNECT_DEFAULT;
665         struct lg_drv_data *drv_data;
666         int ret;
667
668         /* G29 only work with the 1st interface */
669         if ((hdev->product == USB_DEVICE_ID_LOGITECH_G29_WHEEL) &&
670             (iface_num != 0)) {
671                 dbg_hid("%s: ignoring ifnum %d\n", __func__, iface_num);
672                 return -ENODEV;
673         }
674
675         drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL);
676         if (!drv_data) {
677                 hid_err(hdev, "Insufficient memory, cannot allocate driver data\n");
678                 return -ENOMEM;
679         }
680         drv_data->quirks = id->driver_data;
681
682         hid_set_drvdata(hdev, (void *)drv_data);
683
684         if (drv_data->quirks & LG_NOGET)
685                 hdev->quirks |= HID_QUIRK_NOGET;
686
687         ret = hid_parse(hdev);
688         if (ret) {
689                 hid_err(hdev, "parse failed\n");
690                 goto err_free;
691         }
692
693         if (drv_data->quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4))
694                 connect_mask &= ~HID_CONNECT_FF;
695
696         ret = hid_hw_start(hdev, connect_mask);
697         if (ret) {
698                 hid_err(hdev, "hw start failed\n");
699                 goto err_free;
700         }
701
702         /* Setup wireless link with Logitech Wii wheel */
703         if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
704                 const unsigned char cbuf[] = { 0x00, 0xAF,  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
705                 u8 *buf = kmemdup(cbuf, sizeof(cbuf), GFP_KERNEL);
706
707                 if (!buf) {
708                         ret = -ENOMEM;
709                         goto err_stop;
710                 }
711
712                 ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(cbuf),
713                                         HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
714                 if (ret >= 0) {
715                         /* insert a little delay of 10 jiffies ~ 40ms */
716                         wait_queue_head_t wait;
717                         init_waitqueue_head (&wait);
718                         wait_event_interruptible_timeout(wait, 0,
719                                                          msecs_to_jiffies(40));
720
721                         /* Select random Address */
722                         buf[1] = 0xB2;
723                         get_random_bytes(&buf[2], 2);
724
725                         ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(cbuf),
726                                         HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
727                 }
728                 kfree(buf);
729         }
730
731         if (drv_data->quirks & LG_FF)
732                 ret = lgff_init(hdev);
733         else if (drv_data->quirks & LG_FF2)
734                 ret = lg2ff_init(hdev);
735         else if (drv_data->quirks & LG_FF3)
736                 ret = lg3ff_init(hdev);
737         else if (drv_data->quirks & LG_FF4)
738                 ret = lg4ff_init(hdev);
739
740         if (ret)
741                 goto err_stop;
742
743         return 0;
744
745 err_stop:
746         hid_hw_stop(hdev);
747 err_free:
748         kfree(drv_data);
749         return ret;
750 }
751
752 static void lg_remove(struct hid_device *hdev)
753 {
754         struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
755         if (drv_data->quirks & LG_FF4)
756                 lg4ff_deinit(hdev);
757         hid_hw_stop(hdev);
758         kfree(drv_data);
759 }
760
761 static const struct hid_device_id lg_devices[] = {
762         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
763                 .driver_data = LG_RDESC | LG_WIRELESS },
764         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER),
765                 .driver_data = LG_RDESC | LG_WIRELESS },
766         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2),
767                 .driver_data = LG_RDESC | LG_WIRELESS },
768
769         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER),
770                 .driver_data = LG_BAD_RELATIVE_KEYS },
771
772         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP),
773                 .driver_data = LG_DUPLICATE_USAGES },
774         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE),
775                 .driver_data = LG_DUPLICATE_USAGES },
776         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI),
777                 .driver_data = LG_DUPLICATE_USAGES },
778
779         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD),
780                 .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
781         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500),
782                 .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
783
784         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D),
785                 .driver_data = LG_NOGET },
786         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DUAL_ACTION),
787                 .driver_data = LG_NOGET },
788         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL),
789                 .driver_data = LG_NOGET | LG_FF4 },
790
791         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD),
792                 .driver_data = LG_FF2 },
793         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD),
794                 .driver_data = LG_FF },
795         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2),
796                 .driver_data = LG_FF },
797         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G29_WHEEL),
798                 .driver_data = LG_FF4 },
799         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D),
800                 .driver_data = LG_FF },
801         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO),
802                 .driver_data = LG_FF },
803         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL),
804                 .driver_data = LG_NOGET | LG_FF4 },
805         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2),
806                 .driver_data = LG_FF4 },
807         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL),
808                 .driver_data = LG_FF2 },
809         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
810                 .driver_data = LG_FF4 },
811         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL),
812                 .driver_data = LG_FF4 },
813         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL),
814                 .driver_data = LG_FF4 },
815         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL),
816                 .driver_data = LG_NOGET | LG_FF4 },
817         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL),
818                 .driver_data = LG_FF4 },
819         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG),
820                 .driver_data = LG_FF },
821         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
822                 .driver_data = LG_FF2 },
823         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940),
824                 .driver_data = LG_FF3 },
825         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR),
826                 .driver_data = LG_RDESC_REL_ABS },
827         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER),
828                 .driver_data = LG_RDESC_REL_ABS },
829         { }
830 };
831
832 MODULE_DEVICE_TABLE(hid, lg_devices);
833
834 static struct hid_driver lg_driver = {
835         .name = "logitech",
836         .id_table = lg_devices,
837         .report_fixup = lg_report_fixup,
838         .input_mapping = lg_input_mapping,
839         .input_mapped = lg_input_mapped,
840         .event = lg_event,
841         .probe = lg_probe,
842         .remove = lg_remove,
843 };
844 module_hid_driver(lg_driver);
845
846 #ifdef CONFIG_LOGIWHEELS_FF
847 int lg4ff_no_autoswitch = 0;
848 module_param_named(lg4ff_no_autoswitch, lg4ff_no_autoswitch, int, S_IRUGO);
849 MODULE_PARM_DESC(lg4ff_no_autoswitch, "Do not switch multimode wheels to their native mode automatically");
850 #endif
851
852 MODULE_LICENSE("GPL");