HID: fix Logitech DiNovo Edge touchwheel and Logic3 /SpectraVideo middle button

Dongle shipped with Logitech DiNovo Edge (0x046d/0xc714) behaves in a weird
non-standard way - it contains multiple reports with the same usage, which
results in remapping of GenericDesktop.X and GenericDesktop.Y usages to
GenericDesktop.Z and GenericDesktop.RX respectively, thus rendering the
touchwheel unusable.

The commit 35068976916fdef82d6e69ef1f8c9a1c47732759 solved this
in a way that it didn't remap certain usages. This however breaks
(at least) middle button of Logic3 / SpectraVideo (0x1267/0x0210),
which in contrary requires the remapping.

To make both of the harware work, allow remapping of these usages again,
and introduce a quirk for Logitech DiNovo Edge "touchwheel" instead - we
disable remapping for key, abs and rel events only for this hardware.

Signed-off-by: Jiri Kosina <jkosina@suse.cz>

+14 -5
+10 -5
drivers/hid/hid-input.c
··· 71 71 #define map_led(c) do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0) 72 72 73 73 #define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0) 74 - #define map_rel_clear(c) do { map_rel(c); clear_bit(c, bit); } while (0) 75 74 #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) 76 75 77 76 #ifdef CONFIG_USB_HIDINPUT_POWERBOOK ··· 295 296 } 296 297 } 297 298 298 - map_key_clear(code); 299 + map_key(code); 299 300 break; 300 301 301 302 ··· 346 347 case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ: 347 348 case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL: 348 349 if (field->flags & HID_MAIN_ITEM_RELATIVE) 349 - map_rel_clear(usage->hid & 0xf); 350 + map_rel(usage->hid & 0xf); 350 351 else 351 - map_abs_clear(usage->hid & 0xf); 352 + map_abs(usage->hid & 0xf); 352 353 break; 353 354 354 355 case HID_GD_HATSWITCH: ··· 518 519 case 0x22f: map_key_clear(KEY_ZOOMRESET); break; 519 520 case 0x233: map_key_clear(KEY_SCROLLUP); break; 520 521 case 0x234: map_key_clear(KEY_SCROLLDOWN); break; 521 - case 0x238: map_rel_clear(REL_HWHEEL); break; 522 + case 0x238: map_rel(REL_HWHEEL); break; 522 523 case 0x25f: map_key_clear(KEY_CANCEL); break; 523 524 case 0x279: map_key_clear(KEY_REDO); break; 524 525 ··· 665 666 field->flags &= ~HID_MAIN_ITEM_RELATIVE; 666 667 667 668 set_bit(usage->type, input->evbit); 669 + 670 + if (device->quirks & HID_QUIRK_DUPLICATE_USAGES && 671 + (usage->type == EV_KEY || 672 + usage->type == EV_REL || 673 + usage->type == EV_ABS)) 674 + clear_bit(usage->code, bit); 668 675 669 676 while (usage->code <= max && test_and_set_bit(usage->code, bit)) 670 677 usage->code = find_next_zero_bit(bit, max + 1, usage->code);
+3
drivers/usb/input/hid-core.c
··· 756 756 #define USB_VENDOR_ID_LOGITECH 0x046d 757 757 #define USB_DEVICE_ID_LOGITECH_USB_RECEIVER 0xc101 758 758 #define USB_DEVICE_ID_LOGITECH_USB_RECEIVER_2 0xc517 759 + #define USB_DEVICE_ID_DINOVO_EDGE 0xc714 759 760 760 761 #define USB_VENDOR_ID_IMATION 0x0718 761 762 #define USB_DEVICE_ID_DISC_STAKKA 0xd000 ··· 776 775 __u16 idProduct; 777 776 unsigned quirks; 778 777 } hid_blacklist[] = { 778 + 779 + { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES }, 779 780 780 781 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE }, 781 782 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE },
+1
include/linux/hid.h
··· 268 268 #define HID_QUIRK_IGNORE_MOUSE 0x00040000 269 269 #define HID_QUIRK_SONY_PS3_CONTROLLER 0x00080000 270 270 #define HID_QUIRK_LOGITECH_S510_DESCRIPTOR 0x00100000 271 + #define HID_QUIRK_DUPLICATE_USAGES 0x00200000 271 272 272 273 /* 273 274 * This is the global environment of the parser. This information is