Commit 25914662 authored by Jiri Kosina's avatar Jiri Kosina

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 35068976 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: default avatarJiri Kosina <jkosina@suse.cz>
parent a4dff398
...@@ -71,7 +71,6 @@ static const struct { ...@@ -71,7 +71,6 @@ static const struct {
#define map_led(c) do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0) #define map_led(c) do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0)
#define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0) #define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0)
#define map_rel_clear(c) do { map_rel(c); clear_bit(c, bit); } while (0)
#define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0)
#ifdef CONFIG_USB_HIDINPUT_POWERBOOK #ifdef CONFIG_USB_HIDINPUT_POWERBOOK
...@@ -296,7 +295,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel ...@@ -296,7 +295,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
} }
} }
map_key_clear(code); map_key(code);
break; break;
...@@ -347,9 +346,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel ...@@ -347,9 +346,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ: case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ:
case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL: case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL:
if (field->flags & HID_MAIN_ITEM_RELATIVE) if (field->flags & HID_MAIN_ITEM_RELATIVE)
map_rel_clear(usage->hid & 0xf); map_rel(usage->hid & 0xf);
else else
map_abs_clear(usage->hid & 0xf); map_abs(usage->hid & 0xf);
break; break;
case HID_GD_HATSWITCH: case HID_GD_HATSWITCH:
...@@ -519,7 +518,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel ...@@ -519,7 +518,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x22f: map_key_clear(KEY_ZOOMRESET); break; case 0x22f: map_key_clear(KEY_ZOOMRESET); break;
case 0x233: map_key_clear(KEY_SCROLLUP); break; case 0x233: map_key_clear(KEY_SCROLLUP); break;
case 0x234: map_key_clear(KEY_SCROLLDOWN); break; case 0x234: map_key_clear(KEY_SCROLLDOWN); break;
case 0x238: map_rel_clear(REL_HWHEEL); break; case 0x238: map_rel(REL_HWHEEL); break;
case 0x25f: map_key_clear(KEY_CANCEL); break; case 0x25f: map_key_clear(KEY_CANCEL); break;
case 0x279: map_key_clear(KEY_REDO); break; case 0x279: map_key_clear(KEY_REDO); break;
...@@ -667,6 +666,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel ...@@ -667,6 +666,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
set_bit(usage->type, input->evbit); set_bit(usage->type, input->evbit);
if (device->quirks & HID_QUIRK_DUPLICATE_USAGES &&
(usage->type == EV_KEY ||
usage->type == EV_REL ||
usage->type == EV_ABS))
clear_bit(usage->code, bit);
while (usage->code <= max && test_and_set_bit(usage->code, bit)) while (usage->code <= max && test_and_set_bit(usage->code, bit))
usage->code = find_next_zero_bit(bit, max + 1, usage->code); usage->code = find_next_zero_bit(bit, max + 1, usage->code);
......
...@@ -756,6 +756,7 @@ void usbhid_init_reports(struct hid_device *hid) ...@@ -756,6 +756,7 @@ void usbhid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_LOGITECH 0x046d #define USB_VENDOR_ID_LOGITECH 0x046d
#define USB_DEVICE_ID_LOGITECH_USB_RECEIVER 0xc101 #define USB_DEVICE_ID_LOGITECH_USB_RECEIVER 0xc101
#define USB_DEVICE_ID_LOGITECH_USB_RECEIVER_2 0xc517 #define USB_DEVICE_ID_LOGITECH_USB_RECEIVER_2 0xc517
#define USB_DEVICE_ID_DINOVO_EDGE 0xc714
#define USB_VENDOR_ID_IMATION 0x0718 #define USB_VENDOR_ID_IMATION 0x0718
#define USB_DEVICE_ID_DISC_STAKKA 0xd000 #define USB_DEVICE_ID_DISC_STAKKA 0xd000
...@@ -776,6 +777,8 @@ static const struct hid_blacklist { ...@@ -776,6 +777,8 @@ static const struct hid_blacklist {
unsigned quirks; unsigned quirks;
} hid_blacklist[] = { } hid_blacklist[] = {
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },
{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE },
......
...@@ -268,6 +268,7 @@ struct hid_item { ...@@ -268,6 +268,7 @@ struct hid_item {
#define HID_QUIRK_IGNORE_MOUSE 0x00040000 #define HID_QUIRK_IGNORE_MOUSE 0x00040000
#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00080000 #define HID_QUIRK_SONY_PS3_CONTROLLER 0x00080000
#define HID_QUIRK_LOGITECH_S510_DESCRIPTOR 0x00100000 #define HID_QUIRK_LOGITECH_S510_DESCRIPTOR 0x00100000
#define HID_QUIRK_DUPLICATE_USAGES 0x00200000
/* /*
* This is the global environment of the parser. This information is * This is the global environment of the parser. This information is
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment