I have been going around in circles with this for a while trying to get
my clickpad initialised to work with extended w mode.  I don't have it
right but I have noticed if I boot windows or fedora and then reboot to
netbsd I have extended_w.  Doing this I have multi-finger working so you
can hold down a button and scroll though a menu with the other finger.
This patch also provides 3 button emulation for a click pad.  There are
some sysctls that set the size of the mouse button regions (height and
left, middle and right button regions).  I am putting this out there
just in case it works for others and the initialisation issue is just my
hardware.  Even if extended_w does not work it does at least mean that
click pads will have 3 buttons and you can scroll a little bit by moving
the finger that has activated the button (I have been surviving like
this for quite some time).  Any comments/improvements welcome....

Index: synaptics.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pckbport/synaptics.c,v
retrieving revision 1.33
diff -u -r1.33 synaptics.c
--- synaptics.c 4 Mar 2015 22:58:35 -0000       1.33
+++ synaptics.c 24 Oct 2017 08:25:47 -0000
@@ -80,6 +80,10 @@
        signed short    sp_y;
        u_char  sp_z;           /* Z (pressure) */
        u_char  sp_w;           /* W (contact patch width) */
+       signed short    sp_sx;  /* Secondary finger unscaled absolute */
+                               /* X/Y coordinates */
+       signed short    sp_xy;
+       u_char  sp_finger;      /* 0 for primary, 1 for secondary */
        char    sp_left;        /* Left mouse button status */
        char    sp_right;       /* Right mouse button status */
        char    sp_middle;      /* Middle button status (possibly emulated) */
@@ -105,6 +109,9 @@
 static int synaptics_edge_motion_delta = 32;
 static u_int synaptics_finger_high = SYNAPTICS_FINGER_LIGHT + 5;
 static u_int synaptics_finger_low = SYNAPTICS_FINGER_LIGHT - 10;
+static int synaptics_button_boundary = SYNAPTICS_EDGE_BOTTOM + 720;
+static int synaptics_button2 = SYNAPTICS_EDGE_LEFT + (SYNAPTICS_EDGE_RIGHT - 
SYNAPTICS_EDGE_LEFT) / 3;
+static int synaptics_button3 = SYNAPTICS_EDGE_LEFT + 2 * (SYNAPTICS_EDGE_RIGHT 
- SYNAPTICS_EDGE_LEFT) / 3;
 static int synaptics_two_fingers_emul = 0;
 static int synaptics_scale_x = 16;
 static int synaptics_scale_y = 16;
@@ -113,6 +120,9 @@
 static int synaptics_movement_threshold = 4;
 
 /* Sysctl nodes. */
+static int synaptics_button_boundary_nodenum;
+static int synaptics_button2_nodenum;
+static int synaptics_button3_nodenum;
 static int synaptics_up_down_emul_nodenum;
 static int synaptics_up_down_motion_delta_nodenum;
 static int synaptics_gesture_move_nodenum;
@@ -293,6 +303,7 @@
                goto done;
        }
 
+
        /* Query the hardware capabilities. */
        res = pms_sliced_command(psc->sc_kbctag, psc->sc_kbcslot,
            SYNAPTICS_READ_CAPABILITIES);
@@ -385,7 +396,7 @@
 {
        struct pms_softc *psc = vsc;
        struct synaptics_softc *sc = &psc->u.synaptics;
-       u_char cmd[2], resp[2];
+       u_char cmd[2], resp[3], enable_modes;
        int res;
 
        if (sc->flags & SYN_FLAG_HAS_PASSTHROUGH) {
@@ -400,14 +411,68 @@
 
        /*
         * Enable Absolute mode with W (width) reporting, and set
-        * the packet rate to maximum (80 packets per second).
+        * the packet rate to maximum (80 packets per second). Enable
+        * extended W mode if supported so we can report second finger
+        * position.
         */
-       res = pms_sliced_command(psc->sc_kbctag, psc->sc_kbcslot,
-           SYNAPTICS_MODE_ABSOLUTE | SYNAPTICS_MODE_W | SYNAPTICS_MODE_RATE);
+       enable_modes =
+          SYNAPTICS_MODE_ABSOLUTE | SYNAPTICS_MODE_W | SYNAPTICS_MODE_RATE;
+
+       if (sc->flags & SYN_FLAG_HAS_EXTENDED_WMODE) 
+               enable_modes |= SYNAPTICS_MODE_EXTENDED_W;
+
+       /*
+       * Synaptics documentation says to disable device before
+       * setting mode.
+       */
+       cmd[0] = PMS_DEV_DISABLE;
+       res = pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 1, 0,
+           NULL, 0);
+       if (res)
+               aprint_error("synaptics: disable error\n");
+
+       /* a couple of set scales to clear out pending commands */
+       cmd[0] = PMS_SET_SCALE11;
+       res = pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 1, 0,
+           NULL, 0);
+       if (res)
+               aprint_error("synaptics: set scale 1 error\n");
+
+       cmd[0] = PMS_SET_SCALE11;
+       res = pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 1, 0,
+           NULL, 0);
+       if (res)
+               aprint_error("synaptics: set scale 2 error\n");
+
+       res = pms_sliced_command(psc->sc_kbctag, psc->sc_kbcslot, enable_modes);
        cmd[0] = PMS_SET_SAMPLE;
        cmd[1] = SYNAPTICS_CMD_SET_MODE2;
-       res |= pckbport_enqueue_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 2, 0,
-           1, NULL);
+       res |= pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 2, 0,
+               NULL, 0);
+       if (res)
+               aprint_error("synaptics: set mode error\n");
+       
+       /* a couple of set scales to clear out pending commands */
+       cmd[0] = PMS_SET_SCALE11;
+       res = pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 1, 0,
+           NULL, 0);
+       if (res)
+               aprint_error("synaptics: set scale 1 error\n");
+
+       cmd[0] = PMS_SET_SCALE11;
+       res = pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 1, 0,
+           NULL, 0);
+       if (res)
+               aprint_error("synaptics: set scale 2 error\n");
+
+       cmd[0] = PMS_DEV_ENABLE;
+       res = pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 1, 0,
+           NULL, 0);
+       if (res) {
+               aprint_error_dev(psc->sc_dev,
+                   "synaptics_enable: Error enabling device.\n");
+       }
+
        sc->up_down = 0;
        sc->prev_fingers = 0;
        sc->gesture_start_x = sc->gesture_start_y = 0;
@@ -415,12 +480,11 @@
        sc->gesture_tap_packet = 0;
        sc->gesture_type = 0;
        sc->gesture_buttons = 0;
-       sc->rem_x = sc->rem_y = 0;
-       sc->movement_history = 0;
-       if (res) {
-               aprint_error_dev(psc->sc_dev,
-                   "synaptics_enable: Error enabling device.\n");
-       }
+       sc->rem_x[0] = sc->rem_y[0] = 0;
+       sc->rem_x[1] = sc->rem_y[1] = 0;
+       sc->movement_history[0] = 0;
+       sc->movement_history[1] = 0;
+       sc->button_history = 0;
 }
 
 void
@@ -655,6 +719,42 @@
                goto err;
 
        synaptics_movement_threshold_nodenum = node->sysctl_num;
+
+       if ((rc = sysctl_createv(clog, 0, NULL, &node,
+           CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
+           CTLTYPE_INT, "button_boundary",
+           SYSCTL_DESCR("Top edge of button area"),
+           pms_sysctl_synaptics_verify, 0,
+           &synaptics_button_boundary,
+           0, CTL_HW, root_num, CTL_CREATE,
+           CTL_EOL)) != 0)
+               goto err;
+
+       synaptics_button_boundary_nodenum = node->sysctl_num;
+
+       if ((rc = sysctl_createv(clog, 0, NULL, &node,
+           CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
+           CTLTYPE_INT, "button2_edge",
+           SYSCTL_DESCR("Left edge of button 2 region"),
+           pms_sysctl_synaptics_verify, 0,
+           &synaptics_button2,
+           0, CTL_HW, root_num, CTL_CREATE,
+           CTL_EOL)) != 0)
+               goto err;
+
+       synaptics_button2_nodenum = node->sysctl_num;
+
+       if ((rc = sysctl_createv(clog, 0, NULL, &node,
+           CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
+           CTLTYPE_INT, "button3_edge",
+           SYSCTL_DESCR("Left edge of button 3 region"),
+           pms_sysctl_synaptics_verify, 0,
+           &synaptics_button3,
+           0, CTL_HW, root_num, CTL_CREATE,
+           CTL_EOL)) != 0)
+               goto err;
+
+       synaptics_button3_nodenum = node->sysctl_num;
        return;
 
 err:
@@ -716,6 +816,16 @@
                if (t < 0 || t > (SYNAPTICS_EDGE_MAX / 4))
                        return (EINVAL);
        } else
+       if (node.sysctl_num == synaptics_button_boundary) {
+               if (t < 0 || t < SYNAPTICS_EDGE_BOTTOM || 
+                   t > SYNAPTICS_EDGE_TOP)
+                       return (EINVAL);
+       } else
+       if (node.sysctl_num == synaptics_button2 ||
+           node.sysctl_num == synaptics_button3) {
+               if (t < SYNAPTICS_EDGE_LEFT || t > SYNAPTICS_EDGE_RIGHT)
+                       return (EINVAL);
+       } else
                return (EINVAL);
 
        *(int *)rnode->sysctl_data = t;
@@ -733,64 +843,152 @@
 {
        struct synaptics_softc *sc = &psc->u.synaptics;
        struct synaptics_packet sp;
+       char new_buttons, ew_mode;
 
        memset(&sp, 0, sizeof(sp));
 
-       /* Absolute X/Y coordinates of finger */
-       sp.sp_x = psc->packet[4] + ((psc->packet[1] & 0x0f) << 8) +
-          ((psc->packet[3] & 0x10) << 8);
-       sp.sp_y = psc->packet[5] + ((psc->packet[1] & 0xf0) << 4) +
-          ((psc->packet[3] & 0x20) << 7);
-
-       /* Pressure */
-       sp.sp_z = psc->packet[2];
-
        /* Width of finger */
        sp.sp_w = ((psc->packet[0] & 0x30) >> 2) +
           ((psc->packet[0] & 0x04) >> 1) +
           ((psc->packet[3] & 0x04) >> 2);
+       sp.sp_finger = 0;
+       if (sp.sp_w ==  SYNAPTICS_WIDTH_EXTENDED_W) {
+               ew_mode = psc->packet[5] >> 4;
+               switch (ew_mode)
+               {
+               case SYNAPTICS_EW_WHEEL:
+                       /* scroll wheel report, ignore for now */
+                       aprint_debug_dev(psc->sc_dev, "mouse wheel packet\n");
+                       return;
+                       break;
 
-       /* Left/Right button handling. */
-       sp.sp_left = psc->packet[0] & PMS_LBUTMASK;
-       sp.sp_right = psc->packet[0] & PMS_RBUTMASK;
-
-       /* Up/Down buttons. */
-       if (sc->flags & SYN_FLAG_HAS_BUTTONS_4_5) {
-               /* Old up/down buttons. */
-               sp.sp_up = sp.sp_left ^
-                   (psc->packet[3] & PMS_LBUTMASK);
-               sp.sp_down = sp.sp_right ^
-                   (psc->packet[3] & PMS_RBUTMASK);
-       } else
-       if (sc->flags & SYN_FLAG_HAS_UP_DOWN_BUTTONS &&
-          ((psc->packet[0] & PMS_RBUTMASK) ^
-          (psc->packet[3] & PMS_RBUTMASK))) {
-               /* New up/down button. */
-               sp.sp_up = psc->packet[4] & SYN_1BUTMASK;
-               sp.sp_down = psc->packet[5] & SYN_2BUTMASK;
+               case SYNAPTICS_EW_SECONDARY_FINGER:
+                       /* parse the second finger report */
+                       
+                       sp.sp_finger = 1; /* just one other finger for now */
+                       sp.sp_x = psc->packet[1]
+                           + ((psc->packet[4] & 0x0f) << 8);
+                       sp.sp_y = psc->packet[2]
+                           + ((psc->packet[4] & 0xf0) << 4);
+                       sp.sp_z = (psc->packet[3] & 0x30)
+                           + (psc->packet[5] & 0x0f);
+
+                       /* keep same buttons down as primary */
+                       sp.sp_left = sc->button_history & PMS_LBUTMASK;
+                       sp.sp_middle = sc->button_history & PMS_MBUTMASK;
+                       sp.sp_right = sc->button_history & PMS_RBUTMASK;
+                       break;
+
+               case SYNAPTICS_EW_FINGER_STATUS:
+                       /* reports which finger is primary/secondary
+                        * ignore for now.
+                        */
+                       return;
+                       break;
+
+               default:
+                       aprint_error_dev(psc->sc_dev,
+                           "invalid extended w mode %d\n",
+                           ew_mode);
+                       return;
+                       break;
+               }
        } else {
-               sp.sp_up = 0;
-               sp.sp_down = 0;
-       }
 
-       if(sc->flags & SYN_FLAG_HAS_ONE_BUTTON_CLICKPAD) {
-               /* This is not correctly specified. Read this button press
-                * from L/U bit.
-                */
-               sp.sp_left = ((psc->packet[0] ^ psc->packet[3]) & 0x01) ? 1 : 0;
-       } else
-       /* Middle button. */
-       if (sc->flags & SYN_FLAG_HAS_MIDDLE_BUTTON) {
-               /* Old style Middle Button. */
-               sp.sp_middle = (psc->packet[0] & PMS_LBUTMASK) ^
-                   (psc->packet[3] & PMS_LBUTMASK);
-       } else
-       if (synaptics_up_down_emul == 1) {
-               /* Do middle button emulation using up/down buttons */
-               sp.sp_middle = sp.sp_up | sp.sp_down;
-               sp.sp_up = sp.sp_down = 0;
-       } else
-               sp.sp_middle = 0;
+               /* Absolute X/Y coordinates of finger */
+               sp.sp_x = psc->packet[4] + ((psc->packet[1] & 0x0f) << 8) +
+               ((psc->packet[3] & 0x10) << 8);
+               sp.sp_y = psc->packet[5] + ((psc->packet[1] & 0xf0) << 4) +
+               ((psc->packet[3] & 0x20) << 7);
+
+               /* Pressure */
+               sp.sp_z = psc->packet[2];
+
+               /* Left/Right button handling. */
+               sp.sp_left = psc->packet[0] & PMS_LBUTMASK;
+               sp.sp_right = psc->packet[0] & PMS_RBUTMASK;
+
+               /* Up/Down buttons. */
+               if (sc->flags & SYN_FLAG_HAS_BUTTONS_4_5) {
+                       /* Old up/down buttons. */
+                       sp.sp_up = sp.sp_left ^
+                       (psc->packet[3] & PMS_LBUTMASK);
+                       sp.sp_down = sp.sp_right ^
+                       (psc->packet[3] & PMS_RBUTMASK);
+               } else
+               if (sc->flags & SYN_FLAG_HAS_UP_DOWN_BUTTONS &&
+                   ((psc->packet[0] & PMS_RBUTMASK) ^
+                   (psc->packet[3] & PMS_RBUTMASK))) {
+                       /* New up/down button. */
+                       sp.sp_up = psc->packet[4] & SYN_1BUTMASK;
+                       sp.sp_down = psc->packet[5] & SYN_2BUTMASK;
+               } else {
+                       sp.sp_up = 0;
+                       sp.sp_down = 0;
+               }
+
+               new_buttons = 0;
+               if(sc->flags & SYN_FLAG_HAS_ONE_BUTTON_CLICKPAD) {
+                       /* This is not correctly specified. Read this button 
press
+                       * from L/U bit.  Emulate 3 buttons by checking the 
+                       * coordinates of the click and returning the appropriate
+                       * button code.  Outside the button region default to a
+                       * left click.
+                       */
+                       if (sp.sp_y < synaptics_button_boundary) {
+                               if (sp.sp_x > synaptics_button3) {
+                                       sp.sp_right =
+                                               ((psc->packet[0] ^ 
psc->packet[3]) & 0x01) ? PMS_RBUTMASK : 0;
+                               } else if (sp.sp_x > synaptics_button2) {
+                                       sp.sp_middle =
+                                               ((psc->packet[0] ^ 
psc->packet[3]) & 0x01) ? PMS_MBUTMASK : 0;
+                               } else {
+                                       sp.sp_left =
+                                               ((psc->packet[0] ^ 
psc->packet[3]) & 0x01) ? PMS_LBUTMASK : 0;
+                               }
+                       } else
+                               sp.sp_left =
+                                  ((psc->packet[0] ^ psc->packet[3]) & 0x01) ? 
1 : 0;
+                       new_buttons = sp.sp_left | sp.sp_middle | sp.sp_right;
+                       if (new_buttons != sc->button_history) {
+                               if (sc->button_history == 0)
+                                       sc->button_history = new_buttons;
+                               else if (new_buttons == 0) {
+                                       sc->button_history = 0;
+                                       /* ensure all buttons are cleared just 
in
+                                       * case finger comes off in a different
+                                       * region.
+                                       */
+                                       sp.sp_left = 0;
+                                       sp.sp_middle = 0;
+                                       sp.sp_right = 0;
+                               } else {
+                                       /* make sure we keep the same button 
even
+                                       * if the finger moves to a different
+                                       * region.  This precludes chording
+                                       * but, oh well.
+                                       */
+                                       sp.sp_left = sc->button_history & 
PMS_LBUTMASK;
+                                       sp.sp_middle = sc->button_history
+                                       & PMS_MBUTMASK;
+                                       sp.sp_right = sc->button_history & 
PMS_RBUTMASK;
+                               }
+                       }
+               } else
+               /* Middle button. */
+               if (sc->flags & SYN_FLAG_HAS_MIDDLE_BUTTON) {
+                       /* Old style Middle Button. */
+                       sp.sp_middle = (psc->packet[0] & PMS_LBUTMASK) ^
+                       (psc->packet[3] & PMS_LBUTMASK);
+               } else 
+               if (synaptics_up_down_emul == 1) {
+                       /* Do middle button emulation using up/down buttons */
+                       sp.sp_middle = sp.sp_up | sp.sp_down;
+                       sp.sp_up = sp.sp_down = 0;
+               } else
+                       sp.sp_middle = 0;
+
+       }
 
        pms_synaptics_process_packet(psc, &sp);
 }
@@ -853,6 +1051,9 @@
                            "pms_input: unusual delay (%ld.%06ld s), "
                            "scheduling reset\n",
                            (long)diff.tv_sec, (long)diff.tv_usec);
+                           printf("pms_input: unusual delay (%ld.%06ld s), "
+                           "scheduling reset\n",
+                           (long)diff.tv_sec, (long)diff.tv_usec);
                        psc->inputstate = 0;
                        psc->sc_enabled = 0;
                        wakeup(&psc->sc_enabled);
@@ -888,7 +1089,6 @@
                 * Extract the pertinent details.
                 */
                psc->inputstate = 0;
-
                if ((psc->packet[0] & 0xfc) == 0x84 &&
                    (psc->packet[3] & 0xcc) == 0xc4) {
                        /* W = SYNAPTICS_WIDTH_PASSTHROUGH, PS/2 passthrough */
@@ -948,7 +1148,8 @@
         * fingers appear within the tap gesture time period.
         */
        if (sc->flags & SYN_FLAG_HAS_MULTI_FINGER &&
-           SYN_TIME(sc, sc->gesture_start_packet) < synaptics_gesture_length) {
+           SYN_TIME(sc, sc->gesture_start_packet,
+           sp->sp_finger) < synaptics_gesture_length) {
                switch (sp->sp_w) {
                case SYNAPTICS_WIDTH_TWO_FINGERS:
                        fingers = 2;
@@ -985,7 +1186,7 @@
        int gesture_len, gesture_buttons;
        int set_buttons;
 
-       gesture_len = SYN_TIME(sc, sc->gesture_start_packet);
+       gesture_len = SYN_TIME(sc, sc->gesture_start_packet, sp->sp_finger);
        gesture_buttons = sc->gesture_buttons;
 
        if (fingers > 0 && (fingers == sc->prev_fingers)) {
@@ -1010,7 +1211,7 @@
                sc->gesture_start_y = abs(sp->sp_y);
                sc->gesture_move_x = 0;
                sc->gesture_move_y = 0;
-               sc->gesture_start_packet = sc->total_packets;
+               sc->gesture_start_packet = sc->total_packets[0];
 
 #ifdef DIAGNOSTIC
                aprint_debug("Finger applied: gesture_start_x: %d 
gesture_start_y: %d\n",
@@ -1053,7 +1254,7 @@
                                 * Single tap gesture. Set the tap length timer
                                 * and flag a single-click.
                                 */
-                               sc->gesture_tap_packet = sc->total_packets;
+                               sc->gesture_tap_packet = sc->total_packets[0];
                                sc->gesture_type |= SYN_GESTURE_SINGLE;
 
                                /*
@@ -1110,7 +1311,7 @@
                 * Activate the relevant button(s) until the
                 * gesture tap timer has expired.
                 */
-               if (SYN_TIME(sc, sc->gesture_tap_packet) <
+               if (SYN_TIME(sc, sc->gesture_tap_packet, sp->sp_finger) <
                    synaptics_gesture_length)
                        set_buttons = 1;
                else
@@ -1139,11 +1340,12 @@
 }
 
 static inline int
-synaptics_filter_policy(struct synaptics_softc *sc, int *history, int value)
+synaptics_filter_policy(struct synaptics_softc *sc, int finger, int *history,
+                       int value)
 {
        int a, b, rv, count;
 
-       count = sc->total_packets;
+       count = sc->total_packets[finger];
 
        /*
         * Once we've accumulated at least SYN_HIST_SIZE values, combine
@@ -1156,7 +1358,7 @@
         * Using a rolling average helps to filter out jitter caused by
         * tiny finger movements.
         */
-       if (sc->movement_history >= SYN_HIST_SIZE) {
+       if (sc->movement_history[finger] >= SYN_HIST_SIZE) {
                a = (history[(count + 0) % SYN_HIST_SIZE] +
                    history[(count + 1) % SYN_HIST_SIZE]) / 2;
 
@@ -1248,15 +1450,17 @@
 
 static inline void
 synaptics_movement(struct synaptics_softc *sc, struct synaptics_packet *sp,
-    int *dxp, int *dyp)
+    int finger, int *dxp, int *dyp)
 {
        int dx, dy, edge;
 
        /*
         * Compute the next values of dx and dy
         */
-       dx = synaptics_filter_policy(sc, sc->history_x, sp->sp_x);
-       dy = synaptics_filter_policy(sc, sc->history_y, sp->sp_y);
+       dx = synaptics_filter_policy(sc, finger, sc->history_x[finger],
+               sp->sp_x);
+       dy = synaptics_filter_policy(sc, finger, sc->history_y[finger],
+               sp->sp_y);
 
        /*
         * If we're dealing with a drag gesture, and the finger moves to
@@ -1279,8 +1483,8 @@
        /*
         * Apply scaling to both deltas
         */
-       dx = synaptics_scale(dx, synaptics_scale_x, &sc->rem_x);
-       dy = synaptics_scale(dy, synaptics_scale_y, &sc->rem_y);
+       dx = synaptics_scale(dx, synaptics_scale_x, &sc->rem_x[finger]);
+       dy = synaptics_scale(dy, synaptics_scale_y, &sc->rem_y[finger]);
 
        /*
         * Clamp deltas to specified maximums.
@@ -1293,7 +1497,7 @@
        *dxp = dx;
        *dyp = dy;
 
-       sc->movement_history++;
+       sc->movement_history[finger]++;
 }
 
 static void
@@ -1343,9 +1547,10 @@
        fingers = synaptics_finger_detect(sc, sp, &palm);
 
        /*
-        * Do gesture processing only if we didn't detect a palm.
+        * Do gesture processing only if we didn't detect a palm and
+        * it is not the seondary finger.
         */
-       if (palm == 0)
+       if ((sp->sp_finger == 0) && (palm == 0))
                synaptics_gesture_detect(sc, sp, fingers);
        else
                sc->gesture_type = sc->gesture_buttons = 0;
@@ -1362,19 +1567,29 @@
        psc->buttons ^= changed;
 
        sc->prev_fingers = fingers;
-       sc->total_packets++;
+       sc->total_packets[sp->sp_finger]++;
 
        /*
-        * Do movement processing IFF we have a single finger and no palm.
+        * Do movement processing IFF we have a single finger and no palm or
+        * a secondary finger and no palm.
         */
-       if (fingers == 1 && palm == 0)
-               synaptics_movement(sc, sp, &dx, &dy);
-       else {
+       if (palm == 0) {
+               if (fingers == 1) {
+                       synaptics_movement(sc, sp, sp->sp_finger, &dx, &dy);
+               } else {
+                       /*
+                        * No valid finger. Therefore no movement.
+                        */
+                       sc->movement_history[sp->sp_finger] = 0;
+                       sc->rem_x[sp->sp_finger] = sc->rem_y[sp->sp_finger] = 0;
+                       dx = dy = 0;
+               }
+       } else {
                /*
                 * No valid finger. Therefore no movement.
                 */
-               sc->movement_history = 0;
-               sc->rem_x = sc->rem_y = 0;
+               sc->movement_history[0] = 0;
+               sc->rem_x[0] = sc->rem_y[0] = 0;
                dx = dy = 0;
        }
 
Index: synapticsreg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pckbport/synapticsreg.h,v
retrieving revision 1.8
diff -u -r1.8 synapticsreg.h
--- synapticsreg.h      23 May 2014 01:11:29 -0000      1.8
+++ synapticsreg.h      24 Oct 2017 08:25:47 -0000
@@ -69,6 +69,7 @@
 #define        SYNAPTICS_MODE_ABSOLUTE         (1 << 7)
 #define        SYNAPTICS_MODE_RATE             (1 << 6)
 #define        SYNAPTICS_MODE_SLEEP            (1 << 3)
+#define        SYNAPTICS_MODE_EXTENDED_W       (1 << 2) /* double meaning */
 #define        SYNAPTICS_MODE_GEST             (1 << 2)
 #define        SYNAPTICS_MODE_4BYTE_CLIENT     (1 << 1)
 #define        SYNAPTICS_MODE_W                (1)
@@ -97,6 +98,7 @@
 #define        SYNAPTICS_WIDTH_TWO_FINGERS     0
 #define        SYNAPTICS_WIDTH_THREE_OR_MORE   1
 #define        SYNAPTICS_WIDTH_PEN             2
+#define        SYNAPTICS_WIDTH_EXTENDED_W      2
 #define        SYNAPTICS_WIDTH_ADVANCEDGESTURE 2
 #define        SYNAPTICS_WIDTH_PASSTHROUGH     3
 #define        SYNAPTICS_WIDTH_FINGER_MIN      4
@@ -106,4 +108,9 @@
 #define        SYNAPTICS_WIDTH_PALM_MAX        14
 #define        SYNAPTICS_WIDTH_MAX             15
 
+/* Extended W types */
+#define SYNAPTICS_EW_WHEEL             0
+#define SYNAPTICS_EW_SECONDARY_FINGER  1
+#define SYNAPTICS_EW_FINGER_STATUS     2
+
 #endif /* _DEV_PCKBCPORT_SYNAPTICSREG_H_ */
Index: synapticsvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pckbport/synapticsvar.h,v
retrieving revision 1.6
diff -u -r1.6 synapticsvar.h
--- synapticsvar.h      23 May 2014 01:11:29 -0000      1.6
+++ synapticsvar.h      24 Oct 2017 08:25:47 -0000
@@ -55,10 +55,10 @@
 #define        SYN_FLAG_HAS_TWO_BUTTON_CLICKPAD        (1 << 10)
 #define        SYN_FLAG_HAS_EXTENDED_WMODE             (1 << 11)
 
-       u_int   total_packets;          /* Total number of packets received */
-#define        SYN_TIME(sc,c)  (((sc)->total_packets >= (c)) ?         \
-                           ((sc)->total_packets - (c)) :       \
-                           ((c) - (sc)->total_packets))
+       u_int   total_packets[2];       /* Total number of packets received */
+#define        SYN_TIME(sc,c,n)        (((sc)->total_packets[(n)] >= (c)) ?    
\
+                               ((sc)->total_packets[(n)] - (c)) :      \
+                               ((c) - (sc)->total_packets[(n)]))
 
        int     up_down;
        int     prev_fingers;
@@ -78,9 +78,10 @@
 #define        SYN_IS_DRAG(t)          ((t) & SYN_GESTURE_DRAG)
 
 #define        SYN_HIST_SIZE   4
-       int     rem_x, rem_y;
-       u_int   movement_history;
-       int     history_x[SYN_HIST_SIZE], history_y[SYN_HIST_SIZE];
+       char    button_history;
+       int     rem_x[2], rem_y[2];
+       u_int   movement_history[2];
+       int     history_x[2][SYN_HIST_SIZE], history_y[2][SYN_HIST_SIZE];
 };
 
 int pms_synaptics_probe_init(void *vsc);




-- 
Brett Lymn
Let go, or be dragged - Zen proverb.

Reply via email to