Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pckbport Add two finger support and middle/right but...



details:   https://anonhg.NetBSD.org/src/rev/66a4b7f3b802
branches:  trunk
changeset: 827648:66a4b7f3b802
user:      blymn <blymn%NetBSD.org@localhost>
date:      Mon Nov 06 21:07:17 2017 +0000

description:
Add two finger support and middle/right button emulation.

diffstat:

 sys/dev/pckbport/synaptics.c    |  439 +++++++++++++++++++++++++++++----------
 sys/dev/pckbport/synapticsreg.h |    9 +-
 sys/dev/pckbport/synapticsvar.h |   17 +-
 3 files changed, 336 insertions(+), 129 deletions(-)

diffs (truncated from 764 to 300 lines):

diff -r b76106aa1083 -r 66a4b7f3b802 sys/dev/pckbport/synaptics.c
--- a/sys/dev/pckbport/synaptics.c      Mon Nov 06 21:03:58 2017 +0000
+++ b/sys/dev/pckbport/synaptics.c      Mon Nov 06 21:07:17 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: synaptics.c,v 1.33 2015/03/04 22:58:35 christos Exp $  */
+/*     $NetBSD: synaptics.c,v 1.34 2017/11/06 21:07:17 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.33 2015/03/04 22:58:35 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: synaptics.c,v 1.34 2017/11/06 21:07:17 blymn Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -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;
@@ -131,11 +141,56 @@
 static int synaptics_max_speed_y_nodenum;
 static int synaptics_movement_threshold_nodenum;
 
+static int
+synaptics_poll_cmd(struct pms_softc *psc, ...)
+{
+       u_char cmd[4];
+       size_t i;
+       va_list ap;
+
+       va_start(ap, psc);
+
+       for (i = 0; i < __arraycount(cmd); i++)
+               if ((cmd[i] = (u_char)va_arg(ap, int)) == 0)
+                       break;
+       va_end(ap);
+
+       int res = pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, i, 0,
+           NULL, 0);
+       if (res)
+               aprint_error_dev(psc->sc_dev, "command error %#x\n", cmd[0]);
+       return res;
+}
+
+static int
+synaptics_poll_reset(struct pms_softc *psc)
+{
+       u_char resp[2];
+       int res;
+
+       u_char cmd[1] = { PMS_RESET };
+       res = pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 1, 2,
+           resp, 1);
+       aprint_debug_dev(psc->sc_dev, "reset %d 0x%02x 0x%02x\n",
+           res, resp[0], resp[1]);
+       return res;
+}
+
+static int
+synaptics_poll_status(struct pms_softc *psc, u_char slice, u_char resp[3])
+{
+       u_char cmd[1] = { PMS_SEND_DEV_STATUS };
+       int res = pms_sliced_command(psc->sc_kbctag, psc->sc_kbcslot, slice);
+
+       return res | pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot,
+           cmd, 1, 3, resp, 0);
+}
+
 static void
 pms_synaptics_probe_extended(struct pms_softc *psc)
 {
        struct synaptics_softc *sc = &psc->u.synaptics;
-       u_char cmd[1], resp[3];
+       u_char resp[3];
        int res;
 
        aprint_debug_dev(psc->sc_dev,
@@ -156,11 +211,7 @@
        if (((sc->caps & SYNAPTICS_CAP_EXTNUM) + 0x08)
            >= SYNAPTICS_EXTENDED_QUERY)
        {
-               res = pms_sliced_command(psc->sc_kbctag,
-                   psc->sc_kbcslot, SYNAPTICS_EXTENDED_QUERY);
-               cmd[0] = PMS_SEND_DEV_STATUS;
-               res |= pckbport_poll_cmd(psc->sc_kbctag,
-                   psc->sc_kbcslot, cmd, 1, 3, resp, 0);
+               res = synaptics_poll_status(psc, SYNAPTICS_EXTENDED_QUERY, resp);
                if (res == 0) {
                        int buttons = (resp[1] >> 4);
                        aprint_debug_dev(psc->sc_dev,
@@ -192,11 +243,9 @@
        if (((sc->caps & SYNAPTICS_CAP_EXTNUM) + 0x08) >=
            SYNAPTICS_CONTINUED_CAPABILITIES)
        {
-               res = pms_sliced_command(psc->sc_kbctag,
-                   psc->sc_kbcslot, SYNAPTICS_CONTINUED_CAPABILITIES);
-               cmd[0] = PMS_SEND_DEV_STATUS;
-               res |= pckbport_poll_cmd(psc->sc_kbctag,
-                   psc->sc_kbcslot, cmd, 1, 3, resp, 0);
+               res = synaptics_poll_status(psc,
+                   SYNAPTICS_CONTINUED_CAPABILITIES, resp);
+
 /*
  * The following describes response for the
  * SYNAPTICS_CONTINUED_CAPABILITIES query.
@@ -267,10 +316,7 @@
                 * Reset device in case the probe confused it.
                 */
  doreset:
-               cmd[0] = PMS_RESET;
-               (void) pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd,
-                   1, 2, resp, 1);
-               return (res);
+               return synaptics_poll_reset(psc);
        }
 
        if (resp[1] != SYNAPTICS_MAGIC_BYTE) {
@@ -293,12 +339,9 @@
                goto done;
        }
 
+
        /* Query the hardware capabilities. */
-       res = pms_sliced_command(psc->sc_kbctag, psc->sc_kbcslot,
-           SYNAPTICS_READ_CAPABILITIES);
-       cmd[0] = PMS_SEND_DEV_STATUS;
-       res |= pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 1, 3,
-           resp, 0);
+       res = synaptics_poll_status(psc, SYNAPTICS_READ_CAPABILITIES, resp);
        if (res) {
                /* Hmm, failed to get capabilites. */
                aprint_error_dev(psc->sc_dev,
@@ -385,7 +428,7 @@
 {
        struct pms_softc *psc = vsc;
        struct synaptics_softc *sc = &psc->u.synaptics;
-       u_char cmd[2], resp[2];
+       u_char enable_modes;
        int res;
 
        if (sc->flags & SYN_FLAG_HAS_PASSTHROUGH) {
@@ -393,21 +436,43 @@
                 * Extended capability probes can confuse the passthrough device;
                 * reset the touchpad now to cure that.
                 */
-               cmd[0] = PMS_RESET;
-               res = pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd,
-                   1, 2, resp, 1);
+               res = synaptics_poll_reset(psc);
        }
 
        /*
         * 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.
         */
+       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.
+       */
+       synaptics_poll_cmd(psc, PMS_DEV_DISABLE, 0);
+       /* a couple of set scales to clear out pending commands */
+       for (int i = 0; i < 2; i++)
+               synaptics_poll_cmd(psc, PMS_SET_SCALE11, 0);
+
        res = pms_sliced_command(psc->sc_kbctag, psc->sc_kbcslot,
-           SYNAPTICS_MODE_ABSOLUTE | SYNAPTICS_MODE_W | SYNAPTICS_MODE_RATE);
-       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);
+           enable_modes);
+       if (res)
+               aprint_error("synaptics: set mode error\n");
+
+       synaptics_poll_cmd(psc, PMS_SET_SAMPLE, SYNAPTICS_CMD_SET_MODE2, 0);
+       
+       /* a couple of set scales to clear out pending commands */
+       for (int i = 0; i < 2; i++)
+               synaptics_poll_cmd(psc, PMS_SET_SCALE11, 0);
+
+       synaptics_poll_cmd(psc, PMS_DEV_ENABLE, 0);
+
        sc->up_down = 0;
        sc->prev_fingers = 0;
        sc->gesture_start_x = sc->gesture_start_y = 0;
@@ -415,27 +480,17 @@
        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
 pms_synaptics_resume(void *vsc)
 {
-       struct pms_softc *psc = vsc;
-       unsigned char cmd[1],resp[2] = { 0,0 };
-       int res;
-
-       cmd[0] = PMS_RESET;
-       res = pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 1, 2,
-           resp, 1);
-       aprint_debug_dev(psc->sc_dev,
-           "pms_synaptics_resume: reset on resume %d 0x%02x 0x%02x\n",
-           res, resp[0], resp[1]);
+       (void)synaptics_poll_reset(vsc);
 }
 
 static void
@@ -655,6 +710,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;
 



Home | Main Index | Thread Index | Old Index