Home | History | Annotate | Line # | Download | only in tpctl
main.c revision 1.2
      1 /*	$NetBSD: main.c,v 1.2 2004/02/24 15:12:18 wiz Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2002 TAKEMRUA Shin
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. Neither the name of The NetBSD Foundation nor the names of its
     16  *    contributors may be used to endorse or promote products derived
     17  *    from this software without specific prior written permission.
     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 <stdio.h>
     33 #include <strings.h>
     34 #include <stdlib.h>
     35 #include <unistd.h>
     36 #include <err.h>
     37 #include <errno.h>
     38 #include <time.h>
     39 #include <termios.h>
     40 #include <sys/fcntl.h>
     41 #include <sys/mman.h>
     42 #ifdef __STDC__
     43 #include <stdarg.h>
     44 #else
     45 #include <varargs.h>
     46 #endif
     47 
     48 #include "tpctl.h"
     49 
     50 #ifndef lint
     51 #include <sys/cdefs.h>
     52 __RCSID("$NetBSD: main.c,v 1.2 2004/02/24 15:12:18 wiz Exp $");
     53 #endif /* not lint */
     54 
     55 void load_data(char *data_file, struct tpctl_data *);
     56 void save_data(char *data_file, struct tpctl_data *);
     57 int do_calibration(char *, struct tp *, struct wsmouse_calibcoords *);
     58 void drawcross(struct fb *, int, int, int, fb_pixel_t);
     59 int check_esc(void *);
     60 
     61 int opt_verbose;
     62 int opt_noupdate;
     63 int opt_forceupdate;
     64 
     65 static void
     66 usage(void)
     67 {
     68 
     69 	fprintf(stderr, "usage: %s [-D dispdev] [-d dev] [-f file] [-hnuv]\n",
     70 	    getprogname());
     71 	exit(EXIT_FAILURE);
     72 	/* NOTREACHED */
     73 }
     74 
     75 int
     76 main(int argc, char *argv[])
     77 {
     78 	int tpfd, ch;
     79 	struct tp tp;
     80 	struct wsmouse_calibcoords *pref;
     81 	struct tpctl_data data;
     82 	char *data_file;
     83 	char *dev_name;
     84 	char *dispdev_name;
     85 
     86 	/* set default values */
     87 	opt_verbose = 0;
     88 	opt_noupdate = 0;
     89 	opt_forceupdate = 0;
     90 	dev_name = TPCTL_TP_DEVICE;
     91 	dispdev_name = TPCTL_FB_DEVICE;
     92 	data_file = TPCTL_DB_FILENAME;
     93 
     94 	/* parse command line */
     95 	while ((ch = getopt(argc, argv, "d:D:f:hnuv")) != -1) {
     96 		switch (ch) {
     97 		case 'D':
     98 			dispdev_name = optarg;
     99 			break;
    100 		case 'd':
    101 			dev_name = optarg;
    102 			break;
    103 		case 'f':
    104 			data_file = optarg;
    105 			break;
    106 		case 'h':
    107 			usage();
    108 			/* NOTREACHED */
    109 		case 'n':
    110 			opt_noupdate = 1;
    111 			break;
    112 		case 'u':
    113 			opt_forceupdate = 1;
    114 			break;
    115 		case 'v':
    116 			opt_verbose = 1;
    117 			break;
    118 		default:
    119 			usage();
    120 			/* NOTREACHED */
    121 		}
    122 	}
    123 	if (argv[optind] != NULL) {
    124 		usage();
    125 		/* NOTREACHED */
    126 	}
    127 
    128 	/* load calibrarion parameters from specified file */
    129 	load_data(data_file, &data);
    130 
    131 	/* open touch panel device and initialize touch panel routines */
    132 	if ((tpfd = open(dev_name, O_RDWR)) < 0)
    133 		errx(EXIT_FAILURE, "can't open touch panel");
    134 	if (tp_init(&tp, tpfd) < 0)
    135 		errx(EXIT_FAILURE, "can't initialize touch panel");
    136 
    137 	/* find out saved parameters for the touch panel */
    138 	pref = search_data(&data, tp.id);
    139 	if (opt_forceupdate || pref == NULL) {
    140 		/* if the parameters wasn't found or '-f' options was
    141 		   specified, do 'calibrarion' */
    142 		struct wsmouse_calibcoords coords;
    143 
    144 		/* draw cursors and collect samples */
    145 		if (do_calibration(dispdev_name, &tp, &coords) < 0) {
    146 			/* ESC key was pressed to abort */
    147 			exit(EXIT_FAILURE);
    148 		}
    149 		/* update parameters with new one */
    150 		replace_data(&data, tp.id, &coords);
    151 		pref = search_data(&data, tp.id);
    152 	} else {
    153 		/* nothing is updated,
    154 		   so you don't have to write back the data */
    155 		opt_noupdate = 1;
    156 	}
    157 
    158 	if (opt_verbose)
    159 		write_coords(stdout, tp.id, pref);
    160 
    161 	/* set calibration parameters into touch panel device */
    162 	if (tp_setcalibcoords(&tp, pref) < 0)
    163 		errx(EXIT_FAILURE, "can't set samples");
    164 
    165 	/* save calibrarion parameters from specified file */
    166 	if (!opt_noupdate)
    167 		save_data(data_file, &data);
    168 	/* dispose data */
    169 	free_data(&data);
    170 
    171 	exit(EXIT_SUCCESS);
    172 	/* NOTREACHED */
    173 }
    174 
    175 /*
    176  * load calibrarion parameters from specified file
    177  *
    178  * return:	none (it won't return if some error occurs)
    179  */
    180 void
    181 load_data(char *data_file, struct tpctl_data *data)
    182 {
    183 	int err;
    184 
    185 	init_data(data);
    186 	err = read_data(data_file, data);
    187 	switch (err) {
    188 	case ERR_NONE:
    189 		break;
    190 	case ERR_NOFILE:
    191 		fprintf(stderr, "%s: can't open %s\n", getprogname(),
    192 		    data_file);
    193 		/* it might be OK... */
    194 		break;
    195 	case ERR_IO:
    196 		fprintf(stderr, "%s: I/O error on %s\n", getprogname(),
    197 		    data_file);
    198 		exit(EXIT_FAILURE);
    199 		break;
    200 	case ERR_SYNTAX:
    201 		fprintf(stderr, "%s: format error at %s, line %d\n",
    202 		    getprogname(), data_file, data->lineno);
    203 		exit(EXIT_FAILURE);
    204 		break;
    205 	case ERR_DUPNAME:
    206 		fprintf(stderr, "%s: duplicate entry at %s, line %d\n",
    207 		    getprogname(), data_file, data->lineno);
    208 		exit(EXIT_FAILURE);
    209 		break;
    210 	default:
    211 		fprintf(stderr, "%s: internal error\n", getprogname());
    212 		exit(EXIT_FAILURE);
    213 		break;
    214 	}
    215 }
    216 
    217 /*
    218  * save calibrarion parameters to specified file
    219  *
    220  * return:	none (it won't return if some error occurs)
    221  */
    222 void
    223 save_data(char *data_file, struct tpctl_data *data)
    224 {
    225 	int err;
    226 
    227 	err = write_data(data_file, data);
    228 	switch (err) {
    229 	case ERR_NONE:
    230 		break;
    231 	case ERR_NOFILE:
    232 		fprintf(stderr, "%s: can't open %s\n", getprogname(),
    233 		    data_file);
    234 		exit(EXIT_FAILURE);
    235 		break;
    236 	case ERR_IO:
    237 		fprintf(stderr, "%s: I/O error on %s\n", getprogname(),
    238 		    data_file);
    239 		exit(EXIT_FAILURE);
    240 		break;
    241 	default:
    242 		fprintf(stderr, "%s: internal error\n", getprogname());
    243 		exit(EXIT_FAILURE);
    244 		break;
    245 	}
    246 }
    247 
    248 /*
    249  * draw cursors on frame buffer and collect samples in
    250  * wamouse_calibcoords structure.
    251  *
    252  * return:	0	succeeded
    253  *		-1	aborted by user (ESC key was pressed)
    254  *		(it won't return if some error occurs)
    255  */
    256 int
    257 do_calibration(char *dev, struct tp *tp, struct wsmouse_calibcoords *coords)
    258 {
    259 	int fbfd;
    260 	struct fb fb;
    261 	int i, x, y, xm, ym, cursize, err, res;
    262 
    263 	/* open frame buffer device and initialize frame buffer routine */
    264 	if ((fbfd = open(dev, O_RDWR)) < 0)
    265 		errx(EXIT_FAILURE, "can't open frame buffer");
    266 	if (fb_init(&fb, fbfd) < 0)
    267 		errx(EXIT_FAILURE, "can't map frame buffer");
    268 
    269 	memset(coords, 0, sizeof(*coords));
    270 	coords->minx = 0;
    271 	coords->miny = 0;
    272 	coords->maxx = fb.conf.hf_width - 1;
    273 	coords->maxy = fb.conf.hf_height - 1;
    274 	coords->samplelen = 5;
    275 
    276 	cursize = 20;
    277 	xm = fb.conf.hf_width/10;
    278 	ym = fb.conf.hf_height/10;
    279 
    280 	/* center */
    281 	coords->samples[0].x = fb.conf.hf_width/2;
    282 	coords->samples[0].y = fb.conf.hf_height/2;
    283 
    284 	/* top left */
    285 	coords->samples[1].x = xm;
    286 	coords->samples[1].y = ym;
    287 
    288 	/* bottom left */
    289 	coords->samples[2].x = xm;
    290 	coords->samples[2].y = fb.conf.hf_height - ym;
    291 
    292 	/* bottom right */
    293 	coords->samples[3].x = fb.conf.hf_width - xm;
    294 	coords->samples[3].y = fb.conf.hf_height - ym;
    295 
    296 	/* top right */
    297 	coords->samples[4].x = fb.conf.hf_width - xm;
    298 	coords->samples[4].y = ym;
    299 
    300 	tp_setrawmode(tp);
    301 	err = 0;
    302 	for (i = 0; i < coords->samplelen; i++) {
    303 		drawcross(&fb,
    304 		    coords->samples[i].x,
    305 		    coords->samples[i].y,
    306 		    cursize, fb.white);
    307 		fb_flush(&fb);
    308 		tp_flush(tp);
    309 		res = tp_get(tp, &x, &y, check_esc, 0 /* stdin */);
    310 		if (res < 0) {
    311 			err = errno;
    312 			break;
    313 		}
    314 		if (0 < res) {
    315 			fb_dispmode(&fb, WSDISPLAYIO_MODE_EMUL);
    316 			return (-1); /* aborted by user */
    317 		}
    318 		coords->samples[i].rawx = x;
    319 		coords->samples[i].rawy = y;
    320 		drawcross(&fb,
    321 		    coords->samples[i].x,
    322 		    coords->samples[i].y,
    323 		    cursize, fb.black);
    324 		fb_flush(&fb);
    325 		tp_waitup(tp, 200, check_esc, 0 /* stdin */);
    326 	}
    327 
    328 	fb_dispmode(&fb, WSDISPLAYIO_MODE_EMUL);
    329 	close(fbfd);
    330 
    331 	if (opt_verbose) {
    332 		printf("%s: %dx%d (%dbytes/line) %dbit offset=0x%lx\n",
    333 		    getprogname(),
    334 		    fb.conf.hf_width,
    335 		    fb.conf.hf_height,
    336 		    fb.conf.hf_bytes_per_line,
    337 		    fb.conf.hf_pixel_width,
    338 		    fb.conf.hf_offset);
    339 	}
    340 
    341 	if (err) {
    342 		errno = err;
    343 		errx(EXIT_FAILURE, "can't get samples");
    344 	}
    345 
    346 	return (0);
    347 }
    348 
    349 /*
    350  * draw cross cursor on frame buffer
    351  *
    352  * return:	none
    353  */
    354 void
    355 drawcross(struct fb *fb, int x, int y, int size, fb_pixel_t pixel)
    356 {
    357 	size /= 2;
    358 
    359 	fb_drawline(fb, x,     y - size + 1, x,     y - 1,    pixel);
    360 	fb_drawline(fb, x + 1, y - size + 1, x + 1, y - 1,    pixel);
    361 	fb_drawline(fb, x,     y + 2,        x,     y + size, pixel);
    362 	fb_drawline(fb, x + 1, y + 2,        x + 1, y + size, pixel);
    363 
    364 	fb_drawline(fb, x - size + 1, y,     x - 1,    y,     pixel);
    365 	fb_drawline(fb, x - size + 1, y + 1, x - 1,    y + 1, pixel);
    366 	fb_drawline(fb, x + 2,        y,     x + size, y,     pixel);
    367 	fb_drawline(fb, x + 2,        y + 1, x + size, y + 1, pixel);
    368 }
    369 
    370 /*
    371  * check ESC key
    372  *
    373  * date:	input file descriptor
    374  *
    375  * return:	0	nothing has occurred
    376  *		1	ESC key was pressed
    377  *		-1	error
    378  */
    379 int
    380 check_esc(void *data)
    381 {
    382 	int fd = (int)data;
    383 	int flg, n, err;
    384 	char buf[1];
    385 	struct termios tm, raw;
    386 
    387 	if (tcgetattr(fd, &tm) < 0)
    388 		return (-1);
    389 	raw = tm;
    390 	cfmakeraw(&raw);
    391 	if (tcsetattr(fd, TCSANOW, &raw) < 0)
    392 		return (-1);
    393 	if ((flg = fcntl(fd, F_GETFL)) == -1)
    394 		return (-1);
    395 	if (fcntl(fd, F_SETFL, flg | O_NONBLOCK) == -1)
    396 		return (-1);
    397 	n = read(fd, buf, 1);
    398 	err = errno;
    399 	fcntl(fd, F_SETFL, flg);
    400 	tcsetattr(fd, TCSANOW, &tm);
    401 	if (n < 0)
    402 		return (err == EWOULDBLOCK ? 0 : -1);
    403 	if (n == 0)
    404 		return (0); /* EOF */
    405 	if (*buf == 0x1b)
    406 		return (1); /* ESC */
    407 
    408 	return (0);
    409 }
    410