home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / D / SVGALIB / SVGALIB1.TAR / svgalib / src / mouse / ms.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-27  |  8.5 KB  |  330 lines

  1. /* Based on:
  2.  * simple driver for serial mouse
  3.  * Andrew Haylett, 14th December 1992
  4.  * and on the driver in XFree86.
  5.  * Edited for svgalib (hhanemaa@cs.ruu.nl).
  6.  * This probably doesn't work with all types of bus mouse.
  7.  * HH: Added PS/2 mouse support.
  8.  * Fixed Logitech support thanks to Daniel Jackson.
  9.  * MouseSystems movement overflow fixed by Steve VanDevender.
  10.  * Logitech fixed again.
  11.  * Michael: Added support for controlling DTR and RTS.
  12.  */
  13.  
  14. /* This file is included by mouse.c. */
  15.  
  16. #include <unistd.h>
  17. #include <termios.h>
  18. #include <sys/ioctl.h>
  19. #include <fcntl.h>
  20. #include <time.h>
  21.  
  22.  
  23. /* #define DEBUG */
  24.  
  25. static int mtype;
  26. static int mbaud = 1200;    /* Should be 1200. */
  27. static int msample;
  28. static char *mdev;
  29. static int mfd = -1;
  30. static int mfdmode = 0;        /* 0 means don't wait (NDELAY) */
  31. static int m_modem_ctl = 0;
  32.  
  33. /* Settings found on mouse open.. Probably std termios should be restored as well*/
  34. static unsigned long mold_modem_info;    /*  original state of DTR/RTS */
  35. static char mmodem_info_valid = 0;    /*  ==0 means: couldn't get it: old kernel? */
  36.  
  37. static const unsigned short cflag[6] =
  38. {
  39.       (CS7                   | CREAD | CLOCAL | HUPCL ),   /* MicroSoft */
  40.       (CS8 | CSTOPB          | CREAD | CLOCAL | HUPCL ),   /* MouseSystems */
  41.       (CS8 | PARENB | PARODD | CREAD | CLOCAL | HUPCL ),   /* MMSeries */
  42.       (CS8 | CSTOPB          | CREAD | CLOCAL | HUPCL ),   /* Logitech */
  43.       0,                                                   /* BusMouse */
  44.       0                               /* PS/2 */
  45. };
  46.  
  47. static const unsigned char proto[6][5] =
  48. {
  49.     /*  hd_mask hd_id   dp_mask dp_id   nobytes */
  50.     {     0x40,    0x40,    0x40,    0x00,    3     },  /* MicroSoft */
  51.     {    0xf8,    0x80,    0x00,    0x00,    5    },  /* MouseSystems */
  52.     {    0xe0,    0x80,    0x80,    0x00,    3    },  /* MMSeries */
  53.     {    0xe0,    0x80,    0x00,    0x00,    3    },  /* Logitech */
  54.     {    0xf8,    0x80,    0x00,    0x00,    5    },  /* BusMouse */
  55.     {   0xc0,    0x00,    0x00,    0x00,   3    },  /* PS/2 mouse */
  56. };
  57.  
  58. static void
  59. ms_setspeed(const int old, const int new,
  60.             const unsigned short c_cflag)
  61. {
  62.     struct termios tty;
  63.     char *c;
  64.  
  65.     tcgetattr(mfd, &tty);
  66.     
  67.     tty.c_iflag = IGNBRK | IGNPAR;
  68.     tty.c_oflag = 0;
  69.     tty.c_lflag = 0;
  70.     tty.c_line = 0;
  71.     tty.c_cc[VTIME] = 0;
  72.     tty.c_cc[VMIN] = 1;
  73.  
  74.     switch (old)
  75.     {
  76.         case 9600:    tty.c_cflag = c_cflag | B9600; break;
  77.         case 4800:    tty.c_cflag = c_cflag | B4800; break;
  78.         case 2400:    tty.c_cflag = c_cflag | B2400; break;
  79.         case 1200:
  80.     default:    tty.c_cflag = c_cflag | B1200; break;
  81.     }
  82.  
  83.     tcsetattr(mfd, TCSAFLUSH, &tty);
  84.  
  85.     switch (new)
  86.     {
  87.         case 9600:    c = "*q";  tty.c_cflag = c_cflag | B9600; break;
  88.         case 4800:    c = "*p";  tty.c_cflag = c_cflag | B4800; break;
  89.         case 2400:    c = "*o";  tty.c_cflag = c_cflag | B2400; break;
  90.         case 1200:
  91.     default:    c = "*n";  tty.c_cflag = c_cflag | B1200; break;
  92.     }
  93.  
  94.     write(mfd, c, 2);
  95.     usleep(10000);
  96.     tcsetattr(mfd, TCSAFLUSH, &tty);
  97. }
  98.  
  99. static int
  100. ms_init()
  101. {
  102.     /* Added O_NDELAY here. */
  103.     if ((mfd = open(mdev, O_RDWR | O_NDELAY)) < 0)
  104.     return -1;
  105.  
  106.     if (mtype == MOUSE_BUSMOUSE || mtype == MOUSE_PS2)
  107.     m_modem_ctl=0;
  108.  
  109.     /* If no signal will change there is no need to restore
  110.                                   or safe original settings. */
  111.     if(!m_modem_ctl)
  112.     mmodem_info_valid=0;
  113.     else
  114.     {
  115.     /* Get current modem signals; keep silent on errors.. */
  116.     mmodem_info_valid= !ioctl(mfd, TIOCMGET, &mold_modem_info);
  117.  
  118.     if(mmodem_info_valid)
  119.     {
  120.         unsigned long param=mold_modem_info;
  121.  
  122.         /* Prepare new stat: */
  123.  
  124.         /*set DTR as ordered..*/
  125.         if(m_modem_ctl&MOUSE_CHG_DTR)
  126.         {
  127.         param&= ~TIOCM_DTR;
  128.         if(m_modem_ctl&MOUSE_DTR_HIGH)
  129.             param|=TIOCM_DTR;
  130.         }
  131.  
  132.         /*set RTS as ordered..*/
  133.         if(m_modem_ctl&MOUSE_CHG_RTS)
  134.         {
  135.         param&= ~TIOCM_RTS;
  136.         if(m_modem_ctl&MOUSE_RTS_HIGH)
  137.             param|=TIOCM_RTS;
  138.         }
  139.  
  140.         if(ioctl(mfd, TIOCMSET, ¶m))
  141.         mmodem_info_valid=0;    /* No try to restore if this failed */
  142.     }
  143.     }
  144.  
  145.     if (mtype != MOUSE_BUSMOUSE && mtype != MOUSE_PS2)
  146.     {
  147.     ms_setspeed(9600, mbaud, cflag[mtype]);
  148.     ms_setspeed(4800, mbaud, cflag[mtype]);
  149.     ms_setspeed(2400, mbaud, cflag[mtype]);
  150.     ms_setspeed(1200, mbaud, cflag[mtype]);
  151.  
  152.     if (mtype == MOUSE_LOGITECH)
  153.     {
  154.         write(mfd, "S", 1);
  155.         ms_setspeed(mbaud, mbaud, cflag[MOUSE_MMSERIES]);
  156.     }
  157.  
  158.     if    (msample <= 0)        write(mfd, "O", 1);
  159.     else if    (msample <= 15)        write(mfd, "J", 1);
  160.     else if    (msample <= 27)        write(mfd, "K", 1);
  161.     else if    (msample <= 42)        write(mfd, "L", 1);
  162.     else if    (msample <= 60)        write(mfd, "R", 1);
  163.     else if    (msample <= 85)        write(mfd, "M", 1);
  164.     else if    (msample <= 125)    write(mfd, "Q", 1);
  165.     else                write(mfd, "N", 1);
  166.     }
  167.     return 0;
  168. }
  169.  
  170. /* Scooped from X driver. */
  171. static inline void
  172. ms_close() {
  173.     if (mfd == -1)
  174.         return;
  175.     if (mtype == MOUSE_LOGITECH) {
  176.         write(mfd, "U", 1);
  177.         ms_setspeed(mbaud, 1200, cflag[MOUSE_LOGITECH]);
  178.     }
  179.  
  180.     /* Try to restore modem signals if we could get them. */
  181.     if(mmodem_info_valid)
  182.     ioctl(mfd, TIOCMSET, &mold_modem_info);
  183.  
  184.     close(mfd);
  185. }
  186.  
  187.  
  188.  
  189. #define MOUSEBUFFERSIZE 256
  190.  
  191. static int
  192. get_ms_event( int wait )
  193. /*
  194.     Changed to process multiple packets.
  195.     wait value:
  196.     0    Process any mouse events, and return status.
  197.     1    Wait for mouse event, then return.
  198.  
  199.     Status indicates whether an event was processed.
  200. */
  201. {
  202.     static unsigned char buf[MOUSEBUFFERSIZE];
  203.     static int nu_bytes = 0;
  204.     char event_handled = 0;
  205.     int bytesread;
  206.     int i;
  207.     int but;
  208.     int dx, dy;
  209.     int j;
  210.  
  211.     if (mfd == -1)
  212.     return -1;
  213.  
  214. again:
  215.     
  216.     if (mfdmode == 1) {
  217.         /* We don't want to wait, set NDELAY mode. */
  218.         fcntl(mfd, F_SETFL, O_RDONLY | O_NDELAY);
  219.     mfdmode = 0;
  220.     }
  221.  
  222.     bytesread = read(mfd, &buf[nu_bytes], MOUSEBUFFERSIZE - nu_bytes);
  223.  
  224.     i = 0;
  225.  
  226.     if (bytesread >= 1)
  227.         nu_bytes += bytesread;
  228.  
  229. #ifdef DEBUG
  230.     printf("#bytes in buffer: %d\n", nu_bytes);
  231. #endif
  232.  
  233. handle_packets:
  234.  
  235.     /* Handle packets in buffer. */
  236.  
  237. #ifdef DEBUG
  238.     printf("Bytes left in buffer: %d, packet is %d bytes\n",
  239.         nu_bytes - i, proto[mtype][4]);
  240. #endif
  241.  
  242.     if (nu_bytes - i < proto[mtype][4])
  243.         /* No full packet available. */
  244.         if (wait == 0 || (wait == 1 && event_handled)) {
  245.             if (i >= nu_bytes) {
  246.                nu_bytes = 0;
  247.                i = 0;
  248.             }
  249.             else {
  250.             /* Move partial packet to front of buffer. */
  251.             for (j = i; j < nu_bytes; j++)
  252.                 buf[j - i] = buf[j];
  253.             nu_bytes -= i;
  254.         }
  255.             return event_handled;
  256.         }
  257.         else {    /* (wait == 1 && !event_handled) */
  258.             if (i >= nu_bytes) {
  259.                 nu_bytes = 0;
  260.                 i = 0;
  261.             }
  262.             /* Wait mode, we'll sleep on reads. */
  263.             fcntl(mfd, F_SETFL, O_RDONLY);
  264.             mfdmode = 1;
  265.             read(mfd, &buf[nu_bytes], 1);
  266.             nu_bytes++;
  267.             if (nu_bytes - i < proto[mtype][4])
  268.                 /* Not a complete packet. */
  269.                 goto again;
  270.         }
  271.  
  272.     /* Check header byte. */
  273.     if ((buf[i] & proto[mtype][0]) != proto[mtype][1]) {
  274.         /* Not a header byte. */
  275.         i++;
  276.         goto handle_packets;
  277.     }
  278.  
  279.     /* Check whether it's a valid data packet. */
  280.     if (mtype != MOUSE_PS2)
  281.         for (j = 1; j < proto[mtype][4]; j++)
  282.             if ((buf[i + j] & proto[mtype][2]) != proto[mtype][3]
  283.             || buf[i + j] == 0x80) {
  284.                 i = i + j + 1;
  285.             goto handle_packets;
  286.         }
  287.  
  288.     /* Construct the event. */
  289.     switch (mtype) {
  290.     case MOUSE_MICROSOFT:        /* Microsoft */
  291.     default:
  292.         but = ((buf[i] & 0x20) >> 3) | ((buf[i] & 0x10) >> 4);
  293.         dx = (char)(((buf[i] & 0x03) << 6) | (buf[i + 1] & 0x3F));
  294.         dy = (char)(((buf[i] & 0x0C) << 4) | (buf[i + 2] & 0x3F));
  295.         break;
  296.     case MOUSE_MOUSESYSTEMS:    /* Mouse Systems Corp */
  297.         but = (~buf[i]) & 0x07;
  298.             dx =   (char)(buf[i + 1]);
  299.             dx +=  (char)(buf[i + 3]);
  300.             dy = - ((char)(buf[i + 2]));
  301.             dy -=  (char)(buf[i + 4]);
  302.         break;
  303.     case MOUSE_MMSERIES:        /* MM Series */
  304.     case MOUSE_LOGITECH:        /* Logitech */
  305.         but = buf[i] & 0x07;
  306.         dx = (buf[i] & 0x10) ? buf[i + 1] : - buf[i + 1];
  307.         dy = (buf[i] & 0x08) ? - buf[i + 2] : buf[i + 2];
  308.         break;
  309.     case MOUSE_BUSMOUSE:        /* BusMouse */
  310.         but = (~buf[i]) & 0x07;
  311.         dx =   (char)buf[i + 1];
  312.         dy = - (char)buf[i + 2];
  313.         break;
  314.     case MOUSE_PS2:            /* PS/2 mouse */
  315.         but = (buf[i] & 0x04) >> 1 |       /* Middle */
  316.               (buf[i] & 0x02) >> 1 |       /* Right */
  317.           (buf[i] & 0x01) << 2;        /* Left */
  318.         dx = (buf[i] & 0x10) ?    buf[i + 1]-256  :  buf[i + 1];
  319.           dy = (buf[i] & 0x20) ?  -(buf[i + 2]-256) : -buf[i + 2];
  320.           break;
  321.     }
  322.  
  323.     __mouse_eventhandler(but, dx, dy);
  324.  
  325.     i += proto[mtype][4];
  326.     event_handled = 1;
  327.  
  328.     goto handle_packets;
  329. }
  330.