1706f2543Smrg/*
2706f2543Smrg * Copyright � 1999 Keith Packard
3706f2543Smrg *
4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its
5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that
6706f2543Smrg * the above copyright notice appear in all copies and that both that
7706f2543Smrg * copyright notice and this permission notice appear in supporting
8706f2543Smrg * documentation, and that the name of Keith Packard not be used in
9706f2543Smrg * advertising or publicity pertaining to distribution of the software without
10706f2543Smrg * specific, written prior permission.  Keith Packard makes no
11706f2543Smrg * representations about the suitability of this software for any purpose.  It
12706f2543Smrg * is provided "as is" without express or implied warranty.
13706f2543Smrg *
14706f2543Smrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16706f2543Smrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20706f2543Smrg * PERFORMANCE OF THIS SOFTWARE.
21706f2543Smrg */
22706f2543Smrg
23706f2543Smrg#ifdef HAVE_CONFIG_H
24706f2543Smrg#include <kdrive-config.h>
25706f2543Smrg#endif
26706f2543Smrg#include <X11/X.h>
27706f2543Smrg#include <X11/Xproto.h>
28706f2543Smrg#include <X11/Xpoll.h>
29706f2543Smrg#include "inputstr.h"
30706f2543Smrg#include "scrnintstr.h"
31706f2543Smrg#include "kdrive.h"
32706f2543Smrg
33706f2543Smrgstatic int
34706f2543SmrgPs2ReadBytes (int fd, char *buf, int len, int min)
35706f2543Smrg{
36706f2543Smrg    int		    n, tot;
37706f2543Smrg    fd_set	    set;
38706f2543Smrg    struct timeval  tv;
39706f2543Smrg
40706f2543Smrg    tot = 0;
41706f2543Smrg    while (len)
42706f2543Smrg    {
43706f2543Smrg	n = read (fd, buf, len);
44706f2543Smrg	if (n > 0)
45706f2543Smrg	{
46706f2543Smrg	    tot += n;
47706f2543Smrg	    buf += n;
48706f2543Smrg	    len -= n;
49706f2543Smrg	}
50706f2543Smrg	if (tot % min == 0)
51706f2543Smrg	    break;
52706f2543Smrg	FD_ZERO (&set);
53706f2543Smrg	FD_SET (fd, &set);
54706f2543Smrg	tv.tv_sec = 0;
55706f2543Smrg	tv.tv_usec = 100 * 1000;
56706f2543Smrg	n = select (fd + 1, &set, 0, 0, &tv);
57706f2543Smrg	if (n <= 0)
58706f2543Smrg	    break;
59706f2543Smrg    }
60706f2543Smrg    return tot;
61706f2543Smrg}
62706f2543Smrg
63706f2543Smrgchar	*Ps2Names[] = {
64706f2543Smrg    "/dev/psaux",
65706f2543Smrg/*    "/dev/mouse", */
66706f2543Smrg    "/dev/input/mice",
67706f2543Smrg};
68706f2543Smrg
69706f2543Smrg#define NUM_PS2_NAMES	(sizeof (Ps2Names) / sizeof (Ps2Names[0]))
70706f2543Smrg
71706f2543Smrgstatic void
72706f2543SmrgPs2Read (int ps2Port, void *closure)
73706f2543Smrg{
74706f2543Smrg    unsigned char   buf[3 * 200];
75706f2543Smrg    unsigned char   *b;
76706f2543Smrg    int		    n;
77706f2543Smrg    int		    dx, dy;
78706f2543Smrg    unsigned long   flags;
79706f2543Smrg    unsigned long   left_button = KD_BUTTON_1;
80706f2543Smrg    unsigned long   right_button = KD_BUTTON_3;
81706f2543Smrg
82706f2543Smrg#undef SWAP_USB
83706f2543Smrg#ifdef SWAP_USB
84706f2543Smrg    if (id == 2)
85706f2543Smrg    {
86706f2543Smrg	left_button = KD_BUTTON_3;
87706f2543Smrg	right_button = KD_BUTTON_1;
88706f2543Smrg    }
89706f2543Smrg#endif
90706f2543Smrg    while ((n = Ps2ReadBytes (ps2Port, (char *) buf, sizeof (buf), 3)) > 0)
91706f2543Smrg    {
92706f2543Smrg	b = buf;
93706f2543Smrg	while (n >= 3)
94706f2543Smrg	{
95706f2543Smrg	    flags = KD_MOUSE_DELTA;
96706f2543Smrg	    if (b[0] & 4)
97706f2543Smrg		flags |= KD_BUTTON_2;
98706f2543Smrg	    if (b[0] & 2)
99706f2543Smrg		flags |= right_button;
100706f2543Smrg	    if (b[0] & 1)
101706f2543Smrg		flags |= left_button;
102706f2543Smrg
103706f2543Smrg	    dx = b[1];
104706f2543Smrg	    if (b[0] & 0x10)
105706f2543Smrg		dx -= 256;
106706f2543Smrg	    dy = b[2];
107706f2543Smrg	    if (b[0] & 0x20)
108706f2543Smrg		dy -= 256;
109706f2543Smrg	    dy = -dy;
110706f2543Smrg	    n -= 3;
111706f2543Smrg	    b += 3;
112706f2543Smrg	    KdEnqueuePointerEvent (closure, flags, dx, dy, 0);
113706f2543Smrg	}
114706f2543Smrg    }
115706f2543Smrg}
116706f2543Smrg
117706f2543Smrgstatic Status
118706f2543SmrgPs2Init (KdPointerInfo *pi)
119706f2543Smrg{
120706f2543Smrg    int	ps2Port, i;
121706f2543Smrg
122706f2543Smrg    if (!pi->path) {
123706f2543Smrg        for (i = 0; i < NUM_PS2_NAMES; i++) {
124706f2543Smrg            ps2Port = open (Ps2Names[i], 0);
125706f2543Smrg            if (ps2Port >= 0) {
126706f2543Smrg                pi->path = strdup (Ps2Names[i]);
127706f2543Smrg                break;
128706f2543Smrg            }
129706f2543Smrg	}
130706f2543Smrg    }
131706f2543Smrg    else {
132706f2543Smrg        ps2Port = open (pi->path, 0);
133706f2543Smrg    }
134706f2543Smrg
135706f2543Smrg    if (ps2Port < 0)
136706f2543Smrg        return BadMatch;
137706f2543Smrg
138706f2543Smrg    close(ps2Port);
139706f2543Smrg    if (!pi->name)
140706f2543Smrg        pi->name = strdup ("PS/2 Mouse");
141706f2543Smrg
142706f2543Smrg    return Success;
143706f2543Smrg}
144706f2543Smrg
145706f2543Smrgstatic Status
146706f2543SmrgPs2Enable (KdPointerInfo *pi)
147706f2543Smrg{
148706f2543Smrg    int fd;
149706f2543Smrg
150706f2543Smrg    if (!pi)
151706f2543Smrg        return BadImplementation;
152706f2543Smrg
153706f2543Smrg    fd = open (pi->path, 0);
154706f2543Smrg    if (fd < 0)
155706f2543Smrg        return BadMatch;
156706f2543Smrg
157706f2543Smrg    if (!KdRegisterFd (fd, Ps2Read, pi)) {
158706f2543Smrg        close(fd);
159706f2543Smrg        return BadAlloc;
160706f2543Smrg    }
161706f2543Smrg
162706f2543Smrg    pi->driverPrivate = (void *)(intptr_t)fd;
163706f2543Smrg
164706f2543Smrg    return Success;
165706f2543Smrg}
166706f2543Smrg
167706f2543Smrg
168706f2543Smrgstatic void
169706f2543SmrgPs2Disable (KdPointerInfo *pi)
170706f2543Smrg{
171706f2543Smrg    KdUnregisterFd (pi, (int)(intptr_t)pi->driverPrivate, TRUE);
172706f2543Smrg}
173706f2543Smrg
174706f2543Smrgstatic void
175706f2543SmrgPs2Fini (KdPointerInfo *pi)
176706f2543Smrg{
177706f2543Smrg}
178706f2543Smrg
179706f2543SmrgKdPointerDriver Ps2MouseDriver = {
180706f2543Smrg    "ps2",
181706f2543Smrg    Ps2Init,
182706f2543Smrg    Ps2Enable,
183706f2543Smrg    Ps2Disable,
184706f2543Smrg    Ps2Fini,
185706f2543Smrg    NULL,
186706f2543Smrg};
187