On Mon, Nov 29, 2010 at 10:08:22PM +0000, Nicholas Marriott wrote:
> 
> Well, I don't use it so I don't have strong feelings about it, but it
> does work for PS/2 mice and it seems that it would be useful for anyone
> using wsmoused (although there probably aren't many people).
> 
> Would it be so hard to leave it, and if it is really not needed remove
> it entirely as a separate change?
> 
> Otherwise aside from the char -> signed char change I mentioned the diff
> is fine with me.
> 

1) fix char -> signed char
2) Returned WSMOUSEIO_SRES

-- 
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       30 Nov 2010 16:26:20 -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,78 @@ 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)
+{
+       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;
+
+               if (pms_set_resolution(sc, i))
+                       printf("%s: SET_RES command error\n", DEVNAME(sc));
+               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 = (signed 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 +437,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 +453,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 +501,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;
 }

Reply via email to