summaryrefslogtreecommitdiffstats
path: root/historic/selection/mouse.c
diff options
context:
space:
mode:
Diffstat (limited to 'historic/selection/mouse.c')
-rw-r--r--historic/selection/mouse.c367
1 files changed, 367 insertions, 0 deletions
diff --git a/historic/selection/mouse.c b/historic/selection/mouse.c
new file mode 100644
index 000000000..87e9d06ed
--- /dev/null
+++ b/historic/selection/mouse.c
@@ -0,0 +1,367 @@
+/* simple driver for serial mouse */
+/* Andrew Haylett, 17th June 1993 */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "mouse.h"
+
+#define DEF_MDEV "/dev/mouse"
+#define DEF_MTYPE P_MS
+#define DEF_MBAUD 1200
+#define DEF_MSAMPLE 100
+#define DEF_MDELTA 25
+#define DEF_MACCEL 2
+#define DEF_SLACK -1
+
+/* thse settings may be altered by the user */
+static char *mdev = DEF_MDEV; /* mouse device */
+static mouse_type mtype = DEF_MTYPE; /* mouse type */
+static int mbaud = DEF_MBAUD; /* mouse device baud rate */
+static int msample = DEF_MSAMPLE; /* sample rate for Logitech mice */
+static int mdelta = DEF_MDELTA; /* x+y movements more than mdelta pixels..*/
+static int maccel = DEF_MACCEL; /* ..are multiplied by maccel. */
+static int slack = DEF_SLACK; /* < 0 ? no wraparound : amount of slack */
+int ms_copy_button = MS_BUTLEFT,
+ ms_paste_button = MS_BUTRIGHT;
+
+static char *progname;
+
+static void
+ms_usage()
+{
+ printf(
+ "Selection version 1.5, 17th June 1993\n"
+ "Usage: %s [-a accel] [-b baud-rate] [-c l|m|r] [-d delta]\n"
+ " [-m mouse-device] [-p l|m|r] [-s sample-rate] [-t mouse-type]\n"
+ " [-w slack]\n\n", progname);
+ printf(
+ " -a accel sets the acceleration (default %d)\n"
+ " -b baud-rate sets the baud rate (default %d)\n"
+ " -c l|m|r sets the copy button (default `l')\n"
+ " -d delta sets the delta value (default %d)\n"
+ " -m mouse-device sets mouse device (default `%s')\n"
+ " -p l|m|r sets the paste button (default `r')\n"
+ " -s sample-rate sets the sample rate (default %d)\n"
+ " -t mouse-type sets mouse type (default `ms')\n"
+ " Microsoft = `ms', Mouse Systems Corp = `msc',\n"
+ " MM Series = `mm', Logitech = `logi', BusMouse = `bm',\n"
+ " MSC 3-bytes = `sun', PS/2 = `ps2')\n"
+ " -w slack turns on wrap-around and specifies slack (default off)\n",
+ DEF_MACCEL, DEF_MBAUD, DEF_MDELTA, DEF_MDEV, DEF_MSAMPLE);
+ exit(1);
+}
+
+extern int optind;
+extern char *optarg;
+
+void
+ms_params(int argc, char *argv[])
+{
+ int opt;
+
+ progname = (rindex(argv[0], '/')) ? rindex(argv[0], '/') + 1 : argv[0];
+ while ((opt = getopt(argc, argv, "a:b:c:d:m:p:s:t:w:")) != -1)
+ {
+ switch (opt)
+ {
+ case 'a':
+ maccel = atoi(optarg);
+ if (maccel < 2)
+ ms_usage();
+ break;
+ case 'b':
+ mbaud = atoi(optarg);
+ break;
+ case 'c':
+ switch (*optarg)
+ {
+ case 'l': ms_copy_button = MS_BUTLEFT; break;
+ case 'm': ms_copy_button = MS_BUTMIDDLE; break;
+ case 'r': ms_copy_button = MS_BUTRIGHT; break;
+ default: ms_usage(); break;
+ }
+ break;
+ case 'd':
+ mdelta = atoi(optarg);
+ if (mdelta < 2)
+ ms_usage();
+ break;
+ case 'm':
+ mdev = optarg;
+ break;
+ case 'p':
+ switch (*optarg)
+ {
+ case 'l': ms_paste_button = MS_BUTLEFT; break;
+ case 'm': ms_paste_button = MS_BUTMIDDLE; break;
+ case 'r': ms_paste_button = MS_BUTRIGHT; break;
+ default: ms_usage(); break;
+ }
+ break;
+ case 's':
+ msample = atoi(optarg);
+ break;
+ case 't':
+ if (!strcmp(optarg, "ms"))
+ mtype = P_MS;
+ else if (!strcmp(optarg, "sun"))
+ mtype = P_SUN;
+ else if (!strcmp(optarg, "msc"))
+ mtype = P_MSC;
+ else if (!strcmp(optarg, "mm"))
+ mtype = P_MM;
+ else if (!strcmp(optarg, "logi"))
+ mtype = P_LOGI;
+ else if (!strcmp(optarg, "bm"))
+ mtype = P_BM;
+ else if (!strcmp(optarg, "ps2"))
+ mtype = P_PS2;
+ else
+ ms_usage();
+ break;
+ case 'w':
+ slack = atoi (optarg);
+ break;
+ default:
+ ms_usage();
+ break;
+ }
+ }
+}
+
+#define limit(n,l,u,s) n = ((s) < 0 ? \
+ (((n) < (l) ? (l) : ((n) > (u) ? (u) : (n)))) : \
+ (((n) < (l-s) ? (u) : ((n) > (u+s) ? (l) : (n)))))
+
+static int mx = 32767;
+static int my = 32767;
+static int x, y;
+static int mfd = -1;
+
+static const unsigned short cflag[NR_TYPES] =
+{
+ (CS7 | CREAD | CLOCAL | HUPCL ), /* MicroSoft */
+ (CS8 | CSTOPB | CREAD | CLOCAL | HUPCL ), /* MouseSystems 3 */
+ (CS8 | CSTOPB | CREAD | CLOCAL | HUPCL ), /* MouseSystems 5 */
+ (CS8 | PARENB | PARODD | CREAD | CLOCAL | HUPCL ), /* MMSeries */
+ (CS8 | CSTOPB | CREAD | CLOCAL | HUPCL ), /* Logitech */
+ 0, /* BusMouse */
+ 0 /* PS/2 */
+};
+
+static const unsigned char proto[NR_TYPES][5] =
+{
+ /* hd_mask hd_id dp_mask dp_id nobytes */
+ { 0x40, 0x40, 0x40, 0x00, 3 }, /* MicroSoft */
+ { 0xf8, 0x80, 0x00, 0x00, 3 }, /* MouseSystems 3 (Sun) */
+ { 0xf8, 0x80, 0x00, 0x00, 5 }, /* MouseSystems 5 */
+ { 0xe0, 0x80, 0x80, 0x00, 3 }, /* MMSeries */
+ { 0xe0, 0x80, 0x80, 0x00, 3 }, /* Logitech */
+ { 0xf8, 0x80, 0x00, 0x00, 5 }, /* BusMouse */
+ { 0xcc, 0x00, 0x00, 0x00, 3 } /* PS/2 */
+};
+
+static void
+ms_setspeed(const int old, const int new,
+ const unsigned short c_cflag)
+{
+ struct termios tty;
+ char *c;
+
+ tcgetattr(mfd, &tty);
+
+ tty.c_iflag = IGNBRK | IGNPAR;
+ tty.c_oflag = 0;
+ tty.c_lflag = 0;
+ tty.c_line = 0;
+ tty.c_cc[VTIME] = 0;
+ tty.c_cc[VMIN] = 1;
+
+ switch (old)
+ {
+ case 9600: tty.c_cflag = c_cflag | B9600; break;
+ case 4800: tty.c_cflag = c_cflag | B4800; break;
+ case 2400: tty.c_cflag = c_cflag | B2400; break;
+ case 1200:
+ default: tty.c_cflag = c_cflag | B1200; break;
+ }
+
+ tcsetattr(mfd, TCSAFLUSH, &tty);
+
+ switch (new)
+ {
+ case 9600: c = "*q"; tty.c_cflag = c_cflag | B9600; break;
+ case 4800: c = "*p"; tty.c_cflag = c_cflag | B4800; break;
+ case 2400: c = "*o"; tty.c_cflag = c_cflag | B2400; break;
+ case 1200:
+ default: c = "*n"; tty.c_cflag = c_cflag | B1200; break;
+ }
+
+ write(mfd, c, 2);
+ usleep(100000);
+ tcsetattr(mfd, TCSAFLUSH, &tty);
+}
+
+int
+ms_init(const int maxx, const int maxy)
+{
+ if ((mfd = open(mdev, O_RDWR)) < 0)
+ {
+ char buf[32];
+ sprintf(buf, "ms_init: %s", mdev);
+ perror(buf);
+ return -1;
+ }
+
+ if (mtype != P_BM && mtype != P_PS2)
+ {
+ ms_setspeed(9600, mbaud, cflag[mtype]);
+ ms_setspeed(4800, mbaud, cflag[mtype]);
+ ms_setspeed(2400, mbaud, cflag[mtype]);
+ ms_setspeed(1200, mbaud, cflag[mtype]);
+
+ if (mtype == P_LOGI)
+ {
+ write(mfd, "S", 1);
+ ms_setspeed(mbaud, mbaud, cflag[P_MM]);
+ }
+
+ if (msample <= 0) write(mfd, "O", 1);
+ else if (msample <= 15) write(mfd, "J", 1);
+ else if (msample <= 27) write(mfd, "K", 1);
+ else if (msample <= 42) write(mfd, "L", 1);
+ else if (msample <= 60) write(mfd, "R", 1);
+ else if (msample <= 85) write(mfd, "M", 1);
+ else if (msample <= 125) write(mfd, "Q", 1);
+ else write(mfd, "N", 1);
+ }
+
+ mx = maxx;
+ my = maxy;
+ x = mx / 2;
+ y = my / 2;
+ return 0;
+}
+
+int
+get_ms_event(struct ms_event *ev)
+{
+ unsigned char buf[5];
+ char dx, dy;
+ int i, acc;
+
+ if (mfd == -1)
+ return -1;
+ if (mtype != P_BM)
+ {
+ if (read(mfd, &buf[0], 1) != 1)
+ return -1;
+restart:
+ /* find a header packet */
+ while ((buf[0] & proto[mtype][0]) != proto[mtype][1])
+ {
+ if (read(mfd, &buf[0], 1) != 1)
+ {
+ perror("get_ms_event: read");
+ return -1;
+ }
+ }
+
+ /* read in the rest of the packet */
+ for (i = 1; i < proto[mtype][4]; ++i)
+ {
+ if (read(mfd, &buf[i], 1) != 1)
+ {
+ perror("get_ms_event: read");
+ return -1;
+ }
+ /* check whether it's a data packet */
+ if (mtype != P_PS2 && ((buf[i] & proto[mtype][2]) != proto[mtype][3]
+ || buf[i] == 0x80))
+ goto restart;
+ }
+ }
+ else /* bus mouse */
+ {
+ while ((i = read(mfd, buf, 3)) != 3 && errno == EAGAIN)
+ usleep(40000);
+ if (i != 3)
+ {
+ perror("get_ms_event: read");
+ return -1;
+ }
+ }
+
+/* construct the event */
+ switch (mtype)
+ {
+ case P_MS: /* Microsoft */
+ default:
+ ev->ev_butstate = ((buf[0] & 0x20) >> 3) | ((buf[0] & 0x10) >> 4);
+ dx = (char)(((buf[0] & 0x03) << 6) | (buf[1] & 0x3F));
+ dy = (char)(((buf[0] & 0x0C) << 4) | (buf[2] & 0x3F));
+ break;
+ case P_SUN: /* Mouse Systems 3 byte as used in Sun workstations */
+ ev->ev_butstate = (~buf[0]) & 0x07;
+ dx = (char)(buf[1]);
+ dy = -(char)(buf[2]);
+ break;
+ case P_MSC: /* Mouse Systems Corp (5 bytes, PC) */
+ ev->ev_butstate = (~buf[0]) & 0x07;
+ dx = (char)(buf[1]) + (char)(buf[3]);
+ dy = - ((char)(buf[2]) + (char)(buf[4]));
+ break;
+ case P_MM: /* MM Series */
+ case P_LOGI: /* Logitech */
+ ev->ev_butstate = buf[0] & 0x07;
+ dx = (buf[0] & 0x10) ? buf[1] : - buf[1];
+ dy = (buf[0] & 0x08) ? - buf[2] : buf[2];
+ break;
+ case P_BM: /* BusMouse */
+ ev->ev_butstate = (~buf[0]) & 0x07;
+ dx = (char)buf[1];
+ dy = - (char)buf[2];
+ break;
+ case P_PS2: /* PS/2 Mouse */
+ ev->ev_butstate = 0;
+ if (buf[0] & 0x01)
+ ev->ev_butstate |= MS_BUTLEFT;
+ if (buf[0] & 0x02)
+ ev->ev_butstate |= MS_BUTRIGHT;
+ dx = (buf[0] & 0x10) ? buf[1]-256 : buf[1];
+ dy = - ((buf[0] & 0x20) ? buf[2]-256 : buf[2]);
+ break;
+ }
+
+ acc = (abs(ev->ev_dx) + abs(ev->ev_dy) > mdelta) ? maccel : 1;
+ ev->ev_dx = dx * acc;
+ ev->ev_dy = dy * acc;
+ x += ev->ev_dx;
+ y += ev->ev_dy;
+ limit(x, 0, mx, (int) (slack * mx / my));
+ limit(y, 0, my, slack);
+ ev->ev_x = x;
+ ev->ev_y = y;
+ limit(ev->ev_x, 0, mx, -1);
+ limit(ev->ev_y, 0, my, -1);
+ if (dx || dy)
+ {
+ if (ev->ev_butstate)
+ ev->ev_code = MS_DRAG;
+ else
+ ev->ev_code = MS_MOVE;
+ }
+ else
+ {
+ if (ev->ev_butstate)
+ ev->ev_code = MS_BUTDOWN;
+ else
+ ev->ev_code = MS_BUTUP;
+ }
+ return 0;
+}