home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3519 / mouseX386.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-20  |  21.1 KB  |  841 lines

  1. /*
  2.  * Copyright 1990 by Thomas Roell, Dinkelscherben, Germany.
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided that
  6.  * the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Thomas Roell not be used in
  9.  * advertising or publicity pertaining to distribution of the software without
  10.  * specific, written prior permission.  Thomas Roell makes no representations
  11.  * about the suitability of this software for any purpose.  It is provided
  12.  * "as is" without express or implied warranty.
  13.  *
  14.  * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16.  * EVENT SHALL THOMAS ROELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  20.  * PERFORMANCE OF THIS SOFTWARE.
  21.  *
  22.  * Author:  Thomas Roell, roell@lan.informatik.tu-muenchen.de
  23.  *
  24.  * $Header: /proj/X11/mit/server/ddx/at386/RCS/mouse.c,v 1.6 90/11/08 17:49:14 root Exp $
  25.  */
  26.  
  27.  
  28. #include "X386.h"
  29. #include "inputstr.h"
  30. #include "scrnintstr.h"
  31. #include "nintendo.h"
  32.  
  33. /*
  34.  * Private structure for a MouseSystems Mouse
  35.  */
  36. typedef struct {
  37.   X386MouseRec  info;
  38.   int           state;
  39.   int           buttons;
  40.   int           dx,dy;
  41. } MouseSysRec, * MouseSysPtr;
  42.  
  43. /*
  44.  * Private structure for a Microsoft Mouse
  45.  */
  46. typedef struct {
  47.   X386MouseRec  info;
  48.   int           state;
  49.   int           emulate;
  50.   int           buttons;
  51.   int           dx,dy;
  52. } MicrosoftRec, *MicrosoftPtr;
  53.  
  54. /*
  55.  * Private structure for a Bus Mouse
  56.  */
  57. typedef struct {
  58.   X386MouseRec  info;
  59.   int           state;
  60.   int           buttons;
  61.   int           dx,dy;
  62. } BusMouseRec, *BusMousePtr;
  63.  
  64. /*
  65.  * Private structure for a Nintendo Joystick fake mouse
  66.  * Supports configured mappings NES switches to mouse buttons,
  67.  * and non-linear sped up joystick inputs.
  68.  */
  69. typedef struct {
  70.   X386MouseRec  info;
  71.   int        switches;            /* last NES switches */
  72.   int        moves;                /* last NES move bits */
  73.   int           buttons;            /* X buttons */
  74.   int           dx,dy;                /* accumulated movement */
  75.   int        add, dda, shift;        /* nonlinear motion inputs */
  76.   int        A, B, Start, Select, AB;    /* what makes left-middle-right ? */
  77. } NesMouseRec, *NesMousePtr;
  78.  
  79. /*
  80.  * lets create a simple finite-state machine
  81.  */
  82.  
  83. static char state[24][3] = {
  84.   {-1,-1,0},  {-1,-1,4},  {-1,-1,8},  {2, -1,12}, /* nothing pressed */
  85.   { 1, 0,0},  { 1,-1,16}, { 1, 0,8},  {2, -1,12}, /* delayed right */
  86.   { 4, 0,0},  { 4, 0,4},  { 4,-1,20}, {2, -1,12}, /* delayed left */
  87.   { 0,-1,0},  { 0,-1,0},  { 0,-1,0},  {-1,-1,12}, /* pressed middle */
  88.   { 0,-1,0},  {-1,-1,16}, { 0,-1,8},  { 0, 2,12}, /* pressed right */
  89.   { 0,-1,0},  { 0,-1,4},  {-1,-1,20}, { 0, 2,12}, /* pressed left */
  90. };
  91.  
  92.   
  93. /*
  94.  *-----------------------------------------------------------------------
  95.  * MouseCtrl --
  96.  *      Alter the control parameters for the mouse.
  97.  *
  98.  * Results:
  99.  *      None.
  100.  *
  101.  * Side Effects:
  102.  *      None.
  103.  *
  104.  *-----------------------------------------------------------------------
  105.  */
  106. static void
  107. MouseCtrl(pMouse, pCtrl)
  108.      DevicePtr pMouse;
  109.      PtrCtrl   *pCtrl;
  110. {
  111.   X386MousePtr pPriv = (X386MousePtr)pMouse->devicePrivate;
  112.  
  113.   TRACE( ("MouseCtrl(pMouse=0x%x, pCtrl=0x%x)\n", pMouse, pCtrl) );
  114.  
  115.   /*
  116.    * check for reasonable values 
  117.    */
  118.   if ((pCtrl->num > 0) && (pCtrl->den > 0)) {
  119.     pPriv->num = pCtrl->num;
  120.     pPriv->den = pCtrl->den;
  121.   } else {
  122.     pPriv->num = 1;
  123.     pPriv->den = 1;
  124.   }
  125.  
  126.   if (pCtrl->threshold > 0)
  127.     pPriv->threshold = pCtrl->threshold;
  128.   else
  129.     pPriv->threshold = 1;
  130. }
  131.  
  132. /*
  133.  *-----------------------------------------------------------------------
  134.  * GetMotionEvents --
  135.  *      Return the (number of) motion events in the "motion history
  136.  *      buffer" (snicker) between the given times.
  137.  *
  138.  * Results:
  139.  *      The number of events stuffed.
  140.  *
  141.  * Side Effects:
  142.  *      None.
  143.  *
  144.  *-----------------------------------------------------------------------
  145.  */
  146. static int
  147. GetMotionEvents (buff, start, stop, pScreen)
  148.      CARD32 start, stop;
  149.      xTimecoord *buff;
  150.      ScreenPtr pScreen;
  151. {
  152.   TRACE( ("GetMotionEvents(buff=0x%x, start=%d, stop=%d, pScreen=0x%x)\n",
  153.       buff, start, stop, pScreen) );
  154.  
  155.   return 0;
  156. }
  157.  
  158. /*
  159.  *-----------------------------------------------------------------------
  160.  * MouseSysProc --
  161.  *      Handle the initialization, etc. of a mouse
  162.  *
  163.  * Results:
  164.  *      none.
  165.  *
  166.  * Side Effects:
  167.  *      none.
  168.  *
  169.  *-----------------------------------------------------------------------
  170.  */
  171. static int
  172. MouseSysProc(pMouse, what)
  173.      DevicePtr    pMouse;
  174.      int        what;
  175. {
  176.   unchar        map[4];
  177.   struct        termio tty;
  178.   Atom          type;
  179.   X386DevicePtr pPriv = (X386DevicePtr)pMouse->devicePrivate;
  180.   
  181.   TRACE( ("MouseSysProc(pMouse=0x%x, what=%d)\n", pMouse, what) );
  182.  
  183.   switch (what)
  184.     {
  185.     case DEVICE_INIT: 
  186.       if ((pPriv->Fd = open(pPriv->Name,O_RDONLY | O_NDELAY)) < 0) {
  187.     ErrorF ("Cannot open MouseSystemsMouse\n");
  188.     return (!Success); }
  189.       ioctl(pPriv->Fd,TCGETA,&tty);  
  190.       tty.c_iflag = IGNBRK | IGNPAR ;     
  191.       tty.c_oflag = 0;           
  192.       tty.c_cflag = B1200 | CS8 | CSTOPB | CREAD | CLOCAL;
  193.       tty.c_lflag = 0;
  194.       tty.c_cc[VTIME]=0; 
  195.       tty.c_cc[VMIN]=1;
  196.       ioctl(pPriv->Fd,TCSETA,&tty);
  197.  
  198.       ((MouseSysPtr)pPriv)->state = 0;
  199.       ((X386MousePtr)pPriv)->buttons = 0;
  200.       ((X386MousePtr)pPriv)->x = 0;
  201.       ((X386MousePtr)pPriv)->y = 0;
  202.       pMouse->on = FALSE;
  203.  
  204.       map[1] = 3;
  205.       map[2] = 2;
  206.       map[3] = 1;
  207.       InitPointerDeviceStruct(pMouse, map, 3, GetMotionEvents, MouseCtrl, 0);
  208.  
  209. #ifdef XINPUT
  210.       type = MakeAtom(pPriv->type, strlen(pPriv->type), FALSE);
  211.       AssignTypeAndName(pMouse, type, "Mouse Systems Mouse");
  212. #endif      
  213.  
  214.       break;
  215.     
  216.       case DEVICE_ON:
  217.     AddEnabledDevice(pPriv->Fd); 
  218.     pMouse->on = TRUE;
  219.     break;
  220.     
  221.       case DEVICE_CLOSE:
  222.       case DEVICE_OFF:
  223.     RemoveEnabledDevice(pPriv->Fd); 
  224.     pMouse->on = FALSE;
  225.     break;
  226.     }
  227.   return Success;
  228. }
  229.  
  230. /*
  231.  *-----------------------------------------------------------------------
  232.  * MouseSysProcessEvents --
  233.  *      Return the number of processed events.
  234.  *
  235.  * Results:
  236.  *      Number of events processed.
  237.  *
  238.  * Side Effects:
  239.  *      Process Events.
  240.  *-----------------------------------------------------------------------
  241.  */
  242. static void
  243. MouseSysProcessEvents(pMouse)
  244.      DevicePtr    pMouse;
  245. {
  246.   unchar          rBuf[64];
  247.   int             i,nBytes;
  248.   MouseSysPtr pPriv = (MouseSysPtr)pMouse->devicePrivate;
  249.  
  250.   nBytes = read(((X386DevicePtr)pPriv)->Fd, rBuf, sizeof(rBuf));
  251.  
  252.   for ( i=0; i < nBytes; i++) {
  253.     switch(pPriv->state) {
  254.     case 0:
  255.       if ((rBuf[i] & 0xF8) == 0x80) {
  256.     pPriv->buttons = (~rBuf[i]) & 0x07;
  257.     (pPriv->state)++; }
  258.       break;
  259.       
  260.     case 1:
  261.       pPriv->dx = (signed char)rBuf[i];
  262.       (pPriv->state)++;
  263.       break;
  264.       
  265.     case 2:
  266.       pPriv->dy = (signed char)rBuf[i];
  267.       (pPriv->state)++;
  268.       break;
  269.       
  270.     case 3:
  271.       (pPriv->dx) += (signed char)rBuf[i];
  272.       (pPriv->state)++;
  273.       break;
  274.       
  275.     case 4:
  276.       (pPriv->dy) += (signed char)rBuf[i];
  277.       pPriv->state = 0;
  278.       X386MouseEvent(pMouse, pPriv->buttons, pPriv->dx, -pPriv->dy);
  279.       break;
  280.     }
  281.   }
  282. }
  283.  
  284.  
  285. /*
  286.  *-----------------------------------------------------------------------
  287.  * MouseSysConfig --
  288.  *    Read the configuration of a MouseSystems Mouse.
  289.  *
  290.  * Results:
  291.  *    A pointer to the allocated device.
  292.  *
  293.  * Side Effects:
  294.  *
  295.  *-----------------------------------------------------------------------
  296.  */
  297. X386DevicePtr
  298. MouseSysConfig()
  299. {
  300.   X386DevicePtr dev;
  301.  
  302.   TRACE( ("MouseSysConfig()\n") );
  303.  
  304.   if (X386Lex(NULL) != STRING)
  305.     FatalError("Devicename expected (%d)\n",X386LineNo);
  306.  
  307.   dev = (X386DevicePtr)xalloc(sizeof(MouseSysRec));
  308.   dev->deviceProc   = MouseSysProc;
  309.   dev->deviceEvents = MouseSysProcessEvents;
  310.   dev->type = "MOUSE";
  311.   dev->Name = X386Val.str;
  312.   return dev;
  313. }
  314.  
  315. /*
  316.  *-----------------------------------------------------------------------
  317.  * MicrosoftProc --
  318.  *      Handle the initialization, etc. of a mouse
  319.  *
  320.  * Results:
  321.  *      none.
  322.  *
  323.  * Side Effects:
  324.  *      none.
  325.  *
  326.  *-----------------------------------------------------------------------
  327.  */
  328. static int
  329. MicrosoftProc(pMouse, what)
  330.      DevicePtr    pMouse;
  331.      int        what;
  332. {
  333.   unchar        map[4];
  334.   struct        termio tty;
  335.   Atom          type;
  336.   X386DevicePtr pPriv = (X386DevicePtr)pMouse->devicePrivate;
  337.  
  338.   TRACE( ("MicrosoftProc(pMouse=0x%x, what=%d)\n", pMouse, what) );
  339.   
  340.   switch (what)
  341.     {
  342.     case DEVICE_INIT: 
  343.       if ((pPriv->Fd= open(pPriv->Name,O_RDONLY | O_NDELAY)) < 0) {
  344.     Error ("Cannot open MicrosoftMouse\n");
  345.     return (!Success); }
  346.       ioctl(pPriv->Fd,TCGETA,&tty);  
  347.       tty.c_iflag = IGNBRK | IGNPAR ;     
  348.       tty.c_oflag = 0;           
  349.       tty.c_cflag = B1200 | CS7 | CREAD | CLOCAL;
  350.       tty.c_lflag = 0;
  351.       tty.c_cc[VTIME]=0; 
  352.       tty.c_cc[VMIN]=1;
  353.       ioctl(pPriv->Fd,TCSETA,&tty);
  354.       
  355.       ((MicrosoftPtr)pPriv)->state = 0;
  356.       ((MicrosoftPtr)pPriv)->emulate = 0;
  357.       ((X386MousePtr)pPriv)->buttons = 0;
  358.       ((X386MousePtr)pPriv)->x = 0;
  359.       ((X386MousePtr)pPriv)->y = 0;
  360.       pMouse->on = FALSE;
  361.  
  362.       map[1] = 3;
  363.       map[2] = 2;
  364.       map[3] = 1;
  365.       InitPointerDeviceStruct(pMouse, map, 3, GetMotionEvents, MouseCtrl, 0);
  366.  
  367. #ifdef XINPUT
  368.       type = MakeAtom(pPriv->type, strlen(pPriv->type), FALSE);
  369.       AssignTypeAndName(pMouse, type, "Microsoft Mouse");
  370. #endif
  371.  
  372.       break;
  373.       
  374.     case DEVICE_ON:
  375.       AddEnabledDevice(pPriv->Fd);
  376.       pMouse->on = TRUE;
  377.       break;
  378.       
  379.     case DEVICE_CLOSE:
  380.     case DEVICE_OFF:
  381.       RemoveEnabledDevice(pPriv->Fd);
  382.       pMouse->on = FALSE;
  383.       break;
  384.       
  385.     }
  386.   return Success;
  387. }
  388.  
  389. /*
  390.  *-----------------------------------------------------------------------
  391.  * MicrosoftProcessEvents --
  392.  *      Return the number of processed events.
  393.  *
  394.  * Results:
  395.  *      Number of events processed.
  396.  *
  397.  * Side Effects:
  398.  *      Process Events.
  399.  *-----------------------------------------------------------------------
  400.  */
  401. static void
  402. MicrosoftProcessEvents(pMouse)
  403.      DevicePtr    pMouse;
  404. {
  405.   unchar           rBuf[64];
  406.   int              i,nBytes;
  407.   MicrosoftPtr pPriv = (MicrosoftPtr)pMouse->devicePrivate;
  408.  
  409.   nBytes = read(((X386DevicePtr)pPriv)->Fd, rBuf, sizeof(rBuf));
  410.  
  411.   for ( i=0; i < nBytes; i++) {
  412.     switch(pPriv->state) {
  413.     case 0:
  414.       if ((rBuf[i] & 0x40) == 0x40) {
  415.     pPriv->buttons= (rBuf[i]>>4) &0x3;
  416.     pPriv->dy = (signed char)((rBuf[i] &0xC) <<4);
  417.     pPriv->dx = (signed char)((rBuf[i] &0x3) <<6);
  418.     (pPriv->state)++; }
  419.       break;
  420.       
  421.     case 1:
  422.       (pPriv->dx) |= (signed char)(rBuf[i]&0x3F);
  423.       (pPriv->state)++;
  424.       break;
  425.       
  426.     case 2:
  427.       (pPriv->dy) |= (signed char)(rBuf[i]&0x3F);
  428.       pPriv->state = 0;
  429.       X386MouseEvent(pMouse, 
  430.          ((X386MousePtr)pPriv)->buttons, pPriv->dx, pPriv->dy);
  431.       /*
  432.        * emulate the third button by the other two
  433.        */
  434.       if (state[pPriv->buttons + pPriv->emulate][0] != -1)
  435.     X386MouseEvent(pMouse, state[pPriv->buttons+pPriv->emulate][0], 0, 0);
  436.       if (state[pPriv->buttons + pPriv->emulate][1] != -1)
  437.     X386MouseEvent(pMouse, state[pPriv->buttons+pPriv->emulate][1], 0, 0);
  438.  
  439.       pPriv->emulate = state[pPriv->buttons + pPriv->emulate][2];
  440.       break;
  441.     }
  442.   }
  443. }
  444.  
  445.  
  446. /*
  447.  *-----------------------------------------------------------------------
  448.  * MicrosoftConfig --
  449.  *    Read the configuration of a MicroTrash (tm) Mouse.
  450.  *
  451.  * Results:
  452.  *    A pointer to the allocated device.
  453.  *
  454.  * Side Effects:
  455.  *
  456.  *-----------------------------------------------------------------------
  457.  */
  458. X386DevicePtr
  459. MicrosoftConfig()
  460. {
  461.   X386DevicePtr dev;
  462.  
  463.   TRACE( ("MircosoftConfig()\n") );
  464.  
  465.   if (X386Lex(NULL) != STRING)
  466.     FatalError("Devicename expected (%d)\n",X386LineNo);
  467.  
  468.   dev = (X386DevicePtr)xalloc(sizeof(MicrosoftRec));
  469.   dev->deviceProc   = MicrosoftProc;
  470.   dev->deviceEvents = MicrosoftProcessEvents;
  471.   dev->type = "MOUSE";
  472.   dev->Name = X386Val.str;
  473.   return dev;
  474. }
  475.  
  476.  
  477. /*
  478.  *-----------------------------------------------------------------------
  479.  * BusMouseProc --
  480.  *      Handle the initialization, etc. of a mouse
  481.  *
  482.  * Results:
  483.  *      none.
  484.  *
  485.  * Side Effects:
  486.  *      none.
  487.  *
  488.  *-----------------------------------------------------------------------
  489.  */
  490. static int
  491. BusMouseProc(pMouse, what)
  492.      DevicePtr    pMouse;
  493.      int        what;
  494. {
  495.   unchar        map[4];
  496.   Atom          type;
  497.   X386DevicePtr pPriv = (X386DevicePtr)pMouse->devicePrivate;
  498.  
  499.   TRACE( ("BusMouseProc(pMouse=0x%x, what=%d)\n", pMouse, what) );
  500.   
  501.   switch (what)
  502.     {
  503.     case DEVICE_INIT: 
  504.       if ((pPriv->Fd= open(pPriv->Name,O_RDONLY | O_NDELAY)) < 0) {
  505.     Error ("Cannot open BusMouse\n");
  506.     return (!Success); }
  507.       
  508.       ((BusMousePtr)pPriv)->state = 0;
  509.       ((X386MousePtr)pPriv)->buttons = 0;
  510.       ((X386MousePtr)pPriv)->x = 0;
  511.       ((X386MousePtr)pPriv)->y = 0;
  512.       pMouse->on = FALSE;
  513.  
  514.       map[1] = 3;
  515.       map[2] = 2;
  516.       map[3] = 1;
  517.       InitPointerDeviceStruct(pMouse, map, 3, GetMotionEvents, MouseCtrl, 0);
  518.  
  519. #ifdef XINPUT
  520.       type = MakeAtom(pPriv->type, strlen(pPriv->type), FALSE);
  521.       AssignTypeAndName(pMouse, type, "Bus Mouse");
  522. #endif
  523.  
  524.       break;
  525.       
  526.     case DEVICE_ON:
  527.       AddEnabledDevice(pPriv->Fd);
  528.       pMouse->on = TRUE;
  529.       break;
  530.       
  531.     case DEVICE_CLOSE:
  532.     case DEVICE_OFF:
  533.       RemoveEnabledDevice(pPriv->Fd);
  534.       pMouse->on = FALSE;
  535.       break;
  536.       
  537.     }
  538.   return Success;
  539. }
  540.  
  541. /*
  542.  *-----------------------------------------------------------------------
  543.  * BusMouseProcessEvents --
  544.  *      Process the good old BusMouse events.
  545.  *
  546.  * Results:
  547.  *      Number of events processed.
  548.  *
  549.  * Side Effects:
  550.  *      Process Events.
  551.  *-----------------------------------------------------------------------
  552.  */
  553. static void
  554. BusMouseProcessEvents(pMouse)
  555.      DevicePtr    pMouse;
  556. {
  557.   unchar           rBuf[64];
  558.   int              i,nBytes;
  559.   BusMousePtr  pPriv = (BusMousePtr)pMouse->devicePrivate;
  560.  
  561.   nBytes = read(((X386DevicePtr)pPriv)->Fd, rBuf, sizeof(rBuf));
  562.  
  563.   for ( i=0; i < nBytes; i++) {
  564.     switch(pPriv->state) {
  565.     case 0:
  566.       if ((rBuf[i] & 0xF8) == 0x80) {
  567.     pPriv->buttons= (~rBuf[i]) &0x7;
  568.     (pPriv->state)++; }
  569.       break;
  570.       
  571.     case 1:
  572.       (pPriv->dx) = (signed char)(rBuf[i]);
  573.       (pPriv->state)++;
  574.       break;
  575.       
  576.     case 2:
  577.       (pPriv->dy) = (signed char)(rBuf[i]);
  578.       (pPriv->state)++;
  579.       break;
  580.  
  581.     case 3:
  582.       (pPriv->state)++;
  583.       break;
  584.  
  585.     case 4:
  586.       pPriv->state = 0;
  587.       X386MouseEvent(pMouse, pPriv->buttons, pPriv->dx, -pPriv->dy);
  588.       break;
  589.     }
  590.   }
  591. }
  592.  
  593.  
  594. /*
  595.  *-----------------------------------------------------------------------
  596.  * BusMouseConfig --
  597.  *    Read the configuration of a BusMouse.
  598.  *
  599.  * Results:
  600.  *    A pointer to the allocated device.
  601.  *
  602.  * Side Effects:
  603.  *
  604.  *-----------------------------------------------------------------------
  605.  */
  606. X386DevicePtr
  607. BusMouseConfig()
  608. {
  609.   X386DevicePtr dev;
  610.  
  611.   TRACE( ("BusMouseConfig()\n") );
  612.  
  613.   if (X386Lex(NULL) != STRING)
  614.     FatalError("Devicename expected (%d)\n",X386LineNo);
  615.  
  616.   dev = (X386DevicePtr)xalloc(sizeof(BusMouseRec));
  617.   dev->deviceProc   = BusMouseProc;
  618.   dev->deviceEvents = BusMouseProcessEvents;
  619.   dev->type = "MOUSE";
  620.   dev->Name = X386Val.str;
  621.   return dev;
  622. }
  623.  
  624. /*
  625.  *-----------------------------------------------------------------------
  626.  * NesMouseProc --
  627.  *      Handle the initialization, etc. of a Nintendo fake mouse
  628.  *
  629.  * Results:
  630.  *      none.
  631.  *
  632.  * Side Effects:
  633.  *      none.
  634.  *
  635.  *-----------------------------------------------------------------------
  636.  */
  637. static int
  638. NesMouseProc(pMouse, what)
  639.      DevicePtr    pMouse;
  640.      int        what;
  641. {
  642.   unchar        map[4];
  643.   Atom          type;
  644.   X386DevicePtr pPriv = (X386DevicePtr)pMouse->devicePrivate;
  645.  
  646.   TRACE( ("NesMouseProc(pMouse=0x%x, what=%d)\n", pMouse, what) );
  647.   
  648.   switch (what)
  649.     {
  650.     case DEVICE_INIT: 
  651.       if ((pPriv->Fd= open(pPriv->Name,O_RDONLY | O_NDELAY)) < 0) {
  652.     Error ("Cannot open NesMouse\n");
  653.     return (!Success); }
  654.       
  655.       ((NesMousePtr)pPriv)->switches = 0;
  656.       ((NesMousePtr)pPriv)->moves = 0;
  657.       /* dda is set earlier, in NesMouseConfig */
  658.       ((NesMousePtr)pPriv)->add = 128;
  659.       ((NesMousePtr)pPriv)->shift = 7;
  660.       ((X386MousePtr)pPriv)->buttons = 0;
  661.       ((X386MousePtr)pPriv)->x = 0;
  662.       ((X386MousePtr)pPriv)->y = 0;
  663.       pMouse->on = FALSE;
  664.  
  665.       map[1] = 3;
  666.       map[2] = 2;
  667.       map[3] = 1;
  668.       InitPointerDeviceStruct(pMouse, map, 3, GetMotionEvents, MouseCtrl, 0);
  669.  
  670. #ifdef XINPUT
  671.       type = MakeAtom(pPriv->type, strlen(pPriv->type), FALSE);
  672.       AssignTypeAndName(pMouse, type, "NES Mouse");
  673. #endif
  674.  
  675.       break;
  676.       
  677.     case DEVICE_ON:
  678.       AddEnabledDevice(pPriv->Fd);
  679.       pMouse->on = TRUE;
  680.       break;
  681.       
  682.     case DEVICE_CLOSE:
  683.     case DEVICE_OFF:
  684.       RemoveEnabledDevice(pPriv->Fd);
  685.       pMouse->on = FALSE;
  686.       break;
  687.       
  688.     }
  689.   return Success;
  690. }
  691.  
  692. /*
  693.  *-----------------------------------------------------------------------
  694.  * NesMouseProcessEvents --
  695.  *      Process the good old NesMouse events.
  696.  *
  697.  * Results:
  698.  *      Number of events processed.
  699.  *
  700.  * Side Effects:
  701.  *      Process Events.
  702.  *-----------------------------------------------------------------------
  703.  */
  704. static void
  705. NesMouseProcessEvents(pMouse)
  706.      DevicePtr    pMouse;
  707. {
  708.   unchar           rBuf[1024];    /* we can get lots of NES bytes */
  709.   int              i,nBytes;
  710.   NesMousePtr  pPriv = (NesMousePtr)pMouse->devicePrivate;
  711.   int           doinput;
  712.  
  713.   nBytes = read(((X386DevicePtr)pPriv)->Fd, rBuf, sizeof(rBuf));
  714.  
  715.   /* Each byte is encoded as per nintendo.h.  Many samples a second. */
  716.   /* 
  717.    * Decode motion linearly.  With 1K read channel, we can be assured 
  718.    * of pulling all current input.  
  719.    */
  720.   pPriv->dx = pPriv->dy = 0;
  721.   doinput = 0;
  722.   for ( i=0; i < nBytes; i++) {
  723.     if (rBuf[i] & NES_up)
  724.     pPriv->dy -= pPriv->add;
  725.     else if (rBuf[i] & NES_down)
  726.     pPriv->dy += pPriv->add;
  727.     if (rBuf[i] & NES_right)
  728.     pPriv->dx += pPriv->add;
  729.     else if (rBuf[i] & NES_left)
  730.     pPriv->dx -= pPriv->add;
  731.     if (rBuf[i] & NES_MOVES)
  732.     if ((rBuf[i] & NES_MOVES) == pPriv->moves)
  733.         pPriv->add += pPriv->dda;            /* accelerate */
  734.     else
  735.     pPriv->add = (1 << pPriv->shift);        /* downshift */
  736.     pPriv->moves = (rBuf[i] & NES_MOVES);
  737.     if ((rBuf[i] & (NES_SWITCHES)) != pPriv->switches) {
  738.       pPriv->buttons = 0;
  739.       if (rBuf[i] & NES_A)
  740.     pPriv->buttons |= pPriv->A;
  741.       if (rBuf[i] & NES_B)
  742.     pPriv->buttons |= pPriv->B;
  743.       if (rBuf[i] & NES_select)
  744.     pPriv->buttons |= pPriv->Select;
  745.       if (rBuf[i] & NES_start)
  746.     pPriv->buttons |= pPriv->Start;
  747.       /*
  748.        * No AB support yet.  I don't like state machine system above.
  749.        * It really needs to be sub-second timer-based.
  750.        */
  751.       pPriv->switches = rBuf[i] & (NES_SWITCHES);
  752.       doinput++;
  753.     }
  754.     X386MouseEvent(pMouse, pPriv->buttons, 
  755.     pPriv->dx >> pPriv->shift, pPriv->dy >> pPriv->shift);
  756.     pPriv->dx = pPriv->dy = 0;
  757.   }
  758. }
  759.  
  760.  
  761. /*
  762.  *-----------------------------------------------------------------------
  763.  * NesMouseConfig --
  764.  *    Read the configuration of a NesMouse.
  765.  *
  766.  * Results:
  767.  *    A pointer to the allocated device.
  768.  *
  769.  * Side Effects:
  770.  *
  771.  *-----------------------------------------------------------------------
  772.  */
  773.  
  774. X386DevicePtr
  775. NesMouseConfig()
  776. {
  777.   NesMousePtr dev;
  778.   char *cp, *cp2, *strchr();
  779.   int i;
  780.  
  781.   TRACE( ("NesMouseConfig()\n") );
  782.  
  783.   if (X386Lex(NULL) != STRING)
  784.     FatalError("Devicename expected (%d)\n",X386LineNo);
  785.  
  786.   /* Reverse convention from above */
  787.   dev = (NesMousePtr)xalloc(sizeof(NesMouseRec));
  788.   ((X386DevicePtr)dev)->deviceProc   = NesMouseProc;
  789.   ((X386DevicePtr)dev)->deviceEvents = NesMouseProcessEvents;
  790.   ((X386DevicePtr)dev)->type = "MOUSE";
  791.   ((X386DevicePtr)dev)->Name = X386Val.str;
  792.  
  793.   /* Read in Nintendo sub-configuration */
  794.   /* Syntax: button[,button].. " " */
  795.   /* The keyword parser doesn't handle ,'s and I'm too lazy */
  796.   dev->A = dev->B = dev->Start = dev->Select = dev->AB = 0;
  797.   for(i = 2; i >= 0; i--) {
  798.     if (X386Lex(NULL) != STRING)
  799.       FatalError("Nintendo button name expected (%d)\n",X386LineNo);
  800.     cp = X386Val.str;
  801.     if (cp2 = strchr(cp, ','))
  802.     *cp2 = '\0';
  803.     while(cp && *cp) {
  804.       if (streq(cp, "A")) {
  805.       if (dev->A)
  806.           FatalError("Nintendo A button already assigned\n");
  807.       else dev->A = (1<<i);
  808.       } else if (streq(cp, "B")) {
  809.       if (dev->B)
  810.           FatalError("Nintendo B button already assigned\n");
  811.       else dev->B = (1<<i);
  812.       } else if (streq(cp, "Start")) {
  813.       if (dev->Start)
  814.           FatalError("Nintendo Start button already assigned\n");
  815.       else dev->Start = (1<<i);
  816.       } else if (streq(cp, "Select")) {
  817.       if (dev->Select)
  818.           FatalError("Nintendo Select button already assigned\n");
  819.       else dev->Select = (1<<i);
  820.       } else if (streq(cp, "AB")) {
  821.       if (dev->AB)
  822.           FatalError("Nintendo A+B button combination already assigned\n");
  823.       else dev->AB = (1<<i);
  824.       } else 
  825.           FatalError("Nintendo button '%s' not recognized!\n", cp);
  826.       /* Advance to next Nintendo button for this mouse button */
  827.       if (cp2) {
  828.     *cp2++ = ',';    /* restore char to avoid memory leak */
  829.         cp = cp2;
  830.       } else
  831.         cp = 0;
  832.       }
  833.   }
  834.   /* optional DDA argument:  */
  835.   dev->dda = 0;
  836.   if ((X386Lex(NULL) == NUMBER) && (X386Val.num >= 0) && (X386Val.num <= 20))
  837.     dev->dda = X386Val.num;
  838.   return (X386DevicePtr)dev;
  839. }
  840.  
  841.