hid-lg.c revision bd04363d3990c0727b7512a79a08c68436878bb0
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 48270baef1fafab50410e0e395ec26834de2dcc390Simon Wood#define MOMO_RDESC_ORIG_SIZE 87 49dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer 5054bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra/* Fixed report descriptors for Logitech Driving Force (and Pro) 5154bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra * wheel controllers 52dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer * 5354bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra * The original descriptors hide the separate throttle and brake axes in 54dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer * a custom vendor usage page, providing only a combined value as 55dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer * GenericDesktop.Y. 5654bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra * These descriptors remove the combined Y axis and instead report 57dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer * separate throttle (Y) and brake (RZ). 58dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer */ 5954bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarrastatic __u8 df_rdesc_fixed[] = { 6054bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x05, 0x01, /* Usage Page (Desktop), */ 6154bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x09, 0x04, /* Usage (Joystik), */ 6254bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0xA1, 0x01, /* Collection (Application), */ 6354bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0xA1, 0x02, /* Collection (Logical), */ 6454bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x95, 0x01, /* Report Count (1), */ 6554bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x75, 0x0A, /* Report Size (10), */ 6654bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x14, /* Logical Minimum (0), */ 6754bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 6854bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x34, /* Physical Minimum (0), */ 6954bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x46, 0xFF, 0x03, /* Physical Maximum (1023), */ 7054bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x09, 0x30, /* Usage (X), */ 7154bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x81, 0x02, /* Input (Variable), */ 7254bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x95, 0x0C, /* Report Count (12), */ 7354bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x75, 0x01, /* Report Size (1), */ 7454bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x25, 0x01, /* Logical Maximum (1), */ 7554bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x45, 0x01, /* Physical Maximum (1), */ 7654bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x05, 0x09, /* Usage (Buttons), */ 7754bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x19, 0x01, /* Usage Minimum (1), */ 7854bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x29, 0x0c, /* Usage Maximum (12), */ 7954bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x81, 0x02, /* Input (Variable), */ 8054bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x95, 0x02, /* Report Count (2), */ 8154bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x06, 0x00, 0xFF, /* Usage Page (Vendor: 65280), */ 8254bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x09, 0x01, /* Usage (?: 1), */ 8354bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x81, 0x02, /* Input (Variable), */ 8454bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x05, 0x01, /* Usage Page (Desktop), */ 8554bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 8654bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 8754bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x95, 0x01, /* Report Count (1), */ 8854bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x75, 0x08, /* Report Size (8), */ 8954bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x81, 0x02, /* Input (Variable), */ 9054bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x25, 0x07, /* Logical Maximum (7), */ 9154bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x46, 0x3B, 0x01, /* Physical Maximum (315), */ 9254bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x75, 0x04, /* Report Size (4), */ 9354bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x65, 0x14, /* Unit (Degrees), */ 9454bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x09, 0x39, /* Usage (Hat Switch), */ 9554bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x81, 0x42, /* Input (Variable, Null State), */ 9654bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x75, 0x01, /* Report Size (1), */ 9754bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x95, 0x04, /* Report Count (4), */ 9854bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x65, 0x00, /* Unit (none), */ 9954bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x06, 0x00, 0xFF, /* Usage Page (Vendor: 65280), */ 10054bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x09, 0x01, /* Usage (?: 1), */ 10154bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x25, 0x01, /* Logical Maximum (1), */ 10254bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x45, 0x01, /* Physical Maximum (1), */ 10354bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x81, 0x02, /* Input (Variable), */ 1045a9b571bacafffaff75f4f523c4479c85e83cb15Paul Sbarra0x05, 0x01, /* Usage Page (Desktop), */ 1055a9b571bacafffaff75f4f523c4479c85e83cb15Paul Sbarra0x95, 0x01, /* Report Count (1), */ 10654bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x75, 0x08, /* Report Size (8), */ 10754bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 10854bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 1095a9b571bacafffaff75f4f523c4479c85e83cb15Paul Sbarra0x09, 0x31, /* Usage (Y), */ 1105a9b571bacafffaff75f4f523c4479c85e83cb15Paul Sbarra0x81, 0x02, /* Input (Variable), */ 1115a9b571bacafffaff75f4f523c4479c85e83cb15Paul Sbarra0x09, 0x35, /* Usage (Rz), */ 11254bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x81, 0x02, /* Input (Variable), */ 11354bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0xC0, /* End Collection, */ 11454bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0xA1, 0x02, /* Collection (Logical), */ 11554bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 11654bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 11754bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x95, 0x07, /* Report Count (7), */ 11854bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x75, 0x08, /* Report Size (8), */ 11954bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x09, 0x03, /* Usage (?: 3), */ 12054bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0x91, 0x02, /* Output (Variable), */ 12154bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0xC0, /* End Collection, */ 12254bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra0xC0 /* End Collection */ 12354bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra}; 12454bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra 125dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauerstatic __u8 dfp_rdesc_fixed[] = { 126dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x05, 0x01, /* Usage Page (Desktop), */ 127dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x09, 0x04, /* Usage (Joystik), */ 128dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0xA1, 0x01, /* Collection (Application), */ 129dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0xA1, 0x02, /* Collection (Logical), */ 130dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x95, 0x01, /* Report Count (1), */ 131dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x75, 0x0E, /* Report Size (14), */ 132dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x14, /* Logical Minimum (0), */ 133dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x26, 0xFF, 0x3F, /* Logical Maximum (16383), */ 134dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x34, /* Physical Minimum (0), */ 135dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x46, 0xFF, 0x3F, /* Physical Maximum (16383), */ 136dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x09, 0x30, /* Usage (X), */ 137dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x81, 0x02, /* Input (Variable), */ 138dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x95, 0x0E, /* Report Count (14), */ 139dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x75, 0x01, /* Report Size (1), */ 140dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x25, 0x01, /* Logical Maximum (1), */ 141dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x45, 0x01, /* Physical Maximum (1), */ 142dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x05, 0x09, /* Usage Page (Button), */ 143dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x19, 0x01, /* Usage Minimum (01h), */ 144dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x29, 0x0E, /* Usage Maximum (0Eh), */ 145dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x81, 0x02, /* Input (Variable), */ 146dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x05, 0x01, /* Usage Page (Desktop), */ 147dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x95, 0x01, /* Report Count (1), */ 148dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x75, 0x04, /* Report Size (4), */ 149dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x25, 0x07, /* Logical Maximum (7), */ 150dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x46, 0x3B, 0x01, /* Physical Maximum (315), */ 151dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x65, 0x14, /* Unit (Degrees), */ 152dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x09, 0x39, /* Usage (Hat Switch), */ 153dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x81, 0x42, /* Input (Variable, Nullstate), */ 154dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x65, 0x00, /* Unit, */ 155dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 156dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 157dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x75, 0x08, /* Report Size (8), */ 158dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x81, 0x01, /* Input (Constant), */ 159dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x09, 0x31, /* Usage (Y), */ 160dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x81, 0x02, /* Input (Variable), */ 161dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x09, 0x35, /* Usage (Rz), */ 162dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x81, 0x02, /* Input (Variable), */ 163dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x81, 0x01, /* Input (Constant), */ 164dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0xC0, /* End Collection, */ 165dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0xA1, 0x02, /* Collection (Logical), */ 166dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x09, 0x02, /* Usage (02h), */ 167dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x95, 0x07, /* Report Count (7), */ 168dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0x91, 0x02, /* Output (Variable), */ 169dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0xC0, /* End Collection, */ 170dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer0xC0 /* End Collection */ 171dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer}; 172dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer 173270baef1fafab50410e0e395ec26834de2dcc390Simon Woodstatic __u8 momo_rdesc_fixed[] = { 174270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x05, 0x01, /* Usage Page (Desktop), */ 175270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x09, 0x04, /* Usage (Joystik), */ 176270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0xA1, 0x01, /* Collection (Application), */ 177270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0xA1, 0x02, /* Collection (Logical), */ 178270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x95, 0x01, /* Report Count (1), */ 179270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x75, 0x0A, /* Report Size (10), */ 180270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x15, 0x00, /* Logical Minimum (0), */ 181270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 182270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x35, 0x00, /* Physical Minimum (0), */ 183270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x46, 0xFF, 0x03, /* Physical Maximum (1023), */ 184270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x09, 0x30, /* Usage (X), */ 185270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x81, 0x02, /* Input (Variable), */ 186270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x95, 0x08, /* Report Count (8), */ 187270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x75, 0x01, /* Report Size (1), */ 188270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x25, 0x01, /* Logical Maximum (1), */ 189270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x45, 0x01, /* Physical Maximum (1), */ 190270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x05, 0x09, /* Usage Page (Button), */ 191270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x19, 0x01, /* Usage Minimum (01h), */ 192270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x29, 0x08, /* Usage Maximum (08h), */ 193270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x81, 0x02, /* Input (Variable), */ 194270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 195270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x75, 0x0E, /* Report Size (14), */ 196270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x95, 0x01, /* Report Count (1), */ 197270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 198270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 199270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x09, 0x00, /* Usage (00h), */ 200270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x81, 0x02, /* Input (Variable), */ 201270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x05, 0x01, /* Usage Page (Desktop), */ 202270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x75, 0x08, /* Report Size (8), */ 203270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x09, 0x31, /* Usage (Y), */ 204270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x81, 0x02, /* Input (Variable), */ 205270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x09, 0x32, /* Usage (Z), */ 206270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x81, 0x02, /* Input (Variable), */ 207270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 208270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x09, 0x01, /* Usage (01h), */ 209270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x81, 0x02, /* Input (Variable), */ 210270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0xC0, /* End Collection, */ 211270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0xA1, 0x02, /* Collection (Logical), */ 212270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x09, 0x02, /* Usage (02h), */ 213270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x95, 0x07, /* Report Count (7), */ 214270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0x91, 0x02, /* Output (Variable), */ 215270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0xC0, /* End Collection, */ 216270baef1fafab50410e0e395ec26834de2dcc390Simon Wood0xC0 /* End Collection */ 217270baef1fafab50410e0e395ec26834de2dcc390Simon Wood}; 218dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer 2195f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby/* 2205f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby * Certain Logitech keyboards send in report #3 keys which are far 2215f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby * above the logical maximum described in descriptor. This extends 2225f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby * the original value of 0x28c of logical maximum to 0x104d 2235f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby */ 22473e4008ddddc84d5f2499c17012b340a0dae153eNikolai Kondrashovstatic __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, 22573e4008ddddc84d5f2499c17012b340a0dae153eNikolai Kondrashov unsigned int *rsize) 2265f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby{ 2272575155309947063927b123c56119f36dfda3b50Axel Lin struct lg_drv_data *drv_data = hid_get_drvdata(hdev); 22854bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra struct usb_device_descriptor *udesc; 22954bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra __u16 bcdDevice, rev_maj, rev_min; 2305f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 2318577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý if ((drv_data->quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 && 2325f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby rdesc[84] == 0x8c && rdesc[85] == 0x02) { 2334291ee305e9bb0699504a66f0e2b7aefcf0512a5Joe Perches hid_info(hdev, 2344291ee305e9bb0699504a66f0e2b7aefcf0512a5Joe Perches "fixing up Logitech keyboard report descriptor\n"); 2355f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby rdesc[84] = rdesc[89] = 0x4d; 2365f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby rdesc[85] = rdesc[90] = 0x10; 2375f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby } 2388577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 50 && 23924985cf68612a5617d396b0b188cec807641cde1Jiri Kosina rdesc[32] == 0x81 && rdesc[33] == 0x06 && 24024985cf68612a5617d396b0b188cec807641cde1Jiri Kosina rdesc[49] == 0x81 && rdesc[50] == 0x06) { 2414291ee305e9bb0699504a66f0e2b7aefcf0512a5Joe Perches hid_info(hdev, 2424291ee305e9bb0699504a66f0e2b7aefcf0512a5Joe Perches "fixing up rel/abs in Logitech report descriptor\n"); 24324985cf68612a5617d396b0b188cec807641cde1Jiri Kosina rdesc[33] = rdesc[50] = 0x02; 24424985cf68612a5617d396b0b188cec807641cde1Jiri Kosina } 245dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer 246dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer switch (hdev->product) { 24754bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra 24854bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra /* Several wheels report as this id when operating in emulation mode. */ 24954bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra case USB_DEVICE_ID_LOGITECH_WHEEL: 25054bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra udesc = &(hid_to_usb_dev(hdev)->descriptor); 25154bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra if (!udesc) { 25254bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra hid_err(hdev, "NULL USB device descriptor\n"); 25354bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra break; 25454bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra } 25554bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra bcdDevice = le16_to_cpu(udesc->bcdDevice); 25654bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra rev_maj = bcdDevice >> 8; 25754bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra rev_min = bcdDevice & 0xff; 25854bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra 25954bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra /* Update the report descriptor for only the Driving Force wheel */ 26054bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra if (rev_maj == 1 && rev_min == 2 && 26154bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra *rsize == DF_RDESC_ORIG_SIZE) { 26254bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra hid_info(hdev, 26354bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra "fixing up Logitech Driving Force report descriptor\n"); 26454bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra rdesc = df_rdesc_fixed; 26554bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra *rsize = sizeof(df_rdesc_fixed); 26654bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra } 26754bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra break; 26854bfe3f0dab2b2f0ac629690f187537d95adeb4fPaul Sbarra 269270baef1fafab50410e0e395ec26834de2dcc390Simon Wood case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL: 270270baef1fafab50410e0e395ec26834de2dcc390Simon Wood if (*rsize == MOMO_RDESC_ORIG_SIZE) { 271270baef1fafab50410e0e395ec26834de2dcc390Simon Wood hid_info(hdev, 272270baef1fafab50410e0e395ec26834de2dcc390Simon Wood "fixing up Logitech Momo Force (Red) report descriptor\n"); 273270baef1fafab50410e0e395ec26834de2dcc390Simon Wood rdesc = momo_rdesc_fixed; 274270baef1fafab50410e0e395ec26834de2dcc390Simon Wood *rsize = sizeof(momo_rdesc_fixed); 275270baef1fafab50410e0e395ec26834de2dcc390Simon Wood } 276270baef1fafab50410e0e395ec26834de2dcc390Simon Wood break; 277270baef1fafab50410e0e395ec26834de2dcc390Simon Wood 278dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: 279dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer if (*rsize == DFP_RDESC_ORIG_SIZE) { 280dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer hid_info(hdev, 281dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer "fixing up Logitech Driving Force Pro report descriptor\n"); 282dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer rdesc = dfp_rdesc_fixed; 283dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer *rsize = sizeof(dfp_rdesc_fixed); 284dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer } 285dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer break; 286b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood 287b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood case USB_DEVICE_ID_LOGITECH_WII_WHEEL: 288b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood if (*rsize >= 101 && rdesc[41] == 0x95 && rdesc[42] == 0x0B && 289b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood rdesc[47] == 0x05 && rdesc[48] == 0x09) { 290b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood hid_info(hdev, "fixing up Logitech Speed Force Wireless report descriptor\n"); 291b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood rdesc[41] = 0x05; 292b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood rdesc[42] = 0x09; 293b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood rdesc[47] = 0x95; 294b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood rdesc[48] = 0x0B; 295b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood } 296b5836246c127ce1f0afe9790537b94c71efd2d2aSimon Wood break; 297dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer } 298dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bfMichael Bauer 29973e4008ddddc84d5f2499c17012b340a0dae153eNikolai Kondrashov return rdesc; 3005f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby} 3015f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 3025f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby#define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ 3035f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby EV_KEY, (c)) 3045f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 3055f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slabystatic int lg_ultrax_remote_mapping(struct hid_input *hi, 3065f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby struct hid_usage *usage, unsigned long **bit, int *max) 3075f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby{ 3085f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) 3095f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby return 0; 3105f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 3115f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby set_bit(EV_REP, hi->input->evbit); 3125f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby switch (usage->hid & HID_USAGE) { 3135f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby /* Reported on Logitech Ultra X Media Remote */ 3145f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x004: lg_map_key_clear(KEY_AGAIN); break; 3155f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x00d: lg_map_key_clear(KEY_HOME); break; 3165f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x024: lg_map_key_clear(KEY_SHUFFLE); break; 3175f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x025: lg_map_key_clear(KEY_TV); break; 3185f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x026: lg_map_key_clear(KEY_MENU); break; 3195f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x031: lg_map_key_clear(KEY_AUDIO); break; 3205f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x032: lg_map_key_clear(KEY_TEXT); break; 3215f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x033: lg_map_key_clear(KEY_LAST); break; 3225f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x047: lg_map_key_clear(KEY_MP3); break; 3235f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x048: lg_map_key_clear(KEY_DVD); break; 3245f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x049: lg_map_key_clear(KEY_MEDIA); break; 3255f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x04a: lg_map_key_clear(KEY_VIDEO); break; 3265f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x04b: lg_map_key_clear(KEY_ANGLE); break; 3275f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x04c: lg_map_key_clear(KEY_LANGUAGE); break; 3285f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x04d: lg_map_key_clear(KEY_SUBTITLE); break; 3295f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x051: lg_map_key_clear(KEY_RED); break; 3305f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x052: lg_map_key_clear(KEY_CLOSE); break; 3315f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 3325f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby default: 3335f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby return 0; 3345f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby } 3355f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby return 1; 3365f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby} 3375f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 33866d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosinastatic int lg_dinovo_mapping(struct hid_input *hi, struct hid_usage *usage, 33966d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina unsigned long **bit, int *max) 34066d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina{ 34166d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) 34266d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina return 0; 34366d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina 34466d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina switch (usage->hid & HID_USAGE) { 34566d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina 34666d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina case 0x00d: lg_map_key_clear(KEY_MEDIA); break; 34766d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina default: 34866d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina return 0; 34966d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina 35066d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina } 35166d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina return 1; 35266d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina} 35366d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina 3545f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slabystatic int lg_wireless_mapping(struct hid_input *hi, struct hid_usage *usage, 3555f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby unsigned long **bit, int *max) 3565f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby{ 3575f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) 3585f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby return 0; 3595f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 3605f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby switch (usage->hid & HID_USAGE) { 3615f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1001: lg_map_key_clear(KEY_MESSENGER); break; 3625f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1003: lg_map_key_clear(KEY_SOUND); break; 3635f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1004: lg_map_key_clear(KEY_VIDEO); break; 3645f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1005: lg_map_key_clear(KEY_AUDIO); break; 3655f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x100a: lg_map_key_clear(KEY_DOCUMENTS); break; 36618392212932ecbdc71bc6a298ad301328eefb09dLorenzo Castelli /* The following two entries are Playlist 1 and 2 on the MX3200 */ 36718392212932ecbdc71bc6a298ad301328eefb09dLorenzo Castelli case 0x100f: lg_map_key_clear(KEY_FN_1); break; 36818392212932ecbdc71bc6a298ad301328eefb09dLorenzo Castelli case 0x1010: lg_map_key_clear(KEY_FN_2); break; 3695f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1011: lg_map_key_clear(KEY_PREVIOUSSONG); break; 3705f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1012: lg_map_key_clear(KEY_NEXTSONG); break; 3715f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1013: lg_map_key_clear(KEY_CAMERA); break; 3725f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1014: lg_map_key_clear(KEY_MESSENGER); break; 3735f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1015: lg_map_key_clear(KEY_RECORD); break; 3745f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1016: lg_map_key_clear(KEY_PLAYER); break; 3755f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1017: lg_map_key_clear(KEY_EJECTCD); break; 3765f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1018: lg_map_key_clear(KEY_MEDIA); break; 3775f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1019: lg_map_key_clear(KEY_PROG1); break; 3785f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x101a: lg_map_key_clear(KEY_PROG2); break; 3795f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x101b: lg_map_key_clear(KEY_PROG3); break; 38018392212932ecbdc71bc6a298ad301328eefb09dLorenzo Castelli case 0x101c: lg_map_key_clear(KEY_CYCLEWINDOWS); break; 3815f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x101f: lg_map_key_clear(KEY_ZOOMIN); break; 3825f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1020: lg_map_key_clear(KEY_ZOOMOUT); break; 3835f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1021: lg_map_key_clear(KEY_ZOOMRESET); break; 3845f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1023: lg_map_key_clear(KEY_CLOSE); break; 3855f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1027: lg_map_key_clear(KEY_MENU); break; 3865f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby /* this one is marked as 'Rotate' */ 3875f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1028: lg_map_key_clear(KEY_ANGLE); break; 3885f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1029: lg_map_key_clear(KEY_SHUFFLE); break; 3895f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x102a: lg_map_key_clear(KEY_BACK); break; 3905f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x102b: lg_map_key_clear(KEY_CYCLEWINDOWS); break; 39118392212932ecbdc71bc6a298ad301328eefb09dLorenzo Castelli case 0x102d: lg_map_key_clear(KEY_WWW); break; 39218392212932ecbdc71bc6a298ad301328eefb09dLorenzo Castelli /* The following two are 'Start/answer call' and 'End/reject call' 39318392212932ecbdc71bc6a298ad301328eefb09dLorenzo Castelli on the MX3200 */ 39418392212932ecbdc71bc6a298ad301328eefb09dLorenzo Castelli case 0x1031: lg_map_key_clear(KEY_OK); break; 39518392212932ecbdc71bc6a298ad301328eefb09dLorenzo Castelli case 0x1032: lg_map_key_clear(KEY_CANCEL); break; 3965f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1041: lg_map_key_clear(KEY_BATTERY); break; 3975f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1042: lg_map_key_clear(KEY_WORDPROCESSOR); break; 3985f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1043: lg_map_key_clear(KEY_SPREADSHEET); break; 3995f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1044: lg_map_key_clear(KEY_PRESENTATION); break; 4005f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1045: lg_map_key_clear(KEY_UNDO); break; 4015f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1046: lg_map_key_clear(KEY_REDO); break; 4025f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1047: lg_map_key_clear(KEY_PRINT); break; 4035f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1048: lg_map_key_clear(KEY_SAVE); break; 4045f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x1049: lg_map_key_clear(KEY_PROG1); break; 4055f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x104a: lg_map_key_clear(KEY_PROG2); break; 4065f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x104b: lg_map_key_clear(KEY_PROG3); break; 4075f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby case 0x104c: lg_map_key_clear(KEY_PROG4); break; 4085f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 4095f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby default: 4105f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby return 0; 4115f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby } 4125f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby return 1; 4135f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby} 4145f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 4155f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slabystatic int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi, 4165f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby struct hid_field *field, struct hid_usage *usage, 4175f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby unsigned long **bit, int *max) 4185f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby{ 4195f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby /* extended mapping for certain Logitech hardware (Logitech cordless 4205f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby desktop LX500) */ 4215f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby static const u8 e_keymap[] = { 4225f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 0,216, 0,213,175,156, 0, 0, 0, 0, 4235f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 144, 0, 0, 0, 0, 0, 0, 0, 0,212, 4245f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 174,167,152,161,112, 0, 0, 0,154, 0, 4255f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4265f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4275f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4285f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 0, 0, 0, 0, 0,183,184,185,186,187, 4295f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 188,189,190,191,192,193,194, 0, 0, 0 4305f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby }; 4312575155309947063927b123c56119f36dfda3b50Axel Lin struct lg_drv_data *drv_data = hid_get_drvdata(hdev); 4325f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby unsigned int hid = usage->hid; 4335f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 4345f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby if (hdev->product == USB_DEVICE_ID_LOGITECH_RECEIVER && 4355f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby lg_ultrax_remote_mapping(hi, usage, bit, max)) 4365f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby return 1; 4375f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 43866d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina if (hdev->product == USB_DEVICE_ID_DINOVO_MINI && 43966d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina lg_dinovo_mapping(hi, usage, bit, max)) 44066d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina return 1; 44166d61bec697e99476c2fb095f9a6ead3be2e1c21Jiri Kosina 4428577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý if ((drv_data->quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max)) 4435f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby return 1; 4445f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 4455f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby if ((hid & HID_USAGE_PAGE) != HID_UP_BUTTON) 4465f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby return 0; 4475f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 4485f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby hid &= HID_USAGE; 4495f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 4505f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby /* Special handling for Logitech Cordless Desktop */ 4515f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby if (field->application == HID_GD_MOUSE) { 4528577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý if ((drv_data->quirks & LG_IGNORE_DOUBLED_WHEEL) && 4535f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby (hid == 7 || hid == 8)) 4545f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby return -1; 4555f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby } else { 4568577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý if ((drv_data->quirks & LG_EXPANDED_KEYMAP) && 4575f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby hid < ARRAY_SIZE(e_keymap) && 4585f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby e_keymap[hid] != 0) { 4595f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby hid_map_usage(hi, usage, bit, max, EV_KEY, 4605f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby e_keymap[hid]); 4615f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby return 1; 4625f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby } 4635f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby } 4645f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 4655f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby return 0; 4665f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby} 4675f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 4685f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slabystatic int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi, 4695f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby struct hid_field *field, struct hid_usage *usage, 4705f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby unsigned long **bit, int *max) 4715f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby{ 4722575155309947063927b123c56119f36dfda3b50Axel Lin struct lg_drv_data *drv_data = hid_get_drvdata(hdev); 4735f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 4748577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý if ((drv_data->quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY && 4755f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby (field->flags & HID_MAIN_ITEM_RELATIVE)) 4765f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby field->flags &= ~HID_MAIN_ITEM_RELATIVE; 4775f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 4788577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý if ((drv_data->quirks & LG_DUPLICATE_USAGES) && (usage->type == EV_KEY || 4795f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby usage->type == EV_REL || usage->type == EV_ABS)) 4805f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby clear_bit(usage->code, *bit); 4815f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 48294b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood /* Ensure that Logitech wheels are not given a default fuzz/flat value */ 48394b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood if (usage->type == EV_ABS && (usage->code == ABS_X || 48494b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood usage->code == ABS_Y || usage->code == ABS_Z || 48594b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood usage->code == ABS_RZ)) { 48694b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood switch (hdev->product) { 48794b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood case USB_DEVICE_ID_LOGITECH_WHEEL: 48894b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL: 48994b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: 49094b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood case USB_DEVICE_ID_LOGITECH_G25_WHEEL: 49194b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL: 49294b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood case USB_DEVICE_ID_LOGITECH_G27_WHEEL: 49394b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood case USB_DEVICE_ID_LOGITECH_WII_WHEEL: 49494b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2: 495bd04363d3990c0727b7512a79a08c68436878bb0Elias Vanderstuyft case USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL: 49694b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood field->application = HID_GD_MULTIAXIS; 49794b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood break; 49894b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood default: 49994b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood break; 50094b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood } 50194b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood } 50294b3f712fe2cd5c33d57ca0ab9604d2402bc72cdSimon Wood 5035f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby return 0; 5045f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby} 5055f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 5065f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slabystatic int lg_event(struct hid_device *hdev, struct hid_field *field, 5075f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby struct hid_usage *usage, __s32 value) 5085f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby{ 5092575155309947063927b123c56119f36dfda3b50Axel Lin struct lg_drv_data *drv_data = hid_get_drvdata(hdev); 5105f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 5118577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý if ((drv_data->quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) { 5125f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby input_event(field->hidinput->input, usage->type, usage->code, 5135f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby -value); 5145f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby return 1; 5155f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby } 5162b24a960016b8d3221a6dd2764ab97247c48dd97Michal Malý if (drv_data->quirks & LG_FF4) { 5172b24a960016b8d3221a6dd2764ab97247c48dd97Michal Malý return lg4ff_adjust_input_event(hdev, field, usage, value, drv_data); 5182b24a960016b8d3221a6dd2764ab97247c48dd97Michal Malý } 5195f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 5205f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby return 0; 5215f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby} 5225f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 5235f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slabystatic int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) 5245f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby{ 525606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby unsigned int connect_mask = HID_CONNECT_DEFAULT; 5268577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý struct lg_drv_data *drv_data; 5275f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby int ret; 5285f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 5298577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL); 5308577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý if (!drv_data) { 5318577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý hid_err(hdev, "Insufficient memory, cannot allocate driver data\n"); 5328577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý return -ENOMEM; 5338577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý } 5348577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý drv_data->quirks = id->driver_data; 535a80fe5d6e3190f65be8cc7efa487f187eb3dbffaMichal Malý 5368577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý hid_set_drvdata(hdev, (void *)drv_data); 5375f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 5388577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý if (drv_data->quirks & LG_NOGET) 5395f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby hdev->quirks |= HID_QUIRK_NOGET; 5405f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 5415f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby ret = hid_parse(hdev); 5425f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby if (ret) { 5434291ee305e9bb0699504a66f0e2b7aefcf0512a5Joe Perches hid_err(hdev, "parse failed\n"); 5445f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby goto err_free; 5455f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby } 5465f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 5478577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý if (drv_data->quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4)) 548606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby connect_mask &= ~HID_CONNECT_FF; 549606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby 550606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby ret = hid_hw_start(hdev, connect_mask); 5515f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby if (ret) { 5524291ee305e9bb0699504a66f0e2b7aefcf0512a5Joe Perches hid_err(hdev, "hw start failed\n"); 5535f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby goto err_free; 5545f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby } 5555f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 5567362cd2286d2364cca6738b583668f64254fe04bMichal Malý /* Setup wireless link with Logitech Wii wheel */ 557a80fe5d6e3190f65be8cc7efa487f187eb3dbffaMichal Malý if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) { 55832c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood unsigned char buf[] = { 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 55932c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood 56032c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); 56132c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood 56232c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood if (ret >= 0) { 56332c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood /* insert a little delay of 10 jiffies ~ 40ms */ 56432c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood wait_queue_head_t wait; 56532c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood init_waitqueue_head (&wait); 56632c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood wait_event_interruptible_timeout(wait, 0, 10); 56732c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood 56832c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood /* Select random Address */ 56932c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood buf[1] = 0xB2; 57032c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood get_random_bytes(&buf[2], 2); 57132c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood 57232c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); 57332c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood } 57432c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood } 57532c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood 5768577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý if (drv_data->quirks & LG_FF) 577606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby lgff_init(hdev); 5788577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý if (drv_data->quirks & LG_FF2) 579606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby lg2ff_init(hdev); 5808577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý if (drv_data->quirks & LG_FF3) 58174f292ca8c7a2b9370f80d97a49e48174f4c7635Gary Stein lg3ff_init(hdev); 5828577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý if (drv_data->quirks & LG_FF4) 58332c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood lg4ff_init(hdev); 584606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby 5855f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby return 0; 5865f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slabyerr_free: 5878577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý kfree(drv_data); 5885f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby return ret; 5895f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby} 5905f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 59130bb75d71b3732c0adb6297815288ce0fb9cc04cMichal Malýstatic void lg_remove(struct hid_device *hdev) 59230bb75d71b3732c0adb6297815288ce0fb9cc04cMichal Malý{ 5932575155309947063927b123c56119f36dfda3b50Axel Lin struct lg_drv_data *drv_data = hid_get_drvdata(hdev); 5948577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý if (drv_data->quirks & LG_FF4) 59530bb75d71b3732c0adb6297815288ce0fb9cc04cMichal Malý lg4ff_deinit(hdev); 59630bb75d71b3732c0adb6297815288ce0fb9cc04cMichal Malý 59730bb75d71b3732c0adb6297815288ce0fb9cc04cMichal Malý hid_hw_stop(hdev); 5988577dbf9d6eb07213caefb49e2017c177c5f023dMichal Malý kfree(drv_data); 59930bb75d71b3732c0adb6297815288ce0fb9cc04cMichal Malý} 60030bb75d71b3732c0adb6297815288ce0fb9cc04cMichal Malý 6015f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slabystatic const struct hid_device_id lg_devices[] = { 6025f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER), 6035f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby .driver_data = LG_RDESC | LG_WIRELESS }, 6045f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER), 6055f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby .driver_data = LG_RDESC | LG_WIRELESS }, 6065f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2), 6075f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby .driver_data = LG_RDESC | LG_WIRELESS }, 6085f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 6095f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER), 6105f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby .driver_data = LG_BAD_RELATIVE_KEYS }, 6115f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 6125f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP), 6135f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby .driver_data = LG_DUPLICATE_USAGES }, 6145f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE), 6155f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby .driver_data = LG_DUPLICATE_USAGES }, 6165f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI), 6175f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby .driver_data = LG_DUPLICATE_USAGES }, 6185f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 6195f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD), 6205f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP }, 6215f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500), 6225f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP }, 6235f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 6245f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D), 6255f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby .driver_data = LG_NOGET }, 6265f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL), 6277362cd2286d2364cca6738b583668f64254fe04bMichal Malý .driver_data = LG_NOGET | LG_FF4 }, 628606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby 6292c6118e43040034d80894daeba41960bf0035b31Hendrik Iben { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD), 6302c6118e43040034d80894daeba41960bf0035b31Hendrik Iben .driver_data = LG_FF2 }, 631606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD), 632606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby .driver_data = LG_FF }, 633606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2), 634606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby .driver_data = LG_FF }, 635606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D), 636606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby .driver_data = LG_FF }, 637606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO), 638606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby .driver_data = LG_FF }, 639606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL), 640270baef1fafab50410e0e395ec26834de2dcc390Simon Wood .driver_data = LG_NOGET | LG_FF4 }, 641606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2), 6427362cd2286d2364cca6738b583668f64254fe04bMichal Malý .driver_data = LG_FF4 }, 643bd04363d3990c0727b7512a79a08c68436878bb0Elias Vanderstuyft { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL), 644bd04363d3990c0727b7512a79a08c68436878bb0Elias Vanderstuyft .driver_data = LG_FF2 }, 645243b706d8a71364ad6080328d45b73516c8af5f3Christophe Borivant { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL), 6467362cd2286d2364cca6738b583668f64254fe04bMichal Malý .driver_data = LG_FF4 }, 6477362cd2286d2364cca6738b583668f64254fe04bMichal Malý { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL), 6487362cd2286d2364cca6738b583668f64254fe04bMichal Malý .driver_data = LG_FF4 }, 649fdc6807fcd09416c5537f479e1dcd624118e234cPeter Gundermann { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL), 6507362cd2286d2364cca6738b583668f64254fe04bMichal Malý .driver_data = LG_FF4 }, 6515623a24a80814fe471e777f12b9dbbb0f77e002eJiri Kosina { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL), 6527362cd2286d2364cca6738b583668f64254fe04bMichal Malý .driver_data = LG_NOGET | LG_FF4 }, 65332c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL), 65432c88cbc3080f43c429f6456aa9cd845e37f3778Simon Wood .driver_data = LG_FF4 }, 655a80fe5d6e3190f65be8cc7efa487f187eb3dbffaMichal Malý { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG), 656fd30ea8c871552ddd6a5e1c0886de8fef4df53bcJiri Kosina .driver_data = LG_FF }, 657606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2), 658606bd0a8616a0e59021cb2997e942513f24f641dJiri Slaby .driver_data = LG_FF2 }, 65974f292ca8c7a2b9370f80d97a49e48174f4c7635Gary Stein { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940), 66074f292ca8c7a2b9370f80d97a49e48174f4c7635Gary Stein .driver_data = LG_FF3 }, 66124985cf68612a5617d396b0b188cec807641cde1Jiri Kosina { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR), 66224985cf68612a5617d396b0b188cec807641cde1Jiri Kosina .driver_data = LG_RDESC_REL_ABS }, 66324985cf68612a5617d396b0b188cec807641cde1Jiri Kosina { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER), 66424985cf68612a5617d396b0b188cec807641cde1Jiri Kosina .driver_data = LG_RDESC_REL_ABS }, 6655f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby { } 6665f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby}; 66724985cf68612a5617d396b0b188cec807641cde1Jiri Kosina 6685f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri SlabyMODULE_DEVICE_TABLE(hid, lg_devices); 6695f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 6705f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slabystatic struct hid_driver lg_driver = { 6715f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby .name = "logitech", 6725f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby .id_table = lg_devices, 6735f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby .report_fixup = lg_report_fixup, 6745f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby .input_mapping = lg_input_mapping, 6755f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby .input_mapped = lg_input_mapped, 6765f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby .event = lg_event, 6775f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby .probe = lg_probe, 67830bb75d71b3732c0adb6297815288ce0fb9cc04cMichal Malý .remove = lg_remove, 6795f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby}; 680f425458eafd51b6b5ab64f407922e1198c567cb2H Hartley Sweetenmodule_hid_driver(lg_driver); 6815f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri Slaby 6825f22a7992349c5ca3842190be52d5e9a1dd7adf4Jiri SlabyMODULE_LICENSE("GPL"); 683