Hi Alexandr This works fine for me with both with X and wsmoused.
A few things: - Did you deliberately remove WSMOUSEIO_SRES? - Do we know what the XFree86 bug was and is it now fixed? Or do the PMS_PS2_XNEG/YNEG flags make the bounding unnecessary? - "dz = (char)sc->packet[3];" -- shouldn't this be "(signed char)"? - So we now call wsmouse_input even if the buttons haven't changed. This is fine, right? I take it the overall aim of this is to make it easier to add additional mice types in future? Cheers On Thu, Nov 18, 2010 at 12:11:09AM +0500, Alexandr Shadchin wrote: > Add a common interface for various devices > > -- > Alexandr Shadchin > > Index: pms.c > =================================================================== > RCS file: /cvs/src/sys/dev/pckbc/pms.c,v > retrieving revision 1.14 > diff -u -p -r1.14 pms.c > --- pms.c 15 Nov 2010 20:25:31 -0000 1.14 > +++ pms.c 17 Nov 2010 18:23:35 -0000 > @@ -40,6 +40,20 @@ > > #define DEVNAME(sc) ((sc)->sc_dev.dv_xname) > > +struct pms_softc; > + > +struct pms_protocol { > + int type; > +#define PMS_STANDARD 0 > +#define PMS_INTELLI 1 > + int packetsize; > + int (*enable)(struct pms_softc *); > + int (*ioctl)(struct pms_softc *, u_long, caddr_t, int, struct proc *); > + int (*sync)(struct pms_softc *, int); > + void (*proc)(struct pms_softc *); > + void (*disable)(struct pms_softc *); > +}; > + > struct pms_softc { /* driver status information */ > struct device sc_dev; > > @@ -52,14 +66,38 @@ struct pms_softc { /* driver status inf > #define PMS_STATE_SUSPENDED 2 > > int poll; > - int intelli; > int inputstate; > - u_int buttons, oldbuttons; /* mouse button status */ > - signed char dx, dy; > + > + struct pms_protocol protocol; > + > + unsigned char packet[8]; > > struct device *sc_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 > +}; > + > +/* 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 > + > int pmsprobe(struct device *, void *, void *); > void pmsattach(struct device *, struct device *, void *); > int pmsactivate(struct device *, int); > @@ -81,7 +119,11 @@ int pms_reset(struct pms_softc *); > int pms_dev_enable(struct pms_softc *); > int pms_dev_disable(struct pms_softc *); > > -int pms_setintellimode(struct pms_softc *sc); > +int pms_enable_intelli(struct pms_softc *); > + > +int pms_ioctl_mouse(struct pms_softc *, u_long, caddr_t, int, struct proc > *); > +int pms_sync_mouse(struct pms_softc *, int); > +void pms_proc_mouse(struct pms_softc *); > > struct cfattach pms_ca = { > sizeof(struct pms_softc), pmsprobe, pmsattach, NULL, > @@ -98,6 +140,27 @@ const struct wsmouse_accessops pms_acces > pms_disable, > }; > > +const struct pms_protocol pms_mouse[] = { > + /* Generic PS/2 mouse */ > + { > + PMS_STANDARD, 3, > + NULL, > + pms_ioctl_mouse, > + pms_sync_mouse, > + pms_proc_mouse, > + NULL > + }, > + /* Microsoft IntelliMouse */ > + { > + PMS_INTELLI, 4, > + pms_enable_intelli, > + pms_ioctl_mouse, > + pms_sync_mouse, > + pms_proc_mouse, > + NULL > + } > +}; > + > int > pms_cmd(struct pms_softc *sc, u_char *cmd, int len, u_char *resp, int > resplen) > { > @@ -208,7 +271,7 @@ pms_dev_disable(struct pms_softc *sc) > } > > int > -pms_setintellimode(struct pms_softc *sc) > +pms_enable_intelli(struct pms_softc *sc) > { > static const int rates[] = {200, 100, 80}; > u_char resp; > @@ -224,6 +287,65 @@ pms_setintellimode(struct pms_softc *sc) > } > > int > +pms_ioctl_mouse(struct pms_softc *sc, 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_sync_mouse(struct pms_softc *sc, int data) > +{ > + if (sc->inputstate != 0) > + return (0); > + > + switch (sc->protocol.type) { > + case PMS_STANDARD: > + if ((data & 0xc0) != 0) > + return (-1); > + break; > + case PMS_INTELLI: > + if ((data & 0x08) != 0x08) > + return (-1); > + break; > + } > + > + return (0); > +} > + > +void > +pms_proc_mouse(struct pms_softc *sc) > +{ > + u_int buttons; > + int dx, dy, dz; > + > + buttons = butmap[sc->packet[0] & PMS_PS2_BUTTONSMASK]; > + dx = (sc->packet[0] & PMS_PS2_XNEG) ? > + sc->packet[1] - 256 : sc->packet[1]; > + dy = (sc->packet[0] & PMS_PS2_YNEG) ? > + sc->packet[2] - 256 : sc->packet[2]; > + > + switch (sc->protocol.type) { > + case PMS_STANDARD: > + dz = 0; > + break; > + case PMS_INTELLI: > + dz = (char)sc->packet[3]; > + break; > + } > + > + wsmouse_input(sc->sc_wsmousedev, > + buttons, dx, dy, dz, 0, WSMOUSE_INPUT_DELTA); > +} > + > +int > pmsprobe(struct device *parent, void *match, void *aux) > { > struct pckbc_attach_args *pa = aux; > @@ -302,13 +424,14 @@ pmsactivate(struct device *self, int act > int > pms_change_state(struct pms_softc *sc, int newstate) > { > + int i; > + > switch (newstate) { > case PMS_STATE_ENABLED: > if (sc->sc_state == PMS_STATE_ENABLED) > return (EBUSY); > > sc->inputstate = 0; > - sc->oldbuttons = 0; > > pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 1); > > @@ -317,13 +440,24 @@ pms_change_state(struct pms_softc *sc, i > > pms_reset(sc); > > - sc->intelli = pms_setintellimode(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]; > + > +#ifdef DEBUG > + printf("%s: protocol type %d\n", DEVNAME(sc), > sc->protocol.type); > +#endif > > pms_dev_enable(sc); > break; > case PMS_STATE_DISABLED: > case PMS_STATE_SUSPENDED: > pms_dev_disable(sc); > + > + if (sc->protocol.disable) > + sc->protocol.disable(sc); > + > pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0); > break; > } > @@ -354,96 +488,30 @@ int > pms_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) > { > struct pms_softc *sc = v; > - u_char kbcmd[2]; > - int i; > > - switch (cmd) { > - case WSMOUSEIO_GTYPE: > - *(u_int *)data = WSMOUSE_TYPE_PS2; > - break; > - > - case WSMOUSEIO_SRES: > - i = ((int) *(u_int *)data - 12) / 25; > - /* valid values are {0,1,2,3} */ > - if (i < 0) > - i = 0; > - if (i > 3) > - i = 3; > - > - kbcmd[0] = PMS_SET_RES; > - kbcmd[1] = (unsigned char) i; > - i = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, kbcmd, > - 2, 0, 1, 0); > - > - if (i) > - printf("pms_ioctl: SET_RES command error\n"); > - break; > - > - default: > - return (-1); > - } > - return (0); > + return (sc->protocol.ioctl(sc, cmd, data, flag, p)); > } > > -/* Masks for the first byte of a packet */ > -#define PS2LBUTMASK 0x01 > -#define PS2RBUTMASK 0x02 > -#define PS2MBUTMASK 0x04 > - > void > pmsinput(void *vsc, int data) > { > struct pms_softc *sc = vsc; > - signed char dz = 0; > - u_int changed; > > if (sc->sc_state != PMS_STATE_ENABLED) { > /* Interrupts are not expected. Discard the byte. */ > return; > } > > - switch (sc->inputstate) { > - > - case 0: > - if ((data & 0xc0) == 0) { /* no ovfl, bit 3 == 1 too? */ > - sc->buttons = ((data & PS2LBUTMASK) ? 0x1 : 0) | > - ((data & PS2MBUTMASK) ? 0x2 : 0) | > - ((data & PS2RBUTMASK) ? 0x4 : 0); > - ++sc->inputstate; > - } > - break; > - > - case 1: > - sc->dx = data; > - /* Bounding at -127 avoids a bug in XFree86. */ > - sc->dx = (sc->dx == -128) ? -127 : sc->dx; > - ++sc->inputstate; > - break; > - > - case 2: > - sc->dy = data; > - sc->dy = (sc->dy == -128) ? -127 : sc->dy; > - ++sc->inputstate; > - break; > - > - case 3: > - dz = data; > - dz = (dz == -128) ? -127 : dz; > - ++sc->inputstate; > - break; > - } > - > - if ((sc->inputstate == 3 && sc->intelli == 0) || sc->inputstate == 4) { > + if (sc->protocol.sync(sc, data)) { > + printf("%s: not in sync yet, discard input\n", DEVNAME(sc)); > sc->inputstate = 0; > - > - changed = (sc->buttons ^ sc->oldbuttons); > - sc->oldbuttons = sc->buttons; > - > - if (sc->dx || sc->dy || dz || changed) > - wsmouse_input(sc->sc_wsmousedev, > - sc->buttons, sc->dx, sc->dy, dz, 0, > - WSMOUSE_INPUT_DELTA); > + return; > } > > - return; > + sc->packet[sc->inputstate++] = data; > + if (sc->inputstate != sc->protocol.packetsize) > + return; > + > + sc->protocol.proc(sc); > + sc->inputstate = 0; > }