Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f22a799 authored by Jiri Slaby's avatar Jiri Slaby Committed by Jiri Kosina
Browse files

HID: move logitech quirks



Move them from the core and input code to a separate driver.

Signed-off-by: default avatarJiri Slaby <jslaby@suse.cz>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent 022e8c4d
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -67,4 +67,17 @@ config HIDRAW

source "drivers/hid/usbhid/Kconfig"

menu "Special HID drivers"
	depends on HID

config HID_LOGITECH
	tristate "Logitech"
	default m
	depends on USB_HID
	---help---
	Support for some Logitech devices which breaks less or more
	HID specification.

endmenu

endif # HID_SUPPORT
+2 −0
Original line number Diff line number Diff line
@@ -8,6 +8,8 @@ obj-$(CONFIG_HID) += hid.o
hid-$(CONFIG_HID_DEBUG)		+= hid-debug.o
hid-$(CONFIG_HIDRAW)		+= hidraw.o

obj-$(CONFIG_HID_LOGITECH)	+= hid-logitech.o

obj-$(CONFIG_USB_HID)		+= usbhid/
obj-$(CONFIG_USB_MOUSE)		+= usbhid/
obj-$(CONFIG_USB_KBD)		+= usbhid/
+16 −0
Original line number Diff line number Diff line
@@ -33,6 +33,8 @@
#include <linux/hid-debug.h>
#include <linux/hidraw.h>

#include "hid-ids.h"

/*
 * Version Information
 */
@@ -1128,6 +1130,20 @@ static const struct hid_device_id *hid_match_id(struct hid_device *hdev,
}

static const struct hid_device_id hid_blacklist[] = {
	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_LX3) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_V150) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) },
	{ }
};

+0 −96
Original line number Diff line number Diff line
@@ -54,39 +54,6 @@ static int quirk_cherry_cymotion(struct hid_usage *usage,
	return 1;
}

static int quirk_logitech_ultrax_remote(struct hid_usage *usage,
		struct hid_input *hidinput, unsigned long **bit, int *max)
{
	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
		return 0;

	set_bit(EV_REP, hidinput->input->evbit);
	switch(usage->hid & HID_USAGE) {
		/* Reported on Logitech Ultra X Media Remote */
		case 0x004: map_key_clear(KEY_AGAIN);		break;
		case 0x00d: map_key_clear(KEY_HOME);		break;
		case 0x024: map_key_clear(KEY_SHUFFLE);		break;
		case 0x025: map_key_clear(KEY_TV);		break;
		case 0x026: map_key_clear(KEY_MENU);		break;
		case 0x031: map_key_clear(KEY_AUDIO);		break;
		case 0x032: map_key_clear(KEY_TEXT);		break;
		case 0x033: map_key_clear(KEY_LAST);		break;
		case 0x047: map_key_clear(KEY_MP3);		break;
		case 0x048: map_key_clear(KEY_DVD);		break;
		case 0x049: map_key_clear(KEY_MEDIA);		break;
		case 0x04a: map_key_clear(KEY_VIDEO);		break;
		case 0x04b: map_key_clear(KEY_ANGLE);		break;
		case 0x04c: map_key_clear(KEY_LANGUAGE);	break;
		case 0x04d: map_key_clear(KEY_SUBTITLE);	break;
		case 0x051: map_key_clear(KEY_RED);		break;
		case 0x052: map_key_clear(KEY_CLOSE);		break;

		default:
			return 0;
	}
	return 1;
}

static int quirk_gyration_remote(struct hid_usage *usage,
		struct hid_input *hidinput, unsigned long **bit, int *max)
{
@@ -207,58 +174,6 @@ static int quirk_petalynx_remote(struct hid_usage *usage,
	return 1;
}

static int quirk_logitech_wireless(struct hid_usage *usage,
		struct hid_input *hidinput, unsigned long **bit, int *max)
{
	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
		return 0;

	switch (usage->hid & HID_USAGE) {
		case 0x1001: map_key_clear(KEY_MESSENGER);	break;
		case 0x1003: map_key_clear(KEY_SOUND);		break;
		case 0x1004: map_key_clear(KEY_VIDEO);		break;
		case 0x1005: map_key_clear(KEY_AUDIO);		break;
		case 0x100a: map_key_clear(KEY_DOCUMENTS);	break;
		case 0x1011: map_key_clear(KEY_PREVIOUSSONG);	break;
		case 0x1012: map_key_clear(KEY_NEXTSONG);	break;
		case 0x1013: map_key_clear(KEY_CAMERA);		break;
		case 0x1014: map_key_clear(KEY_MESSENGER);	break;
		case 0x1015: map_key_clear(KEY_RECORD);		break;
		case 0x1016: map_key_clear(KEY_PLAYER);		break;
		case 0x1017: map_key_clear(KEY_EJECTCD);	break;
		case 0x1018: map_key_clear(KEY_MEDIA);		break;
		case 0x1019: map_key_clear(KEY_PROG1);		break;
		case 0x101a: map_key_clear(KEY_PROG2);		break;
		case 0x101b: map_key_clear(KEY_PROG3);		break;
		case 0x101f: map_key_clear(KEY_ZOOMIN);		break;
		case 0x1020: map_key_clear(KEY_ZOOMOUT);	break;
		case 0x1021: map_key_clear(KEY_ZOOMRESET);	break;
		case 0x1023: map_key_clear(KEY_CLOSE);		break;
		case 0x1027: map_key_clear(KEY_MENU);		break;
		/* this one is marked as 'Rotate' */
		case 0x1028: map_key_clear(KEY_ANGLE);		break;
		case 0x1029: map_key_clear(KEY_SHUFFLE);	break;
		case 0x102a: map_key_clear(KEY_BACK);		break;
		case 0x102b: map_key_clear(KEY_CYCLEWINDOWS);	break;
		case 0x1041: map_key_clear(KEY_BATTERY);	break;
		case 0x1042: map_key_clear(KEY_WORDPROCESSOR);	break;
		case 0x1043: map_key_clear(KEY_SPREADSHEET);	break;
		case 0x1044: map_key_clear(KEY_PRESENTATION);	break;
		case 0x1045: map_key_clear(KEY_UNDO);		break;
		case 0x1046: map_key_clear(KEY_REDO);		break;
		case 0x1047: map_key_clear(KEY_PRINT);		break;
		case 0x1048: map_key_clear(KEY_SAVE);		break;
		case 0x1049: map_key_clear(KEY_PROG1);		break;
		case 0x104a: map_key_clear(KEY_PROG2);		break;
		case 0x104b: map_key_clear(KEY_PROG3);		break;
		case 0x104c: map_key_clear(KEY_PROG4);		break;

		default:
			return 0;
	}
	return 1;
}

static int quirk_cherry_genius_29e(struct hid_usage *usage,
		struct hid_input *hidinput, unsigned long **bit, int *max)
{
@@ -329,12 +244,6 @@ static int quirk_sunplus_wdesktop(struct hid_usage *usage,
#define VENDOR_ID_GYRATION			0x0c16
#define DEVICE_ID_GYRATION_REMOTE		0x0002

#define VENDOR_ID_LOGITECH			0x046d
#define DEVICE_ID_LOGITECH_RECEIVER		0xc101
#define DEVICE_ID_S510_RECEIVER			0xc50c
#define DEVICE_ID_S510_RECEIVER_2		0xc517
#define DEVICE_ID_MX3000_RECEIVER		0xc513

#define VENDOR_ID_MICROSOFT			0x045e
#define DEVICE_ID_MS4K				0x00db
#define DEVICE_ID_MS6K				0x00f9
@@ -366,11 +275,6 @@ static const struct hid_input_blacklist {

	{ VENDOR_ID_GYRATION, DEVICE_ID_GYRATION_REMOTE, quirk_gyration_remote },

	{ VENDOR_ID_LOGITECH, DEVICE_ID_LOGITECH_RECEIVER, quirk_logitech_ultrax_remote },
	{ VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER, quirk_logitech_wireless },
	{ VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER_2, quirk_logitech_wireless },
	{ VENDOR_ID_LOGITECH, DEVICE_ID_MX3000_RECEIVER, quirk_logitech_wireless },

	{ VENDOR_ID_MICROSOFT, DEVICE_ID_MS4K, quirk_microsoft_ergonomy_kb },
	{ VENDOR_ID_MICROSOFT, DEVICE_ID_MS6K, quirk_microsoft_ergonomy_kb },
	{ VENDOR_ID_MICROSOFT, DEVICE_IS_MS_PRESENTER_8K_BT, quirk_microsoft_presenter_8k },
+0 −38
Original line number Diff line number Diff line
@@ -58,19 +58,6 @@ static const unsigned char hid_keyboard[256] = {
	150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
};

/* extended mapping for certain Logitech hardware (Logitech cordless desktop LX500) */
#define LOGITECH_EXPANDED_KEYMAP_SIZE 80
static int logitech_expanded_keymap[LOGITECH_EXPANDED_KEYMAP_SIZE] = {
	  0,216,  0,213,175,156,  0,  0,  0,  0,
	144,  0,  0,  0,  0,  0,  0,  0,  0,212,
	174,167,152,161,112,  0,  0,  0,154,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,183,184,185,186,187,
	188,189,190,191,192,193,194,  0,  0,  0
};

static const struct {
	__s32 x;
	__s32 y;
@@ -437,21 +424,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
					}
			}

			/* Special handling for Logitech Cordless Desktop */
			if (field->application != HID_GD_MOUSE) {
				if (device->quirks & HID_QUIRK_LOGITECH_EXPANDED_KEYMAP) {
					int hid = usage->hid & HID_USAGE;
					if (hid < LOGITECH_EXPANDED_KEYMAP_SIZE && logitech_expanded_keymap[hid] != 0)
						code = logitech_expanded_keymap[hid];
				}
			} else {
				if (device->quirks & HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL) {
					int hid = usage->hid & HID_USAGE;
					if (hid == 7 || hid == 8)
						goto ignore;
				}
			}

			map_key(code);
			break;

@@ -788,18 +760,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
		|| ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007)))
		goto ignore;

	if ((device->quirks & HID_QUIRK_BAD_RELATIVE_KEYS) &&
		usage->type == EV_KEY && (field->flags & HID_MAIN_ITEM_RELATIVE))
		field->flags &= ~HID_MAIN_ITEM_RELATIVE;

	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))
		usage->code = find_next_zero_bit(bit, max + 1, usage->code);

Loading