On Wed, Jun 15, 2011 at 09:11:43AM +0200, Matthieu Herrb wrote:
> Hi,
> 
> here are a set of patches being worked on to add native synaptics
> touch pad support to OpenBSD and Xenocara.
> 
> The xf86-input-synaptics driver itself is already committed and built
> in Xenocara.
> 
> http://xenocara.org/wscons_config.2.diff is a diff that uses the X
> hot-plug mechanism to configure you input drivers. It will setup
> the xf86-input-synaptics driver for you if you have one, together with
> a regular mouse driver that will handle any external PS/2 or USB mouse
> attached in addition. Touchscreens will also be auto-configured this
> way if one is detected.
> 
> This new code also takes care of the configuration of the keyboard
> layout from the wscons layout. Thus a second diff:
> http://xenocara.org/xf86-input-keyboard.diff removes that code from
> the keyboard driver.
> 
> To apply those patches:
> 
>     cd /usr/xenocara/xserver
>     patch -p0 -E < /path/to/wscons_config.2.diff
>     make -f Makefile.bsd-wrapper obj
>     make -f Makefile.bsd-wrapper build
>     cd /usr/xenocara/driver/xf86-input-keyboard
>     patch -p0 -E < /path/to/xf86-input-keyboard.diff
>     make -f Makefile.bsd-wrapper obj
>     make -f Makefile.bsd-wrapper build
> 
> Once X is ready, apply the kernel patch, and build a new kernel with
> the synaptics support in pms(4):
> http://xenocara.org/sys-synaptics.diff
> 
>     cd /sys
>     patch -p0 -E < /path/to/sys-synaptics.diff
> 
> the new kernel will detect your synaptics touch pad if any, and  X
> will be configured with the xf86-input-synaptics. Read the
> synaptics(4) manual page to discover all its features.
> 
> You can check how the input drivers were configured by running the
> command:
> 
>    xinput list
> 
> If you are configuring input devices manually in xorg,conf you need to
> add this to the ServerFlags section (but may be you should give a try
> at auto-configuration and remove your InputDevice sections all together):
> 
>     Section ServerFlags
>       Option "AutoAddDevices" "false"
>     EndSection
> 
> Please test, comment and report failures. Make sure to include
> /var/log/Xorg.0.log and dmesg outputs in your reports.
> 
> Thanks to Alexandr Shadchin (shadchin@) for his work on this driver and
> to all people who already tested these patches and suggested
> enhancements.
> 
> -- 
> Matthieu Herrb
> 

New sys-synaptics.diff (http://koba.devio.us/distfiles/synaptics.v2.diff)
* fix wrong detect clickpad
* fix ignore buttons if no fingers on touchpad
* if open directly /dev/wsmouseX, then remove this device from mux
  (close device - get back in mux)

Thanks all for your feedback.

-- 
Alexandr Shadchin

Index: dev/pckbc/pms.c
===================================================================
RCS file: /cvs/src/sys/dev/pckbc/pms.c,v
retrieving revision 1.18
diff -u -p -r1.18 pms.c
--- dev/pckbc/pms.c     3 Jan 2011 19:46:34 -0000       1.18
+++ dev/pckbc/pms.c     17 Jun 2011 19:18:55 -0000
@@ -28,6 +28,7 @@
 #include <sys/systm.h>
 #include <sys/device.h>
 #include <sys/ioctl.h>
+#include <sys/malloc.h>
 
 #include <machine/bus.h>
 
@@ -40,12 +41,15 @@
 
 #define DEVNAME(sc)    ((sc)->sc_dev.dv_xname)
 
+#define WSMOUSE_BUTTON(x)      (1 << ((x) - 1))
+
 struct pms_softc;
 
 struct pms_protocol {
        int type;
 #define PMS_STANDARD   0
 #define PMS_INTELLI    1
+#define PMS_SYNAPTICS  2
        u_int packetsize;
        int (*enable)(struct pms_softc *);
        int (*ioctl)(struct pms_softc *, u_long, caddr_t, int, struct proc *);
@@ -54,6 +58,29 @@ struct pms_protocol {
        void (*disable)(struct pms_softc *);
 };
 
+struct synaptics_softc {
+       int identify;
+       int capabilities, ext_capabilities;
+       int model, ext_model;
+       int resolution, dimension;
+
+       int mode;
+
+       int res_x, res_y;
+       int min_x, min_y;
+       int max_x, max_y;
+
+       /* Compat mode */
+       int wsmode;
+       int old_x, old_y;
+       u_int old_buttons;
+       int count;
+#define SYNAPTICS_SCALE                4
+#define SYNAPTICS_PRESSURE     30
+
+       int dev_pt_attach;
+};
+
 struct pms_softc {             /* driver status information */
        struct device sc_dev;
 
@@ -64,56 +91,48 @@ struct pms_softc {          /* driver status inf
 #define PMS_STATE_ENABLED      1
 #define PMS_STATE_SUSPENDED    2
 
+       int sc_dev_enable;
+#define PMS_DEV_IGNORE         0x00
+#define PMS_DEV_PRIMARY                0x01
+#define PMS_DEV_SECONDARY      0x02
+
        int poll;
        int inputstate;
+       int is_touchpad;
 
        const struct pms_protocol *protocol;
+       struct synaptics_softc *synaptics;
 
        u_char packet[8];
 
        struct device *sc_wsmousedev;
+       struct device *sc_pt_wsmousedev;
 };
 
-#define PMS_BUTTON1DOWN                0x0001  /* left */
-#define PMS_BUTTON2DOWN                0x0002  /* middle */
-#define PMS_BUTTON3DOWN                0x0004  /* right */
-
 static const u_int butmap[8] = {
        0,
-       PMS_BUTTON1DOWN,
-       PMS_BUTTON3DOWN,
-       PMS_BUTTON1DOWN | PMS_BUTTON3DOWN,
-       PMS_BUTTON2DOWN,
-       PMS_BUTTON1DOWN | PMS_BUTTON2DOWN,
-       PMS_BUTTON2DOWN | PMS_BUTTON3DOWN,
-       PMS_BUTTON1DOWN | PMS_BUTTON2DOWN | PMS_BUTTON3DOWN
+       WSMOUSE_BUTTON(1),
+       WSMOUSE_BUTTON(3),
+       WSMOUSE_BUTTON(1) | WSMOUSE_BUTTON(3),
+       WSMOUSE_BUTTON(2),
+       WSMOUSE_BUTTON(1) | WSMOUSE_BUTTON(2),
+       WSMOUSE_BUTTON(2) | WSMOUSE_BUTTON(3),
+       WSMOUSE_BUTTON(1) | WSMOUSE_BUTTON(2) | WSMOUSE_BUTTON(3)
 };
 
-/* PS/2 mouse data packet */
-#define PMS_PS2_BUTTONSMASK    0x07
-#define PMS_PS2_BUTTON1                0x01    /* left */
-#define PMS_PS2_BUTTON2                0x04    /* middle */
-#define PMS_PS2_BUTTON3                0x02    /* right */
-#define PMS_PS2_XNEG           0x10
-#define PMS_PS2_YNEG           0x20
-
-#define PMS_INTELLI_MAGIC1     200
-#define PMS_INTELLI_MAGIC2     100
-#define PMS_INTELLI_MAGIC3     80
-#define PMS_INTELLI_ID         0x03
-
 int    pmsprobe(struct device *, void *, void *);
 void   pmsattach(struct device *, struct device *, void *);
 int    pmsactivate(struct device *, int);
 
 void   pmsinput(void *, int);
 
-int    pms_change_state(struct pms_softc *, int);
+int    pms_change_state(struct pms_softc *, int, int);
 int    pms_ioctl(void *, u_long, caddr_t, int, struct proc *);
 int    pms_enable(void *);
 void   pms_disable(void *);
 
 int    pms_cmd(struct pms_softc *, u_char *, int, u_char *, int);
+int    pms_spec_cmd(struct pms_softc *, int);
 int    pms_get_devid(struct pms_softc *, u_char *);
 int    pms_get_status(struct pms_softc *, u_char *);
 int    pms_set_rate(struct pms_softc *, int);
@@ -129,6 +148,21 @@ int        pms_ioctl_mouse(struct pms_softc *, 
 int    pms_sync_mouse(struct pms_softc *, int);
 void   pms_proc_mouse(struct pms_softc *);
 
+int    pms_enable_synaptics(struct pms_softc *);
+int    pms_ioctl_synaptics(struct pms_softc *, u_long, caddr_t, int, struct 
proc *);
+int    pms_sync_synaptics(struct pms_softc *, int);
+void   pms_proc_synaptics(struct pms_softc *);
+void   pms_disable_synaptics(struct pms_softc *);
+
+int    synaptics_set_mode(struct pms_softc *, int);
+int    synaptics_query(struct pms_softc *, int, int *);
+
+void   synaptics_pt_proc(struct pms_softc *);
+
+int    synaptics_pt_ioctl(void *, u_long, caddr_t, int, struct proc *);
+int    synaptics_pt_enable(void *);
+void   synaptics_pt_disable(void *);
+
 struct cfattach pms_ca = {
        sizeof(struct pms_softc), pmsprobe, pmsattach, NULL,
        pmsactivate
@@ -144,6 +178,12 @@ const struct wsmouse_accessops pms_acces
        pms_disable,
 };
 
+const struct wsmouse_accessops synaptics_pt_accessops = {
+       synaptics_pt_enable,
+       synaptics_pt_ioctl,
+       synaptics_pt_disable,
+};
+
 const struct pms_protocol pms_mouse[] = {
        /* Generic PS/2 mouse */
        {
@@ -165,6 +205,18 @@ const struct pms_protocol pms_mouse[] = 
        }
 };
 
+const struct pms_protocol pms_touchpad[] = {
+       /* Synaptics touchpad */
+       {
+               PMS_SYNAPTICS, 6,
+               pms_enable_synaptics,
+               pms_ioctl_synaptics,
+               pms_sync_synaptics,
+               pms_proc_synaptics,
+               pms_disable_synaptics
+       }
+};
+
 int
 pms_cmd(struct pms_softc *sc, u_char *cmd, int len, u_char *resp, int resplen)
 {
@@ -178,6 +230,18 @@ pms_cmd(struct pms_softc *sc, u_char *cm
 }
 
 int
+pms_spec_cmd(struct pms_softc *sc, int cmd)
+{
+       if (pms_set_scaling(sc, 1) ||
+           pms_set_resolution(sc, (cmd >> 6) & 0x03) ||
+           pms_set_resolution(sc, (cmd >> 4) & 0x03) ||
+           pms_set_resolution(sc, (cmd >> 2) & 0x03) ||
+           pms_set_resolution(sc, (cmd >> 0) & 0x03))
+               return (-1);
+       return (0);
+}
+
+int
 pms_get_devid(struct pms_softc *sc, u_char *resp)
 {
        u_char cmd[1];
@@ -395,6 +459,7 @@ pmsattach(struct device *parent, struct 
        struct pms_softc *sc = (void *)self;
        struct pckbc_attach_args *pa = aux;
        struct wsmousedev_attach_args a;
+       int i;
 
        sc->sc_kbctag = pa->pa_tag;
 
@@ -414,11 +479,26 @@ pmsattach(struct device *parent, struct 
         */
        sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
 
-       /* no interrupts until enabled */
        sc->poll = 1;
-       pms_change_state(sc, PMS_STATE_ENABLED);
-       sc->poll = 1; /* XXX */
-       pms_change_state(sc, PMS_STATE_DISABLED);
+
+       sc->sc_dev_enable = 0;
+
+       /* init protocol as generic mouse */
+       sc->protocol = &pms_mouse[0];
+
+       /* try detect touchpad */
+       sc->is_touchpad = 0;
+       for (i = 0; i < nitems(pms_touchpad); i++) {
+               pms_reset(sc);
+               if (pms_touchpad[i].enable(sc)) {
+                       sc->protocol = &pms_touchpad[i];
+                       sc->is_touchpad = 1;
+                       break;
+               }
+       }
+
+       /* no interrupts until enabled */
+       pms_change_state(sc, PMS_STATE_DISABLED, PMS_DEV_IGNORE);
 }
 
 int
@@ -429,26 +509,47 @@ pmsactivate(struct device *self, int act
        switch (act) {
        case DVACT_SUSPEND:
                if (sc->sc_state == PMS_STATE_ENABLED)
-                       pms_change_state(sc, PMS_STATE_SUSPENDED);
+                       pms_change_state(sc, PMS_STATE_SUSPENDED,
+                           PMS_DEV_IGNORE);
                break;
        case DVACT_RESUME:
                if (sc->sc_state == PMS_STATE_SUSPENDED)
-                       pms_change_state(sc, PMS_STATE_ENABLED);
+                       pms_change_state(sc, PMS_STATE_ENABLED,
+                           PMS_DEV_IGNORE);
                break;
        }
        return (0);
 }
 
 int
-pms_change_state(struct pms_softc *sc, int newstate)
+pms_change_state(struct pms_softc *sc, int newstate, int dev)
 {
        int i;
 
+       if (dev != PMS_DEV_IGNORE) {
+               switch (newstate) {
+               case PMS_STATE_ENABLED:
+                       if (sc->sc_dev_enable & dev)
+                               return (EBUSY);
+
+                       sc->sc_dev_enable |= dev;
+
+                       if (sc->sc_state == PMS_STATE_ENABLED)
+                               return (0);
+
+                       break;
+               case PMS_STATE_DISABLED:
+                       sc->sc_dev_enable &= ~dev;
+
+                       if (sc->sc_dev_enable)
+                               return (0);
+
+                       break;
+               }
+       }
+
        switch (newstate) {
        case PMS_STATE_ENABLED:
-               if (sc->sc_state == PMS_STATE_ENABLED)
-                       return (EBUSY);
-
                sc->inputstate = 0;
 
                pckbc_slot_enable(sc->sc_kbctag, PCKBC_AUX_SLOT, 1);
@@ -458,10 +559,14 @@ pms_change_state(struct pms_softc *sc, i
 
                pms_reset(sc);
 
-               sc->protocol = &pms_mouse[0];
-               for (i = 1; i < nitems(pms_mouse); i++)
-                       if (pms_mouse[i].enable(sc))
-                               sc->protocol = &pms_mouse[i];
+               if (sc->is_touchpad) {
+                       sc->protocol->enable(sc);
+               } else {
+                       sc->protocol = &pms_mouse[0];
+                       for (i = 1; i < nitems(pms_mouse); i++)
+                               if (pms_mouse[i].enable(sc))
+                                       sc->protocol = &pms_mouse[i];
+               }
 
 #ifdef DEBUG
                printf("%s: protocol type %d\n", DEVNAME(sc), 
sc->protocol->type);
@@ -491,7 +596,7 @@ pms_enable(void *v)
 {
        struct pms_softc *sc = v;
 
-       return pms_change_state(sc, PMS_STATE_ENABLED);
+       return pms_change_state(sc, PMS_STATE_ENABLED, PMS_DEV_PRIMARY);
 }
 
 void
@@ -499,7 +604,7 @@ pms_disable(void *v)
 {
        struct pms_softc *sc = v;
 
-       pms_change_state(sc, PMS_STATE_DISABLED);
+       pms_change_state(sc, PMS_STATE_DISABLED, PMS_DEV_PRIMARY);
 }
 
 int
@@ -537,4 +642,313 @@ pmsinput(void *vsc, int data)
 
        sc->protocol->proc(sc);
        sc->inputstate = 0;
+}
+
+int
+synaptics_set_mode(struct pms_softc *sc, int mode)
+{
+       struct synaptics_softc *syn = sc->synaptics;
+
+       if (pms_spec_cmd(sc, mode) ||
+           pms_set_rate(sc, SYNAPTICS_CMD_SET_MODE))
+               return (-1);
+
+       syn->mode = mode;
+
+       return (0);
+}
+
+int
+synaptics_query(struct pms_softc *sc, int query, int *val)
+{
+       u_char resp[3];
+
+       if (pms_spec_cmd(sc, query) ||
+           pms_get_status(sc, resp))
+               return (-1);
+
+       if (val)
+               *val = (resp[0] << 16) | (resp[1] << 8) | resp[2];
+
+       return (0);
+}
+
+void
+synaptics_pt_proc(struct pms_softc *sc)
+{
+       u_int buttons;
+       int dx, dy;
+
+       if ((sc->sc_dev_enable & PMS_DEV_SECONDARY) == 0)
+               return;
+
+       buttons = butmap[sc->packet[1] & PMS_PS2_BUTTONSMASK];
+       dx = (sc->packet[1] & PMS_PS2_XNEG) ?
+           (int)sc->packet[4] - 256 : sc->packet[4];
+       dy = (sc->packet[1] & PMS_PS2_YNEG) ?
+           (int)sc->packet[5] - 256 : sc->packet[5];
+
+       wsmouse_input(sc->sc_pt_wsmousedev,
+           buttons, dx, dy, 0, 0, WSMOUSE_INPUT_DELTA);
+}
+
+int
+synaptics_pt_enable(void *v)
+{
+       struct pms_softc *sc = v;
+
+       return (pms_change_state(sc, PMS_STATE_ENABLED, PMS_DEV_SECONDARY));
+}
+
+void
+synaptics_pt_disable(void *v)
+{
+       struct pms_softc *sc = v;
+
+       pms_change_state(sc, PMS_STATE_DISABLED, PMS_DEV_SECONDARY);
+}
+
+int
+synaptics_pt_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
+{
+       switch (cmd) {
+       case WSMOUSEIO_GTYPE:
+               *(u_int *)data = WSMOUSE_TYPE_PS2;
+               break;
+       default:
+               return (-1);
+       }
+       return (0);
+}
+
+int
+pms_enable_synaptics(struct pms_softc *sc)
+{
+       struct synaptics_softc *syn = sc->synaptics;
+       struct wsmousedev_attach_args a;
+       u_char resp[3];
+       int mode, first = 0;
+
+       if (pms_set_resolution(sc, 0) ||
+           pms_set_resolution(sc, 0) ||
+           pms_set_resolution(sc, 0) ||
+           pms_set_resolution(sc, 0) ||
+           pms_get_status(sc, resp) ||
+           resp[1] != SYNAPTICS_ID_MAGIC)
+               return (0);
+
+       if (sc->synaptics == NULL) {
+               syn = malloc(sizeof(struct synaptics_softc), M_DEVBUF,
+                   M_WAITOK | M_ZERO);
+               sc->synaptics = syn;
+               first = 1;
+       }
+
+       synaptics_query(sc, SYNAPTICS_QUE_IDENTIFY, &syn->identify);
+       synaptics_query(sc, SYNAPTICS_QUE_CAPABILITIES, &syn->capabilities);
+       synaptics_query(sc, SYNAPTICS_QUE_MODEL, &syn->model);
+
+       if ((syn->model & SYNAPTICS_MODEL_NEWABS) == 0) {
+               printf("%s: don't support Synaptics OLDABS\n", DEVNAME(sc));
+               return (0);
+       }
+
+       mode = SYNAPTICS_ABSOLUTE_MODE | SYNAPTICS_HIGH_RATE;
+       if (SYNAPTICS_ID_MAJOR(syn->identify) >= 4)
+               mode |= SYNAPTICS_DISABLE_GESTURE;
+       if (syn->capabilities & SYNAPTICS_CAP_EXTENDED)
+               mode |= SYNAPTICS_W_MODE;
+       if (synaptics_set_mode(sc, mode))
+               return (0);
+
+       if (SYNAPTICS_CAP_EXTENDED_QUERIES(syn->capabilities) >= 1)
+               synaptics_query(sc, SYNAPTICS_QUE_EXT_MODEL, &syn->ext_model);
+       if (SYNAPTICS_CAP_EXTENDED_QUERIES(syn->capabilities) >= 4)
+               synaptics_query(sc, SYNAPTICS_QUE_EXT_CAPABILITIES,
+                   &syn->ext_capabilities);
+       if (SYNAPTICS_ID_MAJOR(syn->identify) >= 4)
+               synaptics_query(sc, SYNAPTICS_QUE_RESOLUTION, &syn->resolution);
+       if ((SYNAPTICS_CAP_EXTENDED_QUERIES(syn->capabilities) >= 5) &&
+           (syn->ext_capabilities & SYNAPTICS_EXT_CAP_MAX_DIMENSIONS)) {
+               synaptics_query(sc, SYNAPTICS_QUE_EXT_DIMENSIONS,
+                   &syn->dimension);
+       }
+
+       syn->res_x = SYNAPTICS_RESOLUTION_X(syn->resolution);
+       syn->res_y = SYNAPTICS_RESOLUTION_Y(syn->resolution);
+       syn->min_x = SYNAPTICS_XMIN_BEZEL;
+       syn->min_y = SYNAPTICS_YMIN_BEZEL;
+       syn->max_x = (syn->dimension) ?
+           SYNAPTICS_DIM_X(syn->dimension) : SYNAPTICS_XMAX_BEZEL;
+       syn->max_y = (syn->dimension) ?
+           SYNAPTICS_DIM_Y(syn->dimension) : SYNAPTICS_YMAX_BEZEL;
+
+       if (SYNAPTICS_EXT_MODEL_BUTTONS(syn->ext_model) > 8)
+               syn->ext_model &= ~0xf000;
+
+       if ((syn->dev_pt_attach == 0) &&
+           (syn->capabilities & SYNAPTICS_CAP_PASSTHROUGH)) {
+               a.accessops = &synaptics_pt_accessops;
+               a.accesscookie = sc;
+               sc->sc_pt_wsmousedev = config_found((void *)sc, &a,
+                   wsmousedevprint);
+               syn->dev_pt_attach = 1;
+       }
+
+       if (first) {
+               syn->wsmode = WSMOUSE_COMPAT;
+               syn->count = 0;
+
+               printf("%s: Synaptics %s, firmware %d.%d\n", DEVNAME(sc),
+                   (syn->ext_capabilities & SYNAPTICS_EXT_CAP_CLICKPAD ?
+                       "clickpad" : "touchpad"),
+                   SYNAPTICS_ID_MAJOR(syn->identify),
+                   SYNAPTICS_ID_MINOR(syn->identify));
+       }
+
+       return (1);
+}
+
+int
+pms_ioctl_synaptics(struct pms_softc *sc, u_long cmd, caddr_t data, int flag,
+    struct proc *p)
+{
+       struct synaptics_softc *syn = sc->synaptics;
+       struct wsmouse_calibcoords *wsmc = (struct wsmouse_calibcoords *)data;
+
+       switch (cmd) {
+       case WSMOUSEIO_GTYPE:
+               *(u_int *)data = WSMOUSE_TYPE_SYNAPTICS;
+               break;
+       case WSMOUSEIO_GCALIBCOORDS:
+               wsmc->minx = syn->min_x;
+               wsmc->maxx = syn->max_x;
+               wsmc->miny = syn->min_y;
+               wsmc->maxy = syn->max_y;
+               wsmc->swapxy = 0;
+               wsmc->resx = syn->res_x;
+               wsmc->resy = syn->res_y;
+               break;
+       case WSMOUSEIO_SETMODE:
+               syn->wsmode = (*(u_int *)data == WSMOUSE_NATIVE);
+               break;
+       default:
+               return (-1);
+       }
+       return (0);
+}
+
+int
+pms_sync_synaptics(struct pms_softc *sc, int data)
+{
+       switch (sc->inputstate) {
+       case 0:
+               if ((data & 0xc8) != 0x80)
+                       return (-1);
+               break;
+       case 3:
+               if ((data & 0xc8) != 0xc0)
+                       return (-1);
+               break;
+       }
+
+       return (0);
+}
+
+void
+pms_proc_synaptics(struct pms_softc *sc)
+{
+       struct synaptics_softc *syn = sc->synaptics;
+       u_int buttons;
+       int x, y, z, w, dx, dy;
+
+       w = ((sc->packet[0] & 0x30) >> 2) | ((sc->packet[0] & 0x04) >> 1) |
+           ((sc->packet[3] & 0x04) >> 2);
+
+       if ((syn->capabilities & SYNAPTICS_CAP_PASSTHROUGH) && w == 3) {
+               synaptics_pt_proc(sc);
+               return;
+       }
+
+       if ((sc->sc_dev_enable & PMS_DEV_PRIMARY) == 0)
+               return;
+
+       x = ((sc->packet[3] & 0x10) << 8) | ((sc->packet[1] & 0x0f) << 8) |
+           sc->packet[4];
+       y = ((sc->packet[3] & 0x20) << 7) | ((sc->packet[1] & 0xf0) << 4) |
+           sc->packet[5];
+       z = sc->packet[2];
+
+       buttons = ((sc->packet[0] & 0x01) & (sc->packet[3] & 0x01)) ?
+           WSMOUSE_BUTTON(1) : 0;
+       buttons |= ((sc->packet[0] & 0x02) & (sc->packet[3] & 0x02)) ?
+           WSMOUSE_BUTTON(3) : 0;
+
+       if (syn->ext_capabilities & SYNAPTICS_EXT_CAP_CLICKPAD) {
+               buttons |= ((sc->packet[0] & 0x01) ^ (sc->packet[3] & 0x01)) ?
+                   WSMOUSE_BUTTON(1) : 0;
+       } else if (syn->capabilities & SYNAPTICS_CAP_MIDDLE_BUTTON) {
+               buttons |= ((sc->packet[0] & 0x01) ^ (sc->packet[3] & 0x01)) ?
+                   WSMOUSE_BUTTON(2) : 0;
+       }
+
+       if (syn->capabilities & SYNAPTICS_CAP_FOUR_BUTTON) {
+               buttons |= ((sc->packet[0] & 0x01) ^ (sc->packet[3] & 0x01)) ?
+                   WSMOUSE_BUTTON(4) : 0;
+               buttons |= ((sc->packet[0] & 0x02) ^ (sc->packet[3] & 0x02)) ?
+                   WSMOUSE_BUTTON(5) : 0;
+       } else if (SYNAPTICS_EXT_MODEL_BUTTONS(syn->ext_model) &&
+           ((sc->packet[0] & 0x02) ^ (sc->packet[3] & 0x02))) {
+               buttons |= (sc->packet[4] & 0x01) ? WSMOUSE_BUTTON(6) : 0;
+               buttons |= (sc->packet[5] & 0x01) ? WSMOUSE_BUTTON(7) : 0;
+               buttons |= (sc->packet[4] & 0x02) ? WSMOUSE_BUTTON(8) : 0;
+               buttons |= (sc->packet[5] & 0x02) ? WSMOUSE_BUTTON(9) : 0;
+               buttons |= (sc->packet[4] & 0x04) ? WSMOUSE_BUTTON(10) : 0;
+               buttons |= (sc->packet[5] & 0x04) ? WSMOUSE_BUTTON(11) : 0;
+               buttons |= (sc->packet[4] & 0x08) ? WSMOUSE_BUTTON(12) : 0;
+               buttons |= (sc->packet[5] & 0x08) ? WSMOUSE_BUTTON(13) : 0;
+               x &= ~0x0f;
+               y &= ~0x0f;
+       }
+
+       /* ignore final events that happen when removing all fingers */
+       if (x <= 1 && !z) {
+               x = syn->old_x;
+               y = syn->old_y;
+       }
+
+       if (syn->wsmode == WSMOUSE_NATIVE) {
+               wsmouse_input(sc->sc_wsmousedev, buttons, x, y, z, w,
+                   WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y |
+                   WSMOUSE_INPUT_ABSOLUTE_Z | WSMOUSE_INPUT_ABSOLUTE_W);
+       } else {
+               dx = dy = 0;
+               if (syn->count != 0) {
+                       dx = x - syn->old_x;
+                       dy = y - syn->old_y;
+                       dx /= SYNAPTICS_SCALE;
+                       dy /= SYNAPTICS_SCALE;
+               }
+               if (z < SYNAPTICS_PRESSURE)
+                       syn->count = 0;
+               else
+                       syn->count++;
+               if (dx || dy || buttons != syn->old_buttons)
+                       wsmouse_input(sc->sc_wsmousedev, buttons, dx, dy, 0, 0,
+                           WSMOUSE_INPUT_DELTA);
+               syn->old_buttons = buttons;
+       }
+
+       syn->old_x = x;
+       syn->old_y = y;
+}
+
+void
+pms_disable_synaptics(struct pms_softc *sc)
+{
+       struct synaptics_softc *syn = sc->synaptics;
+
+       if (syn->capabilities & SYNAPTICS_CAP_SLEEP)
+               synaptics_set_mode(sc, SYNAPTICS_SLEEP_MODE |
+                   SYNAPTICS_DISABLE_GESTURE);
 }
Index: dev/pckbc/pmsreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pckbc/pmsreg.h,v
retrieving revision 1.1
diff -u -p -r1.1 pmsreg.h
--- dev/pckbc/pmsreg.h  1 Aug 2007 12:16:59 -0000       1.1
+++ dev/pckbc/pmsreg.h  17 Jun 2011 19:18:55 -0000
@@ -1,20 +1,123 @@
 /* $OpenBSD: pmsreg.h,v 1.1 2007/08/01 12:16:59 kettenis Exp $ */
 /* $NetBSD: psmreg.h,v 1.1 1998/03/22 15:41:28 drochner Exp $ */
 
+#ifndef SYS_DEV_PCKBC_PMSREG_H
+#define SYS_DEV_PCKBC_PMSREG_H
+
 /* mouse commands */
-#define        PMS_SET_SCALE11 0xe6    /* set scaling 1:1 */
-#define        PMS_SET_SCALE21 0xe7    /* set scaling 2:1 */
-#define        PMS_SET_RES     0xe8    /* set resolution (0..3) */
-#define        PMS_GET_SCALE   0xe9    /* get scaling factor */
-#define PMS_SEND_DEV_STATUS    0xe9
-#define        PMS_SET_STREAM  0xea    /* set streaming mode */
-#define PMS_SEND_DEV_DATA      0xeb
+#define PMS_SET_SCALE11                0xe6    /* set scaling 1:1 */
+#define PMS_SET_SCALE21                0xe7    /* set scaling 2:1 */
+#define PMS_SET_RES            0xe8    /* set resolution (0..3) */
+#define PMS_SEND_DEV_STATUS    0xe9    /* status request */
+#define PMS_SET_STREAM_MODE    0xea
+#define PMS_SEND_DEV_DATA      0xeb    /* read data */
+#define PMS_RESET_WRAP_MODE    0xec
+#define PMS_SET_WRAP_MODE      0xed
 #define PMS_SET_REMOTE_MODE    0xf0
-#define PMS_SEND_DEV_ID        0xf2
-#define        PMS_SET_SAMPLE  0xf3    /* set sampling rate */
-#define        PMS_DEV_ENABLE  0xf4    /* mouse on */
-#define        PMS_DEV_DISABLE 0xf5    /* mouse off */
+#define PMS_SEND_DEV_ID                0xf2    /* read device type */
+#define PMS_SET_SAMPLE         0xf3    /* set sampling rate */
+#define PMS_DEV_ENABLE         0xf4    /* mouse on */
+#define PMS_DEV_DISABLE                0xf5    /* mouse off */
 #define PMS_SET_DEFAULTS       0xf6
-#define        PMS_RESET       0xff    /* reset */
+#define PMS_RESEND             0xfe
+#define PMS_RESET              0xff    /* reset */
+
+#define PMS_RSTDONE            0xaa
+
+/* PS/2 mouse data packet */
+#define PMS_PS2_BUTTONSMASK    0x07
+#define PMS_PS2_BUTTON1                0x01    /* left */
+#define PMS_PS2_BUTTON2                0x04    /* middle */
+#define PMS_PS2_BUTTON3                0x02    /* right */
+#define PMS_PS2_XNEG           0x10
+#define PMS_PS2_YNEG           0x20
+
+#define PMS_INTELLI_MAGIC1     200
+#define PMS_INTELLI_MAGIC2     100
+#define PMS_INTELLI_MAGIC3     80
+#define PMS_INTELLI_ID         0x03
+
+/* Synaptics queries */
+#define SYNAPTICS_QUE_IDENTIFY                 0x00
+#define SYNAPTICS_QUE_MODES                    0x01
+#define SYNAPTICS_QUE_CAPABILITIES             0x02
+#define SYNAPTICS_QUE_MODEL                    0x03
+#define SYNAPTICS_QUE_SERIAL_NUMBER_PREFIX     0x06
+#define SYNAPTICS_QUE_SERIAL_NUMBER_SUFFIX     0x07
+#define SYNAPTICS_QUE_RESOLUTION               0x08
+#define SYNAPTICS_QUE_EXT_MODEL                        0x09
+#define SYNAPTICS_QUE_EXT_CAPABILITIES         0x0c
+#define SYNAPTICS_QUE_EXT_DIMENSIONS           0x0d
+
+#define SYNAPTICS_CMD_SET_MODE                 0x14
+#define SYNAPTICS_CMD_SEND_CLIENT              0x28
+
+/* Identify */
+#define SYNAPTICS_ID_MODEL(id)                 (((id) >>  4) & 0x0f)
+#define SYNAPTICS_ID_MINOR(id)                 (((id) >> 16) & 0xff)
+#define SYNAPTICS_ID_MAJOR(id)                 ((id) & 0x0f)
+#define SYNAPTICS_ID_MAGIC                     0x47
+
+/* Modes bits */
+#define SYNAPTICS_ABSOLUTE_MODE                        (1 << 7)
+#define SYNAPTICS_HIGH_RATE                    (1 << 6)
+#define SYNAPTICS_SLEEP_MODE                   (1 << 3)
+#define SYNAPTICS_DISABLE_GESTURE              (1 << 2)
+#define SYNAPTICS_FOUR_BYTE_CLIENT             (1 << 1)
+#define SYNAPTICS_W_MODE                       (1 << 0)
+
+/* Capability bits */
+#define SYNAPTICS_CAP_EXTENDED                 (1 << 23)
+#define SYNAPTICS_CAP_EXTENDED_QUERIES(c)      (((c) >> 20) & 0x07)
+#define SYNAPTICS_CAP_MIDDLE_BUTTON            (1 << 18)
+#define SYNAPTICS_CAP_PASSTHROUGH              (1 << 7)
+#define SYNAPTICS_CAP_SLEEP                    (1 << 4)
+#define SYNAPTICS_CAP_FOUR_BUTTON              (1 << 3)
+#define SYNAPTICS_CAP_BALLISTICS               (1 << 2)
+#define SYNAPTICS_CAP_MULTIFINGER              (1 << 1)
+#define SYNAPTICS_CAP_PALMDETECT               (1 << 0)
+
+/* Model ID bits */
+#define SYNAPTICS_MODEL_ROT180                 (1 << 23)
+#define SYNAPTICS_MODEL_PORTRAIT               (1 << 22)
+#define SYNAPTICS_MODEL_SENSOR(m)              (((m) >> 16) & 0x3f)
+#define SYNAPTICS_MODEL_HARDWARE(m)            (((m) >> 9) & 0x7f)
+#define SYNAPTICS_MODEL_NEWABS                 (1 << 7)
+#define SYNAPTICS_MODEL_PEN                    (1 << 6)
+#define SYNAPTICS_MODEL_SIMPLC                 (1 << 5)
+#define SYNAPTICS_MODEL_GEOMETRY(m)            ((m) & 0x0f)
+
+/* Resolutions */
+#define SYNAPTICS_RESOLUTION_X(r)              (((r) >> 16) & 0xff)
+#define SYNAPTICS_RESOLUTION_Y(r)              ((r) & 0xff)
+
+/* Extended Model ID bits */
+#define SYNAPTICS_EXT_MODEL_LIGHTCONTROL       (1 << 22)
+#define SYNAPTICS_EXT_MODEL_PEAKDETECT         (1 << 21)
+#define SYNAPTICS_EXT_MODEL_VWHEEL             (1 << 19)
+#define SYNAPTICS_EXT_MODEL_EW_MODE            (1 << 18)
+#define SYNAPTICS_EXT_MODEL_HSCROLL            (1 << 17)
+#define SYNAPTICS_EXT_MODEL_VSCROLL            (1 << 16)
+#define SYNAPTICS_EXT_MODEL_BUTTONS(em)                ((em >> 12) & 0x0f)
+#define SYNAPTICS_EXT_MODEL_SENSOR(em)         ((em >> 10) & 0x03)
+#define SYNAPTICS_EXT_MODEL_PRODUCT(em)                ((em) & 0xff)
+
+/* Extended Capability bits */
+#define SYNAPTICS_EXT_CAP_CLICKPAD             (1 << 20)
+#define SYNAPTICS_EXT_CAP_MULTITOUCH           (1 << 19)
+#define SYNAPTICS_EXT_CAP_MAX_DIMENSIONS       (1 << 17)
+#define SYNAPTICS_EXT_CAP_CLICKPAD_2BTN                (1 << 8)
+
+/* Extended Dimensions */
+#define SYNAPTICS_DIM_X(d)                     ((((d) & 0xff0000) >> 11) | \
+                                                (((d) & 0xf00) >> 7))
+#define SYNAPTICS_DIM_Y(d)                     ((((d) & 0xff) << 5) | \
+                                                (((d) & 0xf000) >> 11))
+
+/* Typical bezel limit */
+#define SYNAPTICS_XMIN_BEZEL                   1472
+#define SYNAPTICS_XMAX_BEZEL                   5472
+#define SYNAPTICS_YMIN_BEZEL                   1408
+#define SYNAPTICS_YMAX_BEZEL                   4448
 
-#define        PMS_RSTDONE     0xaa
+#endif /* !define(SYS_DEV_PCKBC_PMSREG_H) */
Index: dev/wscons/wsmouse.c
===================================================================
RCS file: /cvs/src/sys/dev/wscons/wsmouse.c,v
retrieving revision 1.21
diff -u -p -r1.21 wsmouse.c
--- dev/wscons/wsmouse.c        26 Jul 2010 01:56:27 -0000      1.21
+++ dev/wscons/wsmouse.c        17 Jun 2011 19:18:55 -0000
@@ -507,6 +507,14 @@ wsmouseopen(dev_t dev, int flags, int mo
                return (0);                     /* always allow open for write
                                                   so ioctl() is possible. */
 
+#if NWSMUX > 0
+       if (sc->sc_base.me_parent != NULL) {
+               /* Grab the mouse out of the greedy hands of the mux. */
+               DPRINTF(("wsmouseopen: detach\n"));
+               wsmux_detach_sc(&sc->sc_base);
+       }
+#endif
+
        if (sc->sc_base.me_evp != NULL)
                return (EBUSY);
 
@@ -540,6 +548,21 @@ wsmouseclose(dev_t dev, int flags, int m
        sc->sc_base.me_evp = NULL;
        (*sc->sc_accessops->disable)(sc->sc_accesscookie);
        wsevent_fini(evar);
+
+#if NWSMUX > 0
+       if (sc->sc_base.me_parent == NULL) {
+               int mux, error;
+
+               DPRINTF(("wsmouseclose: attach\n"));
+               mux = sc->sc_base.me_dv.dv_cfdata->wsmousedevcf_mux;
+               if (mux >= 0) {
+                       error = wsmux_attach_sc(wsmux_getmux(mux), 
&sc->sc_base);
+                       if (error)
+                               printf("%s: can't attach mux (error=%d)\n",
+                                   sc->sc_base.me_dv.dv_xname, error);
+               }
+       }
+#endif
 
        return (0);
 }

Reply via email to