This patch addresses a bug in certain Elantech-V1 touchpads, which report
invalid position data at the start of single-finger touches.

The patch is derived from this proposal
    https://marc.info/?l=openbsd-tech&m=159957752322249&w=2

This version also removes two bits of obsolete code.  wsmouse ignores
coordinate values when a driver signals that a contact has been released
(reporting any coordinates just avoids a branch in the caller code).  Sorry
for coupling these issues, but opportunities for tests with v1- or v2-models
are rare.

OK?


Index: pms.c
===================================================================
RCS file: /cvs/src/sys/dev/pckbc/pms.c,v
retrieving revision 1.94
diff -u -p -r1.94 pms.c
--- pms.c       10 Aug 2020 21:55:59 -0000      1.94
+++ pms.c       12 Sep 2020 21:09:03 -0000
@@ -142,6 +142,7 @@ struct elantech_softc {

        int max_x, max_y;
        int old_x, old_y;
+       int initial_pkt;
 };
 #define ELANTECH_IS_CLICKPAD(sc) (((sc)->elantech->fw_version & 0x1000) != 0)

@@ -2443,15 +2444,29 @@ pms_proc_elantech_v1(struct pms_softc *s
        else
                w = (sc->packet[0] & 0xc0) >> 6;

+       /*
+        * Firmwares 0x20022 and 0x20600 have a bug, position data in the
+        * first two reports for single-touch contacts may be corrupt.
+        */
+       if (elantech->fw_version == 0x20022 ||
+           elantech->fw_version == 0x20600) {
+               if (w == 1) {
+                       if (elantech->initial_pkt < 2) {
+                               elantech->initial_pkt++;
+                               return;
+                       }
+               } else if (elantech->initial_pkt) {
+                       elantech->initial_pkt = 0;
+               }
+       }
+
        /* Hardware version 1 doesn't report pressure. */
        if (w) {
                x = ((sc->packet[1] & 0x0c) << 6) | sc->packet[2];
                y = ((sc->packet[1] & 0x03) << 8) | sc->packet[3];
                z = SYNAPTICS_PRESSURE;
        } else {
-               x = elantech->old_x;
-               y = elantech->old_y;
-               z = 0;
+               x = y = z = 0;
        }

        WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons, x, y, z, w);
@@ -2488,9 +2503,7 @@ pms_proc_elantech_v2(struct pms_softc *s
                y = (((sc->packet[0] & 0x20) << 3) | sc->packet[2]) << 2;
                z = SYNAPTICS_PRESSURE;
        } else {
-               x = elantech->old_x;
-               y = elantech->old_y;
-               z = 0;
+               x = y = z = 0;
        }

        WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons, x, y, z, w);

Reply via email to