Commit | Line | Data |
---|---|---|
a09e091a JB |
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 | }; |