mouse.c revision 1.10 1 /* $NetBSD: mouse.c,v 1.10 2012/12/24 01:29:20 khorben Exp $ */
2
3 /*-
4 * Copyright (c) 1998, 2006, 2012 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Juergen Hannken-Illjes and Julio M. Merino Vidal.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/ioctl.h>
33 #include <sys/time.h>
34 #include <dev/wscons/wsconsio.h>
35
36 #include <err.h>
37 #include <errno.h>
38 #include <limits.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43 #include "wsconsctl.h"
44
45 static int mstype;
46 static int resolution;
47 static int samplerate;
48 static struct wsmouse_calibcoords calibration;
49 static char *calibration_samples;
50 static struct wsmouse_repeat repeat;
51
52 static void mouse_get_calibration(int);
53 static void mouse_put_calibration(int);
54
55 static void mouse_get_repeat(int);
56 static void mouse_put_repeat(int);
57
58 struct field mouse_field_tab[] = {
59 { "resolution", &resolution, FMT_UINT, FLG_WRONLY },
60 { "samplerate", &samplerate, FMT_UINT, FLG_WRONLY },
61 { "type", &mstype, FMT_MSTYPE, FLG_RDONLY },
62 { "calibration.minx", &calibration.minx,
63 FMT_INT, FLG_MODIFY },
64 { "calibration.miny", &calibration.miny,
65 FMT_INT, FLG_MODIFY },
66 { "calibration.maxx", &calibration.maxx,
67 FMT_INT, FLG_MODIFY },
68 { "calibration.maxy", &calibration.maxy,
69 FMT_INT, FLG_MODIFY },
70 { "calibration.samples", &calibration_samples,
71 FMT_STRING, FLG_MODIFY },
72 { "repeat.buttons", &repeat.wr_buttons,
73 FMT_BITFIELD, FLG_MODIFY },
74 { "repeat.delay.first", &repeat.wr_delay_first,
75 FMT_UINT, FLG_MODIFY },
76 { "repeat.delay.decrement", &repeat.wr_delay_decrement,
77 FMT_UINT, FLG_MODIFY },
78 { "repeat.delay.minimum", &repeat.wr_delay_minimum,
79 FMT_UINT, FLG_MODIFY },
80 };
81
82 int mouse_field_tab_len = sizeof(mouse_field_tab)/
83 sizeof(mouse_field_tab[0]);
84
85 void
86 mouse_get_values(int fd)
87 {
88
89 if (field_by_value(&mstype)->flags & FLG_GET)
90 if (ioctl(fd, WSMOUSEIO_GTYPE, &mstype) < 0)
91 err(EXIT_FAILURE, "WSMOUSEIO_GTYPE");
92
93 if (field_by_value(&calibration.minx)->flags & FLG_GET ||
94 field_by_value(&calibration.miny)->flags & FLG_GET ||
95 field_by_value(&calibration.maxx)->flags & FLG_GET ||
96 field_by_value(&calibration.maxy)->flags & FLG_GET ||
97 field_by_value(&calibration_samples)->flags & FLG_GET)
98 mouse_get_calibration(fd);
99
100 if (field_by_value(&repeat.wr_buttons)->flags & FLG_GET ||
101 field_by_value(&repeat.wr_delay_first)->flags & FLG_GET ||
102 field_by_value(&repeat.wr_delay_decrement)->flags & FLG_GET ||
103 field_by_value(&repeat.wr_delay_minimum)->flags & FLG_GET)
104 mouse_get_repeat(fd);
105 }
106
107 static void
108 mouse_get_calibration(int fd)
109 {
110 struct wsmouse_calibcoords tmp;
111 char *samples;
112 char buf[48];
113 int i;
114
115 if (ioctl(fd, WSMOUSEIO_GCALIBCOORDS, &tmp) < 0) {
116 field_disable_by_value(&calibration.minx);
117 field_disable_by_value(&calibration.miny);
118 field_disable_by_value(&calibration.maxx);
119 field_disable_by_value(&calibration.maxy);
120 field_disable_by_value(&calibration_samples);
121 return;
122 }
123
124 if (field_by_value(&calibration.minx)->flags & FLG_GET)
125 calibration.minx = tmp.minx;
126 if (field_by_value(&calibration.miny)->flags & FLG_GET)
127 calibration.miny = tmp.miny;
128 if (field_by_value(&calibration.maxx)->flags & FLG_GET)
129 calibration.maxx = tmp.maxx;
130 if (field_by_value(&calibration.maxy)->flags & FLG_GET)
131 calibration.maxy = tmp.maxy;
132 if (field_by_value(&calibration_samples)->flags & FLG_GET) {
133 free(calibration_samples);
134 if (tmp.samplelen <= 0) {
135 calibration_samples = strdup("");
136 if (calibration_samples == NULL)
137 err(EXIT_FAILURE, "could not list calibration"
138 " samples");
139 } else {
140 samples = malloc(tmp.samplelen * sizeof(buf));
141 if (samples == NULL)
142 err(EXIT_FAILURE, "could not list calibration"
143 " samples");
144 samples[0] = '\0';
145 for (i = 0; i < tmp.samplelen; i++) {
146 snprintf(buf, sizeof(buf), "%s%d,%d,%d,%d",
147 (i == 0) ? "" : ":",
148 tmp.samples[i].rawx,
149 tmp.samples[i].rawy,
150 tmp.samples[i].x,
151 tmp.samples[i].y);
152 strcat(samples, buf);
153 }
154 calibration_samples = samples;
155 }
156 }
157 }
158
159 static void
160 mouse_get_repeat(int fd)
161 {
162 struct wsmouse_repeat tmp;
163
164 if (ioctl(fd, WSMOUSEIO_GETREPEAT, &tmp) < 0)
165 err(EXIT_FAILURE, "WSMOUSEIO_GETREPEAT");
166
167 if (field_by_value(&repeat.wr_buttons)->flags & FLG_GET)
168 repeat.wr_buttons = tmp.wr_buttons;
169 if (field_by_value(&repeat.wr_delay_first)->flags & FLG_GET)
170 repeat.wr_delay_first = tmp.wr_delay_first;
171 if (field_by_value(&repeat.wr_delay_decrement)->flags & FLG_GET)
172 repeat.wr_delay_decrement = tmp.wr_delay_decrement;
173 if (field_by_value(&repeat.wr_delay_minimum)->flags & FLG_GET)
174 repeat.wr_delay_minimum = tmp.wr_delay_minimum;
175 }
176
177 void
178 mouse_put_values(int fd)
179 {
180 int tmp;
181
182 if (field_by_value(&resolution)->flags & FLG_SET) {
183 tmp = resolution;
184 if (ioctl(fd, WSMOUSEIO_SRES, &tmp) < 0)
185 err(EXIT_FAILURE, "WSMOUSEIO_SRES");
186 pr_field(field_by_value(&resolution), " -> ");
187 }
188
189 if (field_by_value(&samplerate)->flags & FLG_SET) {
190 tmp = samplerate;
191 if (ioctl(fd, WSMOUSEIO_SRATE, &tmp) < 0)
192 err(EXIT_FAILURE, "WSMOUSEIO_SRATE");
193 pr_field(field_by_value(&samplerate), " -> ");
194 }
195
196 if (field_by_value(&calibration.minx)->flags & FLG_SET ||
197 field_by_value(&calibration.miny)->flags & FLG_SET ||
198 field_by_value(&calibration.maxx)->flags & FLG_SET ||
199 field_by_value(&calibration.maxy)->flags & FLG_SET ||
200 field_by_value(&calibration_samples)->flags & FLG_SET)
201 mouse_put_calibration(fd);
202
203 if (field_by_value(&repeat.wr_buttons)->flags & FLG_SET ||
204 field_by_value(&repeat.wr_delay_first)->flags & FLG_SET ||
205 field_by_value(&repeat.wr_delay_decrement)->flags & FLG_SET ||
206 field_by_value(&repeat.wr_delay_minimum)->flags & FLG_SET)
207 mouse_put_repeat(fd);
208 }
209
210 static void
211 mouse_put_calibration(int fd)
212 {
213 struct wsmouse_calibcoords tmp;
214 int i;
215 const char *p;
216 char *q;
217
218 /* Fetch current values into the temporary structure. */
219 if (ioctl(fd, WSMOUSEIO_GCALIBCOORDS, &tmp) < 0)
220 err(EXIT_FAILURE, "WSMOUSEIO_GCALIBCOORDS");
221
222 /* Overwrite the desired values in the temporary structure. */
223 if (field_by_value(&calibration.minx)->flags & FLG_SET)
224 tmp.minx = calibration.minx;
225 if (field_by_value(&calibration.miny)->flags & FLG_SET)
226 tmp.miny = calibration.miny;
227 if (field_by_value(&calibration.maxx)->flags & FLG_SET)
228 tmp.maxx = calibration.maxx;
229 if (field_by_value(&calibration.maxy)->flags & FLG_SET)
230 tmp.maxy = calibration.maxy;
231 if (field_by_value(&calibration_samples)->flags & FLG_SET) {
232 p = calibration_samples;
233 for (i = 0; p[0] != '\0' && i < WSMOUSE_CALIBCOORDS_MAX; i++) {
234 tmp.samples[i].rawx = strtol(p, &q, 0);
235 if (*q != ',')
236 break;
237 p = q + 1;
238 tmp.samples[i].rawy = strtol(p, &q, 0);
239 if (*q != ',')
240 break;
241 p = q + 1;
242 tmp.samples[i].x = strtol(p, &q, 0);
243 if (*q != ',')
244 break;
245 p = q + 1;
246 tmp.samples[i].y = strtol(p, &q, 0);
247 p = q + 1;
248 if (*q != '\0' && *q != ':')
249 break;
250 }
251 if (p[0] != '\0')
252 errx(EXIT_FAILURE, "%s: invalid calibration data",
253 calibration_samples);
254 tmp.samplelen = i;
255 }
256
257 /* Set new values for calibrating events. */
258 if (ioctl(fd, WSMOUSEIO_SCALIBCOORDS, &tmp) < 0)
259 err(EXIT_FAILURE, "WSMOUSEIO_SCALIBCOORDS");
260
261 /* Now print what changed. */
262 if (field_by_value(&calibration.minx)->flags & FLG_SET)
263 pr_field(field_by_value(&calibration.minx), " -> ");
264 if (field_by_value(&calibration.miny)->flags & FLG_SET)
265 pr_field(field_by_value(&calibration.miny), " -> ");
266 if (field_by_value(&calibration.maxx)->flags & FLG_SET)
267 pr_field(field_by_value(&calibration.maxx), " -> ");
268 if (field_by_value(&calibration.maxy)->flags & FLG_SET)
269 pr_field(field_by_value(&calibration.maxy), " -> ");
270 if (field_by_value(&calibration_samples)->flags & FLG_SET)
271 pr_field(field_by_value(&calibration_samples), " -> ");
272 }
273
274 static void
275 mouse_put_repeat(int fd)
276 {
277 struct wsmouse_repeat tmp;
278
279 /* Fetch current values into the temporary structure. */
280 if (ioctl(fd, WSMOUSEIO_GETREPEAT, &tmp) < 0)
281 err(EXIT_FAILURE, "WSMOUSEIO_GETREPEAT");
282
283 /* Overwrite the desired values in the temporary structure. */
284 if (field_by_value(&repeat.wr_buttons)->flags & FLG_SET)
285 tmp.wr_buttons = repeat.wr_buttons;
286 if (field_by_value(&repeat.wr_delay_first)->flags & FLG_SET)
287 tmp.wr_delay_first = repeat.wr_delay_first;
288 if (field_by_value(&repeat.wr_delay_decrement)->flags & FLG_SET)
289 tmp.wr_delay_decrement = repeat.wr_delay_decrement;
290 if (field_by_value(&repeat.wr_delay_minimum)->flags & FLG_SET)
291 tmp.wr_delay_minimum = repeat.wr_delay_minimum;
292
293 /* Set new values for repeating events. */
294 if (ioctl(fd, WSMOUSEIO_SETREPEAT, &tmp) < 0)
295 err(EXIT_FAILURE, "WSMOUSEIO_SETREPEAT");
296
297 /* Now print what changed. */
298 if (field_by_value(&repeat.wr_buttons)->flags & FLG_SET)
299 pr_field(field_by_value(&repeat.wr_buttons), " -> ");
300 if (field_by_value(&repeat.wr_delay_first)->flags & FLG_SET)
301 pr_field(field_by_value(&repeat.wr_delay_first), " -> ");
302 if (field_by_value(&repeat.wr_delay_decrement)->flags & FLG_SET)
303 pr_field(field_by_value(&repeat.wr_delay_decrement), " -> ");
304 if (field_by_value(&repeat.wr_delay_minimum)->flags & FLG_SET)
305 pr_field(field_by_value(&repeat.wr_delay_minimum), " -> ");
306 }
307