On Tue, Dec 13, 2022 at 1:19 AM Benjamin Tissoires <benjamin.tissoires@xxxxxxxxxx> wrote: > > On Tue, Dec 13, 2022 at 2:01 AM Allen Ballway <ballway@xxxxxxxxxxxx> wrote: > > > > Certain touchscreen devices, such as the ELAN9034, are oriented > > incorrectly and report touches on opposite points on the X and Y axes. > > For example, a 100x200 screen touched at (10,20) would report (90, 180) > > and vice versa. > > > > This changed fixes the issue by adding device quirks to transform > > the touch points into the correct spaces, from X -> MAX(X) - X, > > and Y -> MAX(Y) - Y. These quirks are added in hid-quirks checking > > both DMI information and device vendor and product IDs. The quirk > > is handled in hid-multitouch to do the actual transformation. > > > > Signed-off-by: Allen Ballway <ballway@xxxxxxxxxxxx> > > --- > > V2 -> V3: Use existing HID_QUIRK_*_INVERT and match the quirk in > > hid-quirk, passing down to hid-multitouch through the hid device. > > > > V1 -> V2: Address review comments, change to use DMI match. Confirmed > > MT_TOOL_X/Y require transformation and update orientation based on > > flipped axes. > > > > > > drivers/hid/hid-multitouch.c | 43 ++++++++++++++++++++++++++++++++---- > > drivers/hid/hid-quirks.c | 33 +++++++++++++++++++++++++++ > > 2 files changed, 72 insertions(+), 4 deletions(-) > > > > diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c > > index 91a4d3fc30e08..1f4c2aa511359 100644 > > --- a/drivers/hid/hid-multitouch.c > > +++ b/drivers/hid/hid-multitouch.c > > @@ -71,6 +71,8 @@ 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_X_INVERT BIT(22) > > +#define MT_QUIRK_Y_INVERT BIT(23) > > Why duplicate the already available quirks in struct hid_device? This no longer seems necessary, and will be removed. > > > > > #define MT_INPUTMODE_TOUCHSCREEN 0x02 > > #define MT_INPUTMODE_TOUCHPAD 0x03 > > @@ -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,16 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input, > > if (azimuth > max_azimuth * 2) > > azimuth -= max_azimuth * 4; > > orientation = -azimuth; > > + > > + /* Orientation is inverted if the X or Y axes are > > + * flipped, but normalized if both are inverted. > > + */ > > + if (quirks & (MT_QUIRK_X_INVERT | MT_QUIRK_Y_INVERT) && > > + !((quirks & MT_QUIRK_X_INVERT) > > + && (quirks & MT_QUIRK_Y_INVERT))) { > > This is done in every finger slot in every report. We should probably > cache that information somewhere. I can do this once in mt_probe and keep it saved as its own quirk. > > > + orientation = -orientation; > > + } > > + > > } > > > > if (quirks & MT_QUIRK_TOUCH_SIZE_SCALING) { > > @@ -1115,10 +1131,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 = quirks & MT_QUIRK_X_INVERT ? > > + input_abs_get_max(input, ABS_MT_POSITION_X) - *slot->x : > > + *slot->x; > > + y = quirks & MT_QUIRK_Y_INVERT ? > > + input_abs_get_max(input, ABS_MT_POSITION_Y) - *slot->y : > > + *slot->y; > > + cx = quirks & MT_QUIRK_X_INVERT ? > > + input_abs_get_max(input, ABS_MT_POSITION_X) - *slot->cx : > > + *slot->cx; > > + cy = quirks & MT_QUIRK_Y_INVERT ? > > + input_abs_get_max(input, ABS_MT_POSITION_Y) - *slot->cy : > > + *slot->cy; > > I can't help but think that there must be a better way of doing that. > If I didn't postpone HID-BPF to 6.3 I would have asked you to do this > as a BPF program. > > Still, the whole point of the slot pointers was to remove the data > copy everywhere, and you are adding it back. Not to mention that the > same tests and accesses to variables are called multiple times. I can move the transformation to mt_touch_input_mapping which has easier access to the quirks coming from hid_device rather than using duplicated quirks for mt_application/class. > > > + > > + 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 +1764,12 @@ 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; > > > > + if (hdev->quirks & HID_QUIRK_X_INVERT) > > + td->mtclass.quirks |= MT_QUIRK_X_INVERT; > > + > > + if (hdev->quirks & HID_QUIRK_Y_INVERT) > > + td->mtclass.quirks |= MT_QUIRK_Y_INVERT; > > As mentioned above, I don't see the point in doing that duplication of quirks. Will remove > > > + > > /* This allows the driver to correctly support devices > > * that emit events over several HID messages. > > */ > > diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c > > AFAICT, Dmitry told you twice to use i2c-hid, not hid-quirks.c. > > We already have i2c-hid-dmi-quirks.c that you could extend. The > rationale is that this way, the dmi check will be done only for > internal peripherals, leaving aside the USB ones. I had added the quirks to hid_device to i2c-hid-dmi-quirks before trying this but they were getting stomped by the quirks coming from hid-quirks. I will move these back to i2c-hid-dmi-quirks and change hid-device to add them to whatever quirks come from hid-quirks. > > Cheers, > Benjamin > > > index 0e9702c7f7d6c..47c6cd62f019a 100644 > > --- a/drivers/hid/hid-quirks.c > > +++ b/drivers/hid/hid-quirks.c > > @@ -16,6 +16,7 @@ > > #include <linux/export.h> > > #include <linux/slab.h> > > #include <linux/mutex.h> > > +#include <linux/dmi.h> > > #include <linux/input/elan-i2c-ids.h> > > > > #include "hid-ids.h" > > @@ -957,6 +958,29 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { > > { } > > }; > > > > +static const struct hid_device_id 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 dmi_override_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 *)elan_flipped_quirks, > > + }, > > + { } /* Terminate list */ > > +}; > > + > > bool hid_ignore(struct hid_device *hdev) > > { > > int i; > > @@ -1238,6 +1262,7 @@ static unsigned long hid_gets_squirk(const struct hid_device *hdev) > > { > > const struct hid_device_id *bl_entry; > > unsigned long quirks = 0; > > + const struct dmi_system_id *system_id; > > > > if (hid_match_id(hdev, hid_ignore_list)) > > quirks |= HID_QUIRK_IGNORE; > > @@ -1249,6 +1274,14 @@ static unsigned long hid_gets_squirk(const struct hid_device *hdev) > > if (bl_entry != NULL) > > quirks |= bl_entry->driver_data; > > > > + system_id = dmi_first_match(dmi_override_table); > > + if (system_id != NULL) { > > + bl_entry = hid_match_id(hdev, system_id->driver_data); > > + if (bl_entry != NULL) > > + quirks |= bl_entry->driver_data; > > + } > > + > > + > > if (quirks) > > dbg_hid("Found squirk 0x%lx for HID device 0x%04x:0x%04x\n", > > quirks, hdev->vendor, hdev->product); > > -- > > 2.39.0.rc1.256.g54fd8350bd-goog > > > Thanks for the comments, Allen