root/dev/hil/hilms.c

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

DEFINITIONS

This source file includes following definitions.
  1. hilmsprobe
  2. hilmsattach
  3. hilmsdetach
  4. hilms_enable
  5. hilms_disable
  6. hilms_ioctl
  7. hilms_callback

    1 /*      $OpenBSD: hilms.c,v 1.5 2007/04/10 22:37:17 miod Exp $  */
    2 /*
    3  * Copyright (c) 2003, Miodrag Vallat.
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   18  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
   19  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   23  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   24  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   25  * POSSIBILITY OF SUCH DAMAGE.
   26  *
   27  */
   28 
   29 #include <sys/param.h>
   30 #include <sys/systm.h>
   31 #include <sys/device.h>
   32 #include <sys/ioctl.h>
   33 
   34 #include <machine/autoconf.h>
   35 #include <machine/bus.h>
   36 #include <machine/cpu.h>
   37 
   38 #include <dev/hil/hilreg.h>
   39 #include <dev/hil/hilvar.h>
   40 #include <dev/hil/hildevs.h>
   41 
   42 #include <dev/wscons/wsconsio.h>
   43 #include <dev/wscons/wsmousevar.h>
   44 
   45 struct hilms_softc {
   46         struct hildev_softc sc_hildev;
   47 
   48         int             sc_features;
   49         u_int           sc_buttons;
   50         u_int           sc_axes;
   51         int             sc_enabled;
   52         int             sc_buttonstate;
   53 
   54         struct device   *sc_wsmousedev;
   55 };
   56 
   57 int     hilmsprobe(struct device *, void *, void *);
   58 void    hilmsattach(struct device *, struct device *, void *);
   59 int     hilmsdetach(struct device *, int);
   60 
   61 struct cfdriver hilms_cd = {
   62         NULL, "hilms", DV_DULL
   63 };
   64 
   65 struct cfattach hilms_ca = {
   66         sizeof(struct hilms_softc), hilmsprobe, hilmsattach, hilmsdetach,
   67 };
   68 
   69 int     hilms_enable(void *);
   70 int     hilms_ioctl(void *, u_long, caddr_t, int, struct proc *);
   71 void    hilms_disable(void *);
   72 
   73 const struct wsmouse_accessops hilms_accessops = {
   74         hilms_enable,
   75         hilms_ioctl,
   76         hilms_disable,
   77 };
   78 
   79 void    hilms_callback(struct hildev_softc *, u_int, u_int8_t *);
   80 
   81 int
   82 hilmsprobe(struct device *parent, void *match, void *aux)
   83 {
   84         struct hil_attach_args *ha = aux;
   85 
   86         if (ha->ha_type != HIL_DEVICE_MOUSE)
   87                 return (0);
   88 
   89         /*
   90          * Reject anything that has only buttons - they are handled as
   91          * keyboards, really.
   92          */
   93         if (ha->ha_infolen > 1 && (ha->ha_info[1] & HIL_AXMASK) == 0)
   94                 return (0);
   95 
   96         return (1);
   97 }
   98 
   99 void
  100 hilmsattach(struct device *parent, struct device *self, void *aux)
  101 {
  102         struct hilms_softc *sc = (void *)self;
  103         struct hil_attach_args *ha = aux;
  104         struct wsmousedev_attach_args a;
  105         int iob, rx, ry;
  106 
  107         sc->hd_code = ha->ha_code;
  108         sc->hd_type = ha->ha_type;
  109         sc->hd_infolen = ha->ha_infolen;
  110         bcopy(ha->ha_info, sc->hd_info, ha->ha_infolen);
  111         sc->hd_fn = hilms_callback;
  112 
  113         /*
  114          * Interpret the identification bytes, if any
  115          */
  116         rx = ry = 0;
  117         if (ha->ha_infolen > 1) {
  118                 sc->sc_features = ha->ha_info[1];
  119                 sc->sc_axes = sc->sc_features & HIL_AXMASK;
  120 
  121                 if (sc->sc_features & HIL_IOB) {
  122                         /* skip resolution bytes */
  123                         iob = 4;
  124                         if (sc->sc_features & HIL_ABSOLUTE) {
  125                                 /* skip ranges */
  126                                 rx = ha->ha_info[4] | (ha->ha_info[5] << 8);
  127                                 if (sc->sc_axes > 1)
  128                                         ry = ha->ha_info[6] |
  129                                             (ha->ha_info[7] << 8);
  130                                 iob += 2 * sc->sc_axes;
  131                         }
  132 
  133                         if (iob >= ha->ha_infolen) {
  134                                 sc->sc_features &= ~(HIL_IOB | HILIOB_PIO);
  135                         } else {
  136                                 iob = ha->ha_info[iob];
  137                                 sc->sc_buttons = iob & HILIOB_BMASK;
  138                                 sc->sc_features |= (iob & HILIOB_PIO);
  139                         }
  140                 }
  141         }
  142 
  143         printf(", %d axes", sc->sc_axes);
  144         if (sc->sc_buttons == 1)
  145                 printf(", 1 button");
  146         else if (sc->sc_buttons > 1)
  147                 printf(", %d buttons", sc->sc_buttons);
  148         if (sc->sc_features & HILIOB_PIO)
  149                 printf(", pressure sensor");
  150         if (sc->sc_features & HIL_ABSOLUTE) {
  151                 printf ("\n%s: %d", self->dv_xname, rx);
  152                 if (ry != 0)
  153                         printf("x%d", ry);
  154                 else
  155                         printf(" linear");
  156                 printf(" fixed area");
  157         }
  158 
  159         printf("\n");
  160 
  161         sc->sc_enabled = 0;
  162 
  163         a.accessops = &hilms_accessops;
  164         a.accesscookie = sc;
  165 
  166         sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
  167 }
  168 
  169 int
  170 hilmsdetach(struct device *self, int flags)
  171 {
  172         struct hilms_softc *sc = (void *)self;
  173 
  174         if (sc->sc_wsmousedev != NULL)
  175                 return config_detach(sc->sc_wsmousedev, flags);
  176 
  177         return (0);
  178 }
  179 
  180 int
  181 hilms_enable(void *v)
  182 {
  183         struct hilms_softc *sc = v;
  184 
  185         if (sc->sc_enabled)
  186                 return EBUSY;
  187 
  188         sc->sc_enabled = 1;
  189         sc->sc_buttonstate = 0;
  190 
  191         return (0);
  192 }
  193 
  194 void
  195 hilms_disable(void *v)
  196 {
  197         struct hilms_softc *sc = v;
  198 
  199         sc->sc_enabled = 0;
  200 }
  201 
  202 int
  203 hilms_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
  204 {
  205 #if 0
  206         struct hilms_softc *sc = v;
  207 #endif
  208 
  209         switch (cmd) {
  210         case WSMOUSEIO_GTYPE:
  211                 *(int *)data = WSMOUSE_TYPE_HIL;
  212                 return 0;
  213         }
  214 
  215         return -1;
  216 }
  217 
  218 void
  219 hilms_callback(struct hildev_softc *dev, u_int buflen, u_int8_t *buf)
  220 {
  221         struct hilms_softc *sc = (struct hilms_softc *)dev;
  222         int type, flags;
  223         int dx, dy, dz, button;
  224 #ifdef DIAGNOSTIC
  225         int minlen;
  226 #endif
  227 
  228         /*
  229          * Ignore packet if we don't need it
  230          */
  231         if (sc->sc_enabled == 0)
  232                 return;
  233 
  234         type = *buf++;
  235 
  236 #ifdef DIAGNOSTIC
  237         /*
  238          * Check that the packet contains all the expected data,
  239          * ignore it if too short.
  240          */
  241         minlen = 1;
  242         if (type & HIL_MOUSEMOTION) {
  243                 minlen += sc->sc_axes <<
  244                     (sc->sc_features & HIL_16_BITS) ? 1 : 0;
  245         }
  246         if (type & HIL_MOUSEBUTTON)
  247                 minlen++;
  248 
  249         if (minlen > buflen)
  250                 return;
  251 #endif
  252 
  253         /*
  254          * The packet can contain both a mouse motion and a button event.
  255          * In this case, the motion data comes first.
  256          */
  257 
  258         if (type & HIL_MOUSEMOTION) {
  259                 flags = sc->sc_features & HIL_ABSOLUTE ?
  260                     WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y |
  261                     WSMOUSE_INPUT_ABSOLUTE_Z : WSMOUSE_INPUT_DELTA;
  262                 if (sc->sc_features & HIL_16_BITS) {
  263                         dx = *buf++;
  264                         dx |= (*buf++) << 8;
  265                         if (!(sc->sc_features & HIL_ABSOLUTE))
  266                                 dx = (int16_t)dx;
  267                 } else {
  268                         dx = *buf++;
  269                         if (!(sc->sc_features & HIL_ABSOLUTE))
  270                                 dx = (int8_t)dx;
  271                 }
  272                 if (sc->sc_axes > 1) {
  273                         if (sc->sc_features & HIL_16_BITS) {
  274                                 dy = *buf++;
  275                                 dy |= (*buf++) << 8;
  276                                 if (!(sc->sc_features & HIL_ABSOLUTE))
  277                                         dy = (int16_t)dy;
  278                         } else {
  279                                 dy = *buf++;
  280                                 if (!(sc->sc_features & HIL_ABSOLUTE))
  281                                         dy = (int8_t)dy;
  282                         }
  283                         if (sc->sc_axes > 2) {
  284                                 if (sc->sc_features & HIL_16_BITS) {
  285                                         dz = *buf++;
  286                                         dz |= (*buf++) << 8;
  287                                         if (!(sc->sc_features & HIL_ABSOLUTE))
  288                                                 dz = (int16_t)dz;
  289                                 } else {
  290                                         dz = *buf++;
  291                                         if (!(sc->sc_features & HIL_ABSOLUTE))
  292                                                 dz = (int8_t)dz;
  293                                 }
  294                         } else
  295                                 dz = 0;
  296                 } else
  297                         dy = dz = 0;
  298 
  299                 /*
  300                  * Correct Y direction for button boxes.
  301                  */
  302                 if ((sc->sc_features & HIL_ABSOLUTE) == 0 &&
  303                     sc->sc_buttons == 0)
  304                         dy = -dy;
  305         } else
  306                 dx = dy = dz = flags = 0;
  307 
  308         if (type & HIL_MOUSEBUTTON) {
  309                 button = *buf;
  310                 /*
  311                  * The pressure sensor is very primitive and only has
  312                  * a boolean behaviour, as an extra mouse button, which is
  313                  * down if there is pressure or the pen is near the tablet,
  314                  * and up if there is no pressure or the pen is far from the
  315                  * tablet - at least for Tablet id 0x94, P/N 46088B
  316                  *
  317                  * The corresponding codes are 0x8f and 0x8e. Convert them
  318                  * to a pseudo fourth button - even if the tablet never
  319                  * has three buttons.
  320                  */
  321                 button = (button - 0x80) >> 1;
  322                 if (button > 4)
  323                         button = 4;
  324 
  325                 if (*buf & 1) {
  326                         /* Button released, or no pressure */
  327                         sc->sc_buttonstate &= ~(1 << button);
  328                 } else {
  329                         /* Button pressed, or pressure */
  330                         sc->sc_buttonstate |= (1 << button);
  331                 }
  332                 /* buf++; */
  333         }
  334         
  335         if (sc->sc_wsmousedev != NULL)
  336                 wsmouse_input(sc->sc_wsmousedev,
  337                     sc->sc_buttonstate, dx, dy, dz, 0, flags);
  338 }

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