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