1706f2543Smrg/*
2706f2543SmrgCopyright (c) 2001 by Juliusz Chroboczek
3706f2543SmrgCopyright (c) 1999 by Keith Packard
4706f2543Smrg
5706f2543SmrgPermission is hereby granted, free of charge, to any person obtaining a copy
6706f2543Smrgof this software and associated documentation files (the "Software"), to deal
7706f2543Smrgin the Software without restriction, including without limitation the rights
8706f2543Smrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9706f2543Smrgcopies of the Software, and to permit persons to whom the Software is
10706f2543Smrgfurnished to do so, subject to the following conditions:
11706f2543Smrg
12706f2543SmrgThe above copyright notice and this permission notice shall be included in
13706f2543Smrgall copies or substantial portions of the Software.
14706f2543Smrg
15706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18706f2543SmrgAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19706f2543SmrgLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20706f2543SmrgOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21706f2543SmrgTHE SOFTWARE.
22706f2543Smrg*/
23706f2543Smrg
24706f2543Smrg#ifdef HAVE_CONFIG_H
25706f2543Smrg#include <kdrive-config.h>
26706f2543Smrg#endif
27706f2543Smrg#include <errno.h>
28706f2543Smrg#include <termios.h>
29706f2543Smrg#include <X11/X.h>
30706f2543Smrg#include <X11/Xproto.h>
31706f2543Smrg#include <X11/Xpoll.h>
32706f2543Smrg#include "inputstr.h"
33706f2543Smrg#include "scrnintstr.h"
34706f2543Smrg#include "kdrive.h"
35706f2543Smrg
36706f2543Smrgstatic int
37706f2543SmrgMsReadBytes (int fd, char *buf, int len, int min)
38706f2543Smrg{
39706f2543Smrg    int		    n, tot;
40706f2543Smrg    fd_set	    set;
41706f2543Smrg    struct timeval  tv;
42706f2543Smrg
43706f2543Smrg    tot = 0;
44706f2543Smrg    while (len)
45706f2543Smrg    {
46706f2543Smrg	n = read (fd, buf, len);
47706f2543Smrg	if (n > 0)
48706f2543Smrg	{
49706f2543Smrg	    tot += n;
50706f2543Smrg	    buf += n;
51706f2543Smrg	    len -= n;
52706f2543Smrg	}
53706f2543Smrg	if (tot % min == 0)
54706f2543Smrg	    break;
55706f2543Smrg	FD_ZERO (&set);
56706f2543Smrg	FD_SET (fd, &set);
57706f2543Smrg	tv.tv_sec = 0;
58706f2543Smrg	tv.tv_usec = 100 * 1000;
59706f2543Smrg	n = select (fd + 1, &set, 0, 0, &tv);
60706f2543Smrg	if (n <= 0)
61706f2543Smrg	    break;
62706f2543Smrg    }
63706f2543Smrg    return tot;
64706f2543Smrg}
65706f2543Smrg
66706f2543Smrgstatic void
67706f2543SmrgMsRead (int port, void *closure)
68706f2543Smrg{
69706f2543Smrg    unsigned char   buf[3 * 200];
70706f2543Smrg    unsigned char   *b;
71706f2543Smrg    int		    n;
72706f2543Smrg    int		    dx, dy;
73706f2543Smrg    unsigned long   flags;
74706f2543Smrg
75706f2543Smrg    while ((n = MsReadBytes (port, (char *) buf, sizeof (buf), 3)) > 0)
76706f2543Smrg    {
77706f2543Smrg	b = buf;
78706f2543Smrg	while (n >= 3)
79706f2543Smrg	{
80706f2543Smrg	    flags = KD_MOUSE_DELTA;
81706f2543Smrg
82706f2543Smrg	    if (b[0] & 0x20)
83706f2543Smrg		flags |= KD_BUTTON_1;
84706f2543Smrg	    if (b[0] & 0x10)
85706f2543Smrg		flags |= KD_BUTTON_3;
86706f2543Smrg
87706f2543Smrg	    dx = (char)(((b[0] & 0x03) << 6) | (b[1] & 0x3F));
88706f2543Smrg	    dy = (char)(((b[0] & 0x0C) << 4) | (b[2] & 0x3F));
89706f2543Smrg            n -= 3;
90706f2543Smrg            b += 3;
91706f2543Smrg	    KdEnqueuePointerEvent (closure, flags, dx, dy, 0);
92706f2543Smrg	}
93706f2543Smrg    }
94706f2543Smrg}
95706f2543Smrg
96706f2543Smrgstatic Status
97706f2543SmrgMsInit (KdPointerInfo *pi)
98706f2543Smrg{
99706f2543Smrg    if (!pi)
100706f2543Smrg        return BadImplementation;
101706f2543Smrg
102706f2543Smrg    if (!pi->path || strcmp(pi->path, "auto"))
103706f2543Smrg        pi->path = strdup("/dev/mouse");
104706f2543Smrg    if (!pi->name)
105706f2543Smrg        pi->name = strdup("Microsoft protocol mouse");
106706f2543Smrg
107706f2543Smrg    return Success;
108706f2543Smrg}
109706f2543Smrg
110706f2543Smrgstatic Status
111706f2543SmrgMsEnable (KdPointerInfo *pi)
112706f2543Smrg{
113706f2543Smrg    int port;
114706f2543Smrg    struct termios t;
115706f2543Smrg    int ret;
116706f2543Smrg
117706f2543Smrg    port = open (pi->path, O_RDWR | O_NONBLOCK);
118706f2543Smrg    if(port < 0) {
119706f2543Smrg        ErrorF("Couldn't open %s (%d)\n", pi->path, (int)errno);
120706f2543Smrg        return 0;
121706f2543Smrg    } else if (port == 0) {
122706f2543Smrg        ErrorF("Opening %s returned 0!  Please complain to Keith.\n",
123706f2543Smrg               pi->path);
124706f2543Smrg	goto bail;
125706f2543Smrg    }
126706f2543Smrg
127706f2543Smrg    if(!isatty(port)) {
128706f2543Smrg        ErrorF("%s is not a tty\n", pi->path);
129706f2543Smrg        goto bail;
130706f2543Smrg    }
131706f2543Smrg
132706f2543Smrg    ret = tcgetattr(port, &t);
133706f2543Smrg    if(ret < 0) {
134706f2543Smrg        ErrorF("Couldn't tcgetattr(%s): %d\n", pi->path, errno);
135706f2543Smrg        goto bail;
136706f2543Smrg    }
137706f2543Smrg    t.c_iflag &= ~ (IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR |
138706f2543Smrg                   IGNCR | ICRNL | IXON | IXOFF);
139706f2543Smrg    t.c_oflag &= ~ OPOST;
140706f2543Smrg    t.c_lflag &= ~ (ECHO | ECHONL | ICANON | ISIG | IEXTEN);
141706f2543Smrg    t.c_cflag &= ~ (CSIZE | PARENB);
142706f2543Smrg    t.c_cflag |= CS8 | CLOCAL | CSTOPB;
143706f2543Smrg
144706f2543Smrg    cfsetispeed (&t, B1200);
145706f2543Smrg    cfsetospeed (&t, B1200);
146706f2543Smrg    t.c_cc[VMIN] = 1;
147706f2543Smrg    t.c_cc[VTIME] = 0;
148706f2543Smrg    ret = tcsetattr(port, TCSANOW, &t);
149706f2543Smrg    if(ret < 0) {
150706f2543Smrg        ErrorF("Couldn't tcsetattr(%s): %d\n", pi->path, errno);
151706f2543Smrg        goto bail;
152706f2543Smrg    }
153706f2543Smrg    if (KdRegisterFd (port, MsRead, pi))
154706f2543Smrg	return TRUE;
155706f2543Smrg    pi->driverPrivate = (void *)(intptr_t)port;
156706f2543Smrg
157706f2543Smrg    return Success;
158706f2543Smrg
159706f2543Smrg bail:
160706f2543Smrg    close(port);
161706f2543Smrg    return BadMatch;
162706f2543Smrg}
163706f2543Smrg
164706f2543Smrgstatic void
165706f2543SmrgMsDisable (KdPointerInfo *pi)
166706f2543Smrg{
167706f2543Smrg    KdUnregisterFd (pi, (int)(intptr_t)pi->driverPrivate, TRUE);
168706f2543Smrg}
169706f2543Smrg
170706f2543Smrgstatic void
171706f2543SmrgMsFini (KdPointerInfo *pi)
172706f2543Smrg{
173706f2543Smrg}
174706f2543Smrg
175706f2543SmrgKdPointerDriver MsMouseDriver = {
176706f2543Smrg    "ms",
177706f2543Smrg    MsInit,
178706f2543Smrg    MsEnable,
179706f2543Smrg    MsDisable,
180706f2543Smrg    MsFini,
181706f2543Smrg    NULL,
182706f2543Smrg};
183