Merge tag '5.15-rc-ksmbd-part2' of git://git.samba.org/ksmbd
[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_wireless_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_CONSUMER)
575                 return 0;
576
577         switch (usage->hid & HID_USAGE) {
578         case 0x1001: lg_map_key_clear(KEY_MESSENGER);           break;
579         case 0x1003: lg_map_key_clear(KEY_SOUND);               break;
580         case 0x1004: lg_map_key_clear(KEY_VIDEO);               break;
581         case 0x1005: lg_map_key_clear(KEY_AUDIO);               break;
582         case 0x100a: lg_map_key_clear(KEY_DOCUMENTS);           break;
583         /* The following two entries are Playlist 1 and 2 on the MX3200 */
584         case 0x100f: lg_map_key_clear(KEY_FN_1);                break;
585         case 0x1010: lg_map_key_clear(KEY_FN_2);                break;
586         case 0x1011: lg_map_key_clear(KEY_PREVIOUSSONG);        break;
587         case 0x1012: lg_map_key_clear(KEY_NEXTSONG);            break;
588         case 0x1013: lg_map_key_clear(KEY_CAMERA);              break;
589         case 0x1014: lg_map_key_clear(KEY_MESSENGER);           break;
590         case 0x1015: lg_map_key_clear(KEY_RECORD);              break;
591         case 0x1016: lg_map_key_clear(KEY_PLAYER);              break;
592         case 0x1017: lg_map_key_clear(KEY_EJECTCD);             break;
593         case 0x1018: lg_map_key_clear(KEY_MEDIA);               break;
594         case 0x1019: lg_map_key_clear(KEY_PROG1);               break;
595         case 0x101a: lg_map_key_clear(KEY_PROG2);               break;
596         case 0x101b: lg_map_key_clear(KEY_PROG3);               break;
597         case 0x101c: lg_map_key_clear(KEY_CYCLEWINDOWS);        break;
598         case 0x101f: lg_map_key_clear(KEY_ZOOMIN);              break;
599         case 0x1020: lg_map_key_clear(KEY_ZOOMOUT);             break;
600         case 0x1021: lg_map_key_clear(KEY_ZOOMRESET);           break;
601         case 0x1023: lg_map_key_clear(KEY_CLOSE);               break;
602         case 0x1027: lg_map_key_clear(KEY_MENU);                break;
603         /* this one is marked as 'Rotate' */
604         case 0x1028: lg_map_key_clear(KEY_ANGLE);               break;
605         case 0x1029: lg_map_key_clear(KEY_SHUFFLE);             break;
606         case 0x102a: lg_map_key_clear(KEY_BACK);                break;
607         case 0x102b: lg_map_key_clear(KEY_CYCLEWINDOWS);        break;
608         case 0x102d: lg_map_key_clear(KEY_WWW);                 break;
609         /* The following two are 'Start/answer call' and 'End/reject call'
610            on the MX3200 */
611         case 0x1031: lg_map_key_clear(KEY_OK);                  break;
612         case 0x1032: lg_map_key_clear(KEY_CANCEL);              break;
613         case 0x1041: lg_map_key_clear(KEY_BATTERY);             break;
614         case 0x1042: lg_map_key_clear(KEY_WORDPROCESSOR);       break;
615         case 0x1043: lg_map_key_clear(KEY_SPREADSHEET);         break;
616         case 0x1044: lg_map_key_clear(KEY_PRESENTATION);        break;
617         case 0x1045: lg_map_key_clear(KEY_UNDO);                break;
618         case 0x1046: lg_map_key_clear(KEY_REDO);                break;
619         case 0x1047: lg_map_key_clear(KEY_PRINT);               break;
620         case 0x1048: lg_map_key_clear(KEY_SAVE);                break;
621         case 0x1049: lg_map_key_clear(KEY_PROG1);               break;
622         case 0x104a: lg_map_key_clear(KEY_PROG2);               break;
623         case 0x104b: lg_map_key_clear(KEY_PROG3);               break;
624         case 0x104c: lg_map_key_clear(KEY_PROG4);               break;
625
626         default:
627                 return 0;
628         }
629         return 1;
630 }
631
632 static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
633                 struct hid_field *field, struct hid_usage *usage,
634                 unsigned long **bit, int *max)
635 {
636         /* extended mapping for certain Logitech hardware (Logitech cordless
637            desktop LX500) */
638         static const u8 e_keymap[] = {
639                   0,216,  0,213,175,156,  0,  0,  0,  0,
640                 144,  0,  0,  0,  0,  0,  0,  0,  0,212,
641                 174,167,152,161,112,  0,  0,  0,154,  0,
642                   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
643                   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
644                   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
645                   0,  0,  0,  0,  0,183,184,185,186,187,
646                 188,189,190,191,192,193,194,  0,  0,  0
647         };
648         struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
649         unsigned int hid = usage->hid;
650
651         if (hdev->product == USB_DEVICE_ID_LOGITECH_RECEIVER &&
652                         lg_ultrax_remote_mapping(hi, usage, bit, max))
653                 return 1;
654
655         if ((drv_data->quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max))
656                 return 1;
657
658         if ((hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
659                 return 0;
660
661         hid &= HID_USAGE;
662
663         /* Special handling for Logitech Cordless Desktop */
664         if (field->application == HID_GD_MOUSE) {
665                 if ((drv_data->quirks & LG_IGNORE_DOUBLED_WHEEL) &&
666                                 (hid == 7 || hid == 8))
667                         return -1;
668         } else {
669                 if ((drv_data->quirks & LG_EXPANDED_KEYMAP) &&
670                                 hid < ARRAY_SIZE(e_keymap) &&
671                                 e_keymap[hid] != 0) {
672                         hid_map_usage(hi, usage, bit, max, EV_KEY,
673                                         e_keymap[hid]);
674                         return 1;
675                 }
676         }
677
678         return 0;
679 }
680
681 static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
682                 struct hid_field *field, struct hid_usage *usage,
683                 unsigned long **bit, int *max)
684 {
685         struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
686
687         if ((drv_data->quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY &&
688                         (field->flags & HID_MAIN_ITEM_RELATIVE))
689                 field->flags &= ~HID_MAIN_ITEM_RELATIVE;
690
691         if ((drv_data->quirks & LG_DUPLICATE_USAGES) && (usage->type == EV_KEY ||
692                          usage->type == EV_REL || usage->type == EV_ABS))
693                 clear_bit(usage->code, *bit);
694
695         /* Ensure that Logitech wheels are not given a default fuzz/flat value */
696         if (usage->type == EV_ABS && (usage->code == ABS_X ||
697                         usage->code == ABS_Y || usage->code == ABS_Z ||
698                         usage->code == ABS_RZ)) {
699                 switch (hdev->product) {
700                 case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
701                 case USB_DEVICE_ID_LOGITECH_WINGMAN_FG:
702                 case USB_DEVICE_ID_LOGITECH_WINGMAN_FFG:
703                 case USB_DEVICE_ID_LOGITECH_WHEEL:
704                 case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
705                 case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
706                 case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
707                 case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
708                 case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
709                 case USB_DEVICE_ID_LOGITECH_WII_WHEEL:
710                 case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
711                 case USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL:
712                         field->application = HID_GD_MULTIAXIS;
713                         break;
714                 default:
715                         break;
716                 }
717         }
718
719         return 0;
720 }
721
722 static int lg_event(struct hid_device *hdev, struct hid_field *field,
723                 struct hid_usage *usage, __s32 value)
724 {
725         struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
726
727         if ((drv_data->quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) {
728                 input_event(field->hidinput->input, usage->type, usage->code,
729                                 -value);
730                 return 1;
731         }
732         if (drv_data->quirks & LG_FF4) {
733                 return lg4ff_adjust_input_event(hdev, field, usage, value, drv_data);
734         }
735
736         return 0;
737 }
738
739 static int lg_raw_event(struct hid_device *hdev, struct hid_report *report,
740                 u8 *rd, int size)
741 {
742         struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
743
744         if (drv_data->quirks & LG_FF4)
745                 return lg4ff_raw_event(hdev, report, rd, size, drv_data);
746
747         return 0;
748 }
749
750 static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
751 {
752         struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
753         __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
754         unsigned int connect_mask = HID_CONNECT_DEFAULT;
755         struct lg_drv_data *drv_data;
756         int ret;
757
758         /* G29 only work with the 1st interface */
759         if ((hdev->product == USB_DEVICE_ID_LOGITECH_G29_WHEEL) &&
760             (iface_num != 0)) {
761                 dbg_hid("%s: ignoring ifnum %d\n", __func__, iface_num);
762                 return -ENODEV;
763         }
764
765         drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL);
766         if (!drv_data) {
767                 hid_err(hdev, "Insufficient memory, cannot allocate driver data\n");
768                 return -ENOMEM;
769         }
770         drv_data->quirks = id->driver_data;
771
772         hid_set_drvdata(hdev, (void *)drv_data);
773
774         if (drv_data->quirks & LG_NOGET)
775                 hdev->quirks |= HID_QUIRK_NOGET;
776
777         ret = hid_parse(hdev);
778         if (ret) {
779                 hid_err(hdev, "parse failed\n");
780                 goto err_free;
781         }
782
783         if (drv_data->quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4))
784                 connect_mask &= ~HID_CONNECT_FF;
785
786         ret = hid_hw_start(hdev, connect_mask);
787         if (ret) {
788                 hid_err(hdev, "hw start failed\n");
789                 goto err_free;
790         }
791
792         /* Setup wireless link with Logitech Wii wheel */
793         if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
794                 static const unsigned char cbuf[] = {
795                         0x00, 0xAF,  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
796                 };
797                 u8 *buf = kmemdup(cbuf, sizeof(cbuf), GFP_KERNEL);
798
799                 if (!buf) {
800                         ret = -ENOMEM;
801                         goto err_stop;
802                 }
803
804                 ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(cbuf),
805                                         HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
806                 if (ret >= 0) {
807                         /* insert a little delay of 10 jiffies ~ 40ms */
808                         wait_queue_head_t wait;
809                         init_waitqueue_head (&wait);
810                         wait_event_interruptible_timeout(wait, 0,
811                                                          msecs_to_jiffies(40));
812
813                         /* Select random Address */
814                         buf[1] = 0xB2;
815                         get_random_bytes(&buf[2], 2);
816
817                         ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(cbuf),
818                                         HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
819                 }
820                 kfree(buf);
821         }
822
823         if (drv_data->quirks & LG_FF)
824                 ret = lgff_init(hdev);
825         else if (drv_data->quirks & LG_FF2)
826                 ret = lg2ff_init(hdev);
827         else if (drv_data->quirks & LG_FF3)
828                 ret = lg3ff_init(hdev);
829         else if (drv_data->quirks & LG_FF4)
830                 ret = lg4ff_init(hdev);
831
832         if (ret)
833                 goto err_stop;
834
835         return 0;
836
837 err_stop:
838         hid_hw_stop(hdev);
839 err_free:
840         kfree(drv_data);
841         return ret;
842 }
843
844 static void lg_remove(struct hid_device *hdev)
845 {
846         struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
847         if (drv_data->quirks & LG_FF4)
848                 lg4ff_deinit(hdev);
849         hid_hw_stop(hdev);
850         kfree(drv_data);
851 }
852
853 static const struct hid_device_id lg_devices[] = {
854         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER),
855                 .driver_data = LG_RDESC | LG_WIRELESS },
856
857         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER),
858                 .driver_data = LG_BAD_RELATIVE_KEYS },
859
860         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP),
861                 .driver_data = LG_DUPLICATE_USAGES },
862
863         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD),
864                 .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
865         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500),
866                 .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
867
868         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D),
869                 .driver_data = LG_NOGET },
870         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DUAL_ACTION),
871                 .driver_data = LG_NOGET },
872         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL),
873                 .driver_data = LG_NOGET | LG_FF4 },
874
875         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD),
876                 .driver_data = LG_FF2 },
877         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD),
878                 .driver_data = LG_FF },
879         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2),
880                 .driver_data = LG_FF },
881         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G29_WHEEL),
882                 .driver_data = LG_FF4 },
883         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D),
884                 .driver_data = LG_FF },
885         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO),
886                 .driver_data = LG_FF },
887         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL),
888                 .driver_data = LG_NOGET | LG_FF4 },
889         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2),
890                 .driver_data = LG_FF4 },
891         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL),
892                 .driver_data = LG_FF2 },
893         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
894                 .driver_data = LG_FF4 },
895         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL),
896                 .driver_data = LG_FF4 },
897         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL),
898                 .driver_data = LG_FF4 },
899         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL),
900                 .driver_data = LG_NOGET | LG_FF4 },
901         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL),
902                 .driver_data = LG_FF4 },
903         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FG),
904                 .driver_data = LG_NOGET },
905         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG),
906                 .driver_data = LG_NOGET | LG_FF4 },
907         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
908                 .driver_data = LG_NOGET | LG_FF2 },
909         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940),
910                 .driver_data = LG_FF3 },
911         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR),
912                 .driver_data = LG_RDESC_REL_ABS },
913         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER),
914                 .driver_data = LG_RDESC_REL_ABS },
915         { }
916 };
917
918 MODULE_DEVICE_TABLE(hid, lg_devices);
919
920 static struct hid_driver lg_driver = {
921         .name = "logitech",
922         .id_table = lg_devices,
923         .report_fixup = lg_report_fixup,
924         .input_mapping = lg_input_mapping,
925         .input_mapped = lg_input_mapped,
926         .event = lg_event,
927         .raw_event = lg_raw_event,
928         .probe = lg_probe,
929         .remove = lg_remove,
930 };
931 module_hid_driver(lg_driver);
932
933 #ifdef CONFIG_LOGIWHEELS_FF
934 int lg4ff_no_autoswitch = 0;
935 module_param_named(lg4ff_no_autoswitch, lg4ff_no_autoswitch, int, S_IRUGO);
936 MODULE_PARM_DESC(lg4ff_no_autoswitch, "Do not switch multimode wheels to their native mode automatically");
937 #endif
938
939 MODULE_LICENSE("GPL");