xref: /netbsd-src/usr.sbin/tpctl/data.c (revision 50010e742d7715992428e391d175087da72c3fcf)
1*50010e74Snonaka /*	$NetBSD: data.c,v 1.6 2009/04/28 10:57:24 nonaka Exp $	*/
2b8ce6e82Stakemura 
3b8ce6e82Stakemura /*-
4b8ce6e82Stakemura  * Copyright (c) 2002 TAKEMRUA Shin
5b8ce6e82Stakemura  * All rights reserved.
6b8ce6e82Stakemura  *
7b8ce6e82Stakemura  * Redistribution and use in source and binary forms, with or without
8b8ce6e82Stakemura  * modification, are permitted provided that the following conditions
9b8ce6e82Stakemura  * are met:
10b8ce6e82Stakemura  * 1. Redistributions of source code must retain the above copyright
11b8ce6e82Stakemura  *    notice, this list of conditions and the following disclaimer.
12b8ce6e82Stakemura  * 2. Redistributions in binary form must reproduce the above copyright
13b8ce6e82Stakemura  *    notice, this list of conditions and the following disclaimer in the
14b8ce6e82Stakemura  *    documentation and/or other materials provided with the distribution.
155d1469bdSmartin  * 3. Neither the name of The NetBSD Foundation nor the names of its
165d1469bdSmartin  *    contributors may be used to endorse or promote products derived
175d1469bdSmartin  *    from this software without specific prior written permission.
18b8ce6e82Stakemura  *
19b8ce6e82Stakemura  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20b8ce6e82Stakemura  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21b8ce6e82Stakemura  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22b8ce6e82Stakemura  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23b8ce6e82Stakemura  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24b8ce6e82Stakemura  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25b8ce6e82Stakemura  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26b8ce6e82Stakemura  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27b8ce6e82Stakemura  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28b8ce6e82Stakemura  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29b8ce6e82Stakemura  * POSSIBILITY OF SUCH DAMAGE.
30b8ce6e82Stakemura  */
31b8ce6e82Stakemura 
32b8ce6e82Stakemura #include <stdio.h>
33b8ce6e82Stakemura #include <strings.h>
34b8ce6e82Stakemura #include <stdlib.h>
35b8ce6e82Stakemura #include <time.h>
36b8ce6e82Stakemura #include <fcntl.h>
37b8ce6e82Stakemura #include <unistd.h>
38b8ce6e82Stakemura #include <sys/param.h>
39b8ce6e82Stakemura 
40b8ce6e82Stakemura #include "tpctl.h"
41b8ce6e82Stakemura 
42b8ce6e82Stakemura #ifndef lint
43b8ce6e82Stakemura #include <sys/cdefs.h>
44*50010e74Snonaka __RCSID("$NetBSD: data.c,v 1.6 2009/04/28 10:57:24 nonaka Exp $");
45b8ce6e82Stakemura #endif /* not lint */
46b8ce6e82Stakemura 
47b8ce6e82Stakemura static void *
alloc(int size)48b8ce6e82Stakemura alloc(int size)
49b8ce6e82Stakemura {
50b8ce6e82Stakemura 	void *res;
51b8ce6e82Stakemura 
52b8ce6e82Stakemura 	if ((res = malloc(size)) == NULL) {
53b8ce6e82Stakemura 		perror(getprogname());
54b8ce6e82Stakemura 		exit(EXIT_FAILURE);
55b8ce6e82Stakemura 	}
56b8ce6e82Stakemura 
57b8ce6e82Stakemura 	return (res);
58b8ce6e82Stakemura }
59b8ce6e82Stakemura 
60b8ce6e82Stakemura /*
61b8ce6e82Stakemura  * duplicate string
62b8ce6e82Stakemura  * trailing white space will be removed.
63b8ce6e82Stakemura  */
64b8ce6e82Stakemura static char *
strdup_prune(char * s)65b8ce6e82Stakemura strdup_prune(char *s)
66b8ce6e82Stakemura {
67b8ce6e82Stakemura 	char *res, *tail;
68b8ce6e82Stakemura 
69b8ce6e82Stakemura 	tail = &s[strlen(s) - 1];
70b8ce6e82Stakemura 	while (s <= tail && strchr(" \t", *tail) != NULL)
71b8ce6e82Stakemura 		tail--;
72b8ce6e82Stakemura 
73b8ce6e82Stakemura 	res = alloc(tail - s + 2);
74b8ce6e82Stakemura 	memcpy(res, s, tail - s + 1);
75b8ce6e82Stakemura 	res[tail - s + 1] = '\0';
76b8ce6e82Stakemura 
77b8ce6e82Stakemura 	return (res);
78b8ce6e82Stakemura }
79b8ce6e82Stakemura 
80b8ce6e82Stakemura int
init_data(struct tpctl_data * data)81b8ce6e82Stakemura init_data(struct tpctl_data *data)
82b8ce6e82Stakemura {
83b8ce6e82Stakemura 	TAILQ_INIT(&data->list);
84b8ce6e82Stakemura 
85b8ce6e82Stakemura 	return (0);
86b8ce6e82Stakemura }
87b8ce6e82Stakemura 
88b8ce6e82Stakemura int
read_data(const char * filename,struct tpctl_data * data)89*50010e74Snonaka read_data(const char *filename, struct tpctl_data *data)
90b8ce6e82Stakemura {
91b8ce6e82Stakemura 	int res, len, n, i, t;
92b8ce6e82Stakemura 	char buf[MAXDATALEN + 2], *p, *p2;
93b8ce6e82Stakemura 	FILE *fp;
94b8ce6e82Stakemura 	struct tpctl_data_elem *elem;
95b8ce6e82Stakemura 
96b8ce6e82Stakemura 	data->lineno = 0;
97b8ce6e82Stakemura 
98b8ce6e82Stakemura 	if ((fp = fopen(filename, "r")) == NULL)
99b8ce6e82Stakemura 		return (ERR_NOFILE);
100b8ce6e82Stakemura 
101b8ce6e82Stakemura 	while (fgets(buf, sizeof(buf), fp) != NULL) {
102b8ce6e82Stakemura 		data->lineno++;
103b8ce6e82Stakemura 		buf[MAXDATALEN + 1] = '\0';
104b8ce6e82Stakemura 		len = strlen(buf);
105b8ce6e82Stakemura 		if (MAXDATALEN < len) {
106b8ce6e82Stakemura 			res = ERR_SYNTAX;
107b8ce6e82Stakemura 			goto exit_func;
108b8ce6e82Stakemura 		}
109b8ce6e82Stakemura 
110b8ce6e82Stakemura 		/* prune trailing space and newline */;
111b8ce6e82Stakemura 		p = &buf[len - 1];
112b8ce6e82Stakemura 		while (buf <= p && strchr(" \t\n\r", *p) != NULL)
113b8ce6e82Stakemura 			*p-- = '\0';
114b8ce6e82Stakemura 
115b8ce6e82Stakemura 		/* skip space */;
116b8ce6e82Stakemura 		p = buf;
117b8ce6e82Stakemura 		while (*p != '\0' && strchr(" \t", *p) != NULL)
118b8ce6e82Stakemura 			p++;
119b8ce6e82Stakemura 
120b8ce6e82Stakemura 		/* comment or empty line */
121b8ce6e82Stakemura 		if (*p == '#' || *p == '\0') {
122b8ce6e82Stakemura 			elem = alloc(sizeof(*elem));
123b8ce6e82Stakemura 			elem->type = TPCTL_COMMENT;
124b8ce6e82Stakemura 			elem->name = strdup_prune(buf);
125b8ce6e82Stakemura 			TAILQ_INSERT_TAIL(&data->list, elem, link);
126b8ce6e82Stakemura 			continue;
127b8ce6e82Stakemura 		}
128b8ce6e82Stakemura 
129b8ce6e82Stakemura 		/* calibration parameter */
130b8ce6e82Stakemura 		elem = alloc(sizeof(*elem));
131b8ce6e82Stakemura 		elem->type = TPCTL_CALIBCOORDS;
132b8ce6e82Stakemura 		p2 = p;
133b8ce6e82Stakemura 		while (*p2 != ',' && *p2 != '\0')
134b8ce6e82Stakemura 			p2++;
135b8ce6e82Stakemura 		if (*p2 != ',') {
136b8ce6e82Stakemura 			/* missing ',' */
137b8ce6e82Stakemura 			res = ERR_SYNTAX;
138b8ce6e82Stakemura 			free(elem);
139b8ce6e82Stakemura 			goto exit_func;
140b8ce6e82Stakemura 		}
141b8ce6e82Stakemura 		*p2 = '\0';
142b8ce6e82Stakemura 		elem->name = strdup_prune(p);
143b8ce6e82Stakemura 		if (search_data(data, elem->name) != NULL) {
144b8ce6e82Stakemura 			free(elem);
145b8ce6e82Stakemura 			res = ERR_DUPNAME;
146b8ce6e82Stakemura 			goto exit_func;
147b8ce6e82Stakemura 		}
148b8ce6e82Stakemura 		TAILQ_INSERT_TAIL(&data->list, elem, link);
149b8ce6e82Stakemura 		p = p2 + 1;
150b8ce6e82Stakemura 
15156d35e34Stakemura 		/*
15256d35e34Stakemura 		 * minX, maxX, minY, maxY
15356d35e34Stakemura 		 */
15456d35e34Stakemura 		for (i = 0; i < 4; i++) {
15556d35e34Stakemura 			t = strtol(p, &p2, 0);
15656d35e34Stakemura 			if (p == p2) {
15756d35e34Stakemura 				res = ERR_SYNTAX;
15856d35e34Stakemura 				goto exit_func;
15956d35e34Stakemura 			}
16056d35e34Stakemura 			p = p2;
16156d35e34Stakemura 			while (*p != '\0' && strchr(" \t", *p) != NULL)
16256d35e34Stakemura 				p++;
16356d35e34Stakemura 			if (*p != ',') {
16456d35e34Stakemura 				res = ERR_SYNTAX;
16556d35e34Stakemura 				goto exit_func;
16656d35e34Stakemura 			}
16756d35e34Stakemura 			p++;
16856d35e34Stakemura 			switch (i % 4) {
16956d35e34Stakemura 			case 0:
17056d35e34Stakemura 				elem->calibcoords.minx = t;
17156d35e34Stakemura 				break;
17256d35e34Stakemura 			case 1:
17356d35e34Stakemura 				elem->calibcoords.miny = t;
17456d35e34Stakemura 				break;
17556d35e34Stakemura 			case 2:
17656d35e34Stakemura 				elem->calibcoords.maxx = t;
17756d35e34Stakemura 				break;
17856d35e34Stakemura 			case 3:
17956d35e34Stakemura 				elem->calibcoords.maxy = t;
18056d35e34Stakemura 				break;
18156d35e34Stakemura 			}
18256d35e34Stakemura 		}
18356d35e34Stakemura 
18456d35e34Stakemura 		/*
18556d35e34Stakemura 		 * number of samples
18656d35e34Stakemura 		 */
187b8ce6e82Stakemura 		n = strtol(p, &p2, 0);
188b8ce6e82Stakemura 		if (p == p2) {
189b8ce6e82Stakemura 			res = ERR_SYNTAX;
190b8ce6e82Stakemura 			goto exit_func;
191b8ce6e82Stakemura 		}
192b8ce6e82Stakemura 		p = p2;
193b8ce6e82Stakemura 		while (*p != '\0' && strchr(" \t", *p) != NULL)
194b8ce6e82Stakemura 			p++;
195b8ce6e82Stakemura 
196b8ce6e82Stakemura 		if (WSMOUSE_CALIBCOORDS_MAX < n) {
197b8ce6e82Stakemura 			res = ERR_SYNTAX;
198b8ce6e82Stakemura 			goto exit_func;
199b8ce6e82Stakemura 		}
200b8ce6e82Stakemura 		elem->calibcoords.samplelen = n;
20156d35e34Stakemura 
20256d35e34Stakemura 		/*
20356d35e34Stakemura 		 * samples
20456d35e34Stakemura 		 */
205b8ce6e82Stakemura 		for (i = 0; i < n * 4; i++) {
206b8ce6e82Stakemura 			if (*p != ',') {
207b8ce6e82Stakemura 				res = ERR_SYNTAX;
208b8ce6e82Stakemura 				goto exit_func;
209b8ce6e82Stakemura 			}
210b8ce6e82Stakemura 			p++;
211b8ce6e82Stakemura 			t = strtol(p, &p2, 0);
212b8ce6e82Stakemura 			if (p == p2) {
213b8ce6e82Stakemura 				res = ERR_SYNTAX;
214b8ce6e82Stakemura 				goto exit_func;
215b8ce6e82Stakemura 			}
216b8ce6e82Stakemura 			p = p2;
217b8ce6e82Stakemura 			while (*p != '\0' && strchr(" \t", *p) != NULL)
218b8ce6e82Stakemura 				p++;
219b8ce6e82Stakemura 			switch (i % 4) {
220b8ce6e82Stakemura 			case 0:
221b8ce6e82Stakemura 				elem->calibcoords.samples[i / 4].rawx = t;
222b8ce6e82Stakemura 				break;
223b8ce6e82Stakemura 			case 1:
224b8ce6e82Stakemura 				elem->calibcoords.samples[i / 4].rawy = t;
225b8ce6e82Stakemura 				break;
226b8ce6e82Stakemura 			case 2:
227b8ce6e82Stakemura 				elem->calibcoords.samples[i / 4].x = t;
228b8ce6e82Stakemura 				break;
229b8ce6e82Stakemura 			case 3:
230b8ce6e82Stakemura 				elem->calibcoords.samples[i / 4].y = t;
231b8ce6e82Stakemura 				break;
232b8ce6e82Stakemura 			}
233b8ce6e82Stakemura 		}
234b8ce6e82Stakemura 		if (*p != '\0') {
235b8ce6e82Stakemura 			res = ERR_SYNTAX;
236b8ce6e82Stakemura 			goto exit_func;
237b8ce6e82Stakemura 		}
238b8ce6e82Stakemura 	}
239b8ce6e82Stakemura 
240b8ce6e82Stakemura 	if (ferror(fp))
241b8ce6e82Stakemura 		res = ERR_IO;
242b8ce6e82Stakemura 	else
243b8ce6e82Stakemura 		res = ERR_NONE;
244b8ce6e82Stakemura 
245b8ce6e82Stakemura  exit_func:
246b8ce6e82Stakemura 	fclose(fp);
247b8ce6e82Stakemura 	if (res != ERR_NONE) {
248b8ce6e82Stakemura 		free_data(data);
249b8ce6e82Stakemura 	}
250b8ce6e82Stakemura 
251b8ce6e82Stakemura 	return (res);
252b8ce6e82Stakemura }
253b8ce6e82Stakemura 
254b8ce6e82Stakemura int
write_data(const char * filename,struct tpctl_data * data)255*50010e74Snonaka write_data(const char *filename, struct tpctl_data *data)
256b8ce6e82Stakemura {
257b8ce6e82Stakemura 	int res, fd;
258b8ce6e82Stakemura 	FILE *fp;
259b8ce6e82Stakemura 	struct tpctl_data_elem *elem;
260*50010e74Snonaka 	char *p, tempfile[MAXPATHLEN + 1];
261b8ce6e82Stakemura 
26207950b9fShe 	fd = 0;		/* XXXGCC -Wuninitialized [hpcarm] */
26307950b9fShe 
264b8ce6e82Stakemura 	if (filename == NULL) {
265b8ce6e82Stakemura 		fp = stdout;
266b8ce6e82Stakemura 	} else {
267*50010e74Snonaka 		strncpy(tempfile, filename, MAXPATHLEN);
268*50010e74Snonaka 		tempfile[MAXPATHLEN] = '\0';
269*50010e74Snonaka 		if ((p = strrchr(tempfile, '/')) == NULL) {
270*50010e74Snonaka 			strcpy(tempfile, TPCTL_TMP_FILENAME);
271b8ce6e82Stakemura 		} else {
272b8ce6e82Stakemura 			p++;
273b8ce6e82Stakemura 			if (MAXPATHLEN <
274*50010e74Snonaka 			    p - tempfile + strlen(TPCTL_TMP_FILENAME))
275b8ce6e82Stakemura 				return (ERR_NOFILE);/* file name is too long */
276*50010e74Snonaka 			strcat(tempfile, TPCTL_TMP_FILENAME);
277b8ce6e82Stakemura 		}
278*50010e74Snonaka 		if ((fd = open(tempfile, O_RDWR|O_CREAT|O_EXCL, 0644)) < 0) {
279b8ce6e82Stakemura 			fprintf(stderr, "%s: can't create %s\n",
280*50010e74Snonaka 			    getprogname(), tempfile);
281b8ce6e82Stakemura 			return (ERR_NOFILE);
282b8ce6e82Stakemura 		}
283b8ce6e82Stakemura 		if ((fp = fdopen(fd, "w")) == NULL) {
284b8ce6e82Stakemura 			perror("fdopen");
285b8ce6e82Stakemura 			exit(EXIT_FAILURE);
286b8ce6e82Stakemura 		}
287b8ce6e82Stakemura 	}
288b8ce6e82Stakemura 
289b8ce6e82Stakemura 	TAILQ_FOREACH(elem, &data->list, link) {
290b8ce6e82Stakemura 		switch (elem->type) {
291b8ce6e82Stakemura 		case TPCTL_CALIBCOORDS:
292b8ce6e82Stakemura 			write_coords(fp, elem->name, &elem->calibcoords);
293b8ce6e82Stakemura 			break;
294b8ce6e82Stakemura 		case TPCTL_COMMENT:
295b8ce6e82Stakemura 			fprintf(fp, "%s\n", elem->name);
296b8ce6e82Stakemura 			break;
297b8ce6e82Stakemura 		default:
298b8ce6e82Stakemura 			fprintf(stderr, "%s: internal error\n", getprogname());
299b8ce6e82Stakemura 			exit(EXIT_FAILURE);
300b8ce6e82Stakemura 			break;
301b8ce6e82Stakemura 		}
302b8ce6e82Stakemura 	}
303b8ce6e82Stakemura 
304b8ce6e82Stakemura 	if (filename != NULL) {
305b8ce6e82Stakemura 		fclose(fp);
306b8ce6e82Stakemura 		close(fd);
307*50010e74Snonaka 		if (rename(tempfile, filename) < 0) {
308*50010e74Snonaka 			unlink(tempfile);
309b8ce6e82Stakemura 			return (ERR_NOFILE);
310b8ce6e82Stakemura 		}
311b8ce6e82Stakemura 	}
312b8ce6e82Stakemura 	res = ERR_NONE;
313b8ce6e82Stakemura 
314b8ce6e82Stakemura 	return (res);
315b8ce6e82Stakemura }
316b8ce6e82Stakemura 
317b8ce6e82Stakemura void
write_coords(FILE * fp,char * name,struct wsmouse_calibcoords * coords)318b8ce6e82Stakemura write_coords(FILE *fp, char *name, struct wsmouse_calibcoords *coords)
319b8ce6e82Stakemura {
320b8ce6e82Stakemura 	int i;
321b8ce6e82Stakemura 
32256d35e34Stakemura 	fprintf(fp, "%s,%d,%d,%d,%d,%d", name,
32356d35e34Stakemura 		coords->minx, coords->miny,
32456d35e34Stakemura 		coords->maxx, coords->maxy,
32556d35e34Stakemura 		coords->samplelen);
326b8ce6e82Stakemura 	for (i = 0; i < coords->samplelen; i++) {
327b8ce6e82Stakemura 		fprintf(fp, ",%d,%d,%d,%d",
328b8ce6e82Stakemura 		    coords->samples[i].rawx,
329b8ce6e82Stakemura 		    coords->samples[i].rawy,
330b8ce6e82Stakemura 		    coords->samples[i].x,
331b8ce6e82Stakemura 		    coords->samples[i].y);
332b8ce6e82Stakemura 	}
333b8ce6e82Stakemura 	fprintf(fp, "\n");
334b8ce6e82Stakemura }
335b8ce6e82Stakemura 
336b8ce6e82Stakemura void
free_data(struct tpctl_data * data)337b8ce6e82Stakemura free_data(struct tpctl_data *data)
338b8ce6e82Stakemura {
339b8ce6e82Stakemura 	struct tpctl_data_elem *elem;
340b8ce6e82Stakemura 
341b8ce6e82Stakemura 	while (!TAILQ_EMPTY(&data->list)) {
342b8ce6e82Stakemura 		elem = TAILQ_FIRST(&data->list);
343b8ce6e82Stakemura 		TAILQ_REMOVE(&data->list, elem, link);
344b8ce6e82Stakemura 
345b8ce6e82Stakemura 		switch (elem->type) {
346b8ce6e82Stakemura 		case TPCTL_CALIBCOORDS:
347b8ce6e82Stakemura 		case TPCTL_COMMENT:
348b8ce6e82Stakemura 			free(elem->name);
349b8ce6e82Stakemura 			break;
350b8ce6e82Stakemura 		default:
351b8ce6e82Stakemura 			fprintf(stderr, "%s: internal error\n", getprogname());
352b8ce6e82Stakemura 			exit(EXIT_FAILURE);
353b8ce6e82Stakemura 			break;
354b8ce6e82Stakemura 		}
355b8ce6e82Stakemura 	}
356b8ce6e82Stakemura }
357b8ce6e82Stakemura 
358b8ce6e82Stakemura int
replace_data(struct tpctl_data * data,char * name,struct wsmouse_calibcoords * calibcoords)359b8ce6e82Stakemura replace_data(struct tpctl_data *data, char *name, struct wsmouse_calibcoords *calibcoords)
360b8ce6e82Stakemura {
361b8ce6e82Stakemura 	struct tpctl_data_elem *elem;
362b8ce6e82Stakemura 
363b8ce6e82Stakemura 	TAILQ_FOREACH(elem, &data->list, link) {
364b8ce6e82Stakemura 		if (elem->type == TPCTL_CALIBCOORDS &&
365b8ce6e82Stakemura 		    strcmp(name, elem->name) == 0) {
366b8ce6e82Stakemura 			elem->calibcoords = *calibcoords;
367b8ce6e82Stakemura 			return (0);
368b8ce6e82Stakemura 		}
369b8ce6e82Stakemura 	}
370b8ce6e82Stakemura 
371b8ce6e82Stakemura 	elem = alloc(sizeof(*elem));
372b8ce6e82Stakemura 	elem->type = TPCTL_CALIBCOORDS;
373b8ce6e82Stakemura 	elem->name = strdup(name);
374b8ce6e82Stakemura 	elem->calibcoords = *calibcoords;
375b8ce6e82Stakemura 	if (elem->name == NULL) {
376b8ce6e82Stakemura 		perror(getprogname());
377b8ce6e82Stakemura 		exit(EXIT_FAILURE);
378b8ce6e82Stakemura 	}
379b8ce6e82Stakemura 	TAILQ_INSERT_TAIL(&data->list, elem, link);
380b8ce6e82Stakemura 
381b8ce6e82Stakemura 	return (1);
382b8ce6e82Stakemura }
383b8ce6e82Stakemura 
384b8ce6e82Stakemura struct wsmouse_calibcoords *
search_data(struct tpctl_data * data,char * name)385b8ce6e82Stakemura search_data(struct tpctl_data *data, char *name)
386b8ce6e82Stakemura {
387b8ce6e82Stakemura 	struct tpctl_data_elem *elem;
388b8ce6e82Stakemura 
389b8ce6e82Stakemura 	TAILQ_FOREACH(elem, &data->list, link) {
390b8ce6e82Stakemura 		if (elem->type == TPCTL_CALIBCOORDS &&
391b8ce6e82Stakemura 		    strcmp(name, elem->name) == 0) {
392b8ce6e82Stakemura 			return (&elem->calibcoords);
393b8ce6e82Stakemura 		}
394b8ce6e82Stakemura 	}
395b8ce6e82Stakemura 
396b8ce6e82Stakemura 	return (NULL);
397b8ce6e82Stakemura }
398