This patch adds support for Elantech trackpoints to pms.  They can be
treated like other secondary devices and require only minor extensions
in the initialization and input functions.

For now, the patch also extends the set of "IC types" that are accepted
for V4-touchpads from (6,8) to (6,8,15).  It might well be that other
types in the range 6-15 work properly with the driver.

Thanks to Ryan Lennox for help and testing.

OK?


Index: dev/pckbc/pms.c
===================================================================
RCS file: /cvs/src/sys/dev/pckbc/pms.c,v
retrieving revision 1.86
diff -u -p -r1.86 pms.c
--- dev/pckbc/pms.c     29 Apr 2018 08:50:04 -0000      1.86
+++ dev/pckbc/pms.c     12 May 2018 13:08:46 -0000
@@ -130,6 +130,7 @@ struct elantech_softc {
 #define ELANTECH_F_2FINGER_PACKET      0x04
 #define ELANTECH_F_HW_V1_OLD           0x08
 #define ELANTECH_F_CRC_ENABLED         0x10
+#define ELANTECH_F_TRACKPOINT          0x20
        int fw_version;

        u_int mt_slots;
@@ -1938,8 +1939,9 @@ elantech_get_hwinfo_v4(struct pms_softc
        if (synaptics_query(sc, ELANTECH_QUE_FW_VER, &fw_version))
                return (-1);

-       if (((fw_version & 0x0f0000) >> 16) != 6 &&
-           (fw_version & 0x0f0000) >> 16 != 8)
+       if ((fw_version & 0x0f0000) >> 16 != 6
+           && (fw_version & 0x0f0000) >> 16 != 8
+           && (fw_version & 0x0f0000) >> 16 != 15)
                return (-1);

        elantech->fw_version = fw_version;
@@ -1963,6 +1965,9 @@ elantech_get_hwinfo_v4(struct pms_softc
        if ((capabilities[1] < 2) || (capabilities[1] > hw->x_max))
                return (-1);

+       if (capabilities[0] & ELANTECH_CAP_TRACKPOINT)
+               elantech->flags |= ELANTECH_F_TRACKPOINT;
+
        hw->type = WSMOUSE_TYPE_ELANTECH;
        hw->hw_type = WSMOUSEHW_CLICKPAD;
        hw->mt_slots = ELANTECH_MAX_FINGERS;
@@ -2140,6 +2145,7 @@ int
 pms_enable_elantech_v4(struct pms_softc *sc)
 {
        struct elantech_softc *elantech = sc->elantech;
+       struct wsmousedev_attach_args a;

        if (elantech_knock(sc))
                goto err;
@@ -2169,6 +2175,14 @@ pms_enable_elantech_v4(struct pms_softc

                printf("%s: Elantech Clickpad, version %d, firmware 0x%x\n",
                    DEVNAME(sc), 4, sc->elantech->fw_version);
+
+               if (sc->elantech->flags & ELANTECH_F_TRACKPOINT) {
+                       a.accessops = &pms_sec_accessops;
+                       a.accesscookie = sc;
+                       sc->sc_sec_wsmousedev = config_found((void *) sc, &a,
+                           wsmousedevprint);
+               }
+
        } else if (elantech_set_absolute_mode_v4(sc))
                goto err;

@@ -2328,13 +2342,40 @@ pms_sync_elantech_v3(struct pms_softc *s
        return (0);
 }

+/* Extract the type bits from packet[3]. */
+static inline int
+elantech_packet_type(u_char b)
+{
+       return ((b & 4) ? (b & 0xcf) : (b & 0x1f));
+}
+
 int
 pms_sync_elantech_v4(struct pms_softc *sc, int data)
 {
-       if (sc->inputstate == 0 && (data & 0x0c) != 0x04)
+       if (sc->inputstate == 0) {
+               if ((data & 0x0c) == 0x04)
+                       return (0);
+               if ((sc->elantech->flags & ELANTECH_F_TRACKPOINT)
+                   && (data & 0xc8) == 0)
+                       return (0);
                return (-1);
-       else
-               return (0);
+       }
+       if (sc->inputstate == 3) {
+               switch (elantech_packet_type(data)) {
+               case ELANTECH_V4_PKT_STATUS:
+               case ELANTECH_V4_PKT_HEAD:
+               case ELANTECH_V4_PKT_MOTION:
+                       return ((sc->packet[0] & 4) ? 0 : -1);
+               case ELANTECH_PKT_TRACKPOINT:
+                       return ((sc->packet[0] & 0xc8) == 0
+                           && sc->packet[1] == ((data & 0x10) << 3)
+                           && sc->packet[2] == ((data & 0x20) << 2)
+                           && (data ^ (sc->packet[0] & 0x30)) == 0x36
+                           ? 0 : -1);
+               }
+               return (-1);
+       }
+       return (0);
 }

 void
@@ -2474,7 +2515,7 @@ pms_proc_elantech_v4(struct pms_softc *s
        int id, weight, n, x, y, z;
        u_int buttons, slots;

-       switch (sc->packet[3] & 0x1f) {
+       switch (elantech_packet_type(sc->packet[3])) {
        case ELANTECH_V4_PKT_STATUS:
                slots = elantech->mt_slots;
                elantech->mt_slots = sc->packet[1] & 0x1f;
@@ -2509,8 +2550,17 @@ pms_proc_elantech_v4(struct pms_softc *s
                        wsmouse_set(sc_wsmousedev, WSMOUSE_MT_REL_Y, y, id);
                        wsmouse_set(sc_wsmousedev, WSMOUSE_MT_PRESSURE, z, id);
                }
-
                break;
+
+       case ELANTECH_PKT_TRACKPOINT:
+               if (sc->sc_dev_enable & PMS_DEV_SECONDARY) {
+                       x = sc->packet[4] - 0x100 + (sc->packet[1] << 1);
+                       y = sc->packet[5] - 0x100 + (sc->packet[2] << 1);
+                       buttons = butmap[sc->packet[0] & 7];
+                       WSMOUSE_INPUT(sc->sc_sec_wsmousedev,
+                           buttons, x, y, 0, 0);
+               }
+               return;

        default:
                printf("%s: unknown packet type 0x%x\n", DEVNAME(sc),
Index: dev/pckbc/pmsreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pckbc/pmsreg.h,v
retrieving revision 1.15
diff -u -p -r1.15 pmsreg.h
--- dev/pckbc/pmsreg.h  29 Jan 2018 21:54:11 -0000      1.15
+++ dev/pckbc/pmsreg.h  12 May 2018 13:08:46 -0000
@@ -180,6 +180,7 @@

 /* Elantech capabilities */
 #define ELANTECH_CAP_HAS_ROCKER                        4
+#define ELANTECH_CAP_TRACKPOINT                        0x80

 #define ELANTECH_PS2_CUSTOM_COMMAND            0xf8

@@ -209,5 +210,8 @@
 #define ELANTECH_V4_PKT_STATUS                 0x10
 #define ELANTECH_V4_PKT_HEAD                   0x11
 #define ELANTECH_V4_PKT_MOTION                 0x12
+
+/* V3 and V4 may be coupled with trackpoints, pms supports them for V4. */
+#define ELANTECH_PKT_TRACKPOINT                        0x06

 #endif /* SYS_DEV_PCKBC_PMSREG_H */

Reply via email to