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