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