Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / kdrive / linux / ms.c
1 /*
2 Copyright (c) 2001 by Juliusz Chroboczek
3 Copyright (c) 1999 by Keith Packard
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 THE SOFTWARE.
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include <kdrive-config.h>
26 #endif
27 #include <errno.h>
28 #include <termios.h>
29 #include <X11/X.h>
30 #include <X11/Xproto.h>
31 #include <X11/Xpoll.h>
32 #include "inputstr.h"
33 #include "scrnintstr.h"
34 #include "kdrive.h"
35
36 static int
37 MsReadBytes(int fd, char *buf, int len, int min)
38 {
39 int n, tot;
40 fd_set set;
41 struct timeval tv;
42
43 tot = 0;
44 while (len) {
45 n = read(fd, buf, len);
46 if (n > 0) {
47 tot += n;
48 buf += n;
49 len -= n;
50 }
51 if (tot % min == 0)
52 break;
53 FD_ZERO(&set);
54 FD_SET(fd, &set);
55 tv.tv_sec = 0;
56 tv.tv_usec = 100 * 1000;
57 n = select(fd + 1, &set, 0, 0, &tv);
58 if (n <= 0)
59 break;
60 }
61 return tot;
62 }
63
64 static void
65 MsRead(int port, void *closure)
66 {
67 unsigned char buf[3 * 200];
68 unsigned char *b;
69 int n;
70 int dx, dy;
71 unsigned long flags;
72
73 while ((n = MsReadBytes(port, (char *) buf, sizeof(buf), 3)) > 0) {
74 b = buf;
75 while (n >= 3) {
76 flags = KD_MOUSE_DELTA;
77
78 if (b[0] & 0x20)
79 flags |= KD_BUTTON_1;
80 if (b[0] & 0x10)
81 flags |= KD_BUTTON_3;
82
83 dx = (char) (((b[0] & 0x03) << 6) | (b[1] & 0x3F));
84 dy = (char) (((b[0] & 0x0C) << 4) | (b[2] & 0x3F));
85 n -= 3;
86 b += 3;
87 KdEnqueuePointerEvent(closure, flags, dx, dy, 0);
88 }
89 }
90 }
91
92 static Status
93 MsInit(KdPointerInfo * pi)
94 {
95 if (!pi)
96 return BadImplementation;
97
98 if (!pi->path || strcmp(pi->path, "auto"))
99 pi->path = strdup("/dev/mouse");
100 if (!pi->name)
101 pi->name = strdup("Microsoft protocol mouse");
102
103 return Success;
104 }
105
106 static Status
107 MsEnable(KdPointerInfo * pi)
108 {
109 int port;
110 struct termios t;
111 int ret;
112
113 port = open(pi->path, O_RDWR | O_NONBLOCK);
114 if (port < 0) {
115 ErrorF("Couldn't open %s (%d)\n", pi->path, (int) errno);
116 return 0;
117 }
118 else if (port == 0) {
119 ErrorF("Opening %s returned 0! Please complain to Keith.\n", pi->path);
120 goto bail;
121 }
122
123 if (!isatty(port)) {
124 ErrorF("%s is not a tty\n", pi->path);
125 goto bail;
126 }
127
128 ret = tcgetattr(port, &t);
129 if (ret < 0) {
130 ErrorF("Couldn't tcgetattr(%s): %d\n", pi->path, errno);
131 goto bail;
132 }
133 t.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR |
134 IGNCR | ICRNL | IXON | IXOFF);
135 t.c_oflag &= ~OPOST;
136 t.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
137 t.c_cflag &= ~(CSIZE | PARENB);
138 t.c_cflag |= CS8 | CLOCAL | CSTOPB;
139
140 cfsetispeed(&t, B1200);
141 cfsetospeed(&t, B1200);
142 t.c_cc[VMIN] = 1;
143 t.c_cc[VTIME] = 0;
144 ret = tcsetattr(port, TCSANOW, &t);
145 if (ret < 0) {
146 ErrorF("Couldn't tcsetattr(%s): %d\n", pi->path, errno);
147 goto bail;
148 }
149 if (KdRegisterFd(port, MsRead, pi))
150 return TRUE;
151 pi->driverPrivate = (void *) (intptr_t) port;
152
153 return Success;
154
155 bail:
156 close(port);
157 return BadMatch;
158 }
159
160 static void
161 MsDisable(KdPointerInfo * pi)
162 {
163 KdUnregisterFd(pi, (int) (intptr_t) pi->driverPrivate, TRUE);
164 }
165
166 static void
167 MsFini(KdPointerInfo * pi)
168 {
169 }
170
171 KdPointerDriver MsMouseDriver = {
172 "ms",
173 MsInit,
174 MsEnable,
175 MsDisable,
176 MsFini,
177 NULL,
178 };