On 31/01/12(Tue) 16:52, Martin Pieuchot wrote:
> Diff below add support for the missing ALPS Dualpoint touchpads to the
> pms(4) driver. Most of the work has been done by shadchin@ and should
> fix issues you may have seen since pms(4) supports others ALPS devices
> (2011/10).
> 
> It adds support for a slightly different version of the ALPS protocol,
> which send 'interleaved' PS2 packets in between absolute ALPS packets.
> Dell laptops (E6xxx and E5500 at least) have this kind of touchpad.
> 
> You may have notice the problem if you see "pms0: not in sync yet" as
> soon as you move your clitpad.
> 
> Please report any breakage to shadchin@ and myself.

I've got only two reports, nobody has a Dell E6x00, E5500 or Precision
M4400?

Any breakage with your already supported synaptics/alps/psm pointer?

Martin


Index: pms.c
===================================================================
RCS file: /cvs/src/sys/dev/pckbc/pms.c,v
retrieving revision 1.27
diff -u -p -r1.27 pms.c
--- pms.c       28 Jan 2012 21:00:48 -0000      1.27
+++ pms.c       30 Jan 2012 10:41:36 -0000
@@ -87,6 +87,11 @@ struct synaptics_softc {
 
 struct alps_softc {
        int model;
+#define ALPS_GLIDEPOINT                (1 << 1)
+#define ALPS_DUALPOINT         (1 << 2)
+#define ALPS_PASSTHROUGH       (1 << 3)
+#define ALPS_INTERLEAVED       (1 << 4)
+
        int mask;
        int version;
 
@@ -94,6 +99,8 @@ struct alps_softc {
        int max_x, max_y;
        int old_fin;
 
+       u_int sec_buttons;      /* trackpoint */
+
        /* Compat mode */
        int wsmode;
        int old_x, old_y;
@@ -145,18 +152,15 @@ static const struct alps_model {
        int mask;
        int model;
 } alps_models[] = {
-#if 0
-       /* FIXME some clipads are not working yet */
-       { 0x5212, 0xff, ALPS_DUALPOINT | ALPS_PASSTHROUGH },
-       { 0x6222, 0xcf, ALPS_DUALPOINT | ALPS_PASSTHROUGH },
-#endif
        { 0x2021, 0xf8, ALPS_DUALPOINT | ALPS_PASSTHROUGH },
        { 0x2221, 0xf8, ALPS_DUALPOINT | ALPS_PASSTHROUGH },
        { 0x2222, 0xff, ALPS_DUALPOINT | ALPS_PASSTHROUGH },
        { 0x3222, 0xf8, ALPS_DUALPOINT | ALPS_PASSTHROUGH },
+       { 0x5212, 0xff, ALPS_DUALPOINT | ALPS_PASSTHROUGH | ALPS_INTERLEAVED },
        { 0x5321, 0xf8, ALPS_GLIDEPOINT },
        { 0x5322, 0xf8, ALPS_GLIDEPOINT },
        { 0x603b, 0xf8, ALPS_GLIDEPOINT },
+       { 0x6222, 0xcf, ALPS_DUALPOINT | ALPS_PASSTHROUGH | ALPS_INTERLEAVED },
        { 0x6321, 0xf8, ALPS_GLIDEPOINT },
        { 0x6322, 0xf8, ALPS_GLIDEPOINT },
        { 0x6323, 0xf8, ALPS_GLIDEPOINT },
@@ -228,6 +232,7 @@ int synaptics_query(struct pms_softc *, 
 int    synaptics_get_hwinfo(struct pms_softc *);
 void   synaptics_sec_proc(struct pms_softc *);
 
+int    alps_sec_proc(struct pms_softc *);
 int    alps_get_hwinfo(struct pms_softc *);
 
 struct cfattach pms_ca = {
@@ -726,6 +731,7 @@ pmsinput(void *vsc, int data)
                return;
        }
 
+       sc->packet[sc->inputstate] = data;
        if (sc->protocol->sync(sc, data)) {
 #ifdef DIAGNOSTIC
                printf("%s: not in sync yet, discard input\n", DEVNAME(sc));
@@ -734,13 +740,13 @@ pmsinput(void *vsc, int data)
                return;
        }
 
-       sc->packet[sc->inputstate++] = data;
+       sc->inputstate++;
 
        if (sc->inputstate != sc->protocol->packetsize)
                return;
 
-       sc->protocol->proc(sc);
        sc->inputstate = 0;
+       sc->protocol->proc(sc);
 }
 
 int
@@ -1050,6 +1056,40 @@ pms_disable_synaptics(struct pms_softc *
 }
 
 int
+alps_sec_proc(struct pms_softc *sc)
+{
+       struct alps_softc *alps = sc->alps;
+       int dx, dy, pos = 0;
+
+       if ((sc->packet[0] & PMS_ALPS_PS2_MASK) == PMS_ALPS_PS2_VALID) {
+               /*
+                * We need to keep buttons states because interleaved
+                * packets only signalize x/y movements.
+                */
+               alps->sec_buttons = butmap[sc->packet[0] & PMS_PS2_BUTTONSMASK];
+       } else if ((sc->packet[3] & PMS_ALPS_INTERLEAVED_MASK) ==
+           PMS_ALPS_INTERLEAVED_VALID) {
+               sc->inputstate = 3;
+               pos = 3;
+       } else {
+               return (0);
+       }
+
+       if ((sc->sc_dev_enable & PMS_DEV_SECONDARY) == 0)
+               return (1);
+
+       dx = (sc->packet[pos] & PMS_PS2_XNEG) ?
+           (int)sc->packet[pos + 1] - 256 : sc->packet[pos + 1];
+       dy = (sc->packet[pos] & PMS_PS2_YNEG) ?
+           (int)sc->packet[pos + 2] - 256 : sc->packet[pos + 2];
+
+       wsmouse_input(sc->sc_sec_wsmousedev, alps->sec_buttons,
+           dx, dy, 0, 0, WSMOUSE_INPUT_DELTA);
+
+       return (1);
+}
+
+int
 alps_get_hwinfo(struct pms_softc *sc)
 {
        struct alps_softc *alps = sc->alps;
@@ -1161,6 +1201,8 @@ pms_enable_alps(struct pms_softc *sc)
                goto err;
        }
 
+       alps->sec_buttons = 0;
+
        return (1);
 
 err:
@@ -1205,6 +1247,13 @@ pms_sync_alps(struct pms_softc *sc, int 
 {
        struct alps_softc *alps = sc->alps;
 
+       if ((alps->model & ALPS_DUALPOINT) &&
+           (sc->packet[0] & PMS_ALPS_PS2_MASK) == PMS_ALPS_PS2_VALID) {
+               if (sc->inputstate == 2)
+                       sc->inputstate += 3;
+               return (0);
+       }
+
        switch (sc->inputstate) {
        case 0:
                if ((data & alps->mask) != alps->mask)
@@ -1213,9 +1262,13 @@ pms_sync_alps(struct pms_softc *sc, int 
        case 1:
        case 2:
        case 3:
+               if ((data & PMS_ALPS_MASK) != PMS_ALPS_VALID)
+                       return (-1);
+               break;
        case 4:
        case 5:
-               if ((data & 0x80) != 0)
+               if ((alps->model & ALPS_INTERLEAVED) == 0 &&
+                   (data & PMS_ALPS_MASK) != PMS_ALPS_VALID)
                        return (-1);
                break;
        }
@@ -1230,6 +1283,9 @@ pms_proc_alps(struct pms_softc *sc)
        int x, y, z, dx, dy;
        u_int buttons;
        int fin, ges;
+
+       if ((alps->model & ALPS_DUALPOINT) && alps_sec_proc(sc))
+               return;
 
        x = sc->packet[1] | ((sc->packet[2] & 0x78) << 4);
        y = sc->packet[4] | ((sc->packet[3] & 0x70) << 3);
Index: pmsreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pckbc/pmsreg.h,v
retrieving revision 1.6
diff -u -p -r1.6 pmsreg.h
--- pmsreg.h    3 Dec 2011 19:43:00 -0000       1.6
+++ pmsreg.h    30 Jan 2012 10:42:39 -0000
@@ -42,6 +42,21 @@
 #define PMS_ALPS_MAGIC3_1      10
 #define PMS_ALPS_MAGIC3_2      100
 
+/*
+ * Checking for almost-standard PS/2 packet
+ * Note: ALPS devices never signal overflow condition
+ */
+#define PMS_ALPS_PS2_MASK                      0xc8
+#define PMS_ALPS_PS2_VALID                     0x08
+
+/* Checking for interleaved packet */
+#define PMS_ALPS_INTERLEAVED_MASK              0xcf
+#define PMS_ALPS_INTERLEAVED_VALID             0x0f
+
+/* Checking for non first byte */
+#define PMS_ALPS_MASK                          0x80
+#define PMS_ALPS_VALID                         0x00
+
 /* Synaptics queries */
 #define SYNAPTICS_QUE_IDENTIFY                 0x00
 #define SYNAPTICS_QUE_MODES                    0x01
@@ -92,10 +107,6 @@
 #define SYNAPTICS_MODEL_PEN                    (1 << 6)
 #define SYNAPTICS_MODEL_SIMPLC                 (1 << 5)
 #define SYNAPTICS_MODEL_GEOMETRY(m)            ((m) & 0x0f)
-
-#define ALPS_GLIDEPOINT                                (1 << 1)
-#define ALPS_DUALPOINT                         (1 << 2)
-#define ALPS_PASSTHROUGH                       (1 << 3)
 
 /* Resolutions */
 #define SYNAPTICS_RESOLUTION_X(r)              (((r) >> 16) & 0xff)

Reply via email to