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 */