The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/sun/ms.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: ms.c,v 1.28 2003/09/21 19:16:57 jdolecek Exp $ */
    2 
    3 /*
    4  * Copyright (c) 1992, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This software was developed by the Computer Systems Engineering group
    8  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
    9  * contributed to Berkeley.
   10  *
   11  * All advertising materials mentioning features or use of this software
   12  * must display the following acknowledgement:
   13  *      This product includes software developed by the University of
   14  *      California, Lawrence Berkeley Laboratory.
   15  *
   16  * Redistribution and use in source and binary forms, with or without
   17  * modification, are permitted provided that the following conditions
   18  * are met:
   19  * 1. Redistributions of source code must retain the above copyright
   20  *    notice, this list of conditions and the following disclaimer.
   21  * 2. Redistributions in binary form must reproduce the above copyright
   22  *    notice, this list of conditions and the following disclaimer in the
   23  *    documentation and/or other materials provided with the distribution.
   24  * 3. Neither the name of the University nor the names of its contributors
   25  *    may be used to endorse or promote products derived from this software
   26  *    without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   38  * SUCH DAMAGE.
   39  *
   40  *      @(#)ms.c        8.1 (Berkeley) 6/11/93
   41  */
   42 
   43 /*
   44  * Mouse driver (/dev/mouse)
   45  */
   46 
   47 /*
   48  * Zilog Z8530 Dual UART driver (mouse interface)
   49  *
   50  * This is the "slave" driver that will be attached to
   51  * the "zsc" driver for a Sun mouse.
   52  */
   53 
   54 #include <sys/cdefs.h>
   55 __KERNEL_RCSID(0, "$NetBSD: ms.c,v 1.28 2003/09/21 19:16:57 jdolecek Exp $");
   56 
   57 #include <sys/param.h>
   58 #include <sys/systm.h>
   59 #include <sys/conf.h>
   60 #include <sys/device.h>
   61 #include <sys/ioctl.h>
   62 #include <sys/kernel.h>
   63 #include <sys/proc.h>
   64 #include <sys/signal.h>
   65 #include <sys/signalvar.h>
   66 #include <sys/time.h>
   67 #include <sys/syslog.h>
   68 #include <sys/select.h>
   69 #include <sys/poll.h>
   70 
   71 #include <machine/vuid_event.h>
   72 
   73 #include <dev/ic/z8530reg.h>
   74 #include <machine/z8530var.h>
   75 #include <dev/sun/event_var.h>
   76 #include <dev/sun/msvar.h>
   77 
   78 #include <dev/wscons/wsconsio.h>
   79 #include <dev/wscons/wsmousevar.h>
   80 
   81 #include "locators.h"
   82 #include "wsmouse.h"
   83 
   84 extern struct cfdriver ms_cd;
   85 
   86 dev_type_open(msopen);
   87 dev_type_close(msclose);
   88 dev_type_read(msread);
   89 dev_type_ioctl(msioctl);
   90 dev_type_poll(mspoll);
   91 dev_type_kqfilter(mskqfilter);
   92 
   93 const struct cdevsw ms_cdevsw = {
   94         msopen, msclose, msread, nowrite, msioctl,
   95         nostop, notty, mspoll, nommap, mskqfilter,
   96 };
   97 
   98 /****************************************************************
   99  *  Entry points for /dev/mouse
  100  *  (open,close,read,write,...)
  101  ****************************************************************/
  102 
  103 int
  104 msopen(dev, flags, mode, p)
  105         dev_t dev;
  106         int flags, mode;
  107         struct proc *p;
  108 {
  109         struct ms_softc *ms;
  110         int unit;
  111 
  112         unit = minor(dev);
  113         if (unit >= ms_cd.cd_ndevs)
  114                 return (ENXIO);
  115         ms = ms_cd.cd_devs[unit];
  116         if (ms == NULL)
  117                 return (ENXIO);
  118 
  119         /* This is an exclusive open device. */
  120         if (ms->ms_events.ev_io)
  121                 return (EBUSY);
  122 
  123         if (ms->ms_deviopen) {
  124                 int err;
  125                 err = (*ms->ms_deviopen)((struct device *)ms, flags);
  126                 if (err) 
  127                         return (err);
  128         }
  129         ms->ms_events.ev_io = p;
  130         ev_init(&ms->ms_events);        /* may cause sleep */
  131 
  132         ms->ms_ready = 1;               /* start accepting events */
  133         return (0);
  134 }
  135 
  136 int
  137 msclose(dev, flags, mode, p)
  138         dev_t dev;
  139         int flags, mode;
  140         struct proc *p;
  141 {
  142         struct ms_softc *ms;
  143 
  144         ms = ms_cd.cd_devs[minor(dev)];
  145         ms->ms_ready = 0;               /* stop accepting events */
  146         ev_fini(&ms->ms_events);
  147 
  148         ms->ms_events.ev_io = NULL;
  149         if (ms->ms_deviclose) {
  150                 int err;
  151                 err = (*ms->ms_deviclose)((struct device *)ms, flags);
  152                 if (err) 
  153                         return (err);
  154         }
  155         return (0);
  156 }
  157 
  158 int
  159 msread(dev, uio, flags)
  160         dev_t dev;
  161         struct uio *uio;
  162         int flags;
  163 {
  164         struct ms_softc *ms;
  165 
  166         ms = ms_cd.cd_devs[minor(dev)];
  167         return (ev_read(&ms->ms_events, uio, flags));
  168 }
  169 
  170 int
  171 msioctl(dev, cmd, data, flag, p)
  172         dev_t dev;
  173         u_long cmd;
  174         caddr_t data;
  175         int flag;
  176         struct proc *p;
  177 {
  178         struct ms_softc *ms;
  179 
  180         ms = ms_cd.cd_devs[minor(dev)];
  181 
  182         switch (cmd) {
  183 
  184         case FIONBIO:           /* we will remove this someday (soon???) */
  185                 return (0);
  186 
  187         case FIOASYNC:
  188                 ms->ms_events.ev_async = *(int *)data != 0;
  189                 return (0);
  190 
  191         case FIOSETOWN:
  192                 if (-*(int *)data != ms->ms_events.ev_io->p_pgid
  193                     && *(int *)data != ms->ms_events.ev_io->p_pid)
  194                         return (EPERM);
  195                 return (0);
  196 
  197         case TIOCSPGRP:
  198                 if (*(int *)data != ms->ms_events.ev_io->p_pgid)
  199                         return (EPERM);
  200                 return (0);
  201 
  202         case VUIDGFORMAT:
  203                 /* we only do firm_events */
  204                 *(int *)data = VUID_FIRM_EVENT;
  205                 return (0);
  206 
  207         case VUIDSFORMAT:
  208                 if (*(int *)data != VUID_FIRM_EVENT)
  209                         return (EINVAL);
  210                 return (0);
  211         }
  212         return (ENOTTY);
  213 }
  214 
  215 int
  216 mspoll(dev, events, p)
  217         dev_t dev;
  218         int events;
  219         struct proc *p;
  220 {
  221         struct ms_softc *ms;
  222 
  223         ms = ms_cd.cd_devs[minor(dev)];
  224         return (ev_poll(&ms->ms_events, events, p));
  225 }
  226 
  227 int
  228 mskqfilter(dev, kn)
  229         dev_t dev;
  230         struct knote *kn;
  231 {
  232         struct ms_softc *ms;
  233 
  234         ms = ms_cd.cd_devs[minor(dev)];
  235         return (ev_kqfilter(&ms->ms_events, kn));
  236 }
  237 
  238 /****************************************************************
  239  * Middle layer (translator)
  240  ****************************************************************/
  241 
  242 /*
  243  * Called by our ms_softint() routine on input.
  244  */
  245 void
  246 ms_input(ms, c)
  247         struct ms_softc *ms;
  248         int c;
  249 {
  250         struct firm_event *fe;
  251         int mb, ub, d, get, put, any;
  252         static const char to_one[] = { 1, 2, 2, 4, 4, 4, 4 };
  253         static const int to_id[] = { MS_RIGHT, MS_MIDDLE, 0, MS_LEFT };
  254 
  255         /*
  256          * Discard input if not ready.  Drop sync on parity or framing
  257          * error; gain sync on button byte.
  258          */
  259         if (ms->ms_ready == 0)
  260                 return;
  261         if (c == -1) {
  262                 ms->ms_byteno = -1;
  263                 return;
  264         }
  265         if ((c & ~0x0f) == 0x80) {      /* if in 0x80..0x8f */
  266                 if (c & 8) {
  267                         ms->ms_byteno = 1;      /* short form (3 bytes) */
  268                 } else {
  269                         ms->ms_byteno = 0;      /* long form (5 bytes) */
  270                 }
  271         }
  272 
  273         /*
  274          * Run the decode loop, adding to the current information.
  275          * We add, rather than replace, deltas, so that if the event queue
  276          * fills, we accumulate data for when it opens up again.
  277          */
  278         switch (ms->ms_byteno) {
  279 
  280         case -1:
  281                 return;
  282 
  283         case 0:
  284                 /* buttons (long form) */
  285                 ms->ms_byteno = 2;
  286                 ms->ms_mb = (~c) & 0x7;
  287                 return;
  288 
  289         case 1:
  290                 /* buttons (short form) */
  291                 ms->ms_byteno = 4;
  292                 ms->ms_mb = (~c) & 0x7;
  293                 return;
  294 
  295         case 2:
  296                 /* first delta-x */
  297                 ms->ms_byteno = 3;
  298                 ms->ms_dx += (char)c;
  299                 return;
  300 
  301         case 3:
  302                 /* first delta-y */
  303                 ms->ms_byteno = 4;
  304                 ms->ms_dy += (char)c;
  305                 return;
  306 
  307         case 4:
  308                 /* second delta-x */
  309                 ms->ms_byteno = 5;
  310                 ms->ms_dx += (char)c;
  311                 return;
  312 
  313         case 5:
  314                 /* second delta-y */
  315                 ms->ms_byteno = -1;     /* wait for button-byte again */
  316                 ms->ms_dy += (char)c;
  317                 break;
  318 
  319         default:
  320                 panic("ms_rint");
  321                 /* NOTREACHED */
  322         }
  323 
  324 #if NWSMOUSE > 0
  325         if (ms->ms_wsmousedev != NULL && ms->ms_ready == 2) {
  326                 mb = ((ms->ms_mb & 4) >> 2) |
  327                         (ms->ms_mb & 2) |
  328                         ((ms->ms_mb & 1) << 2);
  329                 wsmouse_input(ms->ms_wsmousedev,
  330                               mb, ms->ms_dx, ms->ms_dy, 0,
  331                               WSMOUSE_INPUT_DELTA);
  332                 ms->ms_dx = 0;
  333                 ms->ms_dy = 0;
  334                 return;
  335         }
  336 #endif
  337         /*
  338          * We have at least one event (mouse button, delta-X, or
  339          * delta-Y; possibly all three, and possibly three separate
  340          * button events).  Deliver these events until we are out
  341          * of changes or out of room.  As events get delivered,
  342          * mark them `unchanged'.
  343          */
  344         any = 0;
  345         get = ms->ms_events.ev_get;
  346         put = ms->ms_events.ev_put;
  347         fe = &ms->ms_events.ev_q[put];
  348 
  349         /* NEXT prepares to put the next event, backing off if necessary */
  350 #define NEXT \
  351         if ((++put) % EV_QSIZE == get) { \
  352                 put--; \
  353                 goto out; \
  354         }
  355         /* ADVANCE completes the `put' of the event */
  356 #define ADVANCE \
  357         fe++; \
  358         if (put >= EV_QSIZE) { \
  359                 put = 0; \
  360                 fe = &ms->ms_events.ev_q[0]; \
  361         } \
  362         any = 1
  363 
  364         mb = ms->ms_mb;
  365         ub = ms->ms_ub;
  366         while ((d = mb ^ ub) != 0) {
  367                 /*
  368                  * Mouse button change.  Convert up to three changes
  369                  * to the `first' change, and drop it into the event queue.
  370                  */
  371                 NEXT;
  372                 d = to_one[d - 1];              /* from 1..7 to {1,2,4} */
  373                 fe->id = to_id[d - 1];          /* from {1,2,4} to ID */
  374                 fe->value = mb & d ? VKEY_DOWN : VKEY_UP;
  375                 fe->time = time;
  376                 ADVANCE;
  377                 ub ^= d;
  378         }
  379         if (ms->ms_dx) {
  380                 NEXT;
  381                 fe->id = LOC_X_DELTA;
  382                 fe->value = ms->ms_dx;
  383                 fe->time = time;
  384                 ADVANCE;
  385                 ms->ms_dx = 0;
  386         }
  387         if (ms->ms_dy) {
  388                 NEXT;
  389                 fe->id = LOC_Y_DELTA;
  390                 fe->value = ms->ms_dy;
  391                 fe->time = time;
  392                 ADVANCE;
  393                 ms->ms_dy = 0;
  394         }
  395 out:
  396         if (any) {
  397                 ms->ms_ub = ub;
  398                 ms->ms_events.ev_put = put;
  399                 EV_WAKEUP(&ms->ms_events);
  400         }
  401 }

Cache object: 1e71ad209514ed25f791d3953e3b1480


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.