1/* $NetBSD: mouse.c,v 1.8 2008/04/28 20:23:09 martin 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 45static int mstype; 46static int resolution; 47static int samplerate; 48static struct wsmouse_calibcoords calibration; 49static char *calibration_samples; 50static struct wsmouse_repeat repeat; 51 52static void mouse_get_calibration(int); 53static void mouse_put_calibration(int); 54 55static void mouse_get_repeat(int); 56static void mouse_put_repeat(int); 57 58struct 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 82int mouse_field_tab_len = sizeof(mouse_field_tab)/ 83 sizeof(mouse_field_tab[0]); 84 85void 86mouse_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 107static void 108mouse_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 159static void 160mouse_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 177void 178mouse_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 210static void 211mouse_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 274static void 275mouse_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