~ubuntu-branches/ubuntu/edgy/xorg-server/edgy-updates

« back to all changes in this revision

Viewing changes to hw/kdrive/linux/mouse.c

  • Committer: Bazaar Package Importer
  • Author(s): Rodrigo Parra Novo
  • Date: 2006-07-25 20:06:28 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20060725200628-gjmmd9gxfxdc4ejs
Tags: 1:1.1.1-0ubuntu1
* New Upstream version
* Changed Build-Depends from mesa-swrast-source to mesa-swx11-source,
  following Debian package nomenclature
* Re-did 12_security_policy_in_etc.diff for 1.1.1
* Dropped 15_security_allocate_local.diff (applied upstream)
* Dropped 16_SECURITY_setuid.diff (applied upstream)
* Dropped 000_ubuntu_fix_read_kernel_mapping.patch (applied upstream)
* Dropped 002_ubuntu_fix_for_certain_intel_chipsets.patch (applied upstream)
* Updated versioned Build-Depends on mesa-swx11-source to version
  6.5.0.cvs.20060725-0ubuntu1
* Added arrayobj.c, arrayobj.h, bitset.h & rbadaptors.h to
  GL/symlink-mesa.sh (linked from mesa-swx11-source)
* Added arrayobj.c to default build target on GL/mesa/main

Show diffs side-by-side

added added

removed removed

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