0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/device.h>
0017 #include <linux/hid.h>
0018 #include <linux/module.h>
0019 #include <linux/random.h>
0020 #include <linux/sched.h>
0021 #include <linux/usb.h>
0022 #include <linux/wait.h>
0023
0024 #include "usbhid/usbhid.h"
0025 #include "hid-ids.h"
0026 #include "hid-lg.h"
0027 #include "hid-lg4ff.h"
0028
0029 #define LG_RDESC 0x001
0030 #define LG_BAD_RELATIVE_KEYS 0x002
0031 #define LG_DUPLICATE_USAGES 0x004
0032 #define LG_EXPANDED_KEYMAP 0x010
0033 #define LG_IGNORE_DOUBLED_WHEEL 0x020
0034 #define LG_WIRELESS 0x040
0035 #define LG_INVERT_HWHEEL 0x080
0036 #define LG_NOGET 0x100
0037 #define LG_FF 0x200
0038 #define LG_FF2 0x400
0039 #define LG_RDESC_REL_ABS 0x800
0040 #define LG_FF3 0x1000
0041 #define LG_FF4 0x2000
0042
0043
0044 #define DF_RDESC_ORIG_SIZE 130
0045 #define DFP_RDESC_ORIG_SIZE 97
0046 #define FV_RDESC_ORIG_SIZE 130
0047 #define MOMO_RDESC_ORIG_SIZE 87
0048 #define MOMO2_RDESC_ORIG_SIZE 87
0049 #define FFG_RDESC_ORIG_SIZE 85
0050 #define FG_RDESC_ORIG_SIZE 82
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061 static __u8 df_rdesc_fixed[] = {
0062 0x05, 0x01,
0063 0x09, 0x04,
0064 0xA1, 0x01,
0065 0xA1, 0x02,
0066 0x95, 0x01,
0067 0x75, 0x0A,
0068 0x14,
0069 0x26, 0xFF, 0x03,
0070 0x34,
0071 0x46, 0xFF, 0x03,
0072 0x09, 0x30,
0073 0x81, 0x02,
0074 0x95, 0x0C,
0075 0x75, 0x01,
0076 0x25, 0x01,
0077 0x45, 0x01,
0078 0x05, 0x09,
0079 0x19, 0x01,
0080 0x29, 0x0c,
0081 0x81, 0x02,
0082 0x95, 0x02,
0083 0x06, 0x00, 0xFF,
0084 0x09, 0x01,
0085 0x81, 0x02,
0086 0x05, 0x01,
0087 0x26, 0xFF, 0x00,
0088 0x46, 0xFF, 0x00,
0089 0x95, 0x01,
0090 0x75, 0x08,
0091 0x81, 0x02,
0092 0x25, 0x07,
0093 0x46, 0x3B, 0x01,
0094 0x75, 0x04,
0095 0x65, 0x14,
0096 0x09, 0x39,
0097 0x81, 0x42,
0098 0x75, 0x01,
0099 0x95, 0x04,
0100 0x65, 0x00,
0101 0x06, 0x00, 0xFF,
0102 0x09, 0x01,
0103 0x25, 0x01,
0104 0x45, 0x01,
0105 0x81, 0x02,
0106 0x05, 0x01,
0107 0x95, 0x01,
0108 0x75, 0x08,
0109 0x26, 0xFF, 0x00,
0110 0x46, 0xFF, 0x00,
0111 0x09, 0x31,
0112 0x81, 0x02,
0113 0x09, 0x35,
0114 0x81, 0x02,
0115 0xC0,
0116 0xA1, 0x02,
0117 0x26, 0xFF, 0x00,
0118 0x46, 0xFF, 0x00,
0119 0x95, 0x07,
0120 0x75, 0x08,
0121 0x09, 0x03,
0122 0x91, 0x02,
0123 0xC0,
0124 0xC0
0125 };
0126
0127 static __u8 dfp_rdesc_fixed[] = {
0128 0x05, 0x01,
0129 0x09, 0x04,
0130 0xA1, 0x01,
0131 0xA1, 0x02,
0132 0x95, 0x01,
0133 0x75, 0x0E,
0134 0x14,
0135 0x26, 0xFF, 0x3F,
0136 0x34,
0137 0x46, 0xFF, 0x3F,
0138 0x09, 0x30,
0139 0x81, 0x02,
0140 0x95, 0x0E,
0141 0x75, 0x01,
0142 0x25, 0x01,
0143 0x45, 0x01,
0144 0x05, 0x09,
0145 0x19, 0x01,
0146 0x29, 0x0E,
0147 0x81, 0x02,
0148 0x05, 0x01,
0149 0x95, 0x01,
0150 0x75, 0x04,
0151 0x25, 0x07,
0152 0x46, 0x3B, 0x01,
0153 0x65, 0x14,
0154 0x09, 0x39,
0155 0x81, 0x42,
0156 0x65, 0x00,
0157 0x26, 0xFF, 0x00,
0158 0x46, 0xFF, 0x00,
0159 0x75, 0x08,
0160 0x81, 0x01,
0161 0x09, 0x31,
0162 0x81, 0x02,
0163 0x09, 0x35,
0164 0x81, 0x02,
0165 0x81, 0x01,
0166 0xC0,
0167 0xA1, 0x02,
0168 0x09, 0x02,
0169 0x95, 0x07,
0170 0x91, 0x02,
0171 0xC0,
0172 0xC0
0173 };
0174
0175 static __u8 fv_rdesc_fixed[] = {
0176 0x05, 0x01,
0177 0x09, 0x04,
0178 0xA1, 0x01,
0179 0xA1, 0x02,
0180 0x95, 0x01,
0181 0x75, 0x0A,
0182 0x15, 0x00,
0183 0x26, 0xFF, 0x03,
0184 0x35, 0x00,
0185 0x46, 0xFF, 0x03,
0186 0x09, 0x30,
0187 0x81, 0x02,
0188 0x95, 0x0C,
0189 0x75, 0x01,
0190 0x25, 0x01,
0191 0x45, 0x01,
0192 0x05, 0x09,
0193 0x19, 0x01,
0194 0x29, 0x0C,
0195 0x81, 0x02,
0196 0x95, 0x02,
0197 0x06, 0x00, 0xFF,
0198 0x09, 0x01,
0199 0x81, 0x02,
0200 0x09, 0x02,
0201 0x26, 0xFF, 0x00,
0202 0x46, 0xFF, 0x00,
0203 0x95, 0x01,
0204 0x75, 0x08,
0205 0x81, 0x02,
0206 0x05, 0x01,
0207 0x25, 0x07,
0208 0x46, 0x3B, 0x01,
0209 0x75, 0x04,
0210 0x65, 0x14,
0211 0x09, 0x39,
0212 0x81, 0x42,
0213 0x75, 0x01,
0214 0x95, 0x04,
0215 0x65, 0x00,
0216 0x06, 0x00, 0xFF,
0217 0x09, 0x01,
0218 0x25, 0x01,
0219 0x45, 0x01,
0220 0x81, 0x02,
0221 0x05, 0x01,
0222 0x95, 0x01,
0223 0x75, 0x08,
0224 0x26, 0xFF, 0x00,
0225 0x46, 0xFF, 0x00,
0226 0x09, 0x31,
0227 0x81, 0x02,
0228 0x09, 0x32,
0229 0x81, 0x02,
0230 0xC0,
0231 0xA1, 0x02,
0232 0x26, 0xFF, 0x00,
0233 0x46, 0xFF, 0x00,
0234 0x95, 0x07,
0235 0x75, 0x08,
0236 0x09, 0x03,
0237 0x91, 0x02,
0238 0xC0,
0239 0xC0
0240 };
0241
0242 static __u8 momo_rdesc_fixed[] = {
0243 0x05, 0x01,
0244 0x09, 0x04,
0245 0xA1, 0x01,
0246 0xA1, 0x02,
0247 0x95, 0x01,
0248 0x75, 0x0A,
0249 0x15, 0x00,
0250 0x26, 0xFF, 0x03,
0251 0x35, 0x00,
0252 0x46, 0xFF, 0x03,
0253 0x09, 0x30,
0254 0x81, 0x02,
0255 0x95, 0x08,
0256 0x75, 0x01,
0257 0x25, 0x01,
0258 0x45, 0x01,
0259 0x05, 0x09,
0260 0x19, 0x01,
0261 0x29, 0x08,
0262 0x81, 0x02,
0263 0x06, 0x00, 0xFF,
0264 0x75, 0x0E,
0265 0x95, 0x01,
0266 0x26, 0xFF, 0x00,
0267 0x46, 0xFF, 0x00,
0268 0x09, 0x00,
0269 0x81, 0x02,
0270 0x05, 0x01,
0271 0x75, 0x08,
0272 0x09, 0x31,
0273 0x81, 0x02,
0274 0x09, 0x32,
0275 0x81, 0x02,
0276 0x06, 0x00, 0xFF,
0277 0x09, 0x01,
0278 0x81, 0x02,
0279 0xC0,
0280 0xA1, 0x02,
0281 0x09, 0x02,
0282 0x95, 0x07,
0283 0x91, 0x02,
0284 0xC0,
0285 0xC0
0286 };
0287
0288 static __u8 momo2_rdesc_fixed[] = {
0289 0x05, 0x01,
0290 0x09, 0x04,
0291 0xA1, 0x01,
0292 0xA1, 0x02,
0293 0x95, 0x01,
0294 0x75, 0x0A,
0295 0x15, 0x00,
0296 0x26, 0xFF, 0x03,
0297 0x35, 0x00,
0298 0x46, 0xFF, 0x03,
0299 0x09, 0x30,
0300 0x81, 0x02,
0301 0x95, 0x0A,
0302 0x75, 0x01,
0303 0x25, 0x01,
0304 0x45, 0x01,
0305 0x05, 0x09,
0306 0x19, 0x01,
0307 0x29, 0x0A,
0308 0x81, 0x02,
0309 0x06, 0x00, 0xFF,
0310 0x09, 0x00,
0311 0x95, 0x04,
0312 0x81, 0x02,
0313 0x95, 0x01,
0314 0x75, 0x08,
0315 0x26, 0xFF, 0x00,
0316 0x46, 0xFF, 0x00,
0317 0x09, 0x01,
0318 0x81, 0x02,
0319 0x05, 0x01,
0320 0x09, 0x31,
0321 0x81, 0x02,
0322 0x09, 0x32,
0323 0x81, 0x02,
0324 0x06, 0x00, 0xFF,
0325 0x09, 0x00,
0326 0x81, 0x02,
0327 0xC0,
0328 0xA1, 0x02,
0329 0x09, 0x02,
0330 0x95, 0x07,
0331 0x91, 0x02,
0332 0xC0,
0333 0xC0
0334 };
0335
0336 static __u8 ffg_rdesc_fixed[] = {
0337 0x05, 0x01,
0338 0x09, 0x04,
0339 0xA1, 0x01,
0340 0xA1, 0x02,
0341 0x95, 0x01,
0342 0x75, 0x0A,
0343 0x15, 0x00,
0344 0x26, 0xFF, 0x03,
0345 0x35, 0x00,
0346 0x46, 0xFF, 0x03,
0347 0x09, 0x30,
0348 0x81, 0x02,
0349 0x95, 0x06,
0350 0x75, 0x01,
0351 0x25, 0x01,
0352 0x45, 0x01,
0353 0x05, 0x09,
0354 0x19, 0x01,
0355 0x29, 0x06,
0356 0x81, 0x02,
0357 0x95, 0x01,
0358 0x75, 0x08,
0359 0x26, 0xFF, 0x00,
0360 0x46, 0xFF, 0x00,
0361 0x06, 0x00, 0xFF,
0362 0x09, 0x01,
0363 0x81, 0x02,
0364 0x05, 0x01,
0365 0x81, 0x01,
0366 0x09, 0x31,
0367 0x81, 0x02,
0368 0x09, 0x32,
0369 0x81, 0x02,
0370 0x06, 0x00, 0xFF,
0371 0x09, 0x01,
0372 0x81, 0x02,
0373 0xC0,
0374 0xA1, 0x02,
0375 0x09, 0x02,
0376 0x95, 0x07,
0377 0x91, 0x02,
0378 0xC0,
0379 0xC0
0380 };
0381
0382 static __u8 fg_rdesc_fixed[] = {
0383 0x05, 0x01,
0384 0x09, 0x04,
0385 0xA1, 0x01,
0386 0xA1, 0x02,
0387 0x15, 0x00,
0388 0x26, 0xFF, 0x00,
0389 0x35, 0x00,
0390 0x46, 0xFF, 0x00,
0391 0x75, 0x08,
0392 0x95, 0x01,
0393 0x09, 0x30,
0394 0x81, 0x02,
0395 0xA4,
0396 0x25, 0x01,
0397 0x45, 0x01,
0398 0x75, 0x01,
0399 0x95, 0x02,
0400 0x81, 0x01,
0401 0x95, 0x06,
0402 0x05, 0x09,
0403 0x19, 0x01,
0404 0x29, 0x06,
0405 0x81, 0x02,
0406 0x05, 0x01,
0407 0xB4,
0408 0x81, 0x02,
0409 0x09, 0x31,
0410 0x81, 0x02,
0411 0x09, 0x32,
0412 0x81, 0x02,
0413 0xC0,
0414 0xA1, 0x02,
0415 0x26, 0xFF, 0x00,
0416 0x46, 0xFF, 0x00,
0417 0x75, 0x08,
0418 0x95, 0x04,
0419 0x09, 0x02,
0420 0xB1, 0x02,
0421 0xC0,
0422 0xC0
0423 };
0424
0425
0426
0427
0428
0429
0430 static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
0431 unsigned int *rsize)
0432 {
0433 struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
0434
0435 if ((drv_data->quirks & LG_RDESC) && *rsize >= 91 && rdesc[83] == 0x26 &&
0436 rdesc[84] == 0x8c && rdesc[85] == 0x02) {
0437 hid_info(hdev,
0438 "fixing up Logitech keyboard report descriptor\n");
0439 rdesc[84] = rdesc[89] = 0x4d;
0440 rdesc[85] = rdesc[90] = 0x10;
0441 }
0442 if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 51 &&
0443 rdesc[32] == 0x81 && rdesc[33] == 0x06 &&
0444 rdesc[49] == 0x81 && rdesc[50] == 0x06) {
0445 hid_info(hdev,
0446 "fixing up rel/abs in Logitech report descriptor\n");
0447 rdesc[33] = rdesc[50] = 0x02;
0448 }
0449
0450 switch (hdev->product) {
0451
0452 case USB_DEVICE_ID_LOGITECH_WINGMAN_FG:
0453 if (*rsize == FG_RDESC_ORIG_SIZE) {
0454 hid_info(hdev,
0455 "fixing up Logitech Wingman Formula GP report descriptor\n");
0456 rdesc = fg_rdesc_fixed;
0457 *rsize = sizeof(fg_rdesc_fixed);
0458 } else {
0459 hid_info(hdev,
0460 "rdesc size test failed for formula gp\n");
0461 }
0462 break;
0463
0464
0465 case USB_DEVICE_ID_LOGITECH_WINGMAN_FFG:
0466 if (*rsize == FFG_RDESC_ORIG_SIZE) {
0467 hid_info(hdev,
0468 "fixing up Logitech Wingman Formula Force GP report descriptor\n");
0469 rdesc = ffg_rdesc_fixed;
0470 *rsize = sizeof(ffg_rdesc_fixed);
0471 }
0472 break;
0473
0474
0475 case USB_DEVICE_ID_LOGITECH_WHEEL:
0476 if (*rsize == DF_RDESC_ORIG_SIZE) {
0477 hid_info(hdev,
0478 "fixing up Logitech Driving Force report descriptor\n");
0479 rdesc = df_rdesc_fixed;
0480 *rsize = sizeof(df_rdesc_fixed);
0481 }
0482 break;
0483
0484 case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
0485 if (*rsize == MOMO_RDESC_ORIG_SIZE) {
0486 hid_info(hdev,
0487 "fixing up Logitech Momo Force (Red) report descriptor\n");
0488 rdesc = momo_rdesc_fixed;
0489 *rsize = sizeof(momo_rdesc_fixed);
0490 }
0491 break;
0492
0493 case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
0494 if (*rsize == MOMO2_RDESC_ORIG_SIZE) {
0495 hid_info(hdev,
0496 "fixing up Logitech Momo Racing Force (Black) report descriptor\n");
0497 rdesc = momo2_rdesc_fixed;
0498 *rsize = sizeof(momo2_rdesc_fixed);
0499 }
0500 break;
0501
0502 case USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL:
0503 if (*rsize == FV_RDESC_ORIG_SIZE) {
0504 hid_info(hdev,
0505 "fixing up Logitech Formula Vibration report descriptor\n");
0506 rdesc = fv_rdesc_fixed;
0507 *rsize = sizeof(fv_rdesc_fixed);
0508 }
0509 break;
0510
0511 case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
0512 if (*rsize == DFP_RDESC_ORIG_SIZE) {
0513 hid_info(hdev,
0514 "fixing up Logitech Driving Force Pro report descriptor\n");
0515 rdesc = dfp_rdesc_fixed;
0516 *rsize = sizeof(dfp_rdesc_fixed);
0517 }
0518 break;
0519
0520 case USB_DEVICE_ID_LOGITECH_WII_WHEEL:
0521 if (*rsize >= 101 && rdesc[41] == 0x95 && rdesc[42] == 0x0B &&
0522 rdesc[47] == 0x05 && rdesc[48] == 0x09) {
0523 hid_info(hdev, "fixing up Logitech Speed Force Wireless report descriptor\n");
0524 rdesc[41] = 0x05;
0525 rdesc[42] = 0x09;
0526 rdesc[47] = 0x95;
0527 rdesc[48] = 0x0B;
0528 }
0529 break;
0530 }
0531
0532 return rdesc;
0533 }
0534
0535 #define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
0536 EV_KEY, (c))
0537
0538 static int lg_ultrax_remote_mapping(struct hid_input *hi,
0539 struct hid_usage *usage, unsigned long **bit, int *max)
0540 {
0541 if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
0542 return 0;
0543
0544 set_bit(EV_REP, hi->input->evbit);
0545 switch (usage->hid & HID_USAGE) {
0546
0547 case 0x004: lg_map_key_clear(KEY_AGAIN); break;
0548 case 0x00d: lg_map_key_clear(KEY_HOME); break;
0549 case 0x024: lg_map_key_clear(KEY_SHUFFLE); break;
0550 case 0x025: lg_map_key_clear(KEY_TV); break;
0551 case 0x026: lg_map_key_clear(KEY_MENU); break;
0552 case 0x031: lg_map_key_clear(KEY_AUDIO); break;
0553 case 0x032: lg_map_key_clear(KEY_TEXT); break;
0554 case 0x033: lg_map_key_clear(KEY_LAST); break;
0555 case 0x047: lg_map_key_clear(KEY_MP3); break;
0556 case 0x048: lg_map_key_clear(KEY_DVD); break;
0557 case 0x049: lg_map_key_clear(KEY_MEDIA); break;
0558 case 0x04a: lg_map_key_clear(KEY_VIDEO); break;
0559 case 0x04b: lg_map_key_clear(KEY_ANGLE); break;
0560 case 0x04c: lg_map_key_clear(KEY_LANGUAGE); break;
0561 case 0x04d: lg_map_key_clear(KEY_SUBTITLE); break;
0562 case 0x051: lg_map_key_clear(KEY_RED); break;
0563 case 0x052: lg_map_key_clear(KEY_CLOSE); break;
0564
0565 default:
0566 return 0;
0567 }
0568 return 1;
0569 }
0570
0571 static int lg_wireless_mapping(struct hid_input *hi, struct hid_usage *usage,
0572 unsigned long **bit, int *max)
0573 {
0574 if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
0575 return 0;
0576
0577 switch (usage->hid & HID_USAGE) {
0578 case 0x1001: lg_map_key_clear(KEY_MESSENGER); break;
0579 case 0x1003: lg_map_key_clear(KEY_SOUND); break;
0580 case 0x1004: lg_map_key_clear(KEY_VIDEO); break;
0581 case 0x1005: lg_map_key_clear(KEY_AUDIO); break;
0582 case 0x100a: lg_map_key_clear(KEY_DOCUMENTS); break;
0583
0584 case 0x100f: lg_map_key_clear(KEY_FN_1); break;
0585 case 0x1010: lg_map_key_clear(KEY_FN_2); break;
0586 case 0x1011: lg_map_key_clear(KEY_PREVIOUSSONG); break;
0587 case 0x1012: lg_map_key_clear(KEY_NEXTSONG); break;
0588 case 0x1013: lg_map_key_clear(KEY_CAMERA); break;
0589 case 0x1014: lg_map_key_clear(KEY_MESSENGER); break;
0590 case 0x1015: lg_map_key_clear(KEY_RECORD); break;
0591 case 0x1016: lg_map_key_clear(KEY_PLAYER); break;
0592 case 0x1017: lg_map_key_clear(KEY_EJECTCD); break;
0593 case 0x1018: lg_map_key_clear(KEY_MEDIA); break;
0594 case 0x1019: lg_map_key_clear(KEY_PROG1); break;
0595 case 0x101a: lg_map_key_clear(KEY_PROG2); break;
0596 case 0x101b: lg_map_key_clear(KEY_PROG3); break;
0597 case 0x101c: lg_map_key_clear(KEY_CYCLEWINDOWS); break;
0598 case 0x101f: lg_map_key_clear(KEY_ZOOMIN); break;
0599 case 0x1020: lg_map_key_clear(KEY_ZOOMOUT); break;
0600 case 0x1021: lg_map_key_clear(KEY_ZOOMRESET); break;
0601 case 0x1023: lg_map_key_clear(KEY_CLOSE); break;
0602 case 0x1027: lg_map_key_clear(KEY_MENU); break;
0603
0604 case 0x1028: lg_map_key_clear(KEY_ANGLE); break;
0605 case 0x1029: lg_map_key_clear(KEY_SHUFFLE); break;
0606 case 0x102a: lg_map_key_clear(KEY_BACK); break;
0607 case 0x102b: lg_map_key_clear(KEY_CYCLEWINDOWS); break;
0608 case 0x102d: lg_map_key_clear(KEY_WWW); break;
0609
0610
0611 case 0x1031: lg_map_key_clear(KEY_OK); break;
0612 case 0x1032: lg_map_key_clear(KEY_CANCEL); break;
0613 case 0x1041: lg_map_key_clear(KEY_BATTERY); break;
0614 case 0x1042: lg_map_key_clear(KEY_WORDPROCESSOR); break;
0615 case 0x1043: lg_map_key_clear(KEY_SPREADSHEET); break;
0616 case 0x1044: lg_map_key_clear(KEY_PRESENTATION); break;
0617 case 0x1045: lg_map_key_clear(KEY_UNDO); break;
0618 case 0x1046: lg_map_key_clear(KEY_REDO); break;
0619 case 0x1047: lg_map_key_clear(KEY_PRINT); break;
0620 case 0x1048: lg_map_key_clear(KEY_SAVE); break;
0621 case 0x1049: lg_map_key_clear(KEY_PROG1); break;
0622 case 0x104a: lg_map_key_clear(KEY_PROG2); break;
0623 case 0x104b: lg_map_key_clear(KEY_PROG3); break;
0624 case 0x104c: lg_map_key_clear(KEY_PROG4); break;
0625
0626 default:
0627 return 0;
0628 }
0629 return 1;
0630 }
0631
0632 static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
0633 struct hid_field *field, struct hid_usage *usage,
0634 unsigned long **bit, int *max)
0635 {
0636
0637
0638 static const u8 e_keymap[] = {
0639 0,216, 0,213,175,156, 0, 0, 0, 0,
0640 144, 0, 0, 0, 0, 0, 0, 0, 0,212,
0641 174,167,152,161,112, 0, 0, 0,154, 0,
0642 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0643 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0644 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0645 0, 0, 0, 0, 0,183,184,185,186,187,
0646 188,189,190,191,192,193,194, 0, 0, 0
0647 };
0648 struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
0649 unsigned int hid = usage->hid;
0650
0651 if (hdev->product == USB_DEVICE_ID_LOGITECH_RECEIVER &&
0652 lg_ultrax_remote_mapping(hi, usage, bit, max))
0653 return 1;
0654
0655 if ((drv_data->quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max))
0656 return 1;
0657
0658 if ((hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
0659 return 0;
0660
0661 hid &= HID_USAGE;
0662
0663
0664 if (field->application == HID_GD_MOUSE) {
0665 if ((drv_data->quirks & LG_IGNORE_DOUBLED_WHEEL) &&
0666 (hid == 7 || hid == 8))
0667 return -1;
0668 } else {
0669 if ((drv_data->quirks & LG_EXPANDED_KEYMAP) &&
0670 hid < ARRAY_SIZE(e_keymap) &&
0671 e_keymap[hid] != 0) {
0672 hid_map_usage(hi, usage, bit, max, EV_KEY,
0673 e_keymap[hid]);
0674 return 1;
0675 }
0676 }
0677
0678 return 0;
0679 }
0680
0681 static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
0682 struct hid_field *field, struct hid_usage *usage,
0683 unsigned long **bit, int *max)
0684 {
0685 struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
0686
0687 if ((drv_data->quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY &&
0688 (field->flags & HID_MAIN_ITEM_RELATIVE))
0689 field->flags &= ~HID_MAIN_ITEM_RELATIVE;
0690
0691 if ((drv_data->quirks & LG_DUPLICATE_USAGES) && (usage->type == EV_KEY ||
0692 usage->type == EV_REL || usage->type == EV_ABS))
0693 clear_bit(usage->code, *bit);
0694
0695
0696 if (usage->type == EV_ABS && (usage->code == ABS_X ||
0697 usage->code == ABS_Y || usage->code == ABS_Z ||
0698 usage->code == ABS_RZ)) {
0699 switch (hdev->product) {
0700 case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
0701 case USB_DEVICE_ID_LOGITECH_WINGMAN_FG:
0702 case USB_DEVICE_ID_LOGITECH_WINGMAN_FFG:
0703 case USB_DEVICE_ID_LOGITECH_WHEEL:
0704 case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
0705 case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
0706 case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
0707 case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
0708 case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
0709 case USB_DEVICE_ID_LOGITECH_WII_WHEEL:
0710 case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
0711 case USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL:
0712 field->application = HID_GD_MULTIAXIS;
0713 break;
0714 default:
0715 break;
0716 }
0717 }
0718
0719 return 0;
0720 }
0721
0722 static int lg_event(struct hid_device *hdev, struct hid_field *field,
0723 struct hid_usage *usage, __s32 value)
0724 {
0725 struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
0726
0727 if ((drv_data->quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) {
0728 input_event(field->hidinput->input, usage->type, usage->code,
0729 -value);
0730 return 1;
0731 }
0732 if (drv_data->quirks & LG_FF4) {
0733 return lg4ff_adjust_input_event(hdev, field, usage, value, drv_data);
0734 }
0735
0736 return 0;
0737 }
0738
0739 static int lg_raw_event(struct hid_device *hdev, struct hid_report *report,
0740 u8 *rd, int size)
0741 {
0742 struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
0743
0744 if (drv_data->quirks & LG_FF4)
0745 return lg4ff_raw_event(hdev, report, rd, size, drv_data);
0746
0747 return 0;
0748 }
0749
0750 static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
0751 {
0752 struct usb_interface *iface;
0753 __u8 iface_num;
0754 unsigned int connect_mask = HID_CONNECT_DEFAULT;
0755 struct lg_drv_data *drv_data;
0756 int ret;
0757
0758 if (!hid_is_usb(hdev))
0759 return -EINVAL;
0760
0761 iface = to_usb_interface(hdev->dev.parent);
0762 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
0763
0764
0765 if ((hdev->product == USB_DEVICE_ID_LOGITECH_G29_WHEEL) &&
0766 (iface_num != 0)) {
0767 dbg_hid("%s: ignoring ifnum %d\n", __func__, iface_num);
0768 return -ENODEV;
0769 }
0770
0771 drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL);
0772 if (!drv_data) {
0773 hid_err(hdev, "Insufficient memory, cannot allocate driver data\n");
0774 return -ENOMEM;
0775 }
0776 drv_data->quirks = id->driver_data;
0777
0778 hid_set_drvdata(hdev, (void *)drv_data);
0779
0780 if (drv_data->quirks & LG_NOGET)
0781 hdev->quirks |= HID_QUIRK_NOGET;
0782
0783 ret = hid_parse(hdev);
0784 if (ret) {
0785 hid_err(hdev, "parse failed\n");
0786 goto err_free;
0787 }
0788
0789 if (drv_data->quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4))
0790 connect_mask &= ~HID_CONNECT_FF;
0791
0792 ret = hid_hw_start(hdev, connect_mask);
0793 if (ret) {
0794 hid_err(hdev, "hw start failed\n");
0795 goto err_free;
0796 }
0797
0798
0799 if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
0800 static const unsigned char cbuf[] = {
0801 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0802 };
0803 u8 *buf = kmemdup(cbuf, sizeof(cbuf), GFP_KERNEL);
0804
0805 if (!buf) {
0806 ret = -ENOMEM;
0807 goto err_stop;
0808 }
0809
0810 ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(cbuf),
0811 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
0812 if (ret >= 0) {
0813
0814 wait_queue_head_t wait;
0815 init_waitqueue_head (&wait);
0816 wait_event_interruptible_timeout(wait, 0,
0817 msecs_to_jiffies(40));
0818
0819
0820 buf[1] = 0xB2;
0821 get_random_bytes(&buf[2], 2);
0822
0823 ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(cbuf),
0824 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
0825 }
0826 kfree(buf);
0827 }
0828
0829 if (drv_data->quirks & LG_FF)
0830 ret = lgff_init(hdev);
0831 else if (drv_data->quirks & LG_FF2)
0832 ret = lg2ff_init(hdev);
0833 else if (drv_data->quirks & LG_FF3)
0834 ret = lg3ff_init(hdev);
0835 else if (drv_data->quirks & LG_FF4)
0836 ret = lg4ff_init(hdev);
0837
0838 if (ret)
0839 goto err_stop;
0840
0841 return 0;
0842
0843 err_stop:
0844 hid_hw_stop(hdev);
0845 err_free:
0846 kfree(drv_data);
0847 return ret;
0848 }
0849
0850 static void lg_remove(struct hid_device *hdev)
0851 {
0852 struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
0853 if (drv_data->quirks & LG_FF4)
0854 lg4ff_deinit(hdev);
0855 hid_hw_stop(hdev);
0856 kfree(drv_data);
0857 }
0858
0859 static const struct hid_device_id lg_devices[] = {
0860 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER),
0861 .driver_data = LG_RDESC | LG_WIRELESS },
0862
0863 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER),
0864 .driver_data = LG_BAD_RELATIVE_KEYS },
0865
0866 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP),
0867 .driver_data = LG_DUPLICATE_USAGES },
0868
0869 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD),
0870 .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
0871 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500),
0872 .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
0873
0874 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D),
0875 .driver_data = LG_NOGET },
0876 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DUAL_ACTION),
0877 .driver_data = LG_NOGET },
0878 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL),
0879 .driver_data = LG_NOGET | LG_FF4 },
0880
0881 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD),
0882 .driver_data = LG_FF2 },
0883 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD),
0884 .driver_data = LG_FF },
0885 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2),
0886 .driver_data = LG_FF },
0887 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G29_WHEEL),
0888 .driver_data = LG_FF4 },
0889 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D),
0890 .driver_data = LG_FF },
0891 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO),
0892 .driver_data = LG_FF },
0893 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL),
0894 .driver_data = LG_NOGET | LG_FF4 },
0895 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2),
0896 .driver_data = LG_FF4 },
0897 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL),
0898 .driver_data = LG_FF2 },
0899 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
0900 .driver_data = LG_FF4 },
0901 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL),
0902 .driver_data = LG_FF4 },
0903 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL),
0904 .driver_data = LG_FF4 },
0905 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL),
0906 .driver_data = LG_NOGET | LG_FF4 },
0907 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL),
0908 .driver_data = LG_FF4 },
0909 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FG),
0910 .driver_data = LG_NOGET },
0911 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG),
0912 .driver_data = LG_NOGET | LG_FF4 },
0913 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
0914 .driver_data = LG_NOGET | LG_FF2 },
0915 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940),
0916 .driver_data = LG_FF3 },
0917 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR),
0918 .driver_data = LG_RDESC_REL_ABS },
0919 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER),
0920 .driver_data = LG_RDESC_REL_ABS },
0921 { }
0922 };
0923
0924 MODULE_DEVICE_TABLE(hid, lg_devices);
0925
0926 static struct hid_driver lg_driver = {
0927 .name = "logitech",
0928 .id_table = lg_devices,
0929 .report_fixup = lg_report_fixup,
0930 .input_mapping = lg_input_mapping,
0931 .input_mapped = lg_input_mapped,
0932 .event = lg_event,
0933 .raw_event = lg_raw_event,
0934 .probe = lg_probe,
0935 .remove = lg_remove,
0936 };
0937 module_hid_driver(lg_driver);
0938
0939 #ifdef CONFIG_LOGIWHEELS_FF
0940 int lg4ff_no_autoswitch = 0;
0941 module_param_named(lg4ff_no_autoswitch, lg4ff_no_autoswitch, int, S_IRUGO);
0942 MODULE_PARM_DESC(lg4ff_no_autoswitch, "Do not switch multimode wheels to their native mode automatically");
0943 #endif
0944
0945 MODULE_LICENSE("GPL");