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

Reply via email to