354 lines
9.6 KiB
C
354 lines
9.6 KiB
C
/* provided by hlu, modified slightly by obz */
|
|
/*
|
|
* Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
|
|
*
|
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
* documentation for any purpose is hereby granted without fee, provided that
|
|
* the above copyright notice appear in all copies and that both that
|
|
* copyright notice and this permission notice appear in supporting
|
|
* documentation, and that the name of Thomas Roell not be used in
|
|
* advertising or publicity pertaining to distribution of the software without
|
|
* specific, written prior permission. Thomas Roell makes no representations
|
|
* about the suitability of this software for any purpose. It is provided
|
|
* "as is" without express or implied warranty.
|
|
*
|
|
* THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
* EVENT SHALL THOMAS ROELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*
|
|
* $Header: /proj/X11/mit/server/ddx/x386/RCS/x386Io.c,v 1.2 1991/06/27 00:01:38 root Exp $
|
|
*/
|
|
|
|
#define NEED_EVENTS
|
|
#if 0
|
|
#include "X.h"
|
|
#include "Xproto.h"
|
|
#include "inputstr.h"
|
|
#include "scrnintstr.h"
|
|
|
|
#include "compiler.h"
|
|
|
|
#include "x386Procs.h"
|
|
#include "x386OSD.h"
|
|
#include "atKeynames.h"
|
|
#else
|
|
#include "mouse.h"
|
|
#endif
|
|
|
|
static void
|
|
Error (const char *str)
|
|
{
|
|
fprintf (stderr, "%s\n", str);
|
|
}
|
|
|
|
static void
|
|
x386PostMseEvent (int button, int dx, int dy)
|
|
{
|
|
fprintf (stderr, "button: %d, dx: %d, dy: %d\n", button, dx, dy);
|
|
}
|
|
|
|
static void
|
|
x386SetSpeed(old, new, cflag)
|
|
int old, new;
|
|
unsigned short cflag;
|
|
{
|
|
struct termio tty;
|
|
char *c;
|
|
|
|
(void) ioctl(x386Info.mseFd, TCGETA, &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 = cflag | B9600; break;
|
|
case 4800: tty.c_cflag = cflag | B4800; break;
|
|
case 2400: tty.c_cflag = cflag | B2400; break;
|
|
case 1200:
|
|
default: tty.c_cflag = cflag | B1200; break;
|
|
}
|
|
(void) ioctl(x386Info.mseFd, TCSETAW, &tty);
|
|
|
|
switch(new) {
|
|
case 9600: c = "*q"; tty.c_cflag = cflag | B9600; break;
|
|
case 4800: c = "*p"; tty.c_cflag = cflag | B4800; break;
|
|
case 2400: c = "*o"; tty.c_cflag = cflag | B2400; break;
|
|
case 1200:
|
|
default: c = "*n"; tty.c_cflag = cflag | B1200; break;
|
|
}
|
|
|
|
write(x386Info.mseFd, c, 2);
|
|
usleep(100000);
|
|
|
|
(void) ioctl(x386Info.mseFd, TCSETAW, &tty);
|
|
#ifdef TCMOUSE
|
|
(void) ioctl(x386Info.mseFd, TCMOUSE, 1);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
* x386MseProc --
|
|
* Handle the initialization, etc. of a mouse
|
|
*/
|
|
|
|
int
|
|
x386MseProc(what)
|
|
int what;
|
|
{
|
|
unchar map[4];
|
|
|
|
static unsigned short cflag[5] =
|
|
{
|
|
#ifdef linux_hack /* not needed with patch3 - server doesn't do this! */
|
|
(CS7 | ISTRIP | CREAD | CLOCAL | HUPCL ), /* MicroSoft */
|
|
#else
|
|
(CS7 | CREAD | CLOCAL | HUPCL ), /* MicroSoft */
|
|
#endif
|
|
(CS8 | CSTOPB | CREAD | CLOCAL | HUPCL ), /* MouseSystems */
|
|
(CS8 | PARENB | PARODD | CREAD | CLOCAL | HUPCL ), /* MMSeries */
|
|
(CS8 | CSTOPB | CREAD | CLOCAL | HUPCL ), /* Logitech */
|
|
0, /* BusMouse */
|
|
};
|
|
|
|
switch (what)
|
|
{
|
|
case DEVICE_INIT:
|
|
map[1] = 3;
|
|
map[2] = 2;
|
|
map[3] = 1;
|
|
break;
|
|
|
|
case DEVICE_ON:
|
|
if ((x386Info.mseFd = open(x386Info.mseDevice, O_RDWR | O_NDELAY)) < 0)
|
|
{
|
|
Error ("Cannot open mouse");
|
|
return (!Success);
|
|
}
|
|
|
|
if (x386Info.mseType != P_BM)
|
|
{
|
|
x386SetSpeed(9600, x386Info.baudRate, cflag[x386Info.mseType]);
|
|
x386SetSpeed(4800, x386Info.baudRate, cflag[x386Info.mseType]);
|
|
x386SetSpeed(2400, x386Info.baudRate, cflag[x386Info.mseType]);
|
|
x386SetSpeed(1200, x386Info.baudRate, cflag[x386Info.mseType]);
|
|
|
|
if (x386Info.mseType == P_LOGI)
|
|
{
|
|
write(x386Info.mseFd, "S", 1);
|
|
x386SetSpeed(x386Info.baudRate, x386Info.baudRate, cflag[P_MM]);
|
|
}
|
|
|
|
if (x386Info.sampleRate <= 0) write(x386Info.mseFd, "O", 1);
|
|
else if (x386Info.sampleRate <= 15) write(x386Info.mseFd, "J", 1);
|
|
else if (x386Info.sampleRate <= 27) write(x386Info.mseFd, "K", 1);
|
|
else if (x386Info.sampleRate <= 42) write(x386Info.mseFd, "L", 1);
|
|
else if (x386Info.sampleRate <= 60) write(x386Info.mseFd, "R", 1);
|
|
else if (x386Info.sampleRate <= 85) write(x386Info.mseFd, "M", 1);
|
|
else if (x386Info.sampleRate <= 125) write(x386Info.mseFd, "Q", 1);
|
|
else write(x386Info.mseFd, "N", 1);
|
|
}
|
|
|
|
x386Info.lastButtons = 0;
|
|
x386Info.emulateState = 0;
|
|
break;
|
|
|
|
case DEVICE_OFF:
|
|
case DEVICE_CLOSE:
|
|
if (x386Info.mseType == P_LOGI)
|
|
{
|
|
write(x386Info.mseFd, "U", 1);
|
|
x386SetSpeed(x386Info.baudRate, 1200, cflag[P_LOGI]);
|
|
}
|
|
close(x386Info.mseFd);
|
|
break;
|
|
|
|
}
|
|
|
|
return Success;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* x386MseEvents --
|
|
* Read the new events from the device, and pass them to the eventhandler.
|
|
*/
|
|
|
|
void
|
|
x386MseEvents()
|
|
{
|
|
unchar rBuf[64];
|
|
int i,nBytes, buttons, dx, dy;
|
|
static int pBufP = 0;
|
|
static unsigned char pBuf[8];
|
|
|
|
static unsigned char proto[5][5] = {
|
|
/* hd_mask hd_id dp_mask dp_id nobytes */
|
|
{ 0x40, 0x40, 0x40, 0x00, 3 }, /* MicroSoft */
|
|
{ 0xf8, 0x80, 0x00, 0x00, 5 }, /* MouseSystems */
|
|
{ 0xe0, 0x80, 0x80, 0x00, 3 }, /* MMSeries */
|
|
{ 0xe0, 0x80, 0x80, 0x00, 3 }, /* Logitech */
|
|
{ 0xf8, 0x80, 0x00, 0x00, 5 }, /* BusMouse */
|
|
};
|
|
|
|
if (!(nBytes = read(x386Info.mseFd, (char *)rBuf, sizeof(rBuf)))) return;
|
|
|
|
for ( i=0; i < nBytes; i++) {
|
|
/*
|
|
* Hack for resyncing: We check here for a package that is:
|
|
* a) illegal (detected by wrong data-package header)
|
|
* b) invalid (0x80 == -128 and that might be wrong for MouseSystems)
|
|
* c) bad header-package
|
|
*
|
|
* NOTE: b) is a voilation of the MouseSystems-Protocol, since values of
|
|
* -128 are allowed, but since they are very seldom we can easily
|
|
* use them as package-header with no button pressed.
|
|
*/
|
|
if (pBufP != 0 &&
|
|
((rBuf[i] & proto[x386Info.mseType][2]) != proto[x386Info.mseType][3]
|
|
|| rBuf[i] == 0x80))
|
|
{
|
|
pBufP = 0; /* skip package */
|
|
}
|
|
|
|
if (pBufP == 0 &&
|
|
(rBuf[i] & proto[x386Info.mseType][0]) != proto[x386Info.mseType][1])
|
|
{
|
|
/*
|
|
* Hack for Logitech MouseMan Mouse - Middle button
|
|
*
|
|
* Unfortunately this mouse has variable length packets: the standard
|
|
* Microsoft 3 byte packet plus an optional 4th byte whenever the
|
|
* middle button status changes.
|
|
*
|
|
* We have already processed the standard packet with the movement
|
|
* and button info. Now post an event message with the old status
|
|
* of the left and right buttons and the updated middle button.
|
|
*/
|
|
if (x386Info.mseType == P_MS && (rBuf[i] == 0x20 || rBuf[i] == 0))
|
|
{
|
|
buttons = ((int)(rBuf[i] & 0x20) >> 4)
|
|
| (x386Info.lastButtons & 0x05);
|
|
x386PostMseEvent(buttons, 0, 0);
|
|
}
|
|
|
|
continue; /* skip package */
|
|
}
|
|
|
|
|
|
pBuf[pBufP++] = rBuf[i];
|
|
if (pBufP != proto[x386Info.mseType][4]) continue;
|
|
|
|
/*
|
|
* assembly full package
|
|
*/
|
|
switch(x386Info.mseType) {
|
|
|
|
case P_MS: /* Mircosoft */
|
|
buttons = (x386Info.lastButtons & 2)
|
|
| ((int)(pBuf[0] & 0x20) >> 3)
|
|
| ((int)(pBuf[0] & 0x10) >> 4);
|
|
dx = (char)(((pBuf[0] & 0x03) << 6) | (pBuf[1] & 0x3F));
|
|
dy = (char)(((pBuf[0] & 0x0C) << 4) | (pBuf[2] & 0x3F));
|
|
break;
|
|
|
|
case P_MSC: /* Mouse Systems Corp */
|
|
buttons = (~pBuf[0]) & 0x07;
|
|
dx = (char)(pBuf[1]) + (char)(pBuf[3]);
|
|
dy = - ((char)(pBuf[2]) + (char)(pBuf[4]));
|
|
break;
|
|
|
|
case P_MM: /* MM Series */
|
|
case P_LOGI: /* Logitech Mice */
|
|
buttons = pBuf[0] & 0x07;
|
|
dx = (pBuf[0] & 0x10) ? pBuf[1] : - pBuf[1];
|
|
dy = (pBuf[0] & 0x08) ? - pBuf[2] : pBuf[2];
|
|
break;
|
|
|
|
case P_BM: /* BusMouse */
|
|
buttons = (~pBuf[0]) & 0x07;
|
|
dx = (char)pBuf[1];
|
|
dy = - (char)pBuf[2];
|
|
break;
|
|
}
|
|
|
|
x386PostMseEvent(buttons, dx, dy);
|
|
pBufP = 0;
|
|
}
|
|
}
|
|
|
|
void
|
|
x386MseConfig (char *dev, int type)
|
|
{
|
|
x386Info.mseType = type;
|
|
x386Info.mseDevice = dev;
|
|
x386Info.sampleRate = 150;
|
|
x386Info.emulate3Buttons = FALSE;
|
|
}
|
|
|
|
int stop = FALSE;
|
|
|
|
void
|
|
stopit(int foo)
|
|
{
|
|
stop = TRUE;
|
|
}
|
|
|
|
main (int argc, char **argv)
|
|
{
|
|
int i = 0;
|
|
char *str, *dev;
|
|
|
|
if (argc != 3) {
|
|
fprintf (stderr, "Usage: %s [Microsoft|MouseSystem|MMseries|Logitech] device\n", argv [0]);
|
|
exit (1);
|
|
}
|
|
|
|
i = P_MS;
|
|
if (!strcasecmp (argv [1], "Microsoft")) i = P_MS;
|
|
if (!strcasecmp (argv [1], "MouseSystem")) i = P_MSC;
|
|
if (!strcasecmp (argv [1], "MMseries")) i = P_MM;
|
|
if (!strcasecmp (argv [1], "Logitech")) i = P_LOGI;
|
|
|
|
dev = argv[2];
|
|
|
|
switch (i) {
|
|
case P_MS:
|
|
str = "Microsoft";
|
|
break;
|
|
case P_MSC:
|
|
str = "MouseSystem";
|
|
break;
|
|
case P_MM:
|
|
str= "MMseries";
|
|
break;
|
|
case P_LOGI:
|
|
str = "Logitech";
|
|
break;
|
|
}
|
|
fprintf (stderr, "You are testing %s on %s.\n", str, dev);
|
|
x386MseConfig (dev, i);
|
|
|
|
x386MseProc(DEVICE_INIT);
|
|
x386MseProc(DEVICE_ON);
|
|
/* outb (0x03fb, 0x03); */
|
|
|
|
signal(SIGINT, stopit);
|
|
fprintf(stderr, "Play with the mouse - hit ctrl-c to stop\n");
|
|
for (;;) {
|
|
if (stop)
|
|
break;
|
|
x386MseEvents();
|
|
}
|
|
x386MseProc(DEVICE_CLOSE);
|
|
fprintf(stderr, "finished.\n");
|
|
}
|