Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pckbport Significant update to the synaptics touchpa...



details:   https://anonhg.NetBSD.org/src/rev/e9431105a64a
branches:  trunk
changeset: 989946:e9431105a64a
user:      blymn <blymn%NetBSD.org@localhost>
date:      Thu Oct 21 04:49:28 2021 +0000

description:
Significant update to the synaptics touchpad driver.

* Accumulate packets for primary, secondary, finger count packets
  before handing off to pms_synaptics_process_packet.  This means
  that both primary and, possibly, secondary finger locations will
  be processed at the same time.  Previously the processing each
  packet as it arrived.

* Fix the secondary finger position reporting, there was an off by
  one in the shifts when decoding which effectively halved the
  reported position.

* For a clickpad, make the emulated button region "dead" so that finger
  movements in this region are ignored.  This makes it easier to click
  a button without accidentally repositioning the cursor.  There is a
  sysctl variable "button_region_movement_enable" that will allow
  these finger movements to be reported if this is desirable.

* Reset the finger ballistics when the number of fingers changes.  This
  stops the annoying position jumps when a second finger touch is added
  to or removed from the touchpad.

* Add a level argument to the DPRINTF macro so one can choose their
  level of debug spam via the debug sysctl variable.

diffstat:

 sys/dev/pckbport/synaptics.c    |  606 ++++++++++++++++++++++++++++++++-------
 sys/dev/pckbport/synapticsvar.h |   16 +-
 2 files changed, 496 insertions(+), 126 deletions(-)

diffs (truncated from 980 to 300 lines):

diff -r 9f09205bb840 -r e9431105a64a sys/dev/pckbport/synaptics.c
--- a/sys/dev/pckbport/synaptics.c      Thu Oct 21 04:47:57 2021 +0000
+++ b/sys/dev/pckbport/synaptics.c      Thu Oct 21 04:49:28 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: synaptics.c,v 1.72 2021/09/28 06:16:13 nia Exp $       */
+/*     $NetBSD: synaptics.c,v 1.73 2021/10/21 04:49:28 blymn Exp $     */
 
 /*
  * Copyright (c) 2005, Steve C. Woodford
@@ -48,7 +48,7 @@
 #include "opt_pms.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: synaptics.c,v 1.72 2021/09/28 06:16:13 nia Exp $");
+__KERNEL_RCSID(0, "$NetBSD: synaptics.c,v 1.73 2021/10/21 04:49:28 blymn Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -79,11 +79,14 @@
        signed short    sp_x;   /* Unscaled absolute X/Y coordinates */
        signed short    sp_y;
        u_char  sp_z;           /* Z (pressure) */
+       signed short    sp_sx;  /* Unscaled absolute X/Y coordinates */
+       signed short    sp_sy;  /* for secondary finger */
+       u_char  sp_sz;          /* 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 */
+       u_char  sp_primary;     /* seen primary finger packet */
+       u_char  sp_secondary;   /* seen secondary finger packet */
+       u_char  sp_finger_status; /* seen extended finger packet */
+       u_char  sp_finger_count; /* number of fingers seen */
        char    sp_left;        /* Left mouse button status */
        char    sp_right;       /* Right mouse button status */
        char    sp_middle;      /* Middle button status (possibly emulated) */
@@ -121,12 +124,13 @@
 static int synaptics_max_speed_z = 2;
 static int synaptics_movement_threshold = 4;
 static int synaptics_movement_enable = 1;
+static int synaptics_button_region_movement = 1;
 static bool synaptics_aux_mid_button_scroll = TRUE;
 static int synaptics_debug = 0;
 
-#define        DPRINTF(SC, FMT, ARGS...) do                                          \
+#define        DPRINTF(LEVEL, SC, FMT, ARGS...) do                                           \
 {                                                                            \
-       if (synaptics_debug) {                                                \
+       if (synaptics_debug >= LEVEL) {                                               \
                struct pms_softc *_dprintf_psc =                              \
                    container_of((SC), struct pms_softc, u.synaptics);        \
                device_printf(_dprintf_psc->sc_dev, FMT, ##ARGS);             \
@@ -157,8 +161,16 @@
 static int synaptics_max_speed_z_nodenum;
 static int synaptics_movement_threshold_nodenum;
 static int synaptics_movement_enable_nodenum;
+static int synaptics_button_region_movement_nodenum;
 static int synaptics_aux_mid_button_scroll_nodenum;
 
+/*
+ * This holds the processed packet data, it is global because multiple
+ * packets from the trackpad may be processed when handling multiple
+ * fingers on the trackpad to gather all the data.
+ */
+static struct synaptics_packet packet;
+
 static int
 synaptics_poll_cmd(struct pms_softc *psc, ...)
 {
@@ -490,6 +502,10 @@
            (sc->flags & SYN_FLAG_HAS_ADV_GESTURE_MODE))
                synaptics_special_write(psc, SYNAPTICS_WRITE_DELUXE_3, 0x3); 
 
+       /* Disable motion in the button region for clickpads */
+       if(sc->flags & SYN_FLAG_HAS_ONE_BUTTON_CLICKPAD)
+               synaptics_button_region_movement = 0;
+
        sc->up_down = 0;
        sc->prev_fingers = 0;
        sc->gesture_start_x = sc->gesture_start_y = 0;
@@ -497,11 +513,14 @@
        sc->gesture_tap_packet = 0;
        sc->gesture_type = 0;
        sc->gesture_buttons = 0;
+       sc->total_packets = 0;
        for (i = 0; i < SYN_MAX_FINGERS; i++) {
                sc->rem_x[i] = sc->rem_y[i] = sc->rem_z[i] = 0;
-               sc->movement_history[i] = 0;
        }
        sc->button_history = 0;
+
+       /* clear the packet decode structure */
+       memset(&packet, 0, sizeof(packet));
 }
 
 void
@@ -766,6 +785,18 @@
 
        if ((rc = sysctl_createv(clog, 0, NULL, &node,
            CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
+           CTLTYPE_INT, "button_region_movement_enable",
+           SYSCTL_DESCR("Enable movement within clickpad button region"),
+           pms_sysctl_synaptics_verify, 0,
+           &synaptics_button_region_movement,
+           0, CTL_HW, root_num, CTL_CREATE,
+           CTL_EOL)) != 0)
+               goto err;
+
+       synaptics_button_region_movement_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,
@@ -904,6 +935,10 @@
                if (t < 0 || t > 1)
                        return (EINVAL);
        } else
+       if (node.sysctl_num == synaptics_button_region_movement_nodenum) {
+               if (t < 0 || t > 1)
+                       return (EINVAL);
+       } else
        if (node.sysctl_num == synaptics_aux_mid_button_scroll_nodenum) {
                if (t < 0 || t > 1)
                        return (EINVAL);
@@ -915,6 +950,75 @@
        return (0);
 }
 
+/*
+ * Extract the number of fingers from the current packet and return
+ * it to the caller.
+ */
+static unsigned
+pms_synaptics_get_fingers(struct pms_softc *psc, u_char w, short z)
+{
+       struct synaptics_softc *sc = &psc->u.synaptics;
+       unsigned short ew_mode;
+       unsigned fingers;
+
+       fingers = 0;
+
+
+       /*
+        * If w is zero and z says no fingers then return
+        * no fingers, w == can also mean 2 fingers... confusing.
+        */
+       if (w == 0 && z == SYNAPTICS_FINGER_NONE)
+               return 0;
+
+       if ((sc->flags & SYN_FLAG_HAS_EXTENDED_WMODE) &&
+           (w == SYNAPTICS_WIDTH_EXTENDED_W)) {
+               ew_mode = psc->packet[5] >> 4;
+               switch (ew_mode)
+               {
+               case SYNAPTICS_EW_WHEEL:
+                       break;
+
+               case SYNAPTICS_EW_SECONDARY_FINGER:
+                       /* to get here we must have 2 fingers at least */
+                       fingers = 2;
+                       break;
+
+               case SYNAPTICS_EW_FINGER_STATUS:
+                       fingers = psc->packet[1] & 0x0f;
+                       break;
+
+               default:
+                       aprint_error_dev(psc->sc_dev,
+                           "invalid extended w mode %d\n",
+                           ew_mode);
+                       return 0; /* pretend there are no fingers */
+               }
+       } else {
+
+               fingers = 1;
+
+               /*
+                * If SYN_FLAG_HAS_MULTI_FINGER is set then check
+                * sp_w is below SYNAPTICS_WIDTH_FINGER_MIN, if it is
+                * then this will be the finger count.
+                *
+                * There are a couple of "special" values otherwise
+                * just punt with one finger, if this really is a palm
+                * then it will be caught later.
+                */
+               if (sc->flags & SYN_FLAG_HAS_MULTI_FINGER) {
+                       if (w == SYNAPTICS_WIDTH_TWO_FINGERS)
+                               fingers = 2;
+                       else if (w == SYNAPTICS_WIDTH_THREE_OR_MORE)
+                               fingers = 3;
+               }
+
+       }
+
+       return fingers;
+}
+
 /* Masks for the first byte of a packet */
 #define PMS_LBUTMASK 0x01
 #define PMS_RBUTMASK 0x02
@@ -924,18 +1028,24 @@
 pms_synaptics_parse(struct pms_softc *psc)
 {
        struct synaptics_softc *sc = &psc->u.synaptics;
-       struct synaptics_packet sp;
+       struct synaptics_packet nsp;
        char new_buttons, ew_mode;
+       unsigned v, primary_finger, secondary_finger;
 
-       memset(&sp, 0, sizeof(sp));
+       sc->total_packets++;
+
+       memcpy(&nsp, &packet, sizeof(packet));
 
        /* 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;
+       nsp.sp_w = ((psc->packet[0] & 0x30) >> 2)
+           + ((psc->packet[0] & 0x04) >> 1)
+           + ((psc->packet[3] & 0x04) >> 2);
+
+       v = 0;
+       primary_finger = 0;
+       secondary_finger = 0;
        if ((sc->flags & SYN_FLAG_HAS_EXTENDED_WMODE) &&
-           (sp.sp_w == SYNAPTICS_WIDTH_EXTENDED_W)) {
+           (nsp.sp_w == SYNAPTICS_WIDTH_EXTENDED_W)) {
                ew_mode = psc->packet[5] >> 4;
                switch (ew_mode)
                {
@@ -947,25 +1057,41 @@
                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);
+                       nsp.sp_secondary = 1;
+
+                       nsp.sp_sx = ((psc->packet[1] & 0xfe) << 1)
+                           + ((psc->packet[4] & 0x0f) << 9);
+                       nsp.sp_sy = ((psc->packet[2] & 0xfe) << 1)
+                           + ((psc->packet[4] & 0xf0) << 5);
+                       nsp.sp_sz = (psc->packet[3] & 0x30)
+                           + ((psc->packet[5] & 0x0e) << 1);
+
+                       /* work out the virtual finger width */
+                       v = 8 + (psc->packet[1] & 0x01) +
+                               ((psc->packet[2] & 0x01) << 1) +
+                               ((psc->packet[5] & 0x01) << 2);
 
                        /* 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;
+                       nsp.sp_left = sc->button_history & PMS_LBUTMASK;
+                       nsp.sp_middle = sc->button_history & PMS_MBUTMASK;
+                       nsp.sp_right = sc->button_history & PMS_RBUTMASK;
                        break;
 
                case SYNAPTICS_EW_FINGER_STATUS:
-                       /* reports which finger is primary/secondary
-                        * ignore for now.
+                       /* This works but what is it good for?
+                        * it gives us an index of the primary/secondary
+                        * fingers but no other packets pass this
+                        * index.
+                        *
+                        * XXX Park this, possibly handle a finger
+                        * XXX change if indexes change.
                         */
-                       return;
+                       primary_finger = psc->packet[2];
+                       secondary_finger = psc->packet[4];
+                       nsp.sp_finger_status = 1;
+                       nsp.sp_finger_count = pms_synaptics_get_fingers(psc,
+                           nsp.sp_w, nsp.sp_z);
+                       goto skip_position;
 
                default:
                        aprint_error_dev(psc->sc_dev,
@@ -974,15 +1100,73 @@
                        return;
                }
        } else {
+               nsp.sp_primary = 1;
 
-               /* 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) +



Home | Main Index | Thread Index | Old Index