root/dev/pckbc/pms_intelli.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pmsi_setintellimode
  2. pmsiprobe
  3. pmsiattach
  4. pmsi_enable
  5. pmsi_disable
  6. pmsi_ioctl
  7. pmsiinput

    1 /* $OpenBSD: pms_intelli.c,v 1.1 2007/08/01 12:16:59 kettenis Exp $ */
    2 /* $NetBSD: psm_intelli.c,v 1.8 2000/06/05 22:20:57 sommerfeld Exp $ */
    3 
    4 /*-
    5  * Copyright (c) 1994 Charles M. Hannum.
    6  * Copyright (c) 1992, 1993 Erik Forsberg.
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
   16  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   17  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
   18  * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   22  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   23  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/param.h>
   28 #include <sys/systm.h>
   29 #include <sys/device.h>
   30 #include <sys/ioctl.h>
   31 
   32 #include <machine/bus.h>
   33 
   34 #include <dev/ic/pckbcvar.h>
   35 
   36 #include <dev/pckbc/pmsreg.h>
   37 
   38 #include <dev/wscons/wsconsio.h>
   39 #include <dev/wscons/wsmousevar.h>
   40 
   41 struct pmsi_softc {             /* driver status information */
   42         struct device sc_dev;
   43 
   44         pckbc_tag_t sc_kbctag;
   45         int sc_kbcslot;
   46 
   47         int sc_enabled;         /* input enabled? */
   48         int inputstate;
   49         u_int buttons, oldbuttons;      /* mouse button status */
   50         signed char dx, dy;
   51 
   52         struct device *sc_wsmousedev;
   53 };
   54 
   55 int pmsiprobe(struct device *, void *, void *);
   56 void pmsiattach(struct device *, struct device *, void *);
   57 void pmsiinput(void *, int);
   58 
   59 struct cfattach pmsi_ca = {
   60         sizeof(struct pmsi_softc), pmsiprobe, pmsiattach,
   61 };
   62 
   63 int     pmsi_enable(void *);
   64 int     pmsi_ioctl(void *, u_long, caddr_t, int, struct proc *);
   65 void    pmsi_disable(void *);
   66 
   67 const struct wsmouse_accessops pmsi_accessops = {
   68         pmsi_enable,
   69         pmsi_ioctl,
   70         pmsi_disable,
   71 };
   72 
   73 static int pmsi_setintellimode(pckbc_tag_t, pckbc_slot_t);
   74 
   75 static int
   76 pmsi_setintellimode(tag, slot)
   77         pckbc_tag_t tag;
   78         pckbc_slot_t slot;
   79 {
   80         u_char cmd[2], resp[1];
   81         int i, res;
   82         static u_char rates[] = {200, 100, 80};
   83 
   84         cmd[0] = PMS_SET_SAMPLE;
   85         for (i = 0; i < 3; i++) {
   86                 cmd[1] = rates[i];
   87                 res = pckbc_poll_cmd(tag, slot, cmd, 2, 0, 0, 0);
   88                 if (res)
   89                         return (res);
   90         }
   91 
   92         cmd[0] = PMS_SEND_DEV_ID;
   93         res = pckbc_poll_cmd(tag, slot, cmd, 1, 1, resp, 0);
   94         if (res)
   95                 return (res);
   96         if (resp[0] != 3)
   97                 return (ENXIO);
   98 
   99         return (0);
  100 }
  101 
  102 int
  103 pmsiprobe(parent, match, aux)
  104         struct device *parent;
  105         void *match;
  106         void *aux;
  107 {
  108         struct pckbc_attach_args *pa = aux;
  109         u_char cmd[1], resp[2];
  110         int res;
  111 
  112         if (pa->pa_slot != PCKBC_AUX_SLOT)
  113                 return (0);
  114 
  115         /* Flush any garbage. */
  116         pckbc_flush(pa->pa_tag, pa->pa_slot);
  117 
  118         /* reset the device */
  119         cmd[0] = PMS_RESET;
  120         res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1);
  121         if (res) {
  122 #ifdef DEBUG
  123                 printf("pmsiprobe: reset error %d\n", res);
  124 #endif
  125                 return (0);
  126         }
  127         if (resp[0] != PMS_RSTDONE) {
  128                 printf("pmsiprobe: reset response 0x%x\n", resp[0]);
  129                 return (0);
  130         }
  131 
  132         /* get type number (0 = mouse) */
  133         if (resp[1] != 0) {
  134 #ifdef DEBUG
  135                 printf("pmsiprobe: type 0x%x\n", resp[1]);
  136 #endif
  137                 return (0);
  138         }
  139 
  140         if ((res = pmsi_setintellimode(pa->pa_tag, pa->pa_slot))) {
  141 #ifdef DEBUG
  142                 printf("pmsiprobe: intellimode -> %d\n", res);
  143 #endif
  144                 return (0);
  145         }
  146 
  147         return (20);
  148 }
  149 
  150 void
  151 pmsiattach(parent, self, aux)
  152         struct device *parent, *self;
  153         void *aux;
  154 {
  155         struct pmsi_softc *sc = (void *)self;
  156         struct pckbc_attach_args *pa = aux;
  157         struct wsmousedev_attach_args a;
  158         u_char cmd[1], resp[2];
  159         int res;
  160 
  161         sc->sc_kbctag = pa->pa_tag;
  162         sc->sc_kbcslot = pa->pa_slot;
  163 
  164         printf("\n");
  165 
  166         /* Flush any garbage. */
  167         pckbc_flush(pa->pa_tag, pa->pa_slot);
  168 
  169         /* reset the device */
  170         cmd[0] = PMS_RESET;
  171         res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1);
  172 #ifdef DEBUG
  173         if (res || resp[0] != PMS_RSTDONE || resp[1] != 0) {
  174                 printf("pmsiattach: reset error\n");
  175                 return;
  176         }
  177 #endif
  178         res = pmsi_setintellimode(pa->pa_tag, pa->pa_slot);
  179 #ifdef DEBUG
  180         if (res) {
  181                 printf("pmsiattach: error setting intelli mode\n");
  182                 return;
  183         }
  184 #endif
  185 
  186         /* Other initialization was done by pmsiprobe. */
  187         sc->inputstate = 0;
  188         sc->oldbuttons = 0;
  189 
  190         pckbc_set_inputhandler(sc->sc_kbctag, sc->sc_kbcslot,
  191                                pmsiinput, sc, sc->sc_dev.dv_xname);
  192 
  193         a.accessops = &pmsi_accessops;
  194         a.accesscookie = sc;
  195 
  196         /*
  197          * Attach the wsmouse, saving a handle to it.
  198          * Note that we don't need to check this pointer against NULL
  199          * here or in pmsintr, because if this fails pms_enable() will
  200          * never be called, so pmsiinput() will never be called.
  201          */
  202         sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
  203 
  204         /* no interrupts until enabled */
  205         cmd[0] = PMS_DEV_DISABLE;
  206         res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 0, 0, 0);
  207         if (res)
  208                 printf("pmsiattach: disable error\n");
  209         pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
  210 }
  211 
  212 int
  213 pmsi_enable(v)
  214         void *v;
  215 {
  216         struct pmsi_softc *sc = v;
  217         u_char cmd[1];
  218         int res;
  219 
  220         if (sc->sc_enabled)
  221                 return EBUSY;
  222 
  223         sc->sc_enabled = 1;
  224         sc->inputstate = 0;
  225         sc->oldbuttons = 0;
  226 
  227         pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 1);
  228 
  229         cmd[0] = PMS_DEV_ENABLE;
  230         res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd, 1, 0, 1, 0);
  231         if (res)
  232                 printf("pmsi_enable: command error\n");
  233 
  234         return 0;
  235 }
  236 
  237 void
  238 pmsi_disable(v)
  239         void *v;
  240 {
  241         struct pmsi_softc *sc = v;
  242         u_char cmd[1];
  243         int res;
  244 
  245         cmd[0] = PMS_DEV_DISABLE;
  246         res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd, 1, 0, 1, 0);
  247         if (res)
  248                 printf("pmsi_disable: command error\n");
  249 
  250         pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
  251 
  252         sc->sc_enabled = 0;
  253 }
  254 
  255 int
  256 pmsi_ioctl(v, cmd, data, flag, p)
  257         void *v;
  258         u_long cmd;
  259         caddr_t data;
  260         int flag;
  261         struct proc *p;
  262 {
  263         struct pmsi_softc *sc = v;
  264         u_char kbcmd[2];
  265         int i;
  266 
  267         switch (cmd) {
  268         case WSMOUSEIO_GTYPE:
  269                 *(u_int *)data = WSMOUSE_TYPE_PS2;
  270                 break;
  271                 
  272         case WSMOUSEIO_SRES:
  273                 i = ((int) *(u_int *)data - 12) / 25;           
  274                 /* valid values are {0,1,2,3} */
  275                 if (i < 0)
  276                         i = 0;
  277                 if (i > 3)
  278                         i = 3;
  279 
  280                 kbcmd[0] = PMS_SET_RES;
  281                 kbcmd[1] = (unsigned char) i;                   
  282                 i = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, kbcmd, 
  283                     2, 0, 1, 0);
  284                 
  285                 if (i)
  286                         printf("pms_ioctl: SET_RES command error\n");
  287                 break;
  288                 
  289         default:
  290                 return (-1);
  291         }
  292         return (0);
  293 }
  294 
  295 /* Masks for the first byte of a packet */
  296 #define PS2LBUTMASK 0x01
  297 #define PS2RBUTMASK 0x02
  298 #define PS2MBUTMASK 0x04
  299 
  300 void pmsiinput(vsc, data)
  301 void *vsc;
  302 int data;
  303 {
  304         struct pmsi_softc *sc = vsc;
  305         signed char dz;
  306         u_int changed;
  307 
  308         if (!sc->sc_enabled) {
  309                 /* Interrupts are not expected.  Discard the byte. */
  310                 return;
  311         }
  312 
  313         switch (sc->inputstate) {
  314 
  315         case 0:
  316                 if ((data & 0xc0) == 0) { /* no ovfl, bit 3 == 1 too? */
  317                         sc->buttons = ((data & PS2LBUTMASK) ? 0x1 : 0) |
  318                             ((data & PS2MBUTMASK) ? 0x2 : 0) |
  319                             ((data & PS2RBUTMASK) ? 0x4 : 0);
  320                         ++sc->inputstate;
  321                 }
  322                 break;
  323 
  324         case 1:
  325                 sc->dx = data;
  326                 /* Bounding at -127 avoids a bug in XFree86. */
  327                 sc->dx = (sc->dx == -128) ? -127 : sc->dx;
  328                 ++sc->inputstate;
  329                 break;
  330 
  331         case 2:
  332                 sc->dy = data;
  333                 sc->dy = (sc->dy == -128) ? -127 : sc->dy;
  334                 ++sc->inputstate;
  335                 break;
  336 
  337         case 3:
  338                 dz = data;
  339                 dz = (dz == -128) ? -127 : dz;
  340                 sc->inputstate = 0;
  341 
  342                 changed = (sc->buttons ^ sc->oldbuttons);
  343                 sc->oldbuttons = sc->buttons;
  344 
  345                 if (sc->dx || sc->dy || dz || changed)
  346                         wsmouse_input(sc->sc_wsmousedev,
  347                                       sc->buttons, sc->dx, sc->dy, dz, 0,
  348                                       WSMOUSE_INPUT_DELTA);
  349                 break;
  350         }
  351 
  352         return;
  353 }
  354 
  355 struct cfdriver pmsi_cd = {
  356         NULL, "pmsi", DV_DULL
  357 };

/* [<][>][^][v][top][bottom][index][help] */