Commit d5530d82 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull HID fixes from Jiri Kosina:

 - Various functionality / regression fixes for Logitech devices from
   Hans de Goede

 - Fix for (recently added) GPIO support in mcp2221 driver from Lars
   Povlsen

 - Power management handling fix/quirk in i2c-hid driver for certain
   BIOSes that have strange aproach to power-cycle from Hans de Goede

 - a few device ID additions and device-specific quirks

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid:
  HID: logitech-dj: Fix Dinovo Mini when paired with a MX5x00 receiver
  HID: logitech-dj: Fix an error in mse_bluetooth_descriptor
  HID: Add Logitech Dinovo Edge battery quirk
  HID: logitech-hidpp: Add HIDPP_CONSUMER_VENDOR_KEYS quirk for the Dinovo Edge
  HID: logitech-dj: Handle quad/bluetooth keyboards with a builtin trackpad
  HID: add HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE for Gamevice devices
  HID: mcp2221: Fix GPIO output handling
  HID: hid-sensor-hub: Fix issue with devices with no report ID
  HID: i2c-hid: Put ACPI enumerated devices in D3 on shutdown
  HID: add support for Sega Saturn
  HID: cypress: Support Varmilo Keyboards' media hotkeys
  HID: ite: Replace ABS_MISC 120/121 events with touchpad on/off keypresses
  HID: logitech-hidpp: Add PID for MX Anywhere 2
  HID: uclogic: Add ID for Trust Flex Design Tablet
parents f4b936f5 b4c00e79
Loading
Loading
Loading
Loading
+39 −5
Original line number Diff line number Diff line
@@ -23,19 +23,17 @@
#define CP_2WHEEL_MOUSE_HACK		0x02
#define CP_2WHEEL_MOUSE_HACK_ON		0x04

#define VA_INVAL_LOGICAL_BOUNDARY	0x08

/*
 * Some USB barcode readers from cypress have usage min and usage max in
 * the wrong order
 */
static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
static __u8 *cp_rdesc_fixup(struct hid_device *hdev, __u8 *rdesc,
		unsigned int *rsize)
{
	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
	unsigned int i;

	if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX))
		return rdesc;

	if (*rsize < 4)
		return rdesc;

@@ -48,6 +46,40 @@ static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
	return rdesc;
}

static __u8 *va_logical_boundary_fixup(struct hid_device *hdev, __u8 *rdesc,
		unsigned int *rsize)
{
	/*
	 * Varmilo VA104M (with VID Cypress and device ID 07B1) incorrectly
	 * reports Logical Minimum of its Consumer Control device as 572
	 * (0x02 0x3c). Fix this by setting its Logical Minimum to zero.
	 */
	if (*rsize == 25 &&
			rdesc[0] == 0x05 && rdesc[1] == 0x0c &&
			rdesc[2] == 0x09 && rdesc[3] == 0x01 &&
			rdesc[6] == 0x19 && rdesc[7] == 0x00 &&
			rdesc[11] == 0x16 && rdesc[12] == 0x3c && rdesc[13] == 0x02) {
		hid_info(hdev,
			 "fixing up varmilo VA104M consumer control report descriptor\n");
		rdesc[12] = 0x00;
		rdesc[13] = 0x00;
	}
	return rdesc;
}

static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
		unsigned int *rsize)
{
	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);

	if (quirks & CP_RDESC_SWAPPED_MIN_MAX)
		rdesc = cp_rdesc_fixup(hdev, rdesc, rsize);
	if (quirks & VA_INVAL_LOGICAL_BOUNDARY)
		rdesc = va_logical_boundary_fixup(hdev, rdesc, rsize);

	return rdesc;
}

static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi,
		struct hid_field *field, struct hid_usage *usage,
		unsigned long **bit, int *max)
@@ -128,6 +160,8 @@ static const struct hid_device_id cp_devices[] = {
		.driver_data = CP_RDESC_SWAPPED_MIN_MAX },
	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE),
		.driver_data = CP_2WHEEL_MOUSE_HACK },
	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_VARMILO_VA104M_07B1),
		.driver_data = VA_INVAL_LOGICAL_BOUNDARY },
	{ }
};
MODULE_DEVICE_TABLE(hid, cp_devices);
+9 −0
Original line number Diff line number Diff line
@@ -331,6 +331,8 @@
#define USB_DEVICE_ID_CYPRESS_BARCODE_4	0xed81
#define USB_DEVICE_ID_CYPRESS_TRUETOUCH	0xc001

#define USB_DEVICE_ID_CYPRESS_VARMILO_VA104M_07B1   0X07b1

#define USB_VENDOR_ID_DATA_MODUL	0x7374
#define USB_VENDOR_ID_DATA_MODUL_EASYMAXTOUCH	0x1201

@@ -443,6 +445,10 @@
#define USB_VENDOR_ID_FRUCTEL	0x25B6
#define USB_DEVICE_ID_GAMETEL_MT_MODE	0x0002

#define USB_VENDOR_ID_GAMEVICE	0x27F8
#define USB_DEVICE_ID_GAMEVICE_GV186	0x0BBE
#define USB_DEVICE_ID_GAMEVICE_KISHI	0x0BBF

#define USB_VENDOR_ID_GAMERON		0x0810
#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR	0x0001
#define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR	0x0002
@@ -485,6 +491,7 @@
#define USB_DEVICE_ID_PENPOWER		0x00f4

#define USB_VENDOR_ID_GREENASIA		0x0e8f
#define USB_DEVICE_ID_GREENASIA_DUAL_SAT_ADAPTOR 0x3010
#define USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD	0x3013

#define USB_VENDOR_ID_GRETAGMACBETH	0x0971
@@ -743,6 +750,7 @@
#define USB_VENDOR_ID_LOGITECH		0x046d
#define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
#define USB_DEVICE_ID_LOGITECH_T651	0xb00c
#define USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD	0xb309
#define USB_DEVICE_ID_LOGITECH_C007	0xc007
#define USB_DEVICE_ID_LOGITECH_C077	0xc077
#define USB_DEVICE_ID_LOGITECH_RECEIVER	0xc101
@@ -1298,6 +1306,7 @@

#define USB_VENDOR_ID_UGTIZER			0x2179
#define USB_DEVICE_ID_UGTIZER_TABLET_GP0610	0x0053
#define USB_DEVICE_ID_UGTIZER_TABLET_GT5040	0x0077

#define USB_VENDOR_ID_VIEWSONIC			0x0543
#define USB_DEVICE_ID_VIEWSONIC_PD1011		0xe621
+3 −0
Original line number Diff line number Diff line
@@ -319,6 +319,9 @@ static const struct hid_device_id hid_battery_quirks[] = {
	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK,
		USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD),
	  HID_BATTERY_QUIRK_IGNORE },
	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,
		USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD),
	  HID_BATTERY_QUIRK_IGNORE },
	{}
};

+60 −1
Original line number Diff line number Diff line
@@ -11,6 +11,48 @@

#include "hid-ids.h"

#define QUIRK_TOUCHPAD_ON_OFF_REPORT		BIT(0)

static __u8 *ite_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize)
{
	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);

	if (quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) {
		if (*rsize == 188 && rdesc[162] == 0x81 && rdesc[163] == 0x02) {
			hid_info(hdev, "Fixing up ITE keyboard report descriptor\n");
			rdesc[163] = HID_MAIN_ITEM_RELATIVE;
		}
	}

	return rdesc;
}

static int ite_input_mapping(struct hid_device *hdev,
		struct hid_input *hi, struct hid_field *field,
		struct hid_usage *usage, unsigned long **bit,
		int *max)
{

	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);

	if ((quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) &&
	    (usage->hid & HID_USAGE_PAGE) == 0x00880000) {
		if (usage->hid == 0x00880078) {
			/* Touchpad on, userspace expects F22 for this */
			hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_F22);
			return 1;
		}
		if (usage->hid == 0x00880079) {
			/* Touchpad off, userspace expects F23 for this */
			hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_F23);
			return 1;
		}
		return -1;
	}

	return 0;
}

static int ite_event(struct hid_device *hdev, struct hid_field *field,
		     struct hid_usage *usage, __s32 value)
{
@@ -37,13 +79,27 @@ static int ite_event(struct hid_device *hdev, struct hid_field *field,
	return 0;
}

static int ite_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
	int ret;

	hid_set_drvdata(hdev, (void *)id->driver_data);

	ret = hid_open_report(hdev);
	if (ret)
		return ret;

	return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
}

static const struct hid_device_id ite_devices[] = {
	{ HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) },
	/* ITE8595 USB kbd ctlr, with Synaptics touchpad connected to it. */
	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
		     USB_VENDOR_ID_SYNAPTICS,
		     USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012) },
		     USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012),
	  .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT },
	/* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */
	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
		     USB_VENDOR_ID_SYNAPTICS,
@@ -55,6 +111,9 @@ MODULE_DEVICE_TABLE(hid, ite_devices);
static struct hid_driver ite_driver = {
	.name = "itetech",
	.id_table = ite_devices,
	.probe = ite_probe,
	.report_fixup = ite_report_fixup,
	.input_mapping = ite_input_mapping,
	.event = ite_event,
};
module_hid_driver(ite_driver);
+21 −1
Original line number Diff line number Diff line
@@ -328,7 +328,7 @@ static const char mse_bluetooth_descriptor[] = {
	0x25, 0x01,		/*      LOGICAL_MAX (1)                 */
	0x75, 0x01,		/*      REPORT_SIZE (1)                 */
	0x95, 0x04,		/*      REPORT_COUNT (4)                */
	0x81, 0x06,		/*      INPUT                           */
	0x81, 0x02,		/*      INPUT (Data,Var,Abs)            */
	0xC0,			/*    END_COLLECTION                    */
	0xC0,			/*  END_COLLECTION                      */
};
@@ -866,11 +866,24 @@ static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev,
	schedule_work(&djrcv_dev->work);
}

/*
 * Some quad/bluetooth keyboards have a builtin touchpad in this case we see
 * only 1 paired device with a device_type of REPORT_TYPE_KEYBOARD. For the
 * touchpad to work we must also forward mouse input reports to the dj_hiddev
 * created for the keyboard (instead of forwarding them to a second paired
 * device with a device_type of REPORT_TYPE_MOUSE as we normally would).
 */
static const u16 kbd_builtin_touchpad_ids[] = {
	0xb309, /* Dinovo Edge */
	0xb30c, /* Dinovo Mini */
};

static void logi_hidpp_dev_conn_notif_equad(struct hid_device *hdev,
					    struct hidpp_event *hidpp_report,
					    struct dj_workitem *workitem)
{
	struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
	int i, id;

	workitem->type = WORKITEM_TYPE_PAIRED;
	workitem->device_type = hidpp_report->params[HIDPP_PARAM_DEVICE_INFO] &
@@ -882,6 +895,13 @@ static void logi_hidpp_dev_conn_notif_equad(struct hid_device *hdev,
		workitem->reports_supported |= STD_KEYBOARD | MULTIMEDIA |
					       POWER_KEYS | MEDIA_CENTER |
					       HIDPP;
		id = (workitem->quad_id_msb << 8) | workitem->quad_id_lsb;
		for (i = 0; i < ARRAY_SIZE(kbd_builtin_touchpad_ids); i++) {
			if (id == kbd_builtin_touchpad_ids[i]) {
				workitem->reports_supported |= STD_MOUSE;
				break;
			}
		}
		break;
	case REPORT_TYPE_MOUSE:
		workitem->reports_supported |= STD_MOUSE | HIDPP;
Loading