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/pckbport/pms.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: pms.c,v 1.2 2004/03/18 21:05:19 bjh21 Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 1994 Charles M. Hannum.
    5  * Copyright (c) 1992, 1993 Erik Forsberg.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
   15  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   16  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
   17  * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   22  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   23  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   24  */
   25 
   26 #include <sys/cdefs.h>
   27 __KERNEL_RCSID(0, "$NetBSD: pms.c,v 1.2 2004/03/18 21:05:19 bjh21 Exp $");
   28 
   29 #include <sys/param.h>
   30 #include <sys/systm.h>
   31 #include <sys/device.h>
   32 #include <sys/ioctl.h>
   33 #include <sys/kernel.h>
   34 #include <sys/kthread.h>
   35 
   36 #include <machine/bus.h>
   37 
   38 #include <dev/pckbport/pckbportvar.h>
   39 
   40 #include <dev/pckbport/pmsreg.h>
   41 
   42 #include <dev/wscons/wsconsio.h>
   43 #include <dev/wscons/wsmousevar.h>
   44 
   45 #ifdef PMSDEBUG
   46 int pmsdebug = 1;
   47 #define DPRINTF(x)      if (pmsdebug) printf x
   48 #else
   49 #define DPRINTF(x)
   50 #endif
   51 
   52 enum pms_type { PMS_UNKNOWN, PMS_STANDARD, PMS_SCROLL3, PMS_SCROLL5 };
   53 
   54 struct pms_protocol {
   55         int rates[3];
   56         int response;
   57         const char *name;
   58 } pms_protocols[] = {
   59         { { 0, 0, 0 }, 0, "unknown protocol" },
   60         { { 0, 0, 0 }, 0, "no scroll wheel (3 buttons)" },
   61         { { 200, 100, 80 }, 3, "scroll wheel (3 buttons)" },
   62         { { 200, 200, 80 }, 4, "scroll wheel (5 buttons)" }
   63 };
   64 
   65 enum pms_type tries[] = {
   66         PMS_SCROLL5, PMS_SCROLL3, PMS_STANDARD, PMS_UNKNOWN
   67 };
   68 
   69 struct pms_softc {              /* driver status information */
   70         struct device sc_dev;
   71 
   72         pckbport_tag_t sc_kbctag;
   73         int sc_kbcslot;
   74 
   75         int sc_enabled;         /* input enabled? */
   76 #ifndef PMS_DISABLE_POWERHOOK
   77         void *sc_powerhook;     /* cookie from power hook */
   78         int sc_suspended;       /* suspended? */
   79 #endif /* !PMS_DISABLE_POWERHOOK */
   80         int inputstate;         /* number of bytes received for this packet */
   81         u_int buttons;          /* mouse button status */
   82         enum pms_type protocol;
   83         unsigned char packet[4];
   84         struct timeval last, current;
   85 
   86         struct device *sc_wsmousedev;
   87         struct proc *sc_event_thread;
   88 };
   89 
   90 int pmsprobe(struct device *, struct cfdata *, void *);
   91 void pmsattach(struct device *, struct device *, void *);
   92 void pmsinput(void *, int);
   93 
   94 CFATTACH_DECL(pms, sizeof(struct pms_softc),
   95     pmsprobe, pmsattach, NULL, NULL);
   96 
   97 static int      pms_protocol(pckbport_tag_t, pckbport_slot_t);
   98 static void     do_enable(struct pms_softc *);
   99 static void     do_disable(struct pms_softc *);
  100 static void     pms_reset_thread(void*);
  101 static void     pms_spawn_reset_thread(void*);
  102 int     pms_enable(void *);
  103 int     pms_ioctl(void *, u_long, caddr_t, int, struct proc *);
  104 void    pms_disable(void *);
  105 #ifndef PMS_DISABLE_POWERHOOK
  106 void    pms_power(int, void *);
  107 #endif /* !PMS_DISABLE_POWERHOOK */
  108 
  109 const struct wsmouse_accessops pms_accessops = {
  110         pms_enable,
  111         pms_ioctl,
  112         pms_disable,
  113 };
  114 
  115 static int
  116 pms_protocol(pckbport_tag_t tag, pckbport_slot_t slot)
  117 {
  118         u_char cmd[2], resp[1];
  119         int i, j, res;
  120         struct pms_protocol *p;
  121 
  122         for (j = 0; j < sizeof(tries) / sizeof(tries[0]); ++j) {
  123                 p = &pms_protocols[tries[j]];
  124                 if (!p->rates[0])
  125                         break;
  126                 cmd[0] = PMS_SET_SAMPLE;
  127                 for (i = 0; i < 3; i++) {
  128                         cmd[1] = p->rates[i];
  129                         res = pckbport_enqueue_cmd(tag, slot, cmd, 2, 0, 1, 0);
  130                         if (res)
  131                                 return PMS_STANDARD;
  132                 }
  133 
  134                 cmd[0] = PMS_SEND_DEV_ID;
  135                 res = pckbport_enqueue_cmd(tag, slot, cmd, 1, 1, 1, resp);
  136                 if (res)
  137                         return PMS_UNKNOWN;
  138                 if (resp[0] == p->response) {
  139                         DPRINTF(("pms_protocol: found mouse protocol %d\n",
  140                                 tries[j]));
  141                         return tries[j];
  142                 }
  143         }
  144         DPRINTF(("pms_protocol: standard PS/2 protocol (no scroll wheel)\n"));
  145         return PMS_STANDARD;
  146 }
  147 
  148 int
  149 pmsprobe(struct device *parent, struct cfdata *match, void *aux)
  150 {
  151         struct pckbport_attach_args *pa = aux;
  152         u_char cmd[1], resp[2];
  153         int res;
  154 
  155         if (pa->pa_slot != PCKBPORT_AUX_SLOT)
  156                 return 0;
  157 
  158         /* Flush any garbage. */
  159         pckbport_flush(pa->pa_tag, pa->pa_slot);
  160 
  161         /* reset the device */
  162         cmd[0] = PMS_RESET;
  163         res = pckbport_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1);
  164         if (res) {
  165 #ifdef DEBUG
  166                 printf("pmsprobe: reset error %d\n", res);
  167 #endif
  168                 return 0;
  169         }
  170         if (resp[0] != PMS_RSTDONE) {
  171                 printf("pmsprobe: reset response 0x%x\n", resp[0]);
  172                 return 0;
  173         }
  174 
  175         /* get type number (0 = mouse) */
  176         if (resp[1] != 0) {
  177 #ifdef DEBUG
  178                 printf("pmsprobe: type 0x%x\n", resp[1]);
  179 #endif
  180                 return 0;
  181         }
  182 
  183         return 10;
  184 }
  185 
  186 void
  187 pmsattach(struct device *parent, struct device *self, void *aux)
  188 {
  189         struct pms_softc *sc = (void *)self;
  190         struct pckbport_attach_args *pa = aux;
  191         struct wsmousedev_attach_args a;
  192         u_char cmd[1], resp[2];
  193         int res;
  194 
  195         sc->sc_kbctag = pa->pa_tag;
  196         sc->sc_kbcslot = pa->pa_slot;
  197 
  198         printf("\n");
  199 
  200         /* Flush any garbage. */
  201         pckbport_flush(pa->pa_tag, pa->pa_slot);
  202 
  203         /* reset the device */
  204         cmd[0] = PMS_RESET;
  205         res = pckbport_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1);
  206 #ifdef DEBUG
  207         if (res || resp[0] != PMS_RSTDONE || resp[1] != 0) {
  208                 printf("pmsattach: reset error\n");
  209                 return;
  210         }
  211 #endif
  212         sc->inputstate = 0;
  213         sc->buttons = 0;
  214         sc->protocol = PMS_UNKNOWN;
  215 
  216         pckbport_set_inputhandler(sc->sc_kbctag, sc->sc_kbcslot,
  217                                pmsinput, sc, sc->sc_dev.dv_xname);
  218 
  219         a.accessops = &pms_accessops;
  220         a.accesscookie = sc;
  221 
  222         /*
  223          * Attach the wsmouse, saving a handle to it.
  224          * Note that we don't need to check this pointer against NULL
  225          * here or in pmsintr, because if this fails pms_enable() will
  226          * never be called, so pmsinput() will never be called.
  227          */
  228         sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
  229 
  230         /* no interrupts until enabled */
  231         cmd[0] = PMS_DEV_DISABLE;
  232         res = pckbport_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 0, 0, 0);
  233         if (res)
  234                 printf("pmsattach: disable error\n");
  235         pckbport_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
  236 
  237         kthread_create(pms_spawn_reset_thread, sc);
  238 
  239 #ifndef PMS_DISABLE_POWERHOOK
  240         sc->sc_powerhook = powerhook_establish(pms_power, sc);
  241         sc->sc_suspended = 0;
  242 #endif /* !PMS_DISABLE_POWERHOOK */
  243 }
  244 
  245 static void
  246 do_enable(struct pms_softc *sc)
  247 {
  248         u_char cmd[1];
  249         int res;
  250 
  251         sc->inputstate = 0;
  252         sc->buttons = 0;
  253 
  254         pckbport_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 1);
  255 
  256         cmd[0] = PMS_DEV_ENABLE;
  257         res = pckbport_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd, 1, 0, 1, 0);
  258         if (res)
  259                 printf("pms_enable: command error %d\n", res);
  260 
  261         if (sc->protocol == PMS_UNKNOWN)
  262                 sc->protocol = pms_protocol(sc->sc_kbctag, sc->sc_kbcslot);
  263         DPRINTF(("pms_enable: using %s protocol\n",
  264             pms_protocols[sc->protocol].name));
  265 #if 0
  266         {
  267                 u_char scmd[2];
  268 
  269                 scmd[0] = PMS_SET_RES;
  270                 scmd[1] = 3; /* 8 counts/mm */
  271                 res = pckbport_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, scmd,
  272                     2, 0, 1, 0);
  273                 if (res)
  274                         printf("pms_enable: setup error1 (%d)\n", res);
  275 
  276                 scmd[0] = PMS_SET_SCALE21;
  277                 res = pckbport_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, scmd,
  278                     1, 0, 1, 0);
  279                 if (res)
  280                         printf("pms_enable: setup error2 (%d)\n", res);
  281 
  282                 scmd[0] = PMS_SET_SAMPLE;
  283                 scmd[1] = 100; /* 100 samples/sec */
  284                 res = pckbport_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, scmd,
  285                     2, 0, 1, 0);
  286                 if (res)
  287                         printf("pms_enable: setup error3 (%d)\n", res);
  288         }
  289 #endif
  290 }
  291 
  292 static void
  293 do_disable(struct pms_softc *sc)
  294 {
  295         u_char cmd[1];
  296         int res;
  297 
  298         cmd[0] = PMS_DEV_DISABLE;
  299         res = pckbport_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd, 1, 0, 1, 0);
  300         if (res)
  301                 printf("pms_disable: command error\n");
  302 
  303         pckbport_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
  304 }
  305 
  306 int
  307 pms_enable(void *v)
  308 {
  309         struct pms_softc *sc = v;
  310         int s;
  311 
  312         if (sc->sc_enabled)
  313                 return EBUSY;
  314 
  315         do_enable(sc);
  316 
  317         s = spltty();
  318         sc->sc_enabled = 1;
  319         splx(s);
  320 
  321         return 0;
  322 }
  323 
  324 void
  325 pms_disable(void *v)
  326 {
  327         struct pms_softc *sc = v;
  328         int s;
  329 
  330         do_disable(sc);
  331 
  332         s = spltty();
  333         sc->sc_enabled = 0;
  334         splx(s);
  335 }
  336 
  337 #ifndef PMS_DISABLE_POWERHOOK
  338 void
  339 pms_power(int why, void *v)
  340 {
  341         struct pms_softc *sc = v;
  342 
  343         switch (why) {
  344         case PWR_STANDBY:
  345                 break;
  346         case PWR_SUSPEND:
  347                 if (sc->sc_enabled) {
  348                         do_disable(sc);
  349                         sc->sc_suspended = 1;
  350                 }
  351                 break;
  352         case PWR_RESUME:
  353                 if (sc->sc_enabled && sc->sc_suspended) {
  354                         sc->protocol = PMS_UNKNOWN;     /* recheck protocol & init mouse */
  355                         sc->sc_suspended = 0;
  356                         do_enable(sc); /* only if we were suspended */
  357                 }
  358         case PWR_SOFTSUSPEND:
  359         case PWR_SOFTSTANDBY:
  360         case PWR_SOFTRESUME:
  361                 break;
  362         }
  363 }
  364 #endif /* !PMS_DISABLE_POWERHOOK */
  365 
  366 int
  367 pms_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
  368 {
  369         struct pms_softc *sc = v;
  370         u_char kbcmd[2];
  371         int i;
  372 
  373         switch (cmd) {
  374         case WSMOUSEIO_GTYPE:
  375                 *(u_int *)data = WSMOUSE_TYPE_PS2;
  376                 break;
  377                 
  378         case WSMOUSEIO_SRES:
  379                 i = (*(u_int *)data - 12) / 25;
  380                 
  381                 if (i < 0)
  382                         i = 0;
  383                         
  384                 if (i > 3)
  385                         i = 3;
  386 
  387                 kbcmd[0] = PMS_SET_RES;
  388                 kbcmd[1] = i;                   
  389                 i = pckbport_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, kbcmd, 
  390                     2, 0, 1, 0);
  391                 
  392                 if (i)
  393                         printf("pms_ioctl: SET_RES command error\n");
  394                 break;
  395                 
  396         default:
  397                 return EPASSTHROUGH;
  398         }
  399         return 0;
  400 }
  401 
  402 static void
  403 pms_spawn_reset_thread(void *arg)
  404 {
  405         struct pms_softc *sc = arg;
  406 
  407         kthread_create1(pms_reset_thread, sc, &sc->sc_event_thread,
  408             sc->sc_dev.dv_xname);
  409 }
  410 
  411 static void
  412 pms_reset_thread(void *arg)
  413 {
  414         struct pms_softc *sc = arg;
  415         u_char cmd[1], resp[2];
  416         int res;
  417         int save_protocol;
  418 
  419         for (;;) {
  420                 tsleep(&sc->sc_enabled, PWAIT, "pmsreset", 0);
  421 #ifdef PMSDEBUG
  422                 if (pmsdebug)
  423 #endif
  424 #if defined(PMSDEBUG) || defined(DIAGNOSTIC)
  425                         printf("%s: resetting mouse interface\n", 
  426                             sc->sc_dev.dv_xname);
  427 #endif
  428                 save_protocol = sc->protocol;
  429                 pms_disable(sc);
  430                 cmd[0] = PMS_RESET;
  431                 res = pckbport_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd, 1,
  432                     2, 1, resp);
  433                 if (res)
  434                         DPRINTF(("%s: reset error %d\n", sc->sc_dev.dv_xname, 
  435                             res));
  436                 sc->protocol = PMS_UNKNOWN;
  437                 pms_enable(sc);
  438                 if (sc->protocol != save_protocol) {
  439 #if defined(PMSDEBUG) || defined(DIAGNOSTIC)
  440                         printf("%s: protocol change, sleeping and retrying\n",
  441                             sc->sc_dev.dv_xname);
  442 #endif
  443                         pms_disable(sc);
  444                         cmd[0] = PMS_RESET;
  445                         res = pckbport_enqueue_cmd(sc->sc_kbctag,
  446                             sc->sc_kbcslot, cmd, 1, 2, 1, resp);
  447                         if (res)
  448                                 DPRINTF(("%s: reset error %d\n",
  449                                     sc->sc_dev.dv_xname, res));
  450                         tsleep(pms_reset_thread, PWAIT, "pmsreset", hz);
  451                         cmd[0] = PMS_RESET;
  452                         res = pckbport_enqueue_cmd(sc->sc_kbctag,
  453                             sc->sc_kbcslot, cmd, 1, 2, 1, resp);
  454                         if (res)
  455                                 DPRINTF(("%s: reset error %d\n",
  456                                     sc->sc_dev.dv_xname, res));
  457                         sc->protocol = PMS_UNKNOWN;     /* reprobe protocol */
  458                         pms_enable(sc);
  459 #if defined(PMSDEBUG) || defined(DIAGNOSTIC)
  460                         if (sc->protocol != save_protocol) {
  461                                 printf("%s: protocol changed.\n",
  462                                     sc->sc_dev.dv_xname);
  463                         }
  464 #endif
  465                 }
  466         }
  467 }
  468 
  469 /* Masks for the first byte of a packet */
  470 #define PMS_LBUTMASK 0x01
  471 #define PMS_RBUTMASK 0x02
  472 #define PMS_MBUTMASK 0x04
  473 #define PMS_4BUTMASK 0x10
  474 #define PMS_5BUTMASK 0x20
  475 
  476 void
  477 pmsinput(void *vsc, int data)
  478 {
  479         struct pms_softc *sc = vsc;
  480         u_int changed;
  481         int dx, dy, dz = 0;
  482         int newbuttons = 0;
  483         int s;
  484 
  485         if (!sc->sc_enabled) {
  486                 /* Interrupts are not expected.  Discard the byte. */
  487                 return;
  488         }
  489 
  490         s = splclock();
  491         sc->current = mono_time;
  492         splx(s);
  493 
  494         if (sc->inputstate > 0) {
  495                 struct timeval diff;
  496 
  497                 timersub(&sc->current, &sc->last, &diff);
  498                 /*
  499                  * Empirically, the delay should be about 1700us on a standard
  500                  * PS/2 port.  I have seen delays as large as 4500us (rarely)
  501                  * in regular use.  When using a confused mouse, I generally
  502                  * see delays at least as large as 30,000us.  -seebs
  503                  *
  504                  * The thinkpad trackball returns at 22-23ms. So we use
  505                  * >= 40ms. In the future, I'll implement adaptable timeout
  506                  * by increasing the timeout if the mouse reset happens
  507                  * too frequently -christos
  508                  */
  509                 if (diff.tv_sec > 0 || diff.tv_usec >= 40000) {
  510                         DPRINTF(("pms_input: unusual delay (%ld.%06ld s), "
  511                             "scheduling reset\n",
  512                             (long)diff.tv_sec, (long)diff.tv_usec));
  513                         sc->inputstate = 0;
  514                         sc->sc_enabled = 0;
  515                         wakeup(&sc->sc_enabled);
  516                         return;
  517                 }
  518         }
  519         sc->last = sc->current;
  520 
  521         if (sc->inputstate == 0) {
  522                 /*
  523                  * Some devices (seen on trackballs anytime, and on
  524                  * some mice shortly after reset) output garbage bytes
  525                  * between packets.  Just ignore them.
  526                  */
  527                 if ((data & 0xc0) != 0)
  528                         return; /* not in sync yet, discard input */
  529         }
  530 
  531         sc->packet[sc->inputstate++] = data & 0xff;
  532         switch (sc->inputstate) {
  533         case 0:
  534                 /* no useful processing can be done yet */
  535                 break;
  536 
  537         case 1:
  538                 /*
  539                  * Why should we test for bit 0x8 and insist on it here?
  540                  * The old (psm.c and psm_intelli.c) drivers didn't do
  541                  * it, and there are devices where it does harm (that's
  542                  * why it is not used if using PMS_STANDARD protocol).
  543                  * Anyway, it does not to cause any harm to accept packets
  544                  * without this bit.
  545                  */
  546 #if 0
  547                 if (sc->protocol == PMS_STANDARD)
  548                         break;
  549                 if (!(sc->packet[0] & 0x8)) {
  550                         DPRINTF(("pmsinput: 0x8 not set in first byte "
  551                             "[0x%02x], resetting\n", sc->packet[0]));
  552                         sc->inputstate = 0;
  553                         sc->sc_enabled = 0;
  554                         wakeup(&sc->sc_enabled);
  555                         return;
  556                 }
  557 #endif
  558                 break;
  559 
  560         case 2:
  561                 break;
  562 
  563         case 4:
  564                 /* Case 4 is a superset of case 3. This is *not* an accident. */
  565                 if (sc->protocol == PMS_SCROLL3) {
  566                         dz = sc->packet[3];
  567                         if (dz >= 128)
  568                                 dz -= 256;
  569                         if (dz == -128)
  570                                 dz = -127;
  571                 } else if (sc->protocol == PMS_SCROLL5) {
  572                         dz = sc->packet[3] & 0xf;
  573                         if (dz >= 8)
  574                                 dz -= 16;
  575                         if (sc->packet[3] & PMS_4BUTMASK)
  576                                 newbuttons |= 0x8;
  577                         if (sc->packet[3] & PMS_5BUTMASK)
  578                                 newbuttons |= 0x10;
  579                 } else {
  580                         DPRINTF(("pmsinput: why am I looking at this byte?\n"));
  581                         dz = 0;
  582                 }
  583                 /* FALLTHROUGH */
  584         case 3:
  585                 /*
  586                  * This is only an endpoint for scroll protocols with 4
  587                  * bytes, or the standard protocol with 3.
  588                  */
  589                 if (sc->protocol != PMS_STANDARD && sc->inputstate == 3)
  590                         break;
  591 
  592                 newbuttons |= ((sc->packet[0] & PMS_LBUTMASK) ? 0x1 : 0) |
  593                     ((sc->packet[0] & PMS_MBUTMASK) ? 0x2 : 0) |
  594                     ((sc->packet[0] & PMS_RBUTMASK) ? 0x4 : 0);
  595 
  596                 dx = sc->packet[1];
  597                 if (dx >= 128)
  598                         dx -= 256;
  599                 if (dx == -128)
  600                         dx = -127;
  601 
  602                 dy = sc->packet[2];
  603                 if (dy >= 128)
  604                         dy -= 256;
  605                 if (dy == -128)
  606                         dy = -127;
  607                 
  608                 sc->inputstate = 0;
  609                 changed = (sc->buttons ^ newbuttons);
  610                 sc->buttons = newbuttons;
  611 
  612 #ifdef PMSDEBUG
  613                 if (sc->protocol == PMS_STANDARD) {
  614                         DPRINTF(("pms: packet: 0x%02x%02x%02x\n",
  615                             sc->packet[0], sc->packet[1], sc->packet[2]));
  616                 } else {
  617                         DPRINTF(("pms: packet: 0x%02x%02x%02x%02x\n",
  618                             sc->packet[0], sc->packet[1], sc->packet[2],
  619                             sc->packet[3]));
  620                 }
  621 #endif
  622                 if (dx || dy || dz || changed) {
  623 #ifdef PMSDEBUG
  624                         DPRINTF(("pms: x %+03d y %+03d z %+03d "
  625                             "buttons 0x%02x\n", dx, dy, dz, sc->buttons));
  626 #endif
  627                         wsmouse_input(sc->sc_wsmousedev,
  628                             sc->buttons, dx, dy, dz,
  629                             WSMOUSE_INPUT_DELTA);
  630                 }
  631                 memset(sc->packet, 0, 4);
  632                 break;
  633 
  634         /* If we get here, we have problems. */
  635         default:
  636                 printf("pmsinput: very confused.  resetting.\n");
  637                 sc->inputstate = 0;
  638                 sc->sc_enabled = 0;
  639                 wakeup(&sc->sc_enabled);
  640                 return;
  641         }
  642 }

Cache object: ab0e66d32f35130b2a9f0bf29ed77719


[ 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.