Skip to content

Commit c21c9fe

Browse files
committed
Merge branch 'for-6.3/multitouch' into for-linus
Allow to pass quirks from i2c-hid to hid-multitouch (Allen Ballway & Dmitry Torokhov)
2 parents 3ba2824 + 03a8610 commit c21c9fe

File tree

6 files changed

+86
-7
lines changed

6 files changed

+86
-7
lines changed

drivers/hid/hid-multitouch.c

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ MODULE_LICENSE("GPL");
7171
#define MT_QUIRK_SEPARATE_APP_REPORT BIT(19)
7272
#define MT_QUIRK_FORCE_MULTI_INPUT BIT(20)
7373
#define MT_QUIRK_DISABLE_WAKEUP BIT(21)
74+
#define MT_QUIRK_ORIENTATION_INVERT BIT(22)
7475

7576
#define MT_INPUTMODE_TOUCHSCREEN 0x02
7677
#define MT_INPUTMODE_TOUCHPAD 0x03
@@ -1009,6 +1010,7 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input,
10091010
struct mt_usages *slot)
10101011
{
10111012
struct input_mt *mt = input->mt;
1013+
struct hid_device *hdev = td->hdev;
10121014
__s32 quirks = app->quirks;
10131015
bool valid = true;
10141016
bool confidence_state = true;
@@ -1086,6 +1088,10 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input,
10861088
int orientation = wide;
10871089
int max_azimuth;
10881090
int azimuth;
1091+
int x;
1092+
int y;
1093+
int cx;
1094+
int cy;
10891095

10901096
if (slot->a != DEFAULT_ZERO) {
10911097
/*
@@ -1104,6 +1110,9 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input,
11041110
if (azimuth > max_azimuth * 2)
11051111
azimuth -= max_azimuth * 4;
11061112
orientation = -azimuth;
1113+
if (quirks & MT_QUIRK_ORIENTATION_INVERT)
1114+
orientation = -orientation;
1115+
11071116
}
11081117

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

1118-
input_event(input, EV_ABS, ABS_MT_POSITION_X, *slot->x);
1119-
input_event(input, EV_ABS, ABS_MT_POSITION_Y, *slot->y);
1120-
input_event(input, EV_ABS, ABS_MT_TOOL_X, *slot->cx);
1121-
input_event(input, EV_ABS, ABS_MT_TOOL_Y, *slot->cy);
1127+
x = hdev->quirks & HID_QUIRK_X_INVERT ?
1128+
input_abs_get_max(input, ABS_MT_POSITION_X) - *slot->x :
1129+
*slot->x;
1130+
y = hdev->quirks & HID_QUIRK_Y_INVERT ?
1131+
input_abs_get_max(input, ABS_MT_POSITION_Y) - *slot->y :
1132+
*slot->y;
1133+
cx = hdev->quirks & HID_QUIRK_X_INVERT ?
1134+
input_abs_get_max(input, ABS_MT_POSITION_X) - *slot->cx :
1135+
*slot->cx;
1136+
cy = hdev->quirks & HID_QUIRK_Y_INVERT ?
1137+
input_abs_get_max(input, ABS_MT_POSITION_Y) - *slot->cy :
1138+
*slot->cy;
1139+
1140+
input_event(input, EV_ABS, ABS_MT_POSITION_X, x);
1141+
input_event(input, EV_ABS, ABS_MT_POSITION_Y, y);
1142+
input_event(input, EV_ABS, ABS_MT_TOOL_X, cx);
1143+
input_event(input, EV_ABS, ABS_MT_TOOL_Y, cy);
11221144
input_event(input, EV_ABS, ABS_MT_DISTANCE, !*slot->tip_state);
11231145
input_event(input, EV_ABS, ABS_MT_ORIENTATION, orientation);
11241146
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)
17351757
if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
17361758
td->serial_maybe = true;
17371759

1760+
1761+
/* Orientation is inverted if the X or Y axes are
1762+
* flipped, but normalized if both are inverted.
1763+
*/
1764+
if (hdev->quirks & (HID_QUIRK_X_INVERT | HID_QUIRK_Y_INVERT) &&
1765+
!((hdev->quirks & HID_QUIRK_X_INVERT)
1766+
&& (hdev->quirks & HID_QUIRK_Y_INVERT)))
1767+
td->mtclass.quirks = MT_QUIRK_ORIENTATION_INVERT;
1768+
17381769
/* This allows the driver to correctly support devices
17391770
* that emit events over several HID messages.
17401771
*/

drivers/hid/hid-quirks.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1237,7 +1237,7 @@ EXPORT_SYMBOL_GPL(hid_quirks_exit);
12371237
static unsigned long hid_gets_squirk(const struct hid_device *hdev)
12381238
{
12391239
const struct hid_device_id *bl_entry;
1240-
unsigned long quirks = 0;
1240+
unsigned long quirks = hdev->initial_quirks;
12411241

12421242
if (hid_match_id(hdev, hid_ignore_list))
12431243
quirks |= HID_QUIRK_IGNORE;

drivers/hid/i2c-hid/i2c-hid-core.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,10 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
10251025
hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID);
10261026
hid->product = le16_to_cpu(ihid->hdesc.wProductID);
10271027

1028+
hid->initial_quirks = quirks;
1029+
hid->initial_quirks |= i2c_hid_get_dmi_quirks(hid->vendor,
1030+
hid->product);
1031+
10281032
snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X",
10291033
client->name, (u16)hid->vendor, (u16)hid->product);
10301034
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,
10381042
goto err_mem_free;
10391043
}
10401044

1041-
hid->quirks |= quirks;
1042-
10431045
return 0;
10441046

10451047
err_mem_free:

drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
#include <linux/types.h>
1111
#include <linux/dmi.h>
1212
#include <linux/mod_devicetable.h>
13+
#include <linux/hid.h>
1314

1415
#include "i2c-hid.h"
16+
#include "../hid-ids.h"
1517

1618

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

421+
static const struct hid_device_id i2c_hid_elan_flipped_quirks = {
422+
HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, USB_VENDOR_ID_ELAN, 0x2dcd),
423+
HID_QUIRK_X_INVERT | HID_QUIRK_Y_INVERT
424+
};
425+
426+
/*
427+
* This list contains devices which have specific issues based on the system
428+
* they're on and not just the device itself. The driver_data will have a
429+
* specific hid device to match against.
430+
*/
431+
static const struct dmi_system_id i2c_hid_dmi_quirk_table[] = {
432+
{
433+
.ident = "DynaBook K50/FR",
434+
.matches = {
435+
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dynabook Inc."),
436+
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "dynabook K50/FR"),
437+
},
438+
.driver_data = (void *)&i2c_hid_elan_flipped_quirks,
439+
},
440+
{ } /* Terminate list */
441+
};
442+
419443

420444
struct i2c_hid_desc *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name)
421445
{
@@ -450,3 +474,21 @@ char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name,
450474
*size = override->hid_report_desc_size;
451475
return override->hid_report_desc;
452476
}
477+
478+
u32 i2c_hid_get_dmi_quirks(const u16 vendor, const u16 product)
479+
{
480+
u32 quirks = 0;
481+
const struct dmi_system_id *system_id =
482+
dmi_first_match(i2c_hid_dmi_quirk_table);
483+
484+
if (system_id) {
485+
const struct hid_device_id *device_id =
486+
(struct hid_device_id *)(system_id->driver_data);
487+
488+
if (device_id && device_id->vendor == vendor &&
489+
device_id->product == product)
490+
quirks = device_id->driver_data;
491+
}
492+
493+
return quirks;
494+
}

drivers/hid/i2c-hid/i2c-hid.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@
99
struct i2c_hid_desc *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name);
1010
char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name,
1111
unsigned int *size);
12+
u32 i2c_hid_get_dmi_quirks(const u16 vendor, const u16 product);
1213
#else
1314
static inline struct i2c_hid_desc
1415
*i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name)
1516
{ return NULL; }
1617
static inline char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name,
1718
unsigned int *size)
1819
{ return NULL; }
20+
static inline u32 i2c_hid_get_dmi_quirks(const u16 vendor, const u16 product)
21+
{ return 0; }
1922
#endif
2023

2124
/**

include/linux/hid.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,7 @@ struct hid_device { /* device report descriptor */
621621
unsigned long status; /* see STAT flags above */
622622
unsigned claimed; /* Claimed by hidinput, hiddev? */
623623
unsigned quirks; /* Various quirks the device can pull on us */
624+
unsigned initial_quirks; /* Initial set of quirks supplied when creating device */
624625
bool io_started; /* If IO has started */
625626

626627
struct list_head inputs; /* The list of inputs */

0 commit comments

Comments
 (0)