15f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby/*
25f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby *  HID driver for some logitech "special" devices
35f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby *
45f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby *  Copyright (c) 1999 Andreas Gal
55f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
65f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
75f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby *  Copyright (c) 2006-2007 Jiri Kosina
85f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby *  Copyright (c) 2008 Jiri Slaby
92c6118e43040034d80894daeba41960bf0035b31Hendrik Iben *  Copyright (c) 2010 Hendrik Iben
105f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby */
115f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
125f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby/*
135f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby * This program is free software; you can redistribute it and/or modify it
145f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby * under the terms of the GNU General Public License as published by the Free
155f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby * Software Foundation; either version 2 of the License, or (at your option)
165f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby * any later version.
175f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby */
185f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
195f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby#include <linux/device.h>
205f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby#include <linux/hid.h>
215f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby#include <linux/module.h>
2232c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood#include <linux/random.h>
2332c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood#include <linux/sched.h>
2454bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra#include <linux/usb.h>
2532c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood#include <linux/wait.h>
265f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
2754bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra#include "usbhid/usbhid.h"
285f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby#include "hid-ids.h"
29606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby#include "hid-lg.h"
305f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
315f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby#define LG_RDESC		0x001
325f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby#define LG_BAD_RELATIVE_KEYS	0x002
335f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby#define LG_DUPLICATE_USAGES	0x004
345f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby#define LG_EXPANDED_KEYMAP	0x010
355f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby#define LG_IGNORE_DOUBLED_WHEEL	0x020
365f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby#define LG_WIRELESS		0x040
375f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby#define LG_INVERT_HWHEEL	0x080
385f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby#define LG_NOGET		0x100
39606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby#define LG_FF			0x200
40606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby#define LG_FF2			0x400
4124985cf68612a5617d396b0b188cec807641cde1Jiri Kosina#define LG_RDESC_REL_ABS	0x800
4274f292ca8c7a2b9370f80d97a49e48174f4c7635Gary Stein#define LG_FF3			0x1000
4332c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood#define LG_FF4			0x2000
445f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
4554bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra/* Size of the original descriptors of the Driving Force (and Pro) wheels */
4654bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra#define DF_RDESC_ORIG_SIZE	130
47dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer#define DFP_RDESC_ORIG_SIZE	97
487f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood#define FV_RDESC_ORIG_SIZE	130
49270baef1fafab50410e0e395ec26834de2dcc390Simon Wood#define MOMO_RDESC_ORIG_SIZE	87
50348cbaa800f8161168b20f85f72abb541c145132Simon Wood#define MOMO2_RDESC_ORIG_SIZE	87
51dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer
5254bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra/* Fixed report descriptors for Logitech Driving Force (and Pro)
5354bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra * wheel controllers
54dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer *
5554bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra * The original descriptors hide the separate throttle and brake axes in
56dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer * a custom vendor usage page, providing only a combined value as
57dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer * GenericDesktop.Y.
5854bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra * These descriptors remove the combined Y axis and instead report
59dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer * separate throttle (Y) and brake (RZ).
60dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer */
6154bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarrastatic __u8 df_rdesc_fixed[] = {
6254bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x05, 0x01,         /*  Usage Page (Desktop),                   */
6354bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x09, 0x04,         /*  Usage (Joystik),                        */
6454bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0xA1, 0x01,         /*  Collection (Application),               */
6554bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0xA1, 0x02,         /*      Collection (Logical),               */
6654bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x95, 0x01,         /*          Report Count (1),               */
6754bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x75, 0x0A,         /*          Report Size (10),               */
6854bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x14,               /*          Logical Minimum (0),            */
6954bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),         */
7054bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x34,               /*          Physical Minimum (0),           */
7154bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x46, 0xFF, 0x03,   /*          Physical Maximum (1023),        */
7254bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x09, 0x30,         /*          Usage (X),                      */
7354bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x81, 0x02,         /*          Input (Variable),               */
7454bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x95, 0x0C,         /*          Report Count (12),              */
7554bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x75, 0x01,         /*          Report Size (1),                */
7654bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x25, 0x01,         /*          Logical Maximum (1),            */
7754bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x45, 0x01,         /*          Physical Maximum (1),           */
7854bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x05, 0x09,         /*          Usage (Buttons),                */
7954bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x19, 0x01,         /*          Usage Minimum (1),              */
8054bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x29, 0x0c,         /*          Usage Maximum (12),             */
8154bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x81, 0x02,         /*          Input (Variable),               */
8254bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x95, 0x02,         /*          Report Count (2),               */
8354bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x06, 0x00, 0xFF,   /*          Usage Page (Vendor: 65280),     */
8454bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x09, 0x01,         /*          Usage (?: 1),                   */
8554bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x81, 0x02,         /*          Input (Variable),               */
8654bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x05, 0x01,         /*          Usage Page (Desktop),           */
8754bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
8854bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
8954bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x95, 0x01,         /*          Report Count (1),               */
9054bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x75, 0x08,         /*          Report Size (8),                */
9154bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x81, 0x02,         /*          Input (Variable),               */
9254bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x25, 0x07,         /*          Logical Maximum (7),            */
9354bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x46, 0x3B, 0x01,   /*          Physical Maximum (315),         */
9454bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x75, 0x04,         /*          Report Size (4),                */
9554bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x65, 0x14,         /*          Unit (Degrees),                 */
9654bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x09, 0x39,         /*          Usage (Hat Switch),             */
9754bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x81, 0x42,         /*          Input (Variable, Null State),   */
9854bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x75, 0x01,         /*          Report Size (1),                */
9954bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x95, 0x04,         /*          Report Count (4),               */
10054bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x65, 0x00,         /*          Unit (none),                    */
10154bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x06, 0x00, 0xFF,   /*          Usage Page (Vendor: 65280),     */
10254bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x09, 0x01,         /*          Usage (?: 1),                   */
10354bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x25, 0x01,         /*          Logical Maximum (1),            */
10454bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x45, 0x01,         /*          Physical Maximum (1),           */
10554bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x81, 0x02,         /*          Input (Variable),               */
1065a9b571bacafffaff75f4f523c4479c85e83cb15Paul Sbarra0x05, 0x01,         /*          Usage Page (Desktop),           */
1075a9b571bacafffaff75f4f523c4479c85e83cb15Paul Sbarra0x95, 0x01,         /*          Report Count (1),               */
10854bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x75, 0x08,         /*          Report Size (8),                */
10954bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
11054bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
1115a9b571bacafffaff75f4f523c4479c85e83cb15Paul Sbarra0x09, 0x31,         /*          Usage (Y),                      */
1125a9b571bacafffaff75f4f523c4479c85e83cb15Paul Sbarra0x81, 0x02,         /*          Input (Variable),               */
1135a9b571bacafffaff75f4f523c4479c85e83cb15Paul Sbarra0x09, 0x35,         /*          Usage (Rz),                     */
11454bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x81, 0x02,         /*          Input (Variable),               */
11554bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0xC0,               /*      End Collection,                     */
11654bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0xA1, 0x02,         /*      Collection (Logical),               */
11754bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
11854bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
11954bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x95, 0x07,         /*          Report Count (7),               */
12054bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x75, 0x08,         /*          Report Size (8),                */
12154bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x09, 0x03,         /*          Usage (?: 3),                   */
12254bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x91, 0x02,         /*          Output (Variable),              */
12354bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0xC0,               /*      End Collection,                     */
12454bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0xC0                /*  End Collection                          */
12554bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra};
12654bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra
127dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauerstatic __u8 dfp_rdesc_fixed[] = {
128dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x05, 0x01,         /*  Usage Page (Desktop),                   */
129dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x09, 0x04,         /*  Usage (Joystik),                        */
130dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0xA1, 0x01,         /*  Collection (Application),               */
131dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0xA1, 0x02,         /*      Collection (Logical),               */
132dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x95, 0x01,         /*          Report Count (1),               */
133dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x75, 0x0E,         /*          Report Size (14),               */
134dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x14,               /*          Logical Minimum (0),            */
135dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x26, 0xFF, 0x3F,   /*          Logical Maximum (16383),        */
136dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x34,               /*          Physical Minimum (0),           */
137dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x46, 0xFF, 0x3F,   /*          Physical Maximum (16383),       */
138dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x09, 0x30,         /*          Usage (X),                      */
139dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x81, 0x02,         /*          Input (Variable),               */
140dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x95, 0x0E,         /*          Report Count (14),              */
141dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x75, 0x01,         /*          Report Size (1),                */
142dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x25, 0x01,         /*          Logical Maximum (1),            */
143dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x45, 0x01,         /*          Physical Maximum (1),           */
144dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x05, 0x09,         /*          Usage Page (Button),            */
145dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x19, 0x01,         /*          Usage Minimum (01h),            */
146dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x29, 0x0E,         /*          Usage Maximum (0Eh),            */
147dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x81, 0x02,         /*          Input (Variable),               */
148dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x05, 0x01,         /*          Usage Page (Desktop),           */
149dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x95, 0x01,         /*          Report Count (1),               */
150dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x75, 0x04,         /*          Report Size (4),                */
151dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x25, 0x07,         /*          Logical Maximum (7),            */
152dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x46, 0x3B, 0x01,   /*          Physical Maximum (315),         */
153dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x65, 0x14,         /*          Unit (Degrees),                 */
154dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x09, 0x39,         /*          Usage (Hat Switch),             */
155dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x81, 0x42,         /*          Input (Variable, Nullstate),    */
156dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x65, 0x00,         /*          Unit,                           */
157dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
158dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
159dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x75, 0x08,         /*          Report Size (8),                */
160dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x81, 0x01,         /*          Input (Constant),               */
161dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x09, 0x31,         /*          Usage (Y),                      */
162dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x81, 0x02,         /*          Input (Variable),               */
163dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x09, 0x35,         /*          Usage (Rz),                     */
164dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x81, 0x02,         /*          Input (Variable),               */
165dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x81, 0x01,         /*          Input (Constant),               */
166dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0xC0,               /*      End Collection,                     */
167dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0xA1, 0x02,         /*      Collection (Logical),               */
168dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x09, 0x02,         /*          Usage (02h),                    */
169dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x95, 0x07,         /*          Report Count (7),               */
170dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x91, 0x02,         /*          Output (Variable),              */
171dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0xC0,               /*      End Collection,                     */
172dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0xC0                /*  End Collection                          */
173dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer};
174dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer
1757f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Woodstatic __u8 fv_rdesc_fixed[] = {
1767f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x05, 0x01,         /*  Usage Page (Desktop),                   */
1777f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x09, 0x04,         /*  Usage (Joystik),                        */
1787f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0xA1, 0x01,         /*  Collection (Application),               */
1797f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0xA1, 0x02,         /*      Collection (Logical),               */
1807f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x95, 0x01,         /*          Report Count (1),               */
1817f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x75, 0x0A,         /*          Report Size (10),               */
1827f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x15, 0x00,         /*          Logical Minimum (0),            */
1837f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),         */
1847f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x35, 0x00,         /*          Physical Minimum (0),           */
1857f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x46, 0xFF, 0x03,   /*          Physical Maximum (1023),        */
1867f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x09, 0x30,         /*          Usage (X),                      */
1877f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x81, 0x02,         /*          Input (Variable),               */
1887f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x95, 0x0C,         /*          Report Count (12),              */
1897f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x75, 0x01,         /*          Report Size (1),                */
1907f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x25, 0x01,         /*          Logical Maximum (1),            */
1917f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x45, 0x01,         /*          Physical Maximum (1),           */
1927f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x05, 0x09,         /*          Usage Page (Button),            */
1937f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x19, 0x01,         /*          Usage Minimum (01h),            */
1947f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x29, 0x0C,         /*          Usage Maximum (0Ch),            */
1957f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x81, 0x02,         /*          Input (Variable),               */
1967f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x95, 0x02,         /*          Report Count (2),               */
1977f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),             */
1987f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x09, 0x01,         /*          Usage (01h),                    */
1997f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x81, 0x02,         /*          Input (Variable),               */
2007f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x09, 0x02,         /*          Usage (02h),                    */
2017f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
2027f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
2037f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x95, 0x01,         /*          Report Count (1),               */
2047f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x75, 0x08,         /*          Report Size (8),                */
2057f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x81, 0x02,         /*          Input (Variable),               */
2067f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x05, 0x01,         /*          Usage Page (Desktop),           */
2077f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x25, 0x07,         /*          Logical Maximum (7),            */
2087f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x46, 0x3B, 0x01,   /*          Physical Maximum (315),         */
2097f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x75, 0x04,         /*          Report Size (4),                */
2107f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x65, 0x14,         /*          Unit (Degrees),                 */
2117f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x09, 0x39,         /*          Usage (Hat Switch),             */
2127f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x81, 0x42,         /*          Input (Variable, Null State),   */
2137f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x75, 0x01,         /*          Report Size (1),                */
2147f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x95, 0x04,         /*          Report Count (4),               */
2157f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x65, 0x00,         /*          Unit,                           */
2167f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),             */
2177f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x09, 0x01,         /*          Usage (01h),                    */
2187f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x25, 0x01,         /*          Logical Maximum (1),            */
2197f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x45, 0x01,         /*          Physical Maximum (1),           */
2207f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x81, 0x02,         /*          Input (Variable),               */
2217f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x05, 0x01,         /*          Usage Page (Desktop),           */
2227f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x95, 0x01,         /*          Report Count (1),               */
2237f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x75, 0x08,         /*          Report Size (8),                */
2247f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
2257f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
2267f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x09, 0x31,         /*          Usage (Y),                      */
2277f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x81, 0x02,         /*          Input (Variable),               */
2287f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x09, 0x32,         /*          Usage (Z),                      */
2297f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x81, 0x02,         /*          Input (Variable),               */
2307f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0xC0,               /*      End Collection,                     */
2317f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0xA1, 0x02,         /*      Collection (Logical),               */
2327f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
2337f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
2347f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x95, 0x07,         /*          Report Count (7),               */
2357f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x75, 0x08,         /*          Report Size (8),                */
2367f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x09, 0x03,         /*          Usage (03h),                    */
2377f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0x91, 0x02,         /*          Output (Variable),              */
2387f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0xC0,               /*      End Collection,                     */
2397f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood0xC0                /*  End Collection                          */
2407f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood};
2417f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood
242270baef1fafab50410e0e395ec26834de2dcc390Simon Woodstatic __u8 momo_rdesc_fixed[] = {
243270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x05, 0x01,         /*  Usage Page (Desktop),               */
244270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x09, 0x04,         /*  Usage (Joystik),                    */
245270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0xA1, 0x01,         /*  Collection (Application),           */
246270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0xA1, 0x02,         /*      Collection (Logical),           */
247270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x95, 0x01,         /*          Report Count (1),           */
248270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x75, 0x0A,         /*          Report Size (10),           */
249270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x15, 0x00,         /*          Logical Minimum (0),        */
250270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
251270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x35, 0x00,         /*          Physical Minimum (0),       */
252270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x46, 0xFF, 0x03,   /*          Physical Maximum (1023),    */
253270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x09, 0x30,         /*          Usage (X),                  */
254270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x81, 0x02,         /*          Input (Variable),           */
255270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x95, 0x08,         /*          Report Count (8),           */
256270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x75, 0x01,         /*          Report Size (1),            */
257270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x25, 0x01,         /*          Logical Maximum (1),        */
258270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x45, 0x01,         /*          Physical Maximum (1),       */
259270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x05, 0x09,         /*          Usage Page (Button),        */
260270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x19, 0x01,         /*          Usage Minimum (01h),        */
261270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x29, 0x08,         /*          Usage Maximum (08h),        */
262270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x81, 0x02,         /*          Input (Variable),           */
263270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
264270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x75, 0x0E,         /*          Report Size (14),           */
265270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x95, 0x01,         /*          Report Count (1),           */
266270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
267270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x46, 0xFF, 0x00,   /*          Physical Maximum (255),     */
268270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x09, 0x00,         /*          Usage (00h),                */
269270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x81, 0x02,         /*          Input (Variable),           */
270270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x05, 0x01,         /*          Usage Page (Desktop),       */
271270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x75, 0x08,         /*          Report Size (8),            */
272270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x09, 0x31,         /*          Usage (Y),                  */
273270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x81, 0x02,         /*          Input (Variable),           */
274270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x09, 0x32,         /*          Usage (Z),                  */
275270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x81, 0x02,         /*          Input (Variable),           */
276270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
277270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x09, 0x01,         /*          Usage (01h),                */
278270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x81, 0x02,         /*          Input (Variable),           */
279270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0xC0,               /*      End Collection,                 */
280270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0xA1, 0x02,         /*      Collection (Logical),           */
281270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x09, 0x02,         /*          Usage (02h),                */
282270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x95, 0x07,         /*          Report Count (7),           */
283270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x91, 0x02,         /*          Output (Variable),          */
284270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0xC0,               /*      End Collection,                 */
285270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0xC0                /*  End Collection                      */
286270baef1fafab50410e0e395ec26834de2dcc390Simon Wood};
287dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer
288348cbaa800f8161168b20f85f72abb541c145132Simon Woodstatic __u8 momo2_rdesc_fixed[] = {
289348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x05, 0x01,         /*  Usage Page (Desktop),               */
290348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x09, 0x04,         /*  Usage (Joystik),                    */
291348cbaa800f8161168b20f85f72abb541c145132Simon Wood0xA1, 0x01,         /*  Collection (Application),           */
292348cbaa800f8161168b20f85f72abb541c145132Simon Wood0xA1, 0x02,         /*      Collection (Logical),           */
293348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x95, 0x01,         /*          Report Count (1),           */
294348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x75, 0x0A,         /*          Report Size (10),           */
295348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x15, 0x00,         /*          Logical Minimum (0),        */
296348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
297348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x35, 0x00,         /*          Physical Minimum (0),       */
298348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x46, 0xFF, 0x03,   /*          Physical Maximum (1023),    */
299348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x09, 0x30,         /*          Usage (X),                  */
300348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x81, 0x02,         /*          Input (Variable),           */
301348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x95, 0x0A,         /*          Report Count (10),          */
302348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x75, 0x01,         /*          Report Size (1),            */
303348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x25, 0x01,         /*          Logical Maximum (1),        */
304348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x45, 0x01,         /*          Physical Maximum (1),       */
305348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x05, 0x09,         /*          Usage Page (Button),        */
306348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x19, 0x01,         /*          Usage Minimum (01h),        */
307348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x29, 0x0A,         /*          Usage Maximum (0Ah),        */
308348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x81, 0x02,         /*          Input (Variable),           */
309348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
310348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x09, 0x00,         /*          Usage (00h),                */
311348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x95, 0x04,         /*          Report Count (4),           */
312348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x81, 0x02,         /*          Input (Variable),           */
313348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x95, 0x01,         /*          Report Count (1),           */
314348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x75, 0x08,         /*          Report Size (8),            */
315348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
316348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x46, 0xFF, 0x00,   /*          Physical Maximum (255),     */
317348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x09, 0x01,         /*          Usage (01h),                */
318348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x81, 0x02,         /*          Input (Variable),           */
319348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x05, 0x01,         /*          Usage Page (Desktop),       */
320348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x09, 0x31,         /*          Usage (Y),                  */
321348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x81, 0x02,         /*          Input (Variable),           */
322348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x09, 0x32,         /*          Usage (Z),                  */
323348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x81, 0x02,         /*          Input (Variable),           */
324348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
325348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x09, 0x00,         /*          Usage (00h),                */
326348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x81, 0x02,         /*          Input (Variable),           */
327348cbaa800f8161168b20f85f72abb541c145132Simon Wood0xC0,               /*      End Collection,                 */
328348cbaa800f8161168b20f85f72abb541c145132Simon Wood0xA1, 0x02,         /*      Collection (Logical),           */
329348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x09, 0x02,         /*          Usage (02h),                */
330348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x95, 0x07,         /*          Report Count (7),           */
331348cbaa800f8161168b20f85f72abb541c145132Simon Wood0x91, 0x02,         /*          Output (Variable),          */
332348cbaa800f8161168b20f85f72abb541c145132Simon Wood0xC0,               /*      End Collection,                 */
333348cbaa800f8161168b20f85f72abb541c145132Simon Wood0xC0                /*  End Collection                      */
334348cbaa800f8161168b20f85f72abb541c145132Simon Wood};
335348cbaa800f8161168b20f85f72abb541c145132Simon Wood
3365f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby/*
3375f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby * Certain Logitech keyboards send in report #3 keys which are far
3385f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby * above the logical maximum described in descriptor. This extends
3395f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby * the original value of 0x28c of logical maximum to 0x104d
3405f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby */
34173e4008ddddc84d5f2499c17012b340a0dae153eNikolai Kondrashovstatic __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
34273e4008ddddc84d5f2499c17012b340a0dae153eNikolai Kondrashov		unsigned int *rsize)
3435f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby{
3442575155309947063927b123c56119f36dfda3b50Axel Lin	struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
34554bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra	struct usb_device_descriptor *udesc;
34654bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra	__u16 bcdDevice, rev_maj, rev_min;
3475f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
3484ab25786c87eb20857bbb715c3ae34ec8fd6a214Jiri Kosina	if ((drv_data->quirks & LG_RDESC) && *rsize >= 91 && rdesc[83] == 0x26 &&
3495f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby			rdesc[84] == 0x8c && rdesc[85] == 0x02) {
3504291ee305e9bb0699504a66f0e2b7aefcf0512a5Joe Perches		hid_info(hdev,
3514291ee305e9bb0699504a66f0e2b7aefcf0512a5Joe Perches			 "fixing up Logitech keyboard report descriptor\n");
3525f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		rdesc[84] = rdesc[89] = 0x4d;
3535f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		rdesc[85] = rdesc[90] = 0x10;
3545f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	}
3554ab25786c87eb20857bbb715c3ae34ec8fd6a214Jiri Kosina	if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 51 &&
35624985cf68612a5617d396b0b188cec807641cde1Jiri Kosina			rdesc[32] == 0x81 && rdesc[33] == 0x06 &&
35724985cf68612a5617d396b0b188cec807641cde1Jiri Kosina			rdesc[49] == 0x81 && rdesc[50] == 0x06) {
3584291ee305e9bb0699504a66f0e2b7aefcf0512a5Joe Perches		hid_info(hdev,
3594291ee305e9bb0699504a66f0e2b7aefcf0512a5Joe Perches			 "fixing up rel/abs in Logitech report descriptor\n");
36024985cf68612a5617d396b0b188cec807641cde1Jiri Kosina		rdesc[33] = rdesc[50] = 0x02;
36124985cf68612a5617d396b0b188cec807641cde1Jiri Kosina	}
362dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer
363dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer	switch (hdev->product) {
36454bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra
36554bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra	/* Several wheels report as this id when operating in emulation mode. */
36654bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra	case USB_DEVICE_ID_LOGITECH_WHEEL:
36754bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra		udesc = &(hid_to_usb_dev(hdev)->descriptor);
36854bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra		if (!udesc) {
36954bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra			hid_err(hdev, "NULL USB device descriptor\n");
37054bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra			break;
37154bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra		}
37254bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra		bcdDevice = le16_to_cpu(udesc->bcdDevice);
37354bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra		rev_maj = bcdDevice >> 8;
37454bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra		rev_min = bcdDevice & 0xff;
37554bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra
37654bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra		/* Update the report descriptor for only the Driving Force wheel */
37754bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra		if (rev_maj == 1 && rev_min == 2 &&
37854bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra				*rsize == DF_RDESC_ORIG_SIZE) {
37954bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra			hid_info(hdev,
38054bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra				"fixing up Logitech Driving Force report descriptor\n");
38154bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra			rdesc = df_rdesc_fixed;
38254bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra			*rsize = sizeof(df_rdesc_fixed);
38354bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra		}
38454bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra		break;
38554bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra
386270baef1fafab50410e0e395ec26834de2dcc390Simon Wood	case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
387270baef1fafab50410e0e395ec26834de2dcc390Simon Wood		if (*rsize == MOMO_RDESC_ORIG_SIZE) {
388270baef1fafab50410e0e395ec26834de2dcc390Simon Wood			hid_info(hdev,
389270baef1fafab50410e0e395ec26834de2dcc390Simon Wood				"fixing up Logitech Momo Force (Red) report descriptor\n");
390270baef1fafab50410e0e395ec26834de2dcc390Simon Wood			rdesc = momo_rdesc_fixed;
391270baef1fafab50410e0e395ec26834de2dcc390Simon Wood			*rsize = sizeof(momo_rdesc_fixed);
392270baef1fafab50410e0e395ec26834de2dcc390Simon Wood		}
393270baef1fafab50410e0e395ec26834de2dcc390Simon Wood		break;
394270baef1fafab50410e0e395ec26834de2dcc390Simon Wood
395348cbaa800f8161168b20f85f72abb541c145132Simon Wood	case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
396348cbaa800f8161168b20f85f72abb541c145132Simon Wood		if (*rsize == MOMO2_RDESC_ORIG_SIZE) {
397348cbaa800f8161168b20f85f72abb541c145132Simon Wood			hid_info(hdev,
398348cbaa800f8161168b20f85f72abb541c145132Simon Wood				"fixing up Logitech Momo Racing Force (Black) report descriptor\n");
399348cbaa800f8161168b20f85f72abb541c145132Simon Wood			rdesc = momo2_rdesc_fixed;
400348cbaa800f8161168b20f85f72abb541c145132Simon Wood			*rsize = sizeof(momo2_rdesc_fixed);
401348cbaa800f8161168b20f85f72abb541c145132Simon Wood		}
402348cbaa800f8161168b20f85f72abb541c145132Simon Wood		break;
403348cbaa800f8161168b20f85f72abb541c145132Simon Wood
4047f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood	case USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL:
4057f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood		if (*rsize == FV_RDESC_ORIG_SIZE) {
4067f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood			hid_info(hdev,
4077f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood				"fixing up Logitech Formula Vibration report descriptor\n");
4087f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood			rdesc = fv_rdesc_fixed;
4097f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood			*rsize = sizeof(fv_rdesc_fixed);
4107f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood		}
4117f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood		break;
4127f50547059bd55ac6a98c29fd1989421bdc36ec9Simon Wood
413dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer	case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
414dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer		if (*rsize == DFP_RDESC_ORIG_SIZE) {
415dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer			hid_info(hdev,
416dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer				"fixing up Logitech Driving Force Pro report descriptor\n");
417dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer			rdesc = dfp_rdesc_fixed;
418dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer			*rsize = sizeof(dfp_rdesc_fixed);
419dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer		}
420dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer		break;
421b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood
422b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood	case USB_DEVICE_ID_LOGITECH_WII_WHEEL:
423b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood		if (*rsize >= 101 && rdesc[41] == 0x95 && rdesc[42] == 0x0B &&
424b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood				rdesc[47] == 0x05 && rdesc[48] == 0x09) {
425b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood			hid_info(hdev, "fixing up Logitech Speed Force Wireless report descriptor\n");
426b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood			rdesc[41] = 0x05;
427b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood			rdesc[42] = 0x09;
428b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood			rdesc[47] = 0x95;
429b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood			rdesc[48] = 0x0B;
430b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood		}
431b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood		break;
432dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer	}
433dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer
43473e4008ddddc84d5f2499c17012b340a0dae153eNikolai Kondrashov	return rdesc;
4355f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby}
4365f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
4375f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby#define lg_map_key_clear(c)	hid_map_usage_clear(hi, usage, bit, max, \
4385f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		EV_KEY, (c))
4395f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
4405f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slabystatic int lg_ultrax_remote_mapping(struct hid_input *hi,
4415f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		struct hid_usage *usage, unsigned long **bit, int *max)
4425f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby{
4435f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
4445f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		return 0;
4455f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
4465f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	set_bit(EV_REP, hi->input->evbit);
4475f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	switch (usage->hid & HID_USAGE) {
4485f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	/* Reported on Logitech Ultra X Media Remote */
4495f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x004: lg_map_key_clear(KEY_AGAIN);	break;
4505f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x00d: lg_map_key_clear(KEY_HOME);		break;
4515f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x024: lg_map_key_clear(KEY_SHUFFLE);	break;
4525f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x025: lg_map_key_clear(KEY_TV);		break;
4535f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x026: lg_map_key_clear(KEY_MENU);		break;
4545f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x031: lg_map_key_clear(KEY_AUDIO);	break;
4555f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x032: lg_map_key_clear(KEY_TEXT);		break;
4565f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x033: lg_map_key_clear(KEY_LAST);		break;
4575f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x047: lg_map_key_clear(KEY_MP3);		break;
4585f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x048: lg_map_key_clear(KEY_DVD);		break;
4595f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x049: lg_map_key_clear(KEY_MEDIA);	break;
4605f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x04a: lg_map_key_clear(KEY_VIDEO);	break;
4615f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x04b: lg_map_key_clear(KEY_ANGLE);	break;
4625f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x04c: lg_map_key_clear(KEY_LANGUAGE);	break;
4635f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x04d: lg_map_key_clear(KEY_SUBTITLE);	break;
4645f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x051: lg_map_key_clear(KEY_RED);		break;
4655f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x052: lg_map_key_clear(KEY_CLOSE);	break;
4665f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
4675f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	default:
4685f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		return 0;
4695f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	}
4705f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	return 1;
4715f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby}
4725f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
47366d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosinastatic int lg_dinovo_mapping(struct hid_input *hi, struct hid_usage *usage,
47466d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina		unsigned long **bit, int *max)
47566d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina{
47666d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
47766d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina		return 0;
47866d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina
47966d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina	switch (usage->hid & HID_USAGE) {
48066d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina
48166d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina	case 0x00d: lg_map_key_clear(KEY_MEDIA);	break;
48266d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina	default:
48366d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina		return 0;
48466d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina
48566d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina	}
48666d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina	return 1;
48766d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina}
48866d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina
4895f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slabystatic int lg_wireless_mapping(struct hid_input *hi, struct hid_usage *usage,
4905f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		unsigned long **bit, int *max)
4915f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby{
4925f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
4935f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		return 0;
4945f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
4955f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	switch (usage->hid & HID_USAGE) {
4965f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1001: lg_map_key_clear(KEY_MESSENGER);		break;
4975f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1003: lg_map_key_clear(KEY_SOUND);		break;
4985f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1004: lg_map_key_clear(KEY_VIDEO);		break;
4995f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1005: lg_map_key_clear(KEY_AUDIO);		break;
5005f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x100a: lg_map_key_clear(KEY_DOCUMENTS);		break;
50118392212932ecbdc71bc6a298ad301328eefb09dLorenzo Castelli	/* The following two entries are Playlist 1 and 2 on the MX3200 */
50218392212932ecbdc71bc6a298ad301328eefb09dLorenzo Castelli	case 0x100f: lg_map_key_clear(KEY_FN_1);		break;
50318392212932ecbdc71bc6a298ad301328eefb09dLorenzo Castelli	case 0x1010: lg_map_key_clear(KEY_FN_2);		break;
5045f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1011: lg_map_key_clear(KEY_PREVIOUSSONG);	break;
5055f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1012: lg_map_key_clear(KEY_NEXTSONG);		break;
5065f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1013: lg_map_key_clear(KEY_CAMERA);		break;
5075f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1014: lg_map_key_clear(KEY_MESSENGER);		break;
5085f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1015: lg_map_key_clear(KEY_RECORD);		break;
5095f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1016: lg_map_key_clear(KEY_PLAYER);		break;
5105f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1017: lg_map_key_clear(KEY_EJECTCD);		break;
5115f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1018: lg_map_key_clear(KEY_MEDIA);		break;
5125f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1019: lg_map_key_clear(KEY_PROG1);		break;
5135f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x101a: lg_map_key_clear(KEY_PROG2);		break;
5145f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x101b: lg_map_key_clear(KEY_PROG3);		break;
51518392212932ecbdc71bc6a298ad301328eefb09dLorenzo Castelli	case 0x101c: lg_map_key_clear(KEY_CYCLEWINDOWS);	break;
5165f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x101f: lg_map_key_clear(KEY_ZOOMIN);		break;
5175f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1020: lg_map_key_clear(KEY_ZOOMOUT);		break;
5185f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1021: lg_map_key_clear(KEY_ZOOMRESET);		break;
5195f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1023: lg_map_key_clear(KEY_CLOSE);		break;
5205f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1027: lg_map_key_clear(KEY_MENU);		break;
5215f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	/* this one is marked as 'Rotate' */
5225f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1028: lg_map_key_clear(KEY_ANGLE);		break;
5235f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1029: lg_map_key_clear(KEY_SHUFFLE);		break;
5245f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x102a: lg_map_key_clear(KEY_BACK);		break;
5255f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x102b: lg_map_key_clear(KEY_CYCLEWINDOWS);	break;
52618392212932ecbdc71bc6a298ad301328eefb09dLorenzo Castelli	case 0x102d: lg_map_key_clear(KEY_WWW);			break;
52718392212932ecbdc71bc6a298ad301328eefb09dLorenzo Castelli	/* The following two are 'Start/answer call' and 'End/reject call'
52818392212932ecbdc71bc6a298ad301328eefb09dLorenzo Castelli	   on the MX3200 */
52918392212932ecbdc71bc6a298ad301328eefb09dLorenzo Castelli	case 0x1031: lg_map_key_clear(KEY_OK);			break;
53018392212932ecbdc71bc6a298ad301328eefb09dLorenzo Castelli	case 0x1032: lg_map_key_clear(KEY_CANCEL);		break;
5315f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1041: lg_map_key_clear(KEY_BATTERY);		break;
5325f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1042: lg_map_key_clear(KEY_WORDPROCESSOR);	break;
5335f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1043: lg_map_key_clear(KEY_SPREADSHEET);		break;
5345f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1044: lg_map_key_clear(KEY_PRESENTATION);	break;
5355f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1045: lg_map_key_clear(KEY_UNDO);		break;
5365f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1046: lg_map_key_clear(KEY_REDO);		break;
5375f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1047: lg_map_key_clear(KEY_PRINT);		break;
5385f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1048: lg_map_key_clear(KEY_SAVE);		break;
5395f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x1049: lg_map_key_clear(KEY_PROG1);		break;
5405f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x104a: lg_map_key_clear(KEY_PROG2);		break;
5415f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x104b: lg_map_key_clear(KEY_PROG3);		break;
5425f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	case 0x104c: lg_map_key_clear(KEY_PROG4);		break;
5435f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
5445f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	default:
5455f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		return 0;
5465f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	}
5475f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	return 1;
5485f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby}
5495f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
5505f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slabystatic int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
5515f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		struct hid_field *field, struct hid_usage *usage,
5525f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		unsigned long **bit, int *max)
5535f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby{
5545f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	/* extended mapping for certain Logitech hardware (Logitech cordless
5555f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	   desktop LX500) */
5565f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	static const u8 e_keymap[] = {
5575f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		  0,216,  0,213,175,156,  0,  0,  0,  0,
5585f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		144,  0,  0,  0,  0,  0,  0,  0,  0,212,
5595f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		174,167,152,161,112,  0,  0,  0,154,  0,
5605f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5615f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5625f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5635f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		  0,  0,  0,  0,  0,183,184,185,186,187,
5645f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		188,189,190,191,192,193,194,  0,  0,  0
5655f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	};
5662575155309947063927b123c56119f36dfda3b50Axel Lin	struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
5675f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	unsigned int hid = usage->hid;
5685f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
5695f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	if (hdev->product == USB_DEVICE_ID_LOGITECH_RECEIVER &&
5705f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby			lg_ultrax_remote_mapping(hi, usage, bit, max))
5715f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		return 1;
5725f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
57366d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina	if (hdev->product == USB_DEVICE_ID_DINOVO_MINI &&
57466d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina			lg_dinovo_mapping(hi, usage, bit, max))
57566d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina		return 1;
57666d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina
5778577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý	if ((drv_data->quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max))
5785f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		return 1;
5795f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
5805f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	if ((hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
5815f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		return 0;
5825f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
5835f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	hid &= HID_USAGE;
5845f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
5855f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	/* Special handling for Logitech Cordless Desktop */
5865f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	if (field->application == HID_GD_MOUSE) {
5878577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý		if ((drv_data->quirks & LG_IGNORE_DOUBLED_WHEEL) &&
5885f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby				(hid == 7 || hid == 8))
5895f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby			return -1;
5905f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	} else {
5918577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý		if ((drv_data->quirks & LG_EXPANDED_KEYMAP) &&
5925f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby				hid < ARRAY_SIZE(e_keymap) &&
5935f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby				e_keymap[hid] != 0) {
5945f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby			hid_map_usage(hi, usage, bit, max, EV_KEY,
5955f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby					e_keymap[hid]);
5965f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby			return 1;
5975f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		}
5985f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	}
5995f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
6005f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	return 0;
6015f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby}
6025f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
6035f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slabystatic int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
6045f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		struct hid_field *field, struct hid_usage *usage,
6055f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		unsigned long **bit, int *max)
6065f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby{
6072575155309947063927b123c56119f36dfda3b50Axel Lin	struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
6085f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
6098577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý	if ((drv_data->quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY &&
6105f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby			(field->flags & HID_MAIN_ITEM_RELATIVE))
6115f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		field->flags &= ~HID_MAIN_ITEM_RELATIVE;
6125f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
6138577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý	if ((drv_data->quirks & LG_DUPLICATE_USAGES) && (usage->type == EV_KEY ||
6145f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby			 usage->type == EV_REL || usage->type == EV_ABS))
6155f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		clear_bit(usage->code, *bit);
6165f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
61794b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood	/* Ensure that Logitech wheels are not given a default fuzz/flat value */
61894b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood	if (usage->type == EV_ABS && (usage->code == ABS_X ||
61994b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood			usage->code == ABS_Y || usage->code == ABS_Z ||
62094b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood			usage->code == ABS_RZ)) {
62194b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood		switch (hdev->product) {
62294b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood		case USB_DEVICE_ID_LOGITECH_WHEEL:
62394b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood		case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
62494b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood		case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
62594b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood		case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
62694b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood		case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
62794b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood		case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
62894b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood		case USB_DEVICE_ID_LOGITECH_WII_WHEEL:
62994b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood		case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
630bd04363d3990c0727b7512a79a08c68436878bb0Elias Vanderstuyft		case USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL:
63194b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood			field->application = HID_GD_MULTIAXIS;
63294b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood			break;
63394b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood		default:
63494b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood			break;
63594b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood		}
63694b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood	}
63794b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood
6385f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	return 0;
6395f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby}
6405f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
6415f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slabystatic int lg_event(struct hid_device *hdev, struct hid_field *field,
6425f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		struct hid_usage *usage, __s32 value)
6435f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby{
6442575155309947063927b123c56119f36dfda3b50Axel Lin	struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
6455f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
6468577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý	if ((drv_data->quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) {
6475f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		input_event(field->hidinput->input, usage->type, usage->code,
6485f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby				-value);
6495f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		return 1;
6505f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	}
6512b24a960016b8d3221a6dd2764ab97247c48dd97Michal Malý	if (drv_data->quirks & LG_FF4) {
6522b24a960016b8d3221a6dd2764ab97247c48dd97Michal Malý		return lg4ff_adjust_input_event(hdev, field, usage, value, drv_data);
6532b24a960016b8d3221a6dd2764ab97247c48dd97Michal Malý	}
6545f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
6555f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	return 0;
6565f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby}
6575f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
6585f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slabystatic int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
6595f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby{
660606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby	unsigned int connect_mask = HID_CONNECT_DEFAULT;
6618577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý	struct lg_drv_data *drv_data;
6625f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	int ret;
6635f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
6648577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý	drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL);
6658577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý	if (!drv_data) {
6668577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý		hid_err(hdev, "Insufficient memory, cannot allocate driver data\n");
6678577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý		return -ENOMEM;
6688577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý	}
6698577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý	drv_data->quirks = id->driver_data;
670a80fe5d6e3190f65be8cc7efa487f187eb3dbffaMichal Malý
6718577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý	hid_set_drvdata(hdev, (void *)drv_data);
6725f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
6738577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý	if (drv_data->quirks & LG_NOGET)
6745f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		hdev->quirks |= HID_QUIRK_NOGET;
6755f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
6765f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	ret = hid_parse(hdev);
6775f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	if (ret) {
6784291ee305e9bb0699504a66f0e2b7aefcf0512a5Joe Perches		hid_err(hdev, "parse failed\n");
6795f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		goto err_free;
6805f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	}
6815f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
6828577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý	if (drv_data->quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4))
683606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby		connect_mask &= ~HID_CONNECT_FF;
684606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby
685606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby	ret = hid_hw_start(hdev, connect_mask);
6865f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	if (ret) {
6874291ee305e9bb0699504a66f0e2b7aefcf0512a5Joe Perches		hid_err(hdev, "hw start failed\n");
6885f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		goto err_free;
6895f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	}
6905f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
6917362cd2286d2364cca6738b583668f64254fe04bMichal Malý	/* Setup wireless link with Logitech Wii wheel */
692a80fe5d6e3190f65be8cc7efa487f187eb3dbffaMichal Malý	if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
69332c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood		unsigned char buf[] = { 0x00, 0xAF,  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
69432c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood
695b0dd72aafd785785bedbb6db932955807e454a65Benjamin Tissoires		ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf),
696b0dd72aafd785785bedbb6db932955807e454a65Benjamin Tissoires					HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
69732c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood
69832c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood		if (ret >= 0) {
69932c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood			/* insert a little delay of 10 jiffies ~ 40ms */
70032c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood			wait_queue_head_t wait;
70132c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood			init_waitqueue_head (&wait);
70232c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood			wait_event_interruptible_timeout(wait, 0, 10);
70332c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood
70432c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood			/* Select random Address */
70532c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood			buf[1] = 0xB2;
70632c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood			get_random_bytes(&buf[2], 2);
70732c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood
708b0dd72aafd785785bedbb6db932955807e454a65Benjamin Tissoires			ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf),
709b0dd72aafd785785bedbb6db932955807e454a65Benjamin Tissoires					HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
71032c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood		}
71132c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood	}
71232c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood
7138577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý	if (drv_data->quirks & LG_FF)
714606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby		lgff_init(hdev);
7158577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý	if (drv_data->quirks & LG_FF2)
716606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby		lg2ff_init(hdev);
7178577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý	if (drv_data->quirks & LG_FF3)
71874f292ca8c7a2b9370f80d97a49e48174f4c7635Gary Stein		lg3ff_init(hdev);
7198577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý	if (drv_data->quirks & LG_FF4)
72032c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood		lg4ff_init(hdev);
721606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby
7225f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	return 0;
7235f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slabyerr_free:
7248577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý	kfree(drv_data);
7255f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	return ret;
7265f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby}
7275f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
72830bb75d71b3732c0adb6297815288ce0fb9cc04cMichal Malýstatic void lg_remove(struct hid_device *hdev)
72930bb75d71b3732c0adb6297815288ce0fb9cc04cMichal Malý{
7302575155309947063927b123c56119f36dfda3b50Axel Lin	struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
7318577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý	if (drv_data->quirks & LG_FF4)
73230bb75d71b3732c0adb6297815288ce0fb9cc04cMichal Malý		lg4ff_deinit(hdev);
73330bb75d71b3732c0adb6297815288ce0fb9cc04cMichal Malý
73430bb75d71b3732c0adb6297815288ce0fb9cc04cMichal Malý	hid_hw_stop(hdev);
7358577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý	kfree(drv_data);
73630bb75d71b3732c0adb6297815288ce0fb9cc04cMichal Malý}
73730bb75d71b3732c0adb6297815288ce0fb9cc04cMichal Malý
7385f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slabystatic const struct hid_device_id lg_devices[] = {
7395f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
7405f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		.driver_data = LG_RDESC | LG_WIRELESS },
7415f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER),
7425f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		.driver_data = LG_RDESC | LG_WIRELESS },
7435f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2),
7445f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		.driver_data = LG_RDESC | LG_WIRELESS },
7455f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
7465f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER),
7475f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		.driver_data = LG_BAD_RELATIVE_KEYS },
7485f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
7495f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP),
7505f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		.driver_data = LG_DUPLICATE_USAGES },
7515f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE),
7525f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		.driver_data = LG_DUPLICATE_USAGES },
7535f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI),
7545f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		.driver_data = LG_DUPLICATE_USAGES },
7555f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
7565f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD),
7575f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		.driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
7585f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500),
7595f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		.driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
7605f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
7615f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D),
7625f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby		.driver_data = LG_NOGET },
76356d0c8b7c8fb63505a06b50364d12817ded88daaVitaly Katraew	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DUAL_ACTION),
76456d0c8b7c8fb63505a06b50364d12817ded88daaVitaly Katraew		.driver_data = LG_NOGET },
7655f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL),
7667362cd2286d2364cca6738b583668f64254fe04bMichal Malý		.driver_data = LG_NOGET | LG_FF4 },
767606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby
7682c6118e43040034d80894daeba41960bf0035b31Hendrik Iben	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD),
7692c6118e43040034d80894daeba41960bf0035b31Hendrik Iben		.driver_data = LG_FF2 },
770606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD),
771606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby		.driver_data = LG_FF },
772606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2),
773606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby		.driver_data = LG_FF },
774606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D),
775606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby		.driver_data = LG_FF },
776606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO),
777606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby		.driver_data = LG_FF },
778606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL),
779270baef1fafab50410e0e395ec26834de2dcc390Simon Wood		.driver_data = LG_NOGET | LG_FF4 },
780606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2),
7817362cd2286d2364cca6738b583668f64254fe04bMichal Malý		.driver_data = LG_FF4 },
782bd04363d3990c0727b7512a79a08c68436878bb0Elias Vanderstuyft	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL),
783bd04363d3990c0727b7512a79a08c68436878bb0Elias Vanderstuyft		.driver_data = LG_FF2 },
784243b706d8a71364ad6080328d45b73516c8af5f3Christophe Borivant	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
7857362cd2286d2364cca6738b583668f64254fe04bMichal Malý		.driver_data = LG_FF4 },
7867362cd2286d2364cca6738b583668f64254fe04bMichal Malý	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL),
7877362cd2286d2364cca6738b583668f64254fe04bMichal Malý		.driver_data = LG_FF4 },
788fdc6807fcd09416c5537f479e1dcd624118e234cPeter Gundermann	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL),
7897362cd2286d2364cca6738b583668f64254fe04bMichal Malý		.driver_data = LG_FF4 },
7905623a24a80814fe471e777f12b9dbbb0f77e002eJiri Kosina	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL),
7917362cd2286d2364cca6738b583668f64254fe04bMichal Malý		.driver_data = LG_NOGET | LG_FF4 },
79232c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL),
79332c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood		.driver_data = LG_FF4 },
794a80fe5d6e3190f65be8cc7efa487f187eb3dbffaMichal Malý	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG),
795fd30ea8c871552ddd6a5e1c0886de8fef4df53bcJiri Kosina		.driver_data = LG_FF },
796606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
797606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby		.driver_data = LG_FF2 },
79874f292ca8c7a2b9370f80d97a49e48174f4c7635Gary Stein	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940),
79974f292ca8c7a2b9370f80d97a49e48174f4c7635Gary Stein		.driver_data = LG_FF3 },
80024985cf68612a5617d396b0b188cec807641cde1Jiri Kosina	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR),
80124985cf68612a5617d396b0b188cec807641cde1Jiri Kosina		.driver_data = LG_RDESC_REL_ABS },
80224985cf68612a5617d396b0b188cec807641cde1Jiri Kosina	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER),
80324985cf68612a5617d396b0b188cec807641cde1Jiri Kosina		.driver_data = LG_RDESC_REL_ABS },
8045f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	{ }
8055f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby};
80624985cf68612a5617d396b0b188cec807641cde1Jiri Kosina
8075f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri SlabyMODULE_DEVICE_TABLE(hid, lg_devices);
8085f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
8095f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slabystatic struct hid_driver lg_driver = {
8105f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	.name = "logitech",
8115f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	.id_table = lg_devices,
8125f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	.report_fixup = lg_report_fixup,
8135f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	.input_mapping = lg_input_mapping,
8145f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	.input_mapped = lg_input_mapped,
8155f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	.event = lg_event,
8165f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby	.probe = lg_probe,
81730bb75d71b3732c0adb6297815288ce0fb9cc04cMichal Malý	.remove = lg_remove,
8185f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby};
819f425458eafd51b6b5ab64f407922e1198c567cb2H Hartley Sweetenmodule_hid_driver(lg_driver);
8205f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby
8215f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri SlabyMODULE_LICENSE("GPL");
822