Home | History | Annotate | Line # | Download | only in tpctl
      1  1.8    andvar /*	$NetBSD: main.c,v 1.8 2024/07/12 22:31:40 andvar 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.8    andvar __RCSID("$NetBSD: main.c,v 1.8 2024/07/12 22:31:40 andvar 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.6     joerg 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.8    andvar 	/* load calibration 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.8    andvar 		   specified, do 'calibration' */
    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.8    andvar 	/* save calibration 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.8    andvar  * load calibration 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.8    andvar  * save calibration 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.7  christos 	int fd = (int)(intptr_t)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