Home | History | Annotate | Line # | Download | only in wsconsctl
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