NetBSD-Bugs archive

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

kern/42853: Synaptics touchpad driver breaks passthrough device (ie, trackpoint)



>Number:         42853
>Category:       kern
>Synopsis:       Synaptics touchpad driver breaks passthrough device (ie, 
>trackpoint)
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Feb 20 18:10:00 +0000 2010
>Originator:     Rafal Boni
>Release:        NetBSD 5.99.24 (2010/02/18 15:25:28 -0500)
>Organization:
TNF
>Environment:
        
        
System: NetBSD plasmodium 5.99.24 NetBSD 5.99.24 (MONOLITHIC_DRM) #19: Sat Feb 
20 11:11:03 EST 2010  
rafal@puck:/extra/i386/obj/sys/arch/i386/compile/MONOLITHIC_DRM i386
Architecture: i386 / x86_64
Machine: i386 / amd64
>Description:
        The synaptics driver apparently confuses the attached 'passthrough'
        device i.e., the trackpoint on my T4x during the capability probe
        sequence, resulting in a working touchpad but non-working trackpoint.

>How-To-Repeat:
        Boot -current on a Thinkpad T4x, wonder why the trackpoint doesn't
        work when it does in Windows.
>Fix:
        Resetting the device first think during attach seems to do the
        trick.  Included in the change is a sysctl knob for disabling
        the passthrough device for those who saw this as a 'feature'.
        
        Note that I've also changed the 'pms_synaptics_send_command'
        function to follow the strict(er) protocol followed by e.g.
        the Linux drivers, that is sending the PMS_SET_SCALE11 command
        before the 'sliced' command.  This didn't affect functionality
        but seemed The Right Thing(tm) to do.

diff --git a/sys/dev/pckbport/synaptics.c b/sys/dev/pckbport/synaptics.c
index 6712973..a022907 100644
--- a/sys/dev/pckbport/synaptics.c
+++ b/sys/dev/pckbport/synaptics.c
@@ -111,6 +111,7 @@ static int synaptics_scale_y = 16;
 static int synaptics_max_speed_x = 32;
 static int synaptics_max_speed_y = 32;
 static int synaptics_movement_threshold = 4;
+static int synaptics_passthrough_enable = 1;
 
 /* Sysctl nodes. */
 static int synaptics_up_down_emul_nodenum;
@@ -241,6 +242,10 @@ pms_synaptics_probe_init(void *vsc)
                const char comma[] = ", ";
                const char *sep = "";
                aprint_normal_dev(psc->sc_dev, "");
+               if (sc->flags & SYN_FLAG_HAS_PASSTHROUGH) {
+                       aprint_normal("%sPassthrough", sep);
+                       sep = comma;
+               }
                if (sc->flags & SYN_FLAG_HAS_MIDDLE_BUTTON) {
                        aprint_normal("%sMiddle button", sep);
                        sep = comma;
@@ -276,9 +281,19 @@ pms_synaptics_enable(void *vsc)
 {
        struct pms_softc *psc = vsc;
        struct synaptics_softc *sc = &psc->u.synaptics;
-       u_char cmd[2];
+       u_char cmd[2], resp[2] = { 0,0 };
        int res;
 
+       if (sc->flags & SYN_FLAG_HAS_PASSTHROUGH) {
+           /* 
+            * 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);
+       }
+
        /*
         * Enable Absolute mode with W (width) reporting, and set
         * the packet rate to maximum (80 packets per second).
@@ -286,7 +301,7 @@ pms_synaptics_enable(void *vsc)
        res = pms_synaptics_send_command(psc->sc_kbctag, psc->sc_kbcslot,
            SYNAPTICS_MODE_ABSOLUTE | SYNAPTICS_MODE_W | SYNAPTICS_MODE_RATE);
        cmd[0] = PMS_SET_SAMPLE;
-       cmd[1] = 0x14; /* doit */
+       cmd[1] = SYNAPTICS_CMD_SET_MODE2; /* doit */
        res |= pckbport_enqueue_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 2, 0,
            1, NULL);
        sc->up_down = 0;
@@ -541,6 +556,17 @@ pms_sysctl_synaptics(struct sysctllog **clog)
                goto err;
 
        synaptics_movement_threshold_nodenum = node->sysctl_num;
+
+       if ((rc = sysctl_createv(clog, 0, NULL, &node,
+           CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
+           CTLTYPE_INT, "passthrough_enable",
+           SYSCTL_DESCR("Enable/disable passthrough port"),
+           NULL, 0, 
+           &synaptics_passthrough_enable,
+           0, CTL_HW, root_num, CTL_CREATE,
+           CTL_EOL)) != 0)
+               goto err;
+
        return;
 
 err:
@@ -616,13 +642,16 @@ pms_synaptics_send_command(pckbport_tag_t tag, 
pckbport_slot_t slot,
        u_char cmd[2];
        int res;
 
+       cmd[0] = PMS_SET_SCALE11;
+       res = pckbport_poll_cmd(tag, slot, cmd, 1, 0, NULL, 0);
+
        /*
         * Need to send 4 Set Resolution commands, with the argument
         * encoded in the bottom most 2 bits.
         */
        cmd[0] = PMS_SET_RES;
        cmd[1] = syn_cmd >> 6;
-       res = pckbport_poll_cmd(tag, slot, cmd, 2, 0, NULL, 0);
+       res |= pckbport_poll_cmd(tag, slot, cmd, 2, 0, NULL, 0);
 
        cmd[0] = PMS_SET_RES;
        cmd[1] = (syn_cmd & 0x30) >> 4;
@@ -710,6 +739,9 @@ pms_synaptics_passthrough(struct pms_softc *psc)
        int buttons, changed;
        int s;
 
+       if (!synaptics_passthrough_enable)
+               return;
+
        buttons = ((psc->packet[1] & PMS_LBUTMASK) ? 0x20 : 0) |
                ((psc->packet[1] & PMS_MBUTMASK) ? 0x40 : 0) |
                ((psc->packet[1] & PMS_RBUTMASK) ? 0x80 : 0);
diff --git a/sys/dev/pckbport/synapticsreg.h b/sys/dev/pckbport/synapticsreg.h
index c9c5d6e..a31c47d 100644
--- a/sys/dev/pckbport/synapticsreg.h
+++ b/sys/dev/pckbport/synapticsreg.h
@@ -45,6 +45,10 @@
 #define SYNAPTICS_READ_MODEL_ID                0x3
 #define SYNAPTICS_EXTENDED_QUERY       0x9
 
+/* Synaptics special commands */
+#define SYNAPTICS_CMD_SET_MODE2                0x14
+#define SYNAPTICS_CMD_CLIENT_CMD       0x28
+
 /* Magic numbers. */
 #define SYNAPTICS_MIN_VERSION          45 /* 4.5 */
 #define SYNAPTICS_MAGIC_BYTE           0x47
@@ -64,6 +68,7 @@
 #define SYNAPTICS_MODE_RATE            (1 << 6)
 #define SYNAPTICS_MODE_SLEEP           (1 << 3)
 #define SYNAPTICS_MODE_GEST            (1 << 2)
+#define SYNAPTICS_MODE_4BYTE_CLIENT     (1 << 1)
 #define SYNAPTICS_MODE_W               (1)
 
 /* Extended mode button masks. */



Home | Main Index | Thread Index | Old Index