2
* $RCSId: xc/programs/Xserver/hw/kdrive/linux/mouse.c,v 1.6 2002/08/02 16:11:35 keithp Exp $
4
* Copyright � 2001 Keith Packard
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.
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.
26
#include <kdrive-config.h>
32
#include <X11/Xproto.h>
33
#include <X11/Xpoll.h>
35
#include "scrnintstr.h"
40
#define KBUFIO_SIZE 256
41
#define MOUSE_TIMEOUT 100
43
typedef struct _kbufio {
45
unsigned char buf[KBUFIO_SIZE];
51
MouseWaitForReadable (int fd, int timeout)
54
struct timeval tv, *tp;
58
done = GetTimeInMillis () + timeout;
67
tv.tv_sec = timeout / 1000;
68
tv.tv_usec = (timeout % 1000) * 1000;
71
n = select (fd + 1, &set, 0, 0, tp);
74
if (n < 0 && (errno == EAGAIN || errno == EINTR))
76
timeout = (int) (done - GetTimeInMillis ());
86
MouseReadByte (Kbufio *b, int timeout)
89
if (b->avail <= b->used)
91
if (timeout && !MouseWaitForReadable (b->fd, timeout))
94
ErrorF ("\tTimeout %d\n", timeout);
98
n = read (b->fd, b->buf, KBUFIO_SIZE);
105
ErrorF ("\tget %02x\n", b->buf[b->used]);
107
return b->buf[b->used++];
112
MouseFlush (Kbufio *b, char *buf, int size)
114
CARD32 now = GetTimeInMillis ();
115
CARD32 done = now + 100;
119
while ((c = MouseReadByte (b, done - now)) != -1)
125
memmove (buf, buf + 1, size - 1);
130
now = GetTimeInMillis ();
131
if ((INT32) (now - done) >= 0)
138
MousePeekByte (Kbufio *b, int timeout)
142
c = MouseReadByte (b, timeout);
150
MouseWaitForWritable (int fd, int timeout)
153
struct timeval tv, *tp;
162
tv.tv_sec = timeout / 1000;
163
tv.tv_usec = (timeout % 1000) * 1000;
166
n = select (fd + 1, 0, &set, 0, tp);
173
MouseWriteByte (int fd, unsigned char c, int timeout)
178
ErrorF ("\tput %02x\n", c);
182
ret = write (fd, &c, 1);
187
if (errno != EWOULDBLOCK)
189
if (!MouseWaitForWritable (fd, timeout))
195
MouseWriteBytes (int fd, unsigned char *c, int n, int timeout)
198
if (!MouseWriteByte (fd, *c++, timeout))
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 */
207
typedef struct _kmouseProt {
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;
216
unsigned int c_iflag;
217
unsigned int c_oflag;
218
unsigned int c_lflag;
219
unsigned int c_cflag;
225
typedef enum _kmouseStage {
226
MouseBroken, MouseTesting, MouseWorking
229
typedef struct _kmouse {
231
const KmouseProt *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 */
241
static int mouseValid (KdMouseInfo *mi, unsigned char *ev, int ne)
243
Kmouse *km = mi->driver;
244
const KmouseProt *prot = km->prot;
247
for (i = 0; i < ne; i++)
248
if ((ev[i] & prot->headerMask) == prot->headerValid)
252
for (i = 1; i < ne; i++)
253
if ((ev[i] & prot->dataMask) != prot->dataValid)
258
static Bool threeComplete (KdMouseInfo *mi, unsigned char *ev, int ne)
263
static Bool fourComplete (KdMouseInfo *mi, unsigned char *ev, int ne)
268
static Bool fiveComplete (KdMouseInfo *mi, unsigned char *ev, int ne)
273
static Bool MouseReasonable (KdMouseInfo *mi, unsigned long flags, int dx, int dy)
275
Kmouse *km = mi->driver;
277
if (km->stage == MouseWorking)
279
if (dx < -50 || dx > 50)
282
ErrorF ("Large X %d\n", dx);
286
if (dy < -50 || dy > 50)
289
ErrorF ("Large Y %d\n", dy);
297
* Standard PS/2 mouse protocol
299
static Bool ps2Parse (KdMouseInfo *mi, unsigned char *ev, int ne)
301
Kmouse *km = mi->driver;
304
unsigned long flagsrelease = 0;
306
flags = KD_MOUSE_DELTA;
308
flags |= KD_BUTTON_2;
310
flags |= KD_BUTTON_3;
312
flags |= KD_BUTTON_1;
316
dz = (int) (signed char) ev[3];
319
flags |= KD_BUTTON_4;
320
flagsrelease = KD_BUTTON_4;
324
flags |= KD_BUTTON_5;
325
flagsrelease = KD_BUTTON_5;
336
if (!MouseReasonable (mi, flags, dx, dy))
338
if (km->stage == MouseWorking)
340
KdEnqueueMouseEvent (mi, flags, dx, dy);
343
flags &= ~flagsrelease;
344
KdEnqueueMouseEvent (mi, flags, dx, dy);
350
static Bool ps2Init (KdMouseInfo *mi);
352
static const KmouseProt ps2Prot = {
354
threeComplete, mouseValid, ps2Parse, ps2Init,
355
0x08, 0x08, 0x00, 0x00,
359
static const KmouseProt imps2Prot = {
361
fourComplete, mouseValid, ps2Parse, ps2Init,
362
0x08, 0x08, 0x00, 0x00,
366
static const KmouseProt exps2Prot = {
368
fourComplete, mouseValid, ps2Parse, ps2Init,
369
0x08, 0x08, 0x00, 0x00,
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
378
/* these extracted from FreeBSD 4.3 sys/dev/kbd/atkbdcreg.h */
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
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
402
/* PSMC_SET_SAMPLING_RATE */
403
#define PSMD_MAX_RATE 255 /* FIXME: not sure if it's possible */
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
413
static unsigned char ps2_init[] = {
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,
428
#define NINIT_IMPS2 4
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,
441
#define NINIT_EXPS2 7
443
static unsigned char intelli_init[] = {
444
PSMC_SET_SAMPLING_RATE, 200,
445
PSMC_SET_SAMPLING_RATE, 100,
446
PSMC_SET_SAMPLING_RATE, 80,
450
#define NINIT_INTELLI 3
453
ps2SkipInit (KdMouseInfo *mi, int ninit, Bool ret_next)
455
Kmouse *km = mi->driver;
462
while (ninit || ret_next)
464
c = MouseReadByte (&km->iob, MOUSE_TIMEOUT);
474
/* look for packet start -- not the response */
475
else if ((c & 0x08) == 0x08)
484
ps2Init (KdMouseInfo *mi)
486
Kmouse *km = mi->driver;
493
/* Send Intellimouse initialization sequence */
494
MouseWriteBytes (km->iob.fd, intelli_init, strlen ((char *) intelli_init), 100);
498
if (!MouseWriteByte (km->iob.fd, PSMC_SEND_DEV_ID, 100))
502
id = ps2SkipInit (mi, 0, TRUE);
505
init = wheel_3button_init;
507
km->prot = &imps2Prot;
510
init = wheel_5button_init;
512
km->prot = &exps2Prot;
521
MouseWriteBytes (km->iob.fd, init, strlen ((char *) init), 100);
523
* Flush out the available data to eliminate responses to the
524
* initialization string. Make sure any partial event is
527
(void) ps2SkipInit (mi, ninit, FALSE);
531
static Bool busParse (KdMouseInfo *mi, unsigned char *ev, int ne)
533
Kmouse *km = mi->driver;
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))
548
if (km->stage == MouseWorking)
549
KdEnqueueMouseEvent (mi, flags, dx, dy);
553
static const KmouseProt busProt = {
555
threeComplete, mouseValid, busParse, 0,
556
0xf8, 0x00, 0x00, 0x00,
561
* Standard MS serial protocol, three bytes
564
static Bool msParse (KdMouseInfo *mi, unsigned char *ev, int ne)
566
Kmouse *km = mi->driver;
570
flags = KD_MOUSE_DELTA;
573
flags |= KD_BUTTON_1;
575
flags |= KD_BUTTON_3;
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))
581
if (km->stage == MouseWorking)
582
KdEnqueueMouseEvent (mi, flags, dx, dy);
586
static const KmouseProt msProt = {
588
threeComplete, mouseValid, msParse, 0,
589
0xc0, 0x40, 0xc0, 0x00,
594
CS7 | CSTOPB | CREAD | CLOCAL,
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
603
static Bool logiComplete (KdMouseInfo *mi, unsigned char *ev, int ne)
605
Kmouse *km = mi->driver;
607
if ((ev[0] & 0x40) == 0x40)
609
if (km->stage != MouseBroken && (ev[0] & ~0x23) == 0)
614
static int logiValid (KdMouseInfo *mi, unsigned char *ev, int ne)
616
Kmouse *km = mi->driver;
617
const KmouseProt *prot = km->prot;
620
for (i = 0; i < ne; i++)
622
if ((ev[i] & 0x40) == 0x40)
624
if (km->stage != MouseBroken && (ev[i] & ~0x23) == 0)
629
for (i = 1; i < ne; i++)
630
if ((ev[i] & prot->dataMask) != prot->dataValid)
635
static Bool logiParse (KdMouseInfo *mi, unsigned char *ev, int ne)
637
Kmouse *km = mi->driver;
641
flags = KD_MOUSE_DELTA;
646
flags |= KD_BUTTON_1;
648
flags |= KD_BUTTON_3;
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;
657
flags |= KD_BUTTON_2;
660
flags |= km->state & (KD_BUTTON_1|KD_BUTTON_3);
663
if (!MouseReasonable (mi, flags, dx, dy))
665
if (km->stage == MouseWorking)
666
KdEnqueueMouseEvent (mi, flags, dx, dy);
670
static const KmouseProt logiProt = {
672
logiComplete, logiValid, logiParse, 0,
673
0xc0, 0x40, 0xc0, 0x00,
678
CS7 | CSTOPB | CREAD | CLOCAL,
683
* Mouse systems protocol, 5 bytes
685
static Bool mscParse (KdMouseInfo *mi, unsigned char *ev, int ne)
687
Kmouse *km = mi->driver;
691
flags = KD_MOUSE_DELTA;
694
flags |= KD_BUTTON_1;
696
flags |= KD_BUTTON_2;
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]));
702
if (!MouseReasonable (mi, flags, dx, dy))
704
if (km->stage == MouseWorking)
705
KdEnqueueMouseEvent (mi, flags, dx, dy);
709
static const KmouseProt mscProt = {
711
fiveComplete, mouseValid, mscParse, 0,
712
0xf8, 0x80, 0x00, 0x00,
717
CS8 | CSTOPB | CREAD | CLOCAL,
722
* Use logitech before ms -- they're the same except that
723
* logitech sometimes has a fourth byte
725
static const KmouseProt *kmouseProts[] = {
726
&ps2Prot, &imps2Prot, &exps2Prot, &busProt, &logiProt, &msProt, &mscProt,
729
#define NUM_PROT (sizeof (kmouseProts) / sizeof (kmouseProts[0]))
732
MouseInitProtocol (Kmouse *km)
739
ret = tcgetattr (km->iob.fd, &t);
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);
752
km->stage = MouseBroken;
756
km->state = km->prot->state;
760
MouseFirstProtocol (Kmouse *km, char *prot)
764
for (km->i_prot = 0; km->i_prot < NUM_PROT; km->i_prot++)
765
if (!strcmp (prot, kmouseProts[km->i_prot]->name))
767
if (km->i_prot == NUM_PROT)
770
ErrorF ("Unknown mouse protocol \"%s\". Pick one of:", prot);
771
for (i = 0; i < NUM_PROT; i++)
772
ErrorF (" %s", kmouseProts[i]->name);
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",
781
else if (!km->tty && km->prot->tty)
782
ErrorF ("Mouse device is not serial port, protocol %s is serial protocol\n",
788
for (km->i_prot = 0; kmouseProts[km->i_prot]->tty != km->tty; km->i_prot++)
790
km->prot = kmouseProts[km->i_prot];
792
MouseInitProtocol (km);
796
MouseNextProtocol (Kmouse *km)
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);
811
MouseRead (int mousePort, void *closure)
813
KdMouseInfo *mi = closure;
814
Kmouse *km = mi->driver;
815
unsigned char event[MAX_MOUSE];
825
c = MouseReadByte (&km->iob, timeout);
830
km->invalid += ne + km->tested;
833
km->stage = MouseBroken;
838
i = (*km->prot->Valid) (mi, event, ne);
842
ErrorF ("Mouse protocol %s broken %d of %d bytes bad\n",
843
km->prot->name, i > 0 ? i : ne, ne);
848
memmove (event, event + i, ne);
855
km->invalid += i + km->tested;
858
if (km->stage == MouseWorking)
860
km->stage = MouseBroken;
861
if (km->invalid > MAX_SKIP)
863
MouseNextProtocol (km);
870
if ((*km->prot->Complete) (mi, event, ne))
872
if ((*km->prot->Parse) (mi, event, ne))
878
ErrorF ("Mouse protocol %s seems OK\n",
881
/* do not zero invalid to accumulate invalid bytes */
884
km->stage = MouseTesting;
885
/* fall through ... */
889
if (km->valid > MAX_VALID)
892
ErrorF ("Mouse protocol %s working\n",
895
km->stage = MouseWorking;
899
if (km->prot->Init && !(*km->prot->Init) (mi))
900
km->stage = MouseBroken;
909
km->invalid += ne + km->tested;
912
km->stage = MouseBroken;
918
timeout = MOUSE_TIMEOUT;
925
char *kdefaultMouse[] = {
934
#define NUM_DEFAULT_MOUSE (sizeof (kdefaultMouse) / sizeof (kdefaultMouse[0]))
942
KdMouseInfo *mi, *next;
947
MouseInputType = KdAllocInputType ();
949
for (mi = kdMouseInfo; mi; mi = next)
957
for (i = 0; i < NUM_DEFAULT_MOUSE; i++)
959
fd = open (kdefaultMouse[i], 2);
962
mi->name = KdSaveString (kdefaultMouse[i]);
968
fd = open (mi->name, 2);
972
km = (Kmouse *) xalloc (sizeof (Kmouse));
976
km->iob.avail = km->iob.used = 0;
979
km->tty = isatty (fd);
981
mi->inputType = MouseInputType;
982
MouseFirstProtocol (km, mi->prot);
983
if (KdRegisterFd (MouseInputType, fd, MouseRead, (void *) mi))
998
KdUnregisterFds (MouseInputType, TRUE);
999
for (mi = kdMouseInfo; mi; mi = mi->next)
1001
if (mi->inputType == MouseInputType)
1010
KdMouseFuncs LinuxMouseFuncs = {