Commit c21c9fee authored by Benjamin Tissoires's avatar Benjamin Tissoires
Browse files

Merge branch 'for-6.3/multitouch' into for-linus

Allow to pass quirks from i2c-hid to hid-multitouch (Allen Ballway &
Dmitry Torokhov)
parents 3ba2824c 03a86105
Loading
Loading
Loading
Loading
+35 −4
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ MODULE_LICENSE("GPL");
#define MT_QUIRK_SEPARATE_APP_REPORT	BIT(19)
#define MT_QUIRK_FORCE_MULTI_INPUT	BIT(20)
#define MT_QUIRK_DISABLE_WAKEUP		BIT(21)
#define MT_QUIRK_ORIENTATION_INVERT	BIT(22)

#define MT_INPUTMODE_TOUCHSCREEN	0x02
#define MT_INPUTMODE_TOUCHPAD		0x03
@@ -1009,6 +1010,7 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input,
			    struct mt_usages *slot)
{
	struct input_mt *mt = input->mt;
	struct hid_device *hdev = td->hdev;
	__s32 quirks = app->quirks;
	bool valid = true;
	bool confidence_state = true;
@@ -1086,6 +1088,10 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input,
		int orientation = wide;
		int max_azimuth;
		int azimuth;
		int x;
		int y;
		int cx;
		int cy;

		if (slot->a != DEFAULT_ZERO) {
			/*
@@ -1104,6 +1110,9 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input,
			if (azimuth > max_azimuth * 2)
				azimuth -= max_azimuth * 4;
			orientation = -azimuth;
			if (quirks & MT_QUIRK_ORIENTATION_INVERT)
				orientation = -orientation;

		}

		if (quirks & MT_QUIRK_TOUCH_SIZE_SCALING) {
@@ -1115,10 +1124,23 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input,
			minor = minor >> 1;
		}

		input_event(input, EV_ABS, ABS_MT_POSITION_X, *slot->x);
		input_event(input, EV_ABS, ABS_MT_POSITION_Y, *slot->y);
		input_event(input, EV_ABS, ABS_MT_TOOL_X, *slot->cx);
		input_event(input, EV_ABS, ABS_MT_TOOL_Y, *slot->cy);
		x = hdev->quirks & HID_QUIRK_X_INVERT ?
			input_abs_get_max(input, ABS_MT_POSITION_X) - *slot->x :
			*slot->x;
		y = hdev->quirks & HID_QUIRK_Y_INVERT ?
			input_abs_get_max(input, ABS_MT_POSITION_Y) - *slot->y :
			*slot->y;
		cx = hdev->quirks & HID_QUIRK_X_INVERT ?
			input_abs_get_max(input, ABS_MT_POSITION_X) - *slot->cx :
			*slot->cx;
		cy = hdev->quirks & HID_QUIRK_Y_INVERT ?
			input_abs_get_max(input, ABS_MT_POSITION_Y) - *slot->cy :
			*slot->cy;

		input_event(input, EV_ABS, ABS_MT_POSITION_X, x);
		input_event(input, EV_ABS, ABS_MT_POSITION_Y, y);
		input_event(input, EV_ABS, ABS_MT_TOOL_X, cx);
		input_event(input, EV_ABS, ABS_MT_TOOL_Y, cy);
		input_event(input, EV_ABS, ABS_MT_DISTANCE, !*slot->tip_state);
		input_event(input, EV_ABS, ABS_MT_ORIENTATION, orientation);
		input_event(input, EV_ABS, ABS_MT_PRESSURE, *slot->p);
@@ -1735,6 +1757,15 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
	if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
		td->serial_maybe = true;


	/* Orientation is inverted if the X or Y axes are
	 * flipped, but normalized if both are inverted.
	 */
	if (hdev->quirks & (HID_QUIRK_X_INVERT | HID_QUIRK_Y_INVERT) &&
	    !((hdev->quirks & HID_QUIRK_X_INVERT)
	      && (hdev->quirks & HID_QUIRK_Y_INVERT)))
		td->mtclass.quirks = MT_QUIRK_ORIENTATION_INVERT;

	/* This allows the driver to correctly support devices
	 * that emit events over several HID messages.
	 */
+1 −1
Original line number Diff line number Diff line
@@ -1237,7 +1237,7 @@ EXPORT_SYMBOL_GPL(hid_quirks_exit);
static unsigned long hid_gets_squirk(const struct hid_device *hdev)
{
	const struct hid_device_id *bl_entry;
	unsigned long quirks = 0;
	unsigned long quirks = hdev->initial_quirks;

	if (hid_match_id(hdev, hid_ignore_list))
		quirks |= HID_QUIRK_IGNORE;
+4 −2
Original line number Diff line number Diff line
@@ -1025,6 +1025,10 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
	hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID);
	hid->product = le16_to_cpu(ihid->hdesc.wProductID);

	hid->initial_quirks = quirks;
	hid->initial_quirks |= i2c_hid_get_dmi_quirks(hid->vendor,
						      hid->product);

	snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X",
		 client->name, (u16)hid->vendor, (u16)hid->product);
	strscpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys));
@@ -1038,8 +1042,6 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
		goto err_mem_free;
	}

	hid->quirks |= quirks;

	return 0;

err_mem_free:
+42 −0
Original line number Diff line number Diff line
@@ -10,8 +10,10 @@
#include <linux/types.h>
#include <linux/dmi.h>
#include <linux/mod_devicetable.h>
#include <linux/hid.h>

#include "i2c-hid.h"
#include "../hid-ids.h"


struct i2c_hid_desc_override {
@@ -416,6 +418,28 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = {
	{ }	/* Terminate list */
};

static const struct hid_device_id i2c_hid_elan_flipped_quirks = {
	HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, USB_VENDOR_ID_ELAN, 0x2dcd),
		HID_QUIRK_X_INVERT | HID_QUIRK_Y_INVERT
};

/*
 * This list contains devices which have specific issues based on the system
 * they're on and not just the device itself. The driver_data will have a
 * specific hid device to match against.
 */
static const struct dmi_system_id i2c_hid_dmi_quirk_table[] = {
	{
		.ident = "DynaBook K50/FR",
		.matches = {
			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dynabook Inc."),
			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "dynabook K50/FR"),
		},
		.driver_data = (void *)&i2c_hid_elan_flipped_quirks,
	},
	{ }	/* Terminate list */
};


struct i2c_hid_desc *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name)
{
@@ -450,3 +474,21 @@ char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name,
	*size = override->hid_report_desc_size;
	return override->hid_report_desc;
}

u32 i2c_hid_get_dmi_quirks(const u16 vendor, const u16 product)
{
	u32 quirks = 0;
	const struct dmi_system_id *system_id =
			dmi_first_match(i2c_hid_dmi_quirk_table);

	if (system_id) {
		const struct hid_device_id *device_id =
				(struct hid_device_id *)(system_id->driver_data);

		if (device_id && device_id->vendor == vendor &&
		    device_id->product == product)
			quirks = device_id->driver_data;
	}

	return quirks;
}
+3 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
struct i2c_hid_desc *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name);
char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name,
					       unsigned int *size);
u32 i2c_hid_get_dmi_quirks(const u16 vendor, const u16 product);
#else
static inline struct i2c_hid_desc
		   *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name)
@@ -16,6 +17,8 @@ static inline struct i2c_hid_desc
static inline char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name,
							     unsigned int *size)
{ return NULL; }
static inline u32 i2c_hid_get_dmi_quirks(const u16 vendor, const u16 product)
{ return 0; }
#endif

/**
Loading