root/dev/pckbc/pms.c

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

DEFINITIONS

This source file includes following definitions.
  1. pmsprobe
  2. pmsattach
  3. pms_enable
  4. pms_disable
  5. pms_ioctl
  6. pmsinput

    1 /* $OpenBSD: pms.c,v 1.1 2007/08/01 12:16:59 kettenis Exp $ */
    2 /* $NetBSD: psm.c,v 1.11 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 pms_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;
   51 
   52         struct device *sc_wsmousedev;
   53 };
   54 
   55 int pmsprobe(struct device *, void *, void *);
   56 void pmsattach(struct device *, struct device *, void *);
   57 void pmsinput(void *, int);
   58 
   59 struct cfattach pms_ca = {
   60         sizeof(struct pms_softc), pmsprobe, pmsattach,
   61 };
   62 
   63 int     pms_enable(void *);
   64 int     pms_ioctl(void *, u_long, caddr_t, int, struct proc *);
   65 void    pms_disable(void *);
   66 
   67 const struct wsmouse_accessops pms_accessops = {
   68         pms_enable,
   69         pms_ioctl,
   70         pms_disable,
   71 };
   72 
   73 int
   74 pmsprobe(parent, match, aux)
   75         struct device *parent;
   76         void *match;
   77         void *aux;
   78 {
   79         struct pckbc_attach_args *pa = aux;
   80         u_char cmd[1], resp[2];
   81         int res;
   82 
   83         if (pa->pa_slot != PCKBC_AUX_SLOT)
   84                 return (0);
   85 
   86         /* Flush any garbage. */
   87         pckbc_flush(pa->pa_tag, pa->pa_slot);
   88 
   89         /* reset the device */
   90         cmd[0] = PMS_RESET;
   91         res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1);
   92         if (res) {
   93 #ifdef DEBUG
   94                 printf("pmsprobe: reset error %d\n", res);
   95 #endif
   96                 return (0);
   97         }
   98         if (resp[0] != PMS_RSTDONE) {
   99                 printf("pmsprobe: reset response 0x%x\n", resp[0]);
  100                 return (0);
  101         }
  102 
  103         /* get type number (0 = mouse) */
  104         if (resp[1] != 0) {
  105 #ifdef DEBUG
  106                 printf("pmsprobe: type 0x%x\n", resp[1]);
  107 #endif
  108                 return (0);
  109         }
  110 
  111         return (10);
  112 }
  113 
  114 void
  115 pmsattach(parent, self, aux)
  116         struct device *parent, *self;
  117         void *aux;
  118 {
  119         struct pms_softc *sc = (void *)self;
  120         struct pckbc_attach_args *pa = aux;
  121         struct wsmousedev_attach_args a;
  122         u_char cmd[1], resp[2];
  123         int res;
  124 
  125         sc->sc_kbctag = pa->pa_tag;
  126         sc->sc_kbcslot = pa->pa_slot;
  127 
  128         printf("\n");
  129 
  130         /* Flush any garbage. */
  131         pckbc_flush(pa->pa_tag, pa->pa_slot);
  132 
  133         /* reset the device */
  134         cmd[0] = PMS_RESET;
  135         res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1);
  136 #ifdef DEBUG
  137         if (res || resp[0] != PMS_RSTDONE || resp[1] != 0) {
  138                 printf("pmsattach: reset error\n");
  139                 return;
  140         }
  141 #endif
  142 
  143         sc->inputstate = 0;
  144         sc->oldbuttons = 0;
  145 
  146         pckbc_set_inputhandler(sc->sc_kbctag, sc->sc_kbcslot,
  147                                pmsinput, sc, sc->sc_dev.dv_xname);
  148 
  149         a.accessops = &pms_accessops;
  150         a.accesscookie = sc;
  151 
  152         /*
  153          * Attach the wsmouse, saving a handle to it.
  154          * Note that we don't need to check this pointer against NULL
  155          * here or in pmsintr, because if this fails pms_enable() will
  156          * never be called, so pmsinput() will never be called.
  157          */
  158         sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
  159 
  160         /* no interrupts until enabled */
  161         cmd[0] = PMS_DEV_DISABLE;
  162         res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 0, 0, 0);
  163         if (res)
  164                 printf("pmsattach: disable error\n");
  165         pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
  166 }
  167 
  168 int
  169 pms_enable(v)
  170         void *v;
  171 {
  172         struct pms_softc *sc = v;
  173         u_char cmd[1];
  174         int res;
  175 
  176         if (sc->sc_enabled)
  177                 return EBUSY;
  178 
  179         sc->sc_enabled = 1;
  180         sc->inputstate = 0;
  181         sc->oldbuttons = 0;
  182 
  183         pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 1);
  184 
  185         cmd[0] = PMS_DEV_ENABLE;
  186         res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd, 1, 0, 1, 0);
  187         if (res)
  188                 printf("pms_enable: command error\n");
  189 #if 0
  190         {
  191                 u_char scmd[2];
  192 
  193                 scmd[0] = PMS_SET_RES;
  194                 scmd[1] = 3; /* 8 counts/mm */
  195                 res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, scmd,
  196                                         2, 0, 1, 0);
  197                 if (res)
  198                         printf("pms_enable: setup error1 (%d)\n", res);
  199 
  200                 scmd[0] = PMS_SET_SCALE21;
  201                 res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, scmd,
  202                                         1, 0, 1, 0);
  203                 if (res)
  204                         printf("pms_enable: setup error2 (%d)\n", res);
  205 
  206                 scmd[0] = PMS_SET_SAMPLE;
  207                 scmd[1] = 100; /* 100 samples/sec */
  208                 res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, scmd,
  209                                         2, 0, 1, 0);
  210                 if (res)
  211                         printf("pms_enable: setup error3 (%d)\n", res);
  212         }
  213 #endif
  214 
  215         return 0;
  216 }
  217 
  218 void
  219 pms_disable(v)
  220         void *v;
  221 {
  222         struct pms_softc *sc = v;
  223         u_char cmd[1];
  224         int res;
  225 
  226         cmd[0] = PMS_DEV_DISABLE;
  227         res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd, 1, 0, 1, 0);
  228         if (res)
  229                 printf("pms_disable: command error\n");
  230 
  231         pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
  232 
  233         sc->sc_enabled = 0;
  234 }
  235 
  236 int
  237 pms_ioctl(v, cmd, data, flag, p)
  238         void *v;
  239         u_long cmd;
  240         caddr_t data;
  241         int flag;
  242         struct proc *p;
  243 {
  244         struct pms_softc *sc = v;
  245         u_char kbcmd[2];
  246         int i;
  247 
  248         switch (cmd) {
  249         case WSMOUSEIO_GTYPE:
  250                 *(u_int *)data = WSMOUSE_TYPE_PS2;
  251                 break;
  252                 
  253         case WSMOUSEIO_SRES:
  254                 i = ((int) *(u_int *)data - 12) / 25;           
  255                 /* valid values are {0,1,2,3} */
  256                 if (i < 0)
  257                         i = 0;
  258                 if (i > 3)
  259                         i = 3;
  260                 
  261                 kbcmd[0] = PMS_SET_RES;
  262                 kbcmd[1] = (unsigned char) i;                   
  263                 i = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, kbcmd, 
  264                     2, 0, 1, 0);
  265                 
  266                 if (i)
  267                         printf("pms_ioctl: SET_RES command error\n");
  268                 break;
  269                 
  270         default:
  271                 return (-1);
  272         }
  273         return (0);
  274 }
  275 
  276 /* Masks for the first byte of a packet */
  277 #define PS2LBUTMASK 0x01
  278 #define PS2RBUTMASK 0x02
  279 #define PS2MBUTMASK 0x04
  280 
  281 void pmsinput(vsc, data)
  282 void *vsc;
  283 int data;
  284 {
  285         struct pms_softc *sc = vsc;
  286         signed char dy;
  287         u_int changed;
  288 
  289         if (!sc->sc_enabled) {
  290                 /* Interrupts are not expected.  Discard the byte. */
  291                 return;
  292         }
  293 
  294         switch (sc->inputstate) {
  295 
  296         case 0:
  297                 if ((data & 0xc0) == 0) { /* no ovfl, bit 3 == 1 too? */
  298                         sc->buttons = ((data & PS2LBUTMASK) ? 0x1 : 0) |
  299                             ((data & PS2MBUTMASK) ? 0x2 : 0) |
  300                             ((data & PS2RBUTMASK) ? 0x4 : 0);
  301                         ++sc->inputstate;
  302                 }
  303                 break;
  304 
  305         case 1:
  306                 sc->dx = data;
  307                 /* Bounding at -127 avoids a bug in XFree86. */
  308                 sc->dx = (sc->dx == -128) ? -127 : sc->dx;
  309                 ++sc->inputstate;
  310                 break;
  311 
  312         case 2:
  313                 dy = data;
  314                 dy = (dy == -128) ? -127 : dy;
  315                 sc->inputstate = 0;
  316 
  317                 changed = (sc->buttons ^ sc->oldbuttons);
  318                 sc->oldbuttons = sc->buttons;
  319 
  320                 if (sc->dx || dy || changed)
  321                         wsmouse_input(sc->sc_wsmousedev,
  322                                       sc->buttons, sc->dx, dy, 0, 0,
  323                                       WSMOUSE_INPUT_DELTA);
  324                 break;
  325         }
  326 
  327         return;
  328 }
  329 
  330 struct cfdriver pms_cd = {
  331         NULL, "pms", DV_DULL
  332 };

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