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