123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944 |
- /*
- *
- * Copyright © 2001 Keith Packard
- *
- * 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 Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD 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.
- */
- #ifdef HAVE_CONFIG_H
- #include <kdrive-config.h>
- #endif
- #include <errno.h>
- #include <termios.h>
- #include <X11/X.h>
- #include <X11/Xproto.h>
- #include <X11/Xpoll.h>
- #include "inputstr.h"
- #include "scrnintstr.h"
- #include "kdrive.h"
- #undef DEBUG
- #undef DEBUG_BYTES
- #define KBUFIO_SIZE 256
- #define MOUSE_TIMEOUT 100
- typedef struct _kbufio {
- int fd;
- unsigned char buf[KBUFIO_SIZE];
- int avail;
- int used;
- } Kbufio;
- static Bool MouseWaitForReadable(int fd, int timeout)
- {
- fd_set set;
- struct timeval tv, *tp;
- int n;
- CARD32 done;
- done = GetTimeInMillis() + timeout;
- for (;;) {
- FD_ZERO(&set);
- FD_SET(fd, &set);
- if (timeout == -1)
- tp = 0;
- else {
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout % 1000) * 1000;
- tp = &tv;
- }
- n = select(fd + 1, &set, 0, 0, tp);
- if (n > 0)
- return TRUE;
- if (n < 0 && (errno == EAGAIN || errno == EINTR)) {
- timeout = (int)(done - GetTimeInMillis());
- if (timeout > 0)
- continue;
- }
- break;
- }
- return FALSE;
- }
- static int MouseReadByte(Kbufio * b, int timeout)
- {
- int n;
- if (b->avail <= b->used) {
- if (timeout && !MouseWaitForReadable(b->fd, timeout)) {
- #ifdef DEBUG_BYTES
- ErrorF("\tTimeout %d\n", timeout);
- #endif
- return -1;
- }
- n = read(b->fd, b->buf, KBUFIO_SIZE);
- if (n <= 0)
- return -1;
- b->avail = n;
- b->used = 0;
- }
- #ifdef DEBUG_BYTES
- ErrorF("\tget %02x\n", b->buf[b->used]);
- #endif
- return b->buf[b->used++];
- }
- #if NOTUSED
- static int MouseFlush(Kbufio * b, char *buf, int size)
- {
- CARD32 now = GetTimeInMillis();
- CARD32 done = now + 100;
- int c;
- int n = 0;
- while ((c = MouseReadByte(b, done - now)) != -1) {
- if (buf) {
- if (n == size) {
- memmove(buf, buf + 1, size - 1);
- n--;
- }
- buf[n++] = c;
- }
- now = GetTimeInMillis();
- if ((INT32) (now - done) >= 0)
- break;
- }
- return n;
- }
- static int MousePeekByte(Kbufio * b, int timeout)
- {
- int c;
- c = MouseReadByte(b, timeout);
- if (c != -1)
- --b->used;
- return c;
- }
- #endif /* NOTUSED */
- static Bool MouseWaitForWritable(int fd, int timeout)
- {
- fd_set set;
- struct timeval tv, *tp;
- int n;
- FD_ZERO(&set);
- FD_SET(fd, &set);
- if (timeout == -1)
- tp = 0;
- else {
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout % 1000) * 1000;
- tp = &tv;
- }
- n = select(fd + 1, 0, &set, 0, tp);
- if (n > 0)
- return TRUE;
- return FALSE;
- }
- static Bool MouseWriteByte(const int fd, const unsigned char c, const int timeout)
- {
- int ret;
- #ifdef DEBUG_BYTES
- ErrorF("\tput %02x\n", c);
- #endif
- for (;;) {
- ret = write(fd, &c, 1);
- if (ret == 1)
- return TRUE;
- if (ret == 0)
- return FALSE;
- if (errno != EWOULDBLOCK)
- return FALSE;
- if (!MouseWaitForWritable(fd, timeout))
- return FALSE;
- }
- }
- static Bool MouseWriteBytes(const int fd, const unsigned char *c, int n,
- const int timeout)
- {
- while (n--)
- if (!MouseWriteByte(fd, *c++, timeout))
- return FALSE;
- return TRUE;
- }
- #define MAX_MOUSE 10 /* maximum length of mouse protocol */
- #define MAX_SKIP 16 /* number of error bytes before switching */
- #define MAX_VALID 4 /* number of valid packets before accepting */
- typedef struct _kmouseProt {
- char *name;
- Bool(*Complete) (KdMouseInfo * mi, unsigned char *ev, int ne);
- int (*Valid) (KdMouseInfo * mi, unsigned char *ev, int ne);
- Bool(*Parse) (KdMouseInfo * mi, unsigned char *ev, int ne);
- Bool(*Init) (KdMouseInfo * mi);
- unsigned char headerMask, headerValid;
- unsigned char dataMask, dataValid;
- Bool tty;
- unsigned int c_iflag;
- unsigned int c_oflag;
- unsigned int c_lflag;
- unsigned int c_cflag;
- unsigned int speed;
- unsigned char *init;
- unsigned long state;
- } KmouseProt;
- typedef enum _kmouseStage {
- MouseBroken, MouseTesting, MouseWorking
- } KmouseStage;
- typedef struct _kmouse {
- Kbufio iob;
- const KmouseProt *prot;
- int i_prot;
- KmouseStage stage; /* protocol verification stage */
- Bool tty; /* mouse device is a tty */
- int valid; /* sequential valid events */
- int tested; /* bytes scanned during Testing phase */
- int invalid; /* total invalid bytes for this protocol */
- unsigned long state; /* private per protocol, init to prot->state */
- } Kmouse;
- static int mouseValid(KdMouseInfo * mi, unsigned char *ev, int ne)
- {
- Kmouse *km = mi->driver;
- const KmouseProt *prot = km->prot;
- int i;
- for (i = 0; i < ne; i++)
- if ((ev[i] & prot->headerMask) == prot->headerValid)
- break;
- if (i != 0)
- return i;
- for (i = 1; i < ne; i++)
- if ((ev[i] & prot->dataMask) != prot->dataValid)
- return -1;
- return 0;
- }
- static Bool threeComplete(KdMouseInfo * mi, unsigned char *ev, int ne)
- {
- return ne == 3;
- }
- static Bool fourComplete(KdMouseInfo * mi, unsigned char *ev, int ne)
- {
- return ne == 4;
- }
- static Bool fiveComplete(KdMouseInfo * mi, unsigned char *ev, int ne)
- {
- return ne == 5;
- }
- static Bool MouseReasonable(KdMouseInfo * mi, unsigned long flags, int dx,
- int dy)
- {
- Kmouse *km = mi->driver;
- if (km->stage == MouseWorking)
- return TRUE;
- if (dx < -50 || dx > 50) {
- #ifdef DEBUG
- ErrorF("Large X %d\n", dx);
- #endif
- return FALSE;
- }
- if (dy < -50 || dy > 50) {
- #ifdef DEBUG
- ErrorF("Large Y %d\n", dy);
- #endif
- return FALSE;
- }
- return TRUE;
- }
- /*
- * Standard PS/2 mouse protocol
- */
- static Bool ps2Parse(KdMouseInfo * mi, unsigned char *ev, int ne)
- {
- Kmouse *km = mi->driver;
- int dx, dy, dz;
- unsigned long flags;
- unsigned long flagsrelease = 0;
- flags = KD_MOUSE_DELTA;
- if (ev[0] & 4)
- flags |= KD_BUTTON_2;
- if (ev[0] & 2)
- flags |= KD_BUTTON_3;
- if (ev[0] & 1)
- flags |= KD_BUTTON_1;
- if (ne > 3) {
- dz = (int)(signed char)ev[3];
- if (dz < 0) {
- flags |= KD_BUTTON_4;
- flagsrelease = KD_BUTTON_4;
- } else if (dz > 0) {
- flags |= KD_BUTTON_5;
- flagsrelease = KD_BUTTON_5;
- }
- }
- dx = ev[1];
- if (ev[0] & 0x10)
- dx -= 256;
- dy = ev[2];
- if (ev[0] & 0x20)
- dy -= 256;
- dy = -dy;
- if (!MouseReasonable(mi, flags, dx, dy))
- return FALSE;
- if (km->stage == MouseWorking) {
- KdEnqueueMouseEvent(mi, flags, dx, dy);
- if (flagsrelease) {
- flags &= ~flagsrelease;
- KdEnqueueMouseEvent(mi, flags, dx, dy);
- }
- }
- return TRUE;
- }
- static Bool ps2Init(KdMouseInfo * mi);
- static const KmouseProt ps2Prot = {
- "ps/2",
- threeComplete, mouseValid, ps2Parse, ps2Init,
- 0x08, 0x08, 0x00, 0x00,
- FALSE
- };
- static const KmouseProt imps2Prot = {
- "imps/2",
- fourComplete, mouseValid, ps2Parse, ps2Init,
- 0x08, 0x08, 0x00, 0x00,
- FALSE
- };
- static const KmouseProt exps2Prot = {
- "exps/2",
- fourComplete, mouseValid, ps2Parse, ps2Init,
- 0x08, 0x08, 0x00, 0x00,
- FALSE
- };
- /*
- * Once the mouse is known to speak ps/2 protocol, go and find out
- * what advanced capabilities it has and turn them on
- */
- /* these extracted from FreeBSD 4.3 sys/dev/kbd/atkbdcreg.h */
- /* aux device commands (sent to KBD_DATA_PORT) */
- #define PSMC_SET_SCALING11 0x00e6
- #define PSMC_SET_SCALING21 0x00e7
- #define PSMC_SET_RESOLUTION 0x00e8
- #define PSMC_SEND_DEV_STATUS 0x00e9
- #define PSMC_SET_STREAM_MODE 0x00ea
- #define PSMC_SEND_DEV_DATA 0x00eb
- #define PSMC_SET_REMOTE_MODE 0x00f0
- #define PSMC_SEND_DEV_ID 0x00f2
- #define PSMC_SET_SAMPLING_RATE 0x00f3
- #define PSMC_ENABLE_DEV 0x00f4
- #define PSMC_DISABLE_DEV 0x00f5
- #define PSMC_SET_DEFAULTS 0x00f6
- #define PSMC_RESET_DEV 0x00ff
- /* PSMC_SET_RESOLUTION argument */
- #define PSMD_RES_LOW 0 /* typically 25ppi */
- #define PSMD_RES_MEDIUM_LOW 1 /* typically 50ppi */
- #define PSMD_RES_MEDIUM_HIGH 2 /* typically 100ppi (default) */
- #define PSMD_RES_HIGH 3 /* typically 200ppi */
- #define PSMD_MAX_RESOLUTION PSMD_RES_HIGH
- /* PSMC_SET_SAMPLING_RATE */
- #define PSMD_MAX_RATE 255 /* FIXME: not sure if it's possible */
- /* aux device ID */
- #define PSM_MOUSE_ID 0
- #define PSM_BALLPOINT_ID 2
- #define PSM_INTELLI_ID 3
- #define PSM_EXPLORER_ID 4
- #define PSM_4DMOUSE_ID 6
- #define PSM_4DPLUS_ID 8
- static const unsigned char ps2_init[] = {
- PSMC_ENABLE_DEV,
- 0,
- };
- #define NINIT_PS2 1
- static const unsigned char wheel_3button_init[] = {
- PSMC_SET_SAMPLING_RATE, 200,
- PSMC_SET_SAMPLING_RATE, 100,
- PSMC_SET_SAMPLING_RATE, 80,
- PSMC_SEND_DEV_ID,
- 0,
- };
- #define NINIT_IMPS2 4
- static const unsigned char wheel_5button_init[] = {
- PSMC_SET_SAMPLING_RATE, 200,
- PSMC_SET_SAMPLING_RATE, 100,
- PSMC_SET_SAMPLING_RATE, 80,
- PSMC_SET_SAMPLING_RATE, 200,
- PSMC_SET_SAMPLING_RATE, 200,
- PSMC_SET_SAMPLING_RATE, 80,
- PSMC_SEND_DEV_ID,
- 0
- };
- #define NINIT_EXPS2 7
- static const unsigned char intelli_init[] = {
- PSMC_SET_SAMPLING_RATE, 200,
- PSMC_SET_SAMPLING_RATE, 100,
- PSMC_SET_SAMPLING_RATE, 80,
- 0
- };
- #define NINIT_INTELLI 3
- static int ps2SkipInit(KdMouseInfo * const mi, int ninit, const Bool ret_next)
- {
- Kmouse * const km = mi->driver;
- int c = -1;
- Bool waiting;
- waiting = FALSE;
- while (ninit || ret_next) {
- c = MouseReadByte(&km->iob, 1); // Minimum timeout like in xf86-input-mouse
- if (c == -1)
- break;
- /* look for ACK */
- if (c == 0xfa) {
- ninit--;
- if (ret_next)
- waiting = TRUE;
- }
- /* look for packet start -- not the response */
- else if ((c & 0x08) == 0x08)
- waiting = FALSE;
- else if (waiting)
- break;
- }
- return c;
- }
- static Bool ps2Init(KdMouseInfo * mi)
- {
- Kmouse *km = mi->driver;
- int id;
- const unsigned char *init;
- int ninit;
- /* Send Intellimouse initialization sequence */
- MouseWriteBytes(km->iob.fd, intelli_init, strlen((char *)intelli_init),
- 100);
- /*
- * Send ID command
- */
- if (!MouseWriteByte(km->iob.fd, PSMC_SEND_DEV_ID, 100))
- return FALSE;
- id = ps2SkipInit(mi, 0, TRUE);
- switch (id) {
- case 3:
- init = wheel_3button_init;
- ninit = NINIT_IMPS2;
- km->prot = &imps2Prot;
- break;
- case 4:
- init = wheel_5button_init;
- ninit = NINIT_EXPS2;
- km->prot = &exps2Prot;
- break;
- default:
- init = ps2_init;
- ninit = NINIT_PS2;
- km->prot = &ps2Prot;
- break;
- }
- if (init)
- MouseWriteBytes(km->iob.fd, init, strlen((char *)init), 100);
- /*
- * Flush out the available data to eliminate responses to the
- * initialization string. Make sure any partial event is
- * skipped
- */
- (void)ps2SkipInit(mi, ninit, FALSE);
- return TRUE;
- }
- static Bool busParse(KdMouseInfo * mi, unsigned char *ev, int ne)
- {
- Kmouse *km = mi->driver;
- int dx, dy;
- unsigned long flags;
- flags = KD_MOUSE_DELTA;
- dx = (signed char)ev[1];
- dy = -(signed char)ev[2];
- if ((ev[0] & 4) == 0)
- flags |= KD_BUTTON_1;
- if ((ev[0] & 2) == 0)
- flags |= KD_BUTTON_2;
- if ((ev[0] & 1) == 0)
- flags |= KD_BUTTON_3;
- if (!MouseReasonable(mi, flags, dx, dy))
- return FALSE;
- if (km->stage == MouseWorking)
- KdEnqueueMouseEvent(mi, flags, dx, dy);
- return TRUE;
- }
- static const KmouseProt busProt = {
- "bus",
- threeComplete, mouseValid, busParse, 0,
- 0xf8, 0x00, 0x00, 0x00,
- FALSE
- };
- /*
- * Standard MS serial protocol, three bytes
- */
- static Bool msParse(KdMouseInfo * mi, unsigned char *ev, int ne)
- {
- Kmouse *km = mi->driver;
- int dx, dy;
- unsigned long flags;
- flags = KD_MOUSE_DELTA;
- if (ev[0] & 0x20)
- flags |= KD_BUTTON_1;
- if (ev[0] & 0x10)
- flags |= KD_BUTTON_3;
- dx = (signed char)(((ev[0] & 0x03) << 6) | (ev[1] & 0x3F));
- dy = (signed char)(((ev[0] & 0x0C) << 4) | (ev[2] & 0x3F));
- if (!MouseReasonable(mi, flags, dx, dy))
- return FALSE;
- if (km->stage == MouseWorking)
- KdEnqueueMouseEvent(mi, flags, dx, dy);
- return TRUE;
- }
- static const KmouseProt msProt = {
- "ms",
- threeComplete, mouseValid, msParse, 0,
- 0xc0, 0x40, 0xc0, 0x00,
- TRUE,
- IGNPAR,
- 0,
- 0,
- CS7 | CSTOPB | CREAD | CLOCAL,
- B1200,
- };
- /*
- * Logitech mice send 3 or 4 bytes, the only way to tell is to look at the
- * first byte of a synchronized protocol stream and see if it's got
- * any bits turned on that can't occur in that fourth byte
- */
- static Bool logiComplete(KdMouseInfo * mi, unsigned char *ev, int ne)
- {
- Kmouse *km = mi->driver;
- if ((ev[0] & 0x40) == 0x40)
- return ne == 3;
- if (km->stage != MouseBroken && (ev[0] & ~0x23) == 0)
- return ne == 1;
- return FALSE;
- }
- static int logiValid(KdMouseInfo * mi, unsigned char *ev, int ne)
- {
- Kmouse *km = mi->driver;
- const KmouseProt *prot = km->prot;
- int i;
- for (i = 0; i < ne; i++) {
- if ((ev[i] & 0x40) == 0x40)
- break;
- if (km->stage != MouseBroken && (ev[i] & ~0x23) == 0)
- break;
- }
- if (i != 0)
- return i;
- for (i = 1; i < ne; i++)
- if ((ev[i] & prot->dataMask) != prot->dataValid)
- return -1;
- return 0;
- }
- static Bool logiParse(KdMouseInfo * mi, unsigned char *ev, int ne)
- {
- Kmouse *km = mi->driver;
- int dx, dy;
- unsigned long flags;
- flags = KD_MOUSE_DELTA;
- if (ne == 3) {
- if (ev[0] & 0x20)
- flags |= KD_BUTTON_1;
- if (ev[0] & 0x10)
- flags |= KD_BUTTON_3;
- dx = (signed char)(((ev[0] & 0x03) << 6) | (ev[1] & 0x3F));
- dy = (signed char)(((ev[0] & 0x0C) << 4) | (ev[2] & 0x3F));
- flags |= km->state & KD_BUTTON_2;
- } else {
- if (ev[0] & 0x20)
- flags |= KD_BUTTON_2;
- dx = 0;
- dy = 0;
- flags |= km->state & (KD_BUTTON_1 | KD_BUTTON_3);
- }
- if (!MouseReasonable(mi, flags, dx, dy))
- return FALSE;
- if (km->stage == MouseWorking)
- KdEnqueueMouseEvent(mi, flags, dx, dy);
- return TRUE;
- }
- static const KmouseProt logiProt = {
- "logitech",
- logiComplete, logiValid, logiParse, 0,
- 0xc0, 0x40, 0xc0, 0x00,
- TRUE,
- IGNPAR,
- 0,
- 0,
- CS7 | CSTOPB | CREAD | CLOCAL,
- B1200,
- };
- /*
- * Mouse systems protocol, 5 bytes
- */
- static Bool mscParse(KdMouseInfo * mi, unsigned char *ev, int ne)
- {
- Kmouse *km = mi->driver;
- int dx, dy;
- unsigned long flags;
- flags = KD_MOUSE_DELTA;
- if (!(ev[0] & 0x4))
- flags |= KD_BUTTON_1;
- if (!(ev[0] & 0x2))
- flags |= KD_BUTTON_2;
- if (!(ev[0] & 0x1))
- flags |= KD_BUTTON_3;
- dx = (signed char)(ev[1]) + (signed char)(ev[3]);
- dy = -((signed char)(ev[2]) + (signed char)(ev[4]));
- if (!MouseReasonable(mi, flags, dx, dy))
- return FALSE;
- if (km->stage == MouseWorking)
- KdEnqueueMouseEvent(mi, flags, dx, dy);
- return TRUE;
- }
- static const KmouseProt mscProt = {
- "msc",
- fiveComplete, mouseValid, mscParse, 0,
- 0xf8, 0x80, 0x00, 0x00,
- TRUE,
- IGNPAR,
- 0,
- 0,
- CS8 | CSTOPB | CREAD | CLOCAL,
- B1200,
- };
- /*
- * Use logitech before ms -- they're the same except that
- * logitech sometimes has a fourth byte
- */
- static const KmouseProt *kmouseProts[] = {
- &ps2Prot, &imps2Prot, &exps2Prot, &busProt, &logiProt, &msProt,
- &mscProt,
- };
- #define NUM_PROT (sizeof (kmouseProts) / sizeof (kmouseProts[0]))
- static void MouseInitProtocol(Kmouse * km)
- {
- int ret;
- struct termios t;
- if (km->prot->tty) {
- ret = tcgetattr(km->iob.fd, &t);
- if (ret >= 0) {
- t.c_iflag = km->prot->c_iflag;
- t.c_oflag = km->prot->c_oflag;
- t.c_lflag = km->prot->c_lflag;
- t.c_cflag = km->prot->c_cflag;
- cfsetispeed(&t, km->prot->speed);
- cfsetospeed(&t, km->prot->speed);
- tcsetattr(km->iob.fd, TCSANOW, &t);
- }
- }
- km->stage = MouseBroken;
- km->valid = 0;
- km->tested = 0;
- km->invalid = 0;
- km->state = km->prot->state;
- }
- static void MouseFirstProtocol(Kmouse * km, char *prot)
- {
- if (prot) {
- for (km->i_prot = 0; km->i_prot < NUM_PROT; km->i_prot++)
- if (!strcmp(prot, kmouseProts[km->i_prot]->name))
- break;
- if (km->i_prot == NUM_PROT) {
- int i;
- ErrorF("Unknown mouse protocol \"%s\". Pick one of:",
- prot);
- for (i = 0; i < NUM_PROT; i++)
- ErrorF(" %s", kmouseProts[i]->name);
- ErrorF("\n");
- } else {
- km->prot = kmouseProts[km->i_prot];
- if (km->tty && !km->prot->tty)
- ErrorF
- ("Mouse device is serial port, protocol %s is not serial protocol\n",
- prot);
- else if (!km->tty && km->prot->tty)
- ErrorF
- ("Mouse device is not serial port, protocol %s is serial protocol\n",
- prot);
- }
- }
- if (!km->prot) {
- for (km->i_prot = 0; kmouseProts[km->i_prot]->tty != km->tty;
- km->i_prot++) ;
- km->prot = kmouseProts[km->i_prot];
- }
- MouseInitProtocol(km);
- }
- static void MouseNextProtocol(Kmouse * km)
- {
- do {
- if (!km->prot)
- km->i_prot = 0;
- else if (++km->i_prot == NUM_PROT)
- km->i_prot = 0;
- km->prot = kmouseProts[km->i_prot];
- } while (km->prot->tty != km->tty);
- MouseInitProtocol(km);
- ErrorF("Switching to mouse protocol \"%s\"\n", km->prot->name);
- }
- static void MouseRead(int mousePort, void *closure)
- {
- KdMouseInfo *mi = closure;
- Kmouse *km = mi->driver;
- unsigned char event[MAX_MOUSE];
- int ne;
- int c;
- int i;
- int timeout;
- timeout = 0;
- ne = 0;
- for (;;) {
- c = MouseReadByte(&km->iob, timeout);
- if (c == -1) {
- if (ne) {
- km->invalid += ne + km->tested;
- km->valid = 0;
- km->tested = 0;
- km->stage = MouseBroken;
- }
- break;
- }
- event[ne++] = c;
- i = (*km->prot->Valid) (mi, event, ne);
- if (i != 0) {
- #ifdef DEBUG
- ErrorF("Mouse protocol %s broken %d of %d bytes bad\n",
- km->prot->name, i > 0 ? i : ne, ne);
- #endif
- if (i > 0 && i < ne) {
- ne -= i;
- memmove(event, event + i, ne);
- } else {
- i = ne;
- ne = 0;
- }
- km->invalid += i + km->tested;
- km->valid = 0;
- km->tested = 0;
- if (km->stage == MouseWorking)
- km->i_prot--;
- km->stage = MouseBroken;
- if (km->invalid > MAX_SKIP) {
- MouseNextProtocol(km);
- ne = 0;
- }
- timeout = 0;
- } else {
- if ((*km->prot->Complete) (mi, event, ne)) {
- if ((*km->prot->Parse) (mi, event, ne)) {
- switch (km->stage) {
- case MouseBroken:
- #ifdef DEBUG
- ErrorF
- ("Mouse protocol %s seems OK\n",
- km->prot->name);
- #endif
- /* do not zero invalid to accumulate invalid bytes */
- km->valid = 0;
- km->tested = 0;
- km->stage = MouseTesting;
- /* fall through ... */
- case MouseTesting:
- km->valid++;
- km->tested += ne;
- if (km->valid > MAX_VALID) {
- #ifdef DEBUG
- ErrorF
- ("Mouse protocol %s working\n",
- km->prot->name);
- #endif
- km->stage =
- MouseWorking;
- km->invalid = 0;
- km->tested = 0;
- km->valid = 0;
- if (km->prot->Init
- && !(*km->prot->
- Init) (mi))
- km->stage =
- MouseBroken;
- }
- break;
- case MouseWorking:
- break;
- }
- } else {
- km->invalid += ne + km->tested;
- km->valid = 0;
- km->tested = 0;
- km->stage = MouseBroken;
- }
- ne = 0;
- timeout = 0;
- } else
- timeout = MOUSE_TIMEOUT;
- }
- }
- }
- static int MouseInputType;
- const char * const kdefaultMouse[] = {
- "/dev/mouse",
- "/dev/psaux",
- "/dev/input/mice",
- "/dev/adbmouse",
- "/dev/ttyS0",
- "/dev/ttyS1",
- };
- #define NUM_DEFAULT_MOUSE (sizeof (kdefaultMouse) / sizeof (kdefaultMouse[0]))
- static Bool MouseInit(void)
- {
- int i;
- int fd = -1;
- Kmouse *km;
- KdMouseInfo *mi, *next;
- int n = 0;
- if (!MouseInputType)
- MouseInputType = KdAllocInputType();
- for (mi = kdMouseInfo; mi; mi = next) {
- next = mi->next;
- if (mi->inputType)
- continue;
- if (!mi->name) {
- for (i = 0; i < NUM_DEFAULT_MOUSE; i++) {
- fd = open(kdefaultMouse[i], 2);
- if (fd >= 0) {
- mi->name = strdup(kdefaultMouse[i]);
- break;
- }
- }
- } else
- fd = open(mi->name, 2);
- if (fd >= 0) {
- km = malloc(sizeof(Kmouse));
- if (km) {
- km->iob.fd = fd;
- km->iob.avail = km->iob.used = 0;
- km->prot = 0;
- km->i_prot = 0;
- km->tty = isatty(fd);
- mi->driver = km;
- mi->inputType = MouseInputType;
- MouseFirstProtocol(km, mi->prot);
- if (KdRegisterFd
- (MouseInputType, fd, MouseRead, (void *)mi))
- n++;
- } else
- close(fd);
- }
- }
- return TRUE;
- }
- static void MouseFini(void)
- {
- KdMouseInfo *mi;
- KdUnregisterFds(MouseInputType, TRUE);
- for (mi = kdMouseInfo; mi; mi = mi->next) {
- if (mi->inputType == MouseInputType) {
- free(mi->driver);
- mi->driver = 0;
- mi->inputType = 0;
- }
- }
- }
- const KdMouseFuncs LinuxMouseFuncs = {
- MouseInit,
- MouseFini,
- };
|