home *** CD-ROM | disk | FTP | other *** search
/ Chip 1995 March / CHIP3.mdf / slackwar / a / util / util-lin.10 / util-lin / util-linux-1.10 / selection / mouse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-20  |  9.6 KB  |  368 lines

  1. /* simple driver for serial mouse */
  2. /* Andrew Haylett, 17th June 1993 */
  3.  
  4. #include <unistd.h>
  5. #include <stdlib.h>
  6. #include <termios.h>
  7. #include <fcntl.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10.  
  11. #include "mouse.h"
  12.  
  13. #define DEF_MDEV    "/dev/mouse"
  14. #define DEF_MTYPE    P_MS
  15. #define DEF_MBAUD    1200
  16. #define DEF_MSAMPLE    100
  17. #define DEF_MDELTA    25
  18. #define DEF_MACCEL    2
  19. #define DEF_SLACK    -1
  20.  
  21. /* thse settings may be altered by the user */
  22. static char *mdev = DEF_MDEV;        /* mouse device */
  23. static mouse_type mtype = DEF_MTYPE;    /* mouse type */
  24. static int mbaud = DEF_MBAUD;        /* mouse device baud rate */
  25. static int msample = DEF_MSAMPLE;    /* sample rate for Logitech mice */
  26. static int mdelta = DEF_MDELTA;        /* x+y movements more than mdelta pixels..*/
  27. static int maccel = DEF_MACCEL;        /* ..are multiplied by maccel. */
  28. static int slack = DEF_SLACK;        /* < 0 ? no wraparound : amount of slack */
  29. int ms_copy_button = MS_BUTLEFT,
  30.     ms_paste_button = MS_BUTRIGHT;
  31.  
  32. static char *progname;
  33.  
  34. static void
  35. ms_usage()
  36. {
  37.     printf(
  38.     "Selection version 1.5, 17th June 1993\n"
  39.     "Usage: %s [-a accel] [-b baud-rate] [-c l|m|r] [-d delta]\n"
  40.     "       [-m mouse-device] [-p l|m|r] [-s sample-rate] [-t mouse-type]\n"
  41.     "       [-w slack]\n\n", progname);
  42.     printf(
  43.     "    -a accel         sets the acceleration (default %d)\n"
  44.     "    -b baud-rate     sets the baud rate (default %d)\n"
  45.     "    -c l|m|r         sets the copy button (default `l')\n"
  46.     "    -d delta         sets the delta value (default %d)\n"
  47.     "    -m mouse-device  sets mouse device (default `%s')\n"
  48.     "    -p l|m|r         sets the paste button (default `r')\n"
  49.     "    -s sample-rate   sets the sample rate (default %d)\n"
  50.     "    -t mouse-type    sets mouse type (default `ms')\n"
  51.     "                     Microsoft = `ms', Mouse Systems Corp = `msc',\n"
  52.     "                     MM Series = `mm', Logitech = `logi', BusMouse = `bm',\n"
  53.     "                     MSC 3-bytes = `sun', PS/2 = `ps2')\n"
  54.     "    -w slack         turns on wrap-around and specifies slack (default off)\n",
  55.     DEF_MACCEL, DEF_MBAUD, DEF_MDELTA, DEF_MDEV, DEF_MSAMPLE);
  56.     exit(1);
  57. }
  58.  
  59. extern int optind;
  60. extern char *optarg;
  61.  
  62. void
  63. ms_params(int argc, char *argv[])
  64. {
  65.     int opt;
  66.  
  67.     progname = (rindex(argv[0], '/')) ? rindex(argv[0], '/') + 1 : argv[0];
  68.     while ((opt = getopt(argc, argv, "a:b:c:d:m:p:s:t:w:")) != -1)
  69.     {
  70.     switch (opt)
  71.     {
  72.         case 'a':
  73.         maccel = atoi(optarg);
  74.         if (maccel < 2)
  75.             ms_usage();
  76.         break;
  77.         case 'b':
  78.         mbaud = atoi(optarg);
  79.         break;
  80.         case 'c':
  81.             switch (*optarg)
  82.             {
  83.                 case 'l':    ms_copy_button = MS_BUTLEFT; break;
  84.                 case 'm':    ms_copy_button = MS_BUTMIDDLE; break;
  85.                 case 'r':    ms_copy_button = MS_BUTRIGHT; break;
  86.                 default:    ms_usage(); break;
  87.             }
  88.         break;
  89.         case 'd':
  90.         mdelta = atoi(optarg);
  91.         if (mdelta < 2)
  92.             ms_usage();
  93.         break;
  94.         case 'm':
  95.         mdev = optarg;
  96.         break;
  97.         case 'p':
  98.             switch (*optarg)
  99.             {
  100.                 case 'l':    ms_paste_button = MS_BUTLEFT; break;
  101.                 case 'm':    ms_paste_button = MS_BUTMIDDLE; break;
  102.                 case 'r':    ms_paste_button = MS_BUTRIGHT; break;
  103.                 default:    ms_usage(); break;
  104.             }
  105.         break;
  106.         case 's':
  107.         msample = atoi(optarg);
  108.         break;
  109.         case 't':
  110.         if (!strcmp(optarg, "ms"))
  111.             mtype = P_MS;
  112.         else if (!strcmp(optarg, "sun"))
  113.             mtype = P_SUN;
  114.         else if (!strcmp(optarg, "msc"))
  115.             mtype = P_MSC;
  116.         else if (!strcmp(optarg, "mm"))
  117.             mtype = P_MM;
  118.         else if (!strcmp(optarg, "logi"))
  119.             mtype = P_LOGI;
  120.         else if (!strcmp(optarg, "bm"))
  121.             mtype = P_BM;
  122.         else if (!strcmp(optarg, "ps2"))
  123.             mtype = P_PS2;
  124.         else
  125.             ms_usage();
  126.         break;
  127.         case 'w':
  128.         slack = atoi (optarg);
  129.         break;
  130.         default:
  131.         ms_usage();
  132.         break;
  133.     }
  134.     }
  135. }
  136.  
  137. #define limit(n,l,u,s)    n = ((s) < 0 ? \
  138.     (((n) < (l) ? (l) : ((n) > (u) ? (u) : (n)))) : \
  139.     (((n) < (l-s) ? (u) : ((n) > (u+s) ? (l) : (n)))))
  140.  
  141. static int mx = 32767;
  142. static int my = 32767;
  143. static int x, y;
  144. static int mfd = -1;
  145.  
  146. static const unsigned short cflag[NR_TYPES] =
  147. {
  148.       (CS7                   | CREAD | CLOCAL | HUPCL ),   /* MicroSoft */
  149.       (CS8 | CSTOPB          | CREAD | CLOCAL | HUPCL ),   /* MouseSystems 3 */
  150.       (CS8 | CSTOPB          | CREAD | CLOCAL | HUPCL ),   /* MouseSystems 5 */
  151.       (CS8 | PARENB | PARODD | CREAD | CLOCAL | HUPCL ),   /* MMSeries */
  152.       (CS8 | CSTOPB          | CREAD | CLOCAL | HUPCL ),   /* Logitech */
  153.       0,                                                   /* BusMouse */
  154.       0                                                    /* PS/2 */
  155. };
  156.  
  157. static const unsigned char proto[NR_TYPES][5] =
  158. {
  159.     /*  hd_mask hd_id   dp_mask dp_id   nobytes */
  160.     {     0x40,    0x40,    0x40,    0x00,    3     },  /* MicroSoft */
  161.     {    0xf8,    0x80,    0x00,    0x00,    3    },  /* MouseSystems 3 (Sun) */
  162.     {    0xf8,    0x80,    0x00,    0x00,    5    },  /* MouseSystems 5 */
  163.     {    0xe0,    0x80,    0x80,    0x00,    3    },  /* MMSeries */
  164.     {    0xe0,    0x80,    0x80,    0x00,    3    },  /* Logitech */
  165.     {    0xf8,    0x80,    0x00,    0x00,    5    },  /* BusMouse */
  166.     {   0xcc,    0x00,    0x00,    0x00,    3    }   /* PS/2 */
  167. };
  168.  
  169. static void
  170. ms_setspeed(const int old, const int new,
  171.             const unsigned short c_cflag)
  172. {
  173.     struct termios tty;
  174.     char *c;
  175.  
  176.     tcgetattr(mfd, &tty);
  177.     
  178.     tty.c_iflag = IGNBRK | IGNPAR;
  179.     tty.c_oflag = 0;
  180.     tty.c_lflag = 0;
  181.     tty.c_line = 0;
  182.     tty.c_cc[VTIME] = 0;
  183.     tty.c_cc[VMIN] = 1;
  184.  
  185.     switch (old)
  186.     {
  187.         case 9600:    tty.c_cflag = c_cflag | B9600; break;
  188.         case 4800:    tty.c_cflag = c_cflag | B4800; break;
  189.         case 2400:    tty.c_cflag = c_cflag | B2400; break;
  190.         case 1200:
  191.     default:    tty.c_cflag = c_cflag | B1200; break;
  192.     }
  193.  
  194.     tcsetattr(mfd, TCSAFLUSH, &tty);
  195.  
  196.     switch (new)
  197.     {
  198.         case 9600:    c = "*q";  tty.c_cflag = c_cflag | B9600; break;
  199.         case 4800:    c = "*p";  tty.c_cflag = c_cflag | B4800; break;
  200.         case 2400:    c = "*o";  tty.c_cflag = c_cflag | B2400; break;
  201.         case 1200:
  202.     default:    c = "*n";  tty.c_cflag = c_cflag | B1200; break;
  203.     }
  204.  
  205.     write(mfd, c, 2);
  206.     usleep(100000);
  207.     tcsetattr(mfd, TCSAFLUSH, &tty);
  208. }
  209.  
  210. int
  211. ms_init(const int maxx, const int maxy)
  212. {
  213.     if ((mfd = open(mdev, O_RDWR)) < 0)
  214.     {
  215.         char buf[32];
  216.     sprintf(buf, "ms_init: %s", mdev);
  217.     perror(buf);
  218.     return -1;
  219.     }
  220.  
  221.     if (mtype != P_BM && mtype != P_PS2)
  222.     {
  223.     ms_setspeed(9600, mbaud, cflag[mtype]);
  224.     ms_setspeed(4800, mbaud, cflag[mtype]);
  225.     ms_setspeed(2400, mbaud, cflag[mtype]);
  226.     ms_setspeed(1200, mbaud, cflag[mtype]);
  227.  
  228.     if (mtype == P_LOGI)
  229.     {
  230.         write(mfd, "S", 1);
  231.         ms_setspeed(mbaud, mbaud, cflag[P_MM]);
  232.     }
  233.  
  234.     if    (msample <= 0)        write(mfd, "O", 1);
  235.     else if    (msample <= 15)        write(mfd, "J", 1);
  236.     else if    (msample <= 27)        write(mfd, "K", 1);
  237.     else if    (msample <= 42)        write(mfd, "L", 1);
  238.     else if    (msample <= 60)        write(mfd, "R", 1);
  239.     else if    (msample <= 85)        write(mfd, "M", 1);
  240.     else if    (msample <= 125)    write(mfd, "Q", 1);
  241.     else                write(mfd, "N", 1);
  242.     }
  243.  
  244.     mx = maxx;
  245.     my = maxy;
  246.     x = mx / 2;
  247.     y = my / 2;
  248.     return 0;
  249. }
  250.  
  251. int
  252. get_ms_event(struct ms_event *ev)
  253. {
  254.     unsigned char buf[5];
  255.     char dx, dy;
  256.     int i, acc;
  257.  
  258.     if (mfd == -1)
  259.     return -1;
  260.     if (mtype != P_BM)
  261.     {
  262.     if (read(mfd, &buf[0], 1) != 1)
  263.             return -1;
  264. restart:
  265.     /* find a header packet */
  266.     while ((buf[0] & proto[mtype][0]) != proto[mtype][1])
  267.     {
  268.         if (read(mfd, &buf[0], 1) != 1)
  269.         {
  270.             perror("get_ms_event: read");
  271.         return -1;
  272.         }
  273.     }
  274.  
  275.     /* read in the rest of the packet */
  276.     for (i = 1; i < proto[mtype][4]; ++i)
  277.     {
  278.         if (read(mfd, &buf[i], 1) != 1)
  279.         {
  280.             perror("get_ms_event: read");
  281.         return -1;
  282.         }
  283.     /* check whether it's a data packet */
  284.         if (mtype != P_PS2 && ((buf[i] & proto[mtype][2]) != proto[mtype][3]
  285.             || buf[i] == 0x80))
  286.         goto restart;
  287.     }
  288.     }
  289.     else    /* bus mouse */
  290.     {
  291.     while ((i = read(mfd, buf, 3)) != 3 && errno == EAGAIN)
  292.         usleep(40000);
  293.     if (i != 3)
  294.     {
  295.         perror("get_ms_event: read");
  296.         return -1;
  297.     }
  298.     }
  299.  
  300. /* construct the event */
  301.     switch (mtype)
  302.     {
  303.     case P_MS:        /* Microsoft */
  304.     default:
  305.         ev->ev_butstate = ((buf[0] & 0x20) >> 3) | ((buf[0] & 0x10) >> 4);
  306.         dx = (char)(((buf[0] & 0x03) << 6) | (buf[1] & 0x3F));
  307.         dy = (char)(((buf[0] & 0x0C) << 4) | (buf[2] & 0x3F));
  308.         break;
  309.         case P_SUN:        /* Mouse Systems 3 byte as used in Sun workstations */
  310.         ev->ev_butstate = (~buf[0]) & 0x07;
  311.         dx =  (char)(buf[1]);
  312.         dy = -(char)(buf[2]);
  313.         break;
  314.     case P_MSC:             /* Mouse Systems Corp (5 bytes, PC) */
  315.         ev->ev_butstate = (~buf[0]) & 0x07;
  316.         dx =    (char)(buf[1]) + (char)(buf[3]);
  317.         dy = - ((char)(buf[2]) + (char)(buf[4]));
  318.         break;
  319.     case P_MM:              /* MM Series */
  320.     case P_LOGI:            /* Logitech */
  321.         ev->ev_butstate = buf[0] & 0x07;
  322.         dx = (buf[0] & 0x10) ?   buf[1] : - buf[1];
  323.         dy = (buf[0] & 0x08) ? - buf[2] :   buf[2];
  324.         break;
  325.     case P_BM:              /* BusMouse */
  326.         ev->ev_butstate = (~buf[0]) & 0x07;
  327.         dx =   (char)buf[1];
  328.         dy = - (char)buf[2];
  329.         break;
  330.     case P_PS2:            /* PS/2 Mouse */
  331.         ev->ev_butstate = 0;
  332.         if (buf[0] & 0x01)
  333.         ev->ev_butstate |= MS_BUTLEFT;
  334.         if (buf[0] & 0x02)
  335.         ev->ev_butstate |= MS_BUTRIGHT;
  336.         dx =    (buf[0] & 0x10) ? buf[1]-256 : buf[1];
  337.         dy = - ((buf[0] & 0x20) ? buf[2]-256 : buf[2]);
  338.         break;
  339.     }
  340.  
  341.     acc = (abs(ev->ev_dx) + abs(ev->ev_dy) > mdelta) ? maccel : 1;
  342.     ev->ev_dx = dx * acc;
  343.     ev->ev_dy = dy * acc;
  344.     x += ev->ev_dx;
  345.     y += ev->ev_dy;
  346.     limit(x, 0, mx, (int) (slack * mx / my));
  347.     limit(y, 0, my, slack);
  348.     ev->ev_x = x;
  349.     ev->ev_y = y;
  350.     limit(ev->ev_x, 0, mx, -1);
  351.     limit(ev->ev_y, 0, my, -1);
  352.     if (dx || dy)
  353.     {
  354.     if (ev->ev_butstate)
  355.         ev->ev_code = MS_DRAG;
  356.     else
  357.         ev->ev_code = MS_MOVE;
  358.     }
  359.     else
  360.     {
  361.     if (ev->ev_butstate)
  362.         ev->ev_code = MS_BUTDOWN;
  363.     else
  364.         ev->ev_code = MS_BUTUP;
  365.     }
  366.     return 0;
  367. }
  368.