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