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); }