Home | History | Annotate | Line # | Download | only in linux
      1 /*
      2  * Copyright  2001 Keith Packard
      3  *
      4  * Permission to use, copy, modify, distribute, and sell this software and its
      5  * documentation for any purpose is hereby granted without fee, provided that
      6  * the above copyright notice appear in all copies and that both that
      7  * copyright notice and this permission notice appear in supporting
      8  * documentation, and that the name of Keith Packard not be used in
      9  * advertising or publicity pertaining to distribution of the software without
     10  * specific, written prior permission.  Keith Packard makes no
     11  * representations about the suitability of this software for any purpose.  It
     12  * is provided "as is" without express or implied warranty.
     13  *
     14  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     16  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     20  * PERFORMANCE OF THIS SOFTWARE.
     21  */
     22 
     23 #ifdef HAVE_CONFIG_H
     24 #include <kdrive-config.h>
     25 #endif
     26 #include <errno.h>
     27 #include <termios.h>
     28 #include <X11/X.h>
     29 #include <X11/Xproto.h>
     30 #include <X11/Xpoll.h>
     31 #include "inputstr.h"
     32 #include "scrnintstr.h"
     33 #include "kdrive.h"
     34 
     35 #undef DEBUG
     36 #undef DEBUG_BYTES
     37 #define KBUFIO_SIZE 256
     38 #define MOUSE_TIMEOUT	100
     39 
     40 typedef struct _kbufio {
     41     int		    fd;
     42     unsigned char   buf[KBUFIO_SIZE];
     43     int		    avail;
     44     int		    used;
     45 } Kbufio;
     46 
     47 static Bool
     48 MouseWaitForReadable (int fd, int timeout)
     49 {
     50     fd_set	    set;
     51     struct timeval  tv, *tp;
     52     int		    n;
     53     CARD32	    done;
     54 
     55     done = GetTimeInMillis () + timeout;
     56     for (;;)
     57     {
     58 	FD_ZERO (&set);
     59 	FD_SET (fd, &set);
     60 	if (timeout == -1)
     61 	    tp = 0;
     62 	else
     63 	{
     64 	    tv.tv_sec = timeout / 1000;
     65 	    tv.tv_usec = (timeout % 1000) * 1000;
     66 	    tp = &tv;
     67 	}
     68 	n = select (fd + 1, &set, 0, 0, tp);
     69 	if (n > 0)
     70 	    return TRUE;
     71 	if (n < 0 && (errno == EAGAIN || errno == EINTR))
     72 	{
     73 	    timeout = (int) (done - GetTimeInMillis ());
     74 	    if (timeout > 0)
     75 		continue;
     76 	}
     77 	break;
     78     }
     79     return FALSE;
     80 }
     81 
     82 static int
     83 MouseReadByte (Kbufio *b, int timeout)
     84 {
     85     int	n;
     86     if (b->avail <= b->used)
     87     {
     88 	if (timeout && !MouseWaitForReadable (b->fd, timeout))
     89 	{
     90 #ifdef DEBUG_BYTES
     91 	    ErrorF ("\tTimeout %d\n", timeout);
     92 #endif
     93 	    return -1;
     94 	}
     95 	n = read (b->fd, b->buf, KBUFIO_SIZE);
     96 	if (n <= 0)
     97 	    return -1;
     98         b->avail = n;
     99         b->used = 0;
    100     }
    101 #ifdef DEBUG_BYTES
    102     ErrorF ("\tget %02x\n", b->buf[b->used]);
    103 #endif
    104     return b->buf[b->used++];
    105 }
    106 
    107 #if NOTUSED
    108 static int
    109 MouseFlush (Kbufio *b, char *buf, int size)
    110 {
    111     CARD32  now = GetTimeInMillis ();
    112     CARD32  done = now + 100;
    113     int	    c;
    114     int	    n = 0;
    115 
    116     while ((c = MouseReadByte (b, done - now)) != -1)
    117     {
    118 	if (buf)
    119 	{
    120 	    if (n == size)
    121 	    {
    122 		memmove (buf, buf + 1, size - 1);
    123 		n--;
    124 	    }
    125 	    buf[n++] = c;
    126 	}
    127 	now = GetTimeInMillis ();
    128 	if ((INT32) (now - done) >= 0)
    129 	    break;
    130     }
    131     return n;
    132 }
    133 
    134 static int
    135 MousePeekByte (Kbufio *b, int timeout)
    136 {
    137     int	    c;
    138 
    139     c = MouseReadByte (b, timeout);
    140     if (c != -1)
    141 	--b->used;
    142     return c;
    143 }
    144 #endif /* NOTUSED */
    145 
    146 static Bool
    147 MouseWaitForWritable (int fd, int timeout)
    148 {
    149     fd_set	    set;
    150     struct timeval  tv, *tp;
    151     int		    n;
    152 
    153     FD_ZERO (&set);
    154     FD_SET (fd, &set);
    155     if (timeout == -1)
    156 	tp = 0;
    157     else
    158     {
    159 	tv.tv_sec = timeout / 1000;
    160 	tv.tv_usec = (timeout % 1000) * 1000;
    161 	tp = &tv;
    162     }
    163     n = select (fd + 1, 0, &set, 0, tp);
    164     if (n > 0)
    165 	return TRUE;
    166     return FALSE;
    167 }
    168 
    169 static Bool
    170 MouseWriteByte (int fd, unsigned char c, int timeout)
    171 {
    172     int	ret;
    173 
    174 #ifdef DEBUG_BYTES
    175     ErrorF ("\tput %02x\n", c);
    176 #endif
    177     for (;;)
    178     {
    179 	ret = write (fd, &c, 1);
    180 	if (ret == 1)
    181 	    return TRUE;
    182 	if (ret == 0)
    183 	    return FALSE;
    184 	if (errno != EWOULDBLOCK)
    185 	    return FALSE;
    186 	if (!MouseWaitForWritable (fd, timeout))
    187 	    return FALSE;
    188     }
    189 }
    190 
    191 static Bool
    192 MouseWriteBytes (int fd, unsigned char *c, int n, int timeout)
    193 {
    194     while (n--)
    195 	if (!MouseWriteByte (fd, *c++, timeout))
    196 	    return FALSE;
    197     return TRUE;
    198 }
    199 
    200 #define MAX_MOUSE   10	    /* maximum length of mouse protocol */
    201 #define MAX_SKIP    16	    /* number of error bytes before switching */
    202 #define MAX_VALID   4	    /* number of valid packets before accepting */
    203 
    204 typedef struct _kmouseProt {
    205     char	    *name;
    206     Bool	    (*Complete) (KdPointerInfo *pi, unsigned char *ev, int ne);
    207     int		    (*Valid) (KdPointerInfo *pi, unsigned char *ev, int ne);
    208     Bool	    (*Parse) (KdPointerInfo *pi, unsigned char *ev, int ne);
    209     Bool	    (*Init) (KdPointerInfo *pi);
    210     unsigned char   headerMask, headerValid;
    211     unsigned char   dataMask, dataValid;
    212     Bool	    tty;
    213     unsigned int    c_iflag;
    214     unsigned int    c_oflag;
    215     unsigned int    c_lflag;
    216     unsigned int    c_cflag;
    217     unsigned int    speed;
    218     unsigned char   *init;
    219     unsigned long   state;
    220 } KmouseProt;
    221 
    222 typedef enum _kmouseStage {
    223     MouseBroken, MouseTesting, MouseWorking
    224 } KmouseStage;
    225 
    226 typedef struct _kmouse {
    227     Kbufio		iob;
    228     const KmouseProt	*prot;
    229     int			i_prot;
    230     KmouseStage		stage;	/* protocol verification stage */
    231     Bool		tty;	/* mouse device is a tty */
    232     int			valid;	/* sequential valid events */
    233     int			tested;	/* bytes scanned during Testing phase */
    234     int			invalid;/* total invalid bytes for this protocol */
    235     unsigned long	state;	/* private per protocol, init to prot->state */
    236 } Kmouse;
    237 
    238 static int mouseValid (KdPointerInfo *pi, unsigned char *ev, int ne)
    239 {
    240     Kmouse		*km = pi->driverPrivate;
    241     const KmouseProt	*prot = km->prot;
    242     int	    i;
    243 
    244     for (i = 0; i < ne; i++)
    245 	if ((ev[i] & prot->headerMask) == prot->headerValid)
    246 	    break;
    247     if (i != 0)
    248 	return i;
    249     for (i = 1; i < ne; i++)
    250 	if ((ev[i] & prot->dataMask) != prot->dataValid)
    251 	    return -1;
    252     return 0;
    253 }
    254 
    255 static Bool threeComplete (KdPointerInfo *pi, unsigned char *ev, int ne)
    256 {
    257     return ne == 3;
    258 }
    259 
    260 static Bool fourComplete (KdPointerInfo *pi, unsigned char *ev, int ne)
    261 {
    262     return ne == 4;
    263 }
    264 
    265 static Bool fiveComplete (KdPointerInfo *pi, unsigned char *ev, int ne)
    266 {
    267     return ne == 5;
    268 }
    269 
    270 static Bool MouseReasonable (KdPointerInfo *pi, unsigned long flags, int dx, int dy)
    271 {
    272     Kmouse		*km = pi->driverPrivate;
    273 
    274     if (km->stage == MouseWorking)
    275 	return TRUE;
    276     if (dx < -50 || dx > 50)
    277     {
    278 #ifdef DEBUG
    279 	ErrorF ("Large X %d\n", dx);
    280 #endif
    281 	return FALSE;
    282     }
    283     if (dy < -50 || dy > 50)
    284     {
    285 #ifdef DEBUG
    286 	ErrorF ("Large Y %d\n", dy);
    287 #endif
    288 	return FALSE;
    289     }
    290     return TRUE;
    291 }
    292 
    293 /*
    294  * Standard PS/2 mouse protocol
    295  */
    296 static Bool ps2Parse (KdPointerInfo *pi, unsigned char *ev, int ne)
    297 {
    298     Kmouse	    *km = pi->driverPrivate;
    299     int		    dx, dy, dz;
    300     unsigned long   flags;
    301     unsigned long   flagsrelease = 0;
    302 
    303     flags = KD_MOUSE_DELTA;
    304     if (ev[0] & 4)
    305 	flags |= KD_BUTTON_2;
    306     if (ev[0] & 2)
    307 	flags |= KD_BUTTON_3;
    308     if (ev[0] & 1)
    309 	flags |= KD_BUTTON_1;
    310 
    311     if (ne > 3)
    312     {
    313 	dz = (int) (signed char) ev[3];
    314 	if (dz < 0)
    315 	{
    316 	    flags |= KD_BUTTON_4;
    317 	    flagsrelease = KD_BUTTON_4;
    318 	}
    319 	else if (dz > 0)
    320 	{
    321 	    flags |= KD_BUTTON_5;
    322 	    flagsrelease = KD_BUTTON_5;
    323 	}
    324     }
    325 
    326     dx = ev[1];
    327     if (ev[0] & 0x10)
    328 	dx -= 256;
    329     dy = ev[2];
    330     if (ev[0] & 0x20)
    331 	dy -= 256;
    332     dy = -dy;
    333     if (!MouseReasonable (pi, flags, dx, dy))
    334 	return FALSE;
    335     if (km->stage == MouseWorking)
    336     {
    337 	KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
    338 	if (flagsrelease)
    339 	{
    340 	    flags &= ~flagsrelease;
    341 	    KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
    342 	}
    343     }
    344     return TRUE;
    345 }
    346 
    347 static Bool ps2Init (KdPointerInfo *pi);
    348 
    349 static const KmouseProt ps2Prot = {
    350     "ps/2",
    351     threeComplete, mouseValid, ps2Parse, ps2Init,
    352     0x08, 0x08, 0x00, 0x00,
    353     FALSE
    354 };
    355 
    356 static const KmouseProt imps2Prot = {
    357     "imps/2",
    358     fourComplete, mouseValid, ps2Parse, ps2Init,
    359     0x08, 0x08, 0x00, 0x00,
    360     FALSE
    361 };
    362 
    363 static const KmouseProt exps2Prot = {
    364     "exps/2",
    365     fourComplete, mouseValid, ps2Parse, ps2Init,
    366     0x08, 0x08, 0x00, 0x00,
    367     FALSE
    368 };
    369 
    370 /*
    371  * Once the mouse is known to speak ps/2 protocol, go and find out
    372  * what advanced capabilities it has and turn them on
    373  */
    374 
    375 /* these extracted from FreeBSD 4.3 sys/dev/kbd/atkbdcreg.h */
    376 
    377 /* aux device commands (sent to KBD_DATA_PORT) */
    378 #define PSMC_SET_SCALING11      0x00e6
    379 #define PSMC_SET_SCALING21      0x00e7
    380 #define PSMC_SET_RESOLUTION     0x00e8
    381 #define PSMC_SEND_DEV_STATUS    0x00e9
    382 #define PSMC_SET_STREAM_MODE    0x00ea
    383 #define PSMC_SEND_DEV_DATA      0x00eb
    384 #define PSMC_SET_REMOTE_MODE    0x00f0
    385 #define PSMC_SEND_DEV_ID        0x00f2
    386 #define PSMC_SET_SAMPLING_RATE  0x00f3
    387 #define PSMC_ENABLE_DEV         0x00f4
    388 #define PSMC_DISABLE_DEV        0x00f5
    389 #define PSMC_SET_DEFAULTS       0x00f6
    390 #define PSMC_RESET_DEV          0x00ff
    391 
    392 /* PSMC_SET_RESOLUTION argument */
    393 #define PSMD_RES_LOW            0       /* typically 25ppi */
    394 #define PSMD_RES_MEDIUM_LOW     1       /* typically 50ppi */
    395 #define PSMD_RES_MEDIUM_HIGH    2       /* typically 100ppi (default) */
    396 #define PSMD_RES_HIGH           3       /* typically 200ppi */
    397 #define PSMD_MAX_RESOLUTION     PSMD_RES_HIGH
    398 
    399 /* PSMC_SET_SAMPLING_RATE */
    400 #define PSMD_MAX_RATE           255     /* FIXME: not sure if it's possible */
    401 
    402 /* aux device ID */
    403 #define PSM_MOUSE_ID            0
    404 #define PSM_BALLPOINT_ID        2
    405 #define PSM_INTELLI_ID          3
    406 #define PSM_EXPLORER_ID         4
    407 #define PSM_4DMOUSE_ID          6
    408 #define PSM_4DPLUS_ID           8
    409 
    410 static unsigned char	ps2_init[] = {
    411     PSMC_ENABLE_DEV,
    412     0,
    413 };
    414 
    415 #define NINIT_PS2   1
    416 
    417 static unsigned char    wheel_3button_init[] = {
    418     PSMC_SET_SAMPLING_RATE, 200,
    419     PSMC_SET_SAMPLING_RATE, 100,
    420     PSMC_SET_SAMPLING_RATE,  80,
    421     PSMC_SEND_DEV_ID,
    422     0,
    423 };
    424 
    425 #define NINIT_IMPS2 4
    426 
    427 static unsigned char    wheel_5button_init[] = {
    428     PSMC_SET_SAMPLING_RATE, 200,
    429     PSMC_SET_SAMPLING_RATE, 100,
    430     PSMC_SET_SAMPLING_RATE,  80,
    431     PSMC_SET_SAMPLING_RATE, 200,
    432     PSMC_SET_SAMPLING_RATE, 200,
    433     PSMC_SET_SAMPLING_RATE,  80,
    434     PSMC_SEND_DEV_ID,
    435     0
    436 };
    437 
    438 #define NINIT_EXPS2 7
    439 
    440 static unsigned char	intelli_init[] = {
    441     PSMC_SET_SAMPLING_RATE, 200,
    442     PSMC_SET_SAMPLING_RATE, 100,
    443     PSMC_SET_SAMPLING_RATE,  80,
    444     0
    445 };
    446 
    447 #define NINIT_INTELLI	3
    448 
    449 static int
    450 ps2SkipInit (KdPointerInfo *pi, int ninit, Bool ret_next)
    451 {
    452     Kmouse  *km = pi->driverPrivate;
    453     int	    c = -1;
    454     int	    skipping;
    455     Bool    waiting;
    456 
    457     skipping = 0;
    458     waiting = FALSE;
    459     while (ninit || ret_next)
    460     {
    461 	c = MouseReadByte (&km->iob, MOUSE_TIMEOUT);
    462 	if (c == -1)
    463 	    break;
    464 	/* look for ACK */
    465 	if (c == 0xfa)
    466 	{
    467 	    ninit--;
    468 	    if (ret_next)
    469 		waiting = TRUE;
    470 	}
    471 	/* look for packet start -- not the response */
    472 	else if ((c & 0x08) == 0x08)
    473 	    waiting = FALSE;
    474 	else if (waiting)
    475 	    break;
    476     }
    477     return c;
    478 }
    479 
    480 static Bool
    481 ps2Init (KdPointerInfo *pi)
    482 {
    483     Kmouse	    *km = pi->driverPrivate;
    484     int		    skipping;
    485     Bool	    waiting;
    486     int		    id;
    487     unsigned char   *init;
    488     int		    ninit;
    489 
    490     /* Send Intellimouse initialization sequence */
    491     MouseWriteBytes (km->iob.fd, intelli_init, strlen ((char *) intelli_init), 100);
    492     /*
    493      * Send ID command
    494      */
    495     if (!MouseWriteByte (km->iob.fd, PSMC_SEND_DEV_ID, 100))
    496 	return FALSE;
    497     skipping = 0;
    498     waiting = FALSE;
    499     id = ps2SkipInit (pi, 0, TRUE);
    500     switch (id) {
    501     case 3:
    502 	init = wheel_3button_init;
    503 	ninit = NINIT_IMPS2;
    504 	km->prot = &imps2Prot;
    505 	break;
    506     case 4:
    507 	init = wheel_5button_init;
    508 	ninit = NINIT_EXPS2;
    509 	km->prot = &exps2Prot;
    510 	break;
    511     default:
    512 	init = ps2_init;
    513 	ninit = NINIT_PS2;
    514 	km->prot = &ps2Prot;
    515 	break;
    516     }
    517     if (init)
    518 	MouseWriteBytes (km->iob.fd, init, strlen ((char *) init), 100);
    519     /*
    520      * Flush out the available data to eliminate responses to the
    521      * initialization string.  Make sure any partial event is
    522      * skipped
    523      */
    524     (void) ps2SkipInit (pi, ninit, FALSE);
    525     return TRUE;
    526 }
    527 
    528 static Bool busParse (KdPointerInfo *pi, unsigned char *ev, int ne)
    529 {
    530     Kmouse	    *km = pi->driverPrivate;
    531     int		    dx, dy;
    532     unsigned long   flags;
    533 
    534     flags = KD_MOUSE_DELTA;
    535     dx = (signed char) ev[1];
    536     dy = -(signed char) ev[2];
    537     if ((ev[0] & 4) == 0)
    538 	flags |= KD_BUTTON_1;
    539     if ((ev[0] & 2) == 0)
    540 	flags |= KD_BUTTON_2;
    541     if ((ev[0] & 1) == 0)
    542 	flags |= KD_BUTTON_3;
    543     if (!MouseReasonable (pi, flags, dx, dy))
    544 	return FALSE;
    545     if (km->stage == MouseWorking)
    546 	KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
    547     return TRUE;
    548 }
    549 
    550 static const KmouseProt busProt = {
    551     "bus",
    552     threeComplete, mouseValid, busParse, 0,
    553     0xf8, 0x00, 0x00, 0x00,
    554     FALSE
    555 };
    556 
    557 /*
    558  * Standard MS serial protocol, three bytes
    559  */
    560 
    561 static Bool msParse (KdPointerInfo *pi, unsigned char *ev, int ne)
    562 {
    563     Kmouse	    *km = pi->driverPrivate;
    564     int		    dx, dy;
    565     unsigned long   flags;
    566 
    567     flags = KD_MOUSE_DELTA;
    568 
    569     if (ev[0] & 0x20)
    570 	flags |= KD_BUTTON_1;
    571     if (ev[0] & 0x10)
    572 	flags |= KD_BUTTON_3;
    573 
    574     dx = (signed char)(((ev[0] & 0x03) << 6) | (ev[1] & 0x3F));
    575     dy = (signed char)(((ev[0] & 0x0C) << 4) | (ev[2] & 0x3F));
    576     if (!MouseReasonable (pi, flags, dx, dy))
    577 	return FALSE;
    578     if (km->stage == MouseWorking)
    579 	KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
    580     return TRUE;
    581 }
    582 
    583 static const KmouseProt msProt = {
    584     "ms",
    585     threeComplete, mouseValid, msParse, 0,
    586     0xc0, 0x40, 0xc0, 0x00,
    587     TRUE,
    588     IGNPAR,
    589     0,
    590     0,
    591     CS7 | CSTOPB | CREAD | CLOCAL,
    592     B1200,
    593 };
    594 
    595 /*
    596  * Logitech mice send 3 or 4 bytes, the only way to tell is to look at the
    597  * first byte of a synchronized protocol stream and see if it's got
    598  * any bits turned on that can't occur in that fourth byte
    599  */
    600 static Bool logiComplete (KdPointerInfo *pi, unsigned char *ev, int ne)
    601 {
    602     Kmouse		*km = pi->driverPrivate;
    603 
    604     if ((ev[0] & 0x40) == 0x40)
    605 	return ne == 3;
    606     if (km->stage != MouseBroken && (ev[0] & ~0x23) == 0)
    607 	return ne == 1;
    608     return FALSE;
    609 }
    610 
    611 static int logiValid (KdPointerInfo *pi, unsigned char *ev, int ne)
    612 {
    613     Kmouse		*km = pi->driverPrivate;
    614     const KmouseProt	*prot = km->prot;
    615     int	    i;
    616 
    617     for (i = 0; i < ne; i++)
    618     {
    619 	if ((ev[i] & 0x40) == 0x40)
    620 	    break;
    621 	if (km->stage != MouseBroken && (ev[i] & ~0x23) == 0)
    622 	    break;
    623     }
    624     if (i != 0)
    625 	return i;
    626     for (i = 1; i < ne; i++)
    627 	if ((ev[i] & prot->dataMask) != prot->dataValid)
    628 	    return -1;
    629     return 0;
    630 }
    631 
    632 static Bool logiParse (KdPointerInfo *pi, unsigned char *ev, int ne)
    633 {
    634     Kmouse	    *km = pi->driverPrivate;
    635     int		    dx, dy;
    636     unsigned long   flags;
    637 
    638     flags = KD_MOUSE_DELTA;
    639 
    640     if (ne == 3)
    641     {
    642 	if (ev[0] & 0x20)
    643 	    flags |= KD_BUTTON_1;
    644 	if (ev[0] & 0x10)
    645 	    flags |= KD_BUTTON_3;
    646 
    647 	dx = (signed char)(((ev[0] & 0x03) << 6) | (ev[1] & 0x3F));
    648 	dy = (signed char)(((ev[0] & 0x0C) << 4) | (ev[2] & 0x3F));
    649 	flags |= km->state & KD_BUTTON_2;
    650     }
    651     else
    652     {
    653 	if (ev[0] & 0x20)
    654 	    flags |= KD_BUTTON_2;
    655 	dx = 0;
    656 	dy = 0;
    657 	flags |= km->state & (KD_BUTTON_1|KD_BUTTON_3);
    658     }
    659 
    660     if (!MouseReasonable (pi, flags, dx, dy))
    661 	return FALSE;
    662     if (km->stage == MouseWorking)
    663 	KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
    664     return TRUE;
    665 }
    666 
    667 static const KmouseProt logiProt = {
    668     "logitech",
    669     logiComplete, logiValid, logiParse, 0,
    670     0xc0, 0x40, 0xc0, 0x00,
    671     TRUE,
    672     IGNPAR,
    673     0,
    674     0,
    675     CS7 | CSTOPB | CREAD | CLOCAL,
    676     B1200,
    677 };
    678 
    679 /*
    680  * Mouse systems protocol, 5 bytes
    681  */
    682 static Bool mscParse (KdPointerInfo *pi, unsigned char *ev, int ne)
    683 {
    684     Kmouse	    *km = pi->driverPrivate;
    685     int		    dx, dy;
    686     unsigned long   flags;
    687 
    688     flags = KD_MOUSE_DELTA;
    689 
    690     if (!(ev[0] & 0x4))
    691 	flags |= KD_BUTTON_1;
    692     if (!(ev[0] & 0x2))
    693 	flags |= KD_BUTTON_2;
    694     if (!(ev[0] & 0x1))
    695 	flags |= KD_BUTTON_3;
    696     dx =    (signed char)(ev[1]) + (signed char)(ev[3]);
    697     dy = - ((signed char)(ev[2]) + (signed char)(ev[4]));
    698 
    699     if (!MouseReasonable (pi, flags, dx, dy))
    700 	return FALSE;
    701     if (km->stage == MouseWorking)
    702 	KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
    703     return TRUE;
    704 }
    705 
    706 static const KmouseProt mscProt = {
    707     "msc",
    708     fiveComplete, mouseValid, mscParse, 0,
    709     0xf8, 0x80, 0x00, 0x00,
    710     TRUE,
    711     IGNPAR,
    712     0,
    713     0,
    714     CS8 | CSTOPB | CREAD | CLOCAL,
    715     B1200,
    716 };
    717 
    718 /*
    719  * Use logitech before ms -- they're the same except that
    720  * logitech sometimes has a fourth byte
    721  */
    722 static const KmouseProt *kmouseProts[] = {
    723     &ps2Prot, &imps2Prot, &exps2Prot, &busProt, &logiProt, &msProt, &mscProt,
    724 };
    725 
    726 #define NUM_PROT    (sizeof (kmouseProts) / sizeof (kmouseProts[0]))
    727 
    728 static void
    729 MouseInitProtocol (Kmouse *km)
    730 {
    731     int		    ret;
    732     struct termios  t;
    733 
    734     if (km->prot->tty)
    735     {
    736 	ret = tcgetattr (km->iob.fd, &t);
    737 
    738 	if (ret >= 0)
    739 	{
    740 	    t.c_iflag = km->prot->c_iflag;
    741 	    t.c_oflag = km->prot->c_oflag;
    742 	    t.c_lflag = km->prot->c_lflag;
    743 	    t.c_cflag = km->prot->c_cflag;
    744 	    cfsetispeed (&t, km->prot->speed);
    745 	    cfsetospeed (&t, km->prot->speed);
    746 	    ret = tcsetattr (km->iob.fd, TCSANOW, &t);
    747 	}
    748     }
    749     km->stage = MouseBroken;
    750     km->valid = 0;
    751     km->tested = 0;
    752     km->invalid = 0;
    753     km->state = km->prot->state;
    754 }
    755 
    756 static void
    757 MouseFirstProtocol (Kmouse *km, char *prot)
    758 {
    759     if (prot)
    760     {
    761 	for (km->i_prot = 0; km->i_prot < NUM_PROT; km->i_prot++)
    762 	    if (!strcmp (prot, kmouseProts[km->i_prot]->name))
    763 		break;
    764 	if (km->i_prot == NUM_PROT)
    765 	{
    766 	    int	i;
    767 	    ErrorF ("Unknown mouse protocol \"%s\". Pick one of:", prot);
    768 	    for (i = 0; i < NUM_PROT; i++)
    769 		ErrorF (" %s", kmouseProts[i]->name);
    770 	    ErrorF ("\n");
    771 	}
    772 	else
    773 	{
    774 	    km->prot = kmouseProts[km->i_prot];
    775 	    if (km->tty && !km->prot->tty)
    776 		ErrorF ("Mouse device is serial port, protocol %s is not serial protocol\n",
    777 			prot);
    778 	    else if (!km->tty && km->prot->tty)
    779 		ErrorF ("Mouse device is not serial port, protocol %s is serial protocol\n",
    780 			prot);
    781 	}
    782     }
    783     if (!km->prot)
    784     {
    785 	for (km->i_prot = 0; kmouseProts[km->i_prot]->tty != km->tty; km->i_prot++)
    786 	    ;
    787 	km->prot = kmouseProts[km->i_prot];
    788     }
    789     MouseInitProtocol (km);
    790 }
    791 
    792 static void
    793 MouseNextProtocol (Kmouse *km)
    794 {
    795     do
    796     {
    797 	if (!km->prot)
    798 	    km->i_prot = 0;
    799 	else
    800 	    if (++km->i_prot == NUM_PROT) km->i_prot = 0;
    801 	km->prot = kmouseProts[km->i_prot];
    802     } while (km->prot->tty != km->tty);
    803     MouseInitProtocol (km);
    804     ErrorF ("Switching to mouse protocol \"%s\"\n", km->prot->name);
    805 }
    806 
    807 static void
    808 MouseRead (int mousePort, void *closure)
    809 {
    810     KdPointerInfo   *pi = closure;
    811     Kmouse	    *km = pi->driverPrivate;
    812     unsigned char   event[MAX_MOUSE];
    813     int		    ne;
    814     int		    c;
    815     int		    i;
    816     int		    timeout;
    817 
    818     timeout = 0;
    819     ne = 0;
    820     for(;;)
    821     {
    822 	c = MouseReadByte (&km->iob, timeout);
    823 	if (c == -1)
    824 	{
    825 	    if (ne)
    826 	    {
    827 		km->invalid += ne + km->tested;
    828 		km->valid = 0;
    829 		km->tested = 0;
    830 		km->stage = MouseBroken;
    831 	    }
    832 	    break;
    833 	}
    834 	event[ne++] = c;
    835 	i = (*km->prot->Valid) (pi, event, ne);
    836 	if (i != 0)
    837 	{
    838 #ifdef DEBUG
    839 	    ErrorF ("Mouse protocol %s broken %d of %d bytes bad\n",
    840 		    km->prot->name, i > 0 ? i : ne, ne);
    841 #endif
    842 	    if (i > 0 && i < ne)
    843 	    {
    844 		ne -= i;
    845 		memmove (event, event + i, ne);
    846 	    }
    847 	    else
    848 	    {
    849 		i = ne;
    850 		ne = 0;
    851 	    }
    852 	    km->invalid += i + km->tested;
    853 	    km->valid = 0;
    854 	    km->tested = 0;
    855 	    if (km->stage == MouseWorking)
    856 		km->i_prot--;
    857 	    km->stage = MouseBroken;
    858 	    if (km->invalid > MAX_SKIP)
    859 	    {
    860 		MouseNextProtocol (km);
    861 		ne = 0;
    862 	    }
    863 	    timeout = 0;
    864 	}
    865 	else
    866 	{
    867 	    if ((*km->prot->Complete) (pi, event, ne))
    868 	    {
    869 		if ((*km->prot->Parse) (pi, event, ne))
    870 		{
    871 		    switch (km->stage)
    872 		    {
    873 		    case MouseBroken:
    874 #ifdef DEBUG
    875 			ErrorF ("Mouse protocol %s seems OK\n",
    876 				km->prot->name);
    877 #endif
    878 			/* do not zero invalid to accumulate invalid bytes */
    879 			km->valid = 0;
    880 			km->tested = 0;
    881 			km->stage = MouseTesting;
    882 			/* fall through ... */
    883 		    case MouseTesting:
    884 			km->valid++;
    885 			km->tested += ne;
    886 			if (km->valid > MAX_VALID)
    887 			{
    888 #ifdef DEBUG
    889 			    ErrorF ("Mouse protocol %s working\n",
    890 				    km->prot->name);
    891 #endif
    892 			    km->stage = MouseWorking;
    893 			    km->invalid = 0;
    894 			    km->tested = 0;
    895 			    km->valid = 0;
    896 			    if (km->prot->Init && !(*km->prot->Init) (pi))
    897 				km->stage = MouseBroken;
    898 			}
    899 			break;
    900 		    case MouseWorking:
    901 			break;
    902 		    }
    903 		}
    904 		else
    905 		{
    906 		    km->invalid += ne + km->tested;
    907 		    km->valid = 0;
    908 		    km->tested = 0;
    909 		    km->stage = MouseBroken;
    910 		}
    911 		ne = 0;
    912 		timeout = 0;
    913 	    }
    914 	    else
    915 		timeout = MOUSE_TIMEOUT;
    916 	}
    917     }
    918 }
    919 
    920 int MouseInputType;
    921 
    922 char *kdefaultMouse[] =  {
    923     "/dev/input/mice",
    924     "/dev/mouse",
    925     "/dev/psaux",
    926     "/dev/adbmouse",
    927     "/dev/ttyS0",
    928     "/dev/ttyS1",
    929 };
    930 
    931 #define NUM_DEFAULT_MOUSE    (sizeof (kdefaultMouse) / sizeof (kdefaultMouse[0]))
    932 
    933 static Status
    934 MouseInit (KdPointerInfo *pi)
    935 {
    936     int		i;
    937     int		fd;
    938     Kmouse	*km;
    939 
    940     if (!pi)
    941         return BadImplementation;
    942 
    943     if (!pi->path || strcmp(pi->path, "auto") == 0) {
    944         for (i = 0; i < NUM_DEFAULT_MOUSE; i++) {
    945             fd = open (kdefaultMouse[i], 2);
    946             if (fd >= 0) {
    947                 pi->path = strdup (kdefaultMouse[i]);
    948                 break;
    949             }
    950         }
    951     }
    952     else {
    953         fd = open (pi->path, 2);
    954     }
    955 
    956     if (fd < 0)
    957         return BadMatch;
    958 
    959     close(fd);
    960 
    961     km = (Kmouse *) malloc(sizeof (Kmouse));
    962     if (km) {
    963         km->iob.avail = km->iob.used = 0;
    964         MouseFirstProtocol(km, pi->protocol ? pi->protocol : "exps/2");
    965         /* MouseFirstProtocol sets state to MouseBroken for later protocol
    966          * checks. Skip these checks if a protocol was supplied */
    967         if (pi->protocol)
    968                 km->state = MouseWorking;
    969         km->i_prot = 0;
    970         km->tty = isatty (fd);
    971         km->iob.fd = -1;
    972         pi->driverPrivate = km;
    973     }
    974     else {
    975         close (fd);
    976         return BadAlloc;
    977     }
    978 
    979     return Success;
    980 }
    981 
    982 static Status
    983 MouseEnable (KdPointerInfo *pi)
    984 {
    985     Kmouse *km;
    986 
    987     if (!pi || !pi->driverPrivate || !pi->path)
    988         return BadImplementation;
    989 
    990     km = pi->driverPrivate;
    991 
    992     km->iob.fd = open(pi->path, 2);
    993     if (km->iob.fd < 0)
    994         return BadMatch;
    995 
    996     if (!KdRegisterFd (km->iob.fd, MouseRead, pi))
    997     {
    998         close(km->iob.fd);
    999         return BadAlloc;
   1000     }
   1001 
   1002     return Success;
   1003 }
   1004 
   1005 static void
   1006 MouseDisable (KdPointerInfo *pi)
   1007 {
   1008     Kmouse *km;
   1009     if (!pi || !pi->driverPrivate)
   1010         return;
   1011 
   1012     km = pi->driverPrivate;
   1013     KdUnregisterFd (pi, km->iob.fd, TRUE);
   1014 }
   1015 
   1016 static void
   1017 MouseFini (KdPointerInfo *pi)
   1018 {
   1019     free(pi->driverPrivate);
   1020     pi->driverPrivate = NULL;
   1021 }
   1022 
   1023 KdPointerDriver LinuxMouseDriver = {
   1024     "mouse",
   1025     MouseInit,
   1026     MouseEnable,
   1027     MouseDisable,
   1028     MouseFini,
   1029     NULL,
   1030 };
   1031