xref: /freebsd/tools/test/ppsapi/ppsapitest.c (revision 724e52cd0dd6494889b65466e9350632f4d6eaa8)
13d9368b2SPoul-Henning Kamp /*-
23d9368b2SPoul-Henning Kamp  * Copyright (c) 1998-2003 Poul-Henning Kamp
33d9368b2SPoul-Henning Kamp  *
43d9368b2SPoul-Henning Kamp  * Please see src/share/examples/etc/bsd-style-copyright.
53d9368b2SPoul-Henning Kamp  *
63d9368b2SPoul-Henning Kamp  */
73d9368b2SPoul-Henning Kamp 
83d9368b2SPoul-Henning Kamp #include <sys/cdefs.h>
93d9368b2SPoul-Henning Kamp __FBSDID("$FreeBSD$");
103d9368b2SPoul-Henning Kamp 
113d9368b2SPoul-Henning Kamp #include <stdio.h>
123d9368b2SPoul-Henning Kamp #include <stdint.h>
133d9368b2SPoul-Henning Kamp #include <stdlib.h>
143d9368b2SPoul-Henning Kamp #include <unistd.h>
153d9368b2SPoul-Henning Kamp #include <fcntl.h>
163d9368b2SPoul-Henning Kamp #include <err.h>
173d9368b2SPoul-Henning Kamp #include <sys/timepps.h>
183d9368b2SPoul-Henning Kamp 
193d9368b2SPoul-Henning Kamp static int aflag, Aflag, cflag, Cflag, eflag, uflag, vflag;
203d9368b2SPoul-Henning Kamp 
213d9368b2SPoul-Henning Kamp static void
223d9368b2SPoul-Henning Kamp Chew(struct timespec *tsa, struct timespec *tsc, unsigned sa, unsigned sc)
233d9368b2SPoul-Henning Kamp {
243d9368b2SPoul-Henning Kamp 	printf("%jd .%09ld %u", (intmax_t)tsa->tv_sec, tsa->tv_nsec, sa);
253d9368b2SPoul-Henning Kamp 	printf(" %jd .%09ld %u\n", (intmax_t)tsc->tv_sec, tsc->tv_nsec, sc);
263d9368b2SPoul-Henning Kamp 	if (uflag)
273d9368b2SPoul-Henning Kamp 		fflush(stdout);
283d9368b2SPoul-Henning Kamp }
293d9368b2SPoul-Henning Kamp 
303d9368b2SPoul-Henning Kamp int
313d9368b2SPoul-Henning Kamp main(int argc, char **argv)
323d9368b2SPoul-Henning Kamp {
333d9368b2SPoul-Henning Kamp 	int fd;
34724e52cdSPoul-Henning Kamp 	FILE *fdo;
353d9368b2SPoul-Henning Kamp 	pps_info_t pi;
363d9368b2SPoul-Henning Kamp 	pps_params_t pp;
373d9368b2SPoul-Henning Kamp 	pps_handle_t ph;
383d9368b2SPoul-Henning Kamp 	int i, mode;
393d9368b2SPoul-Henning Kamp 	u_int olda, oldc;
403d9368b2SPoul-Henning Kamp 	struct timespec to;
41724e52cdSPoul-Henning Kamp 	char const *ofn;
423d9368b2SPoul-Henning Kamp 
43724e52cdSPoul-Henning Kamp 	ofn = NULL;
44724e52cdSPoul-Henning Kamp 	while ((i = getopt(argc, argv, "aAbBcCeo:uv")) != -1) {
453d9368b2SPoul-Henning Kamp 		switch (i) {
463d9368b2SPoul-Henning Kamp 		case 'a': aflag = 1; break;
473d9368b2SPoul-Henning Kamp 		case 'A': Aflag = 1; break;
483d9368b2SPoul-Henning Kamp 		case 'b': aflag = 1; cflag = 1; break;
493d9368b2SPoul-Henning Kamp 		case 'B': Aflag = 1; Cflag = 1; break;
503d9368b2SPoul-Henning Kamp 		case 'c': cflag = 1; break;
513d9368b2SPoul-Henning Kamp 		case 'C': Cflag = 1; break;
523d9368b2SPoul-Henning Kamp 		case 'e': eflag = 1; break;
53724e52cdSPoul-Henning Kamp 		case 'o': ofn = optarg; break;
543d9368b2SPoul-Henning Kamp 		case 'u': uflag = 1; break;
553d9368b2SPoul-Henning Kamp 		case 'v': vflag = 1; break;
563d9368b2SPoul-Henning Kamp 		case '?':
573d9368b2SPoul-Henning Kamp 		default:
583d9368b2SPoul-Henning Kamp 			fprintf(stderr,
593d9368b2SPoul-Henning Kamp 			    "Usage: ppsapitest [-aAcC] device\n");
603d9368b2SPoul-Henning Kamp 			exit (1);
613d9368b2SPoul-Henning Kamp 		}
623d9368b2SPoul-Henning Kamp 	}
63724e52cdSPoul-Henning Kamp 	if (ofn != NULL) {
64724e52cdSPoul-Henning Kamp 		fdo = fopen(ofn, "w");
65724e52cdSPoul-Henning Kamp 		if (fdo == NULL)
66724e52cdSPoul-Henning Kamp 			err(1, "Cannot open %s", ofn);
67724e52cdSPoul-Henning Kamp 	} else {
68724e52cdSPoul-Henning Kamp 		fdo = NULL;
69724e52cdSPoul-Henning Kamp 	}
703d9368b2SPoul-Henning Kamp 	argc -= optind;
713d9368b2SPoul-Henning Kamp 	argv += optind;
723d9368b2SPoul-Henning Kamp 	if (argc > 0) {
733d9368b2SPoul-Henning Kamp 		fd = open(argv[0], O_RDONLY);
743d9368b2SPoul-Henning Kamp 		if (fd < 0)
753d9368b2SPoul-Henning Kamp 			err(1, argv[0]);
763d9368b2SPoul-Henning Kamp 	} else {
773d9368b2SPoul-Henning Kamp 		fd = 0;
783d9368b2SPoul-Henning Kamp 	}
793d9368b2SPoul-Henning Kamp 	i = time_pps_create(fd, &ph);
803d9368b2SPoul-Henning Kamp 	if (i < 0)
813d9368b2SPoul-Henning Kamp 		err(1, "time_pps_create");
823d9368b2SPoul-Henning Kamp 
833d9368b2SPoul-Henning Kamp 	i = time_pps_getcap(ph, &mode);
843d9368b2SPoul-Henning Kamp 	if (i < 0)
853d9368b2SPoul-Henning Kamp 		err(1, "time_pps_getcap");
863d9368b2SPoul-Henning Kamp 	if (vflag) {
873d9368b2SPoul-Henning Kamp 		fprintf(stderr, "Supported modebits:");
883d9368b2SPoul-Henning Kamp 		if (mode & PPS_CAPTUREASSERT)
893d9368b2SPoul-Henning Kamp 			fprintf(stderr, " CAPTUREASSERT");
903d9368b2SPoul-Henning Kamp 		if (mode & PPS_CAPTURECLEAR)
913d9368b2SPoul-Henning Kamp 			fprintf(stderr, " CAPTURECLEAR");
923d9368b2SPoul-Henning Kamp 		if (mode & PPS_OFFSETASSERT)
933d9368b2SPoul-Henning Kamp 			fprintf(stderr, " OFFSETASSERT");
943d9368b2SPoul-Henning Kamp 		if (mode & PPS_OFFSETCLEAR)
953d9368b2SPoul-Henning Kamp 			fprintf(stderr, " OFFSETCLEAR");
963d9368b2SPoul-Henning Kamp 		if (mode & PPS_ECHOASSERT)
973d9368b2SPoul-Henning Kamp 			fprintf(stderr, " ECHOASSERT");
983d9368b2SPoul-Henning Kamp 		if (mode & PPS_ECHOCLEAR)
993d9368b2SPoul-Henning Kamp 			fprintf(stderr, " ECHOCLEAR");
1003d9368b2SPoul-Henning Kamp 		if (mode & PPS_CANWAIT)
1013d9368b2SPoul-Henning Kamp 			fprintf(stderr, " CANWAIT");
1023d9368b2SPoul-Henning Kamp 		if (mode & PPS_CANPOLL)
1033d9368b2SPoul-Henning Kamp 			fprintf(stderr, " CANPOLL");
1043d9368b2SPoul-Henning Kamp 		if (mode & PPS_TSFMT_TSPEC)
1053d9368b2SPoul-Henning Kamp 			fprintf(stderr, " TSPEC");
1063d9368b2SPoul-Henning Kamp 		if (mode & PPS_TSFMT_NTPFP)
1073d9368b2SPoul-Henning Kamp 			fprintf(stderr, " NTPFP");
1083d9368b2SPoul-Henning Kamp 		fprintf(stderr, "\n");
1093d9368b2SPoul-Henning Kamp 	}
1103d9368b2SPoul-Henning Kamp 
1113d9368b2SPoul-Henning Kamp 	if (!aflag && !cflag) {
1123d9368b2SPoul-Henning Kamp 		if (mode & PPS_CAPTUREASSERT)
1133d9368b2SPoul-Henning Kamp 			aflag = 1;
1143d9368b2SPoul-Henning Kamp 		if (mode & PPS_CAPTURECLEAR)
1153d9368b2SPoul-Henning Kamp 			cflag = 1;
1163d9368b2SPoul-Henning Kamp 	}
1173d9368b2SPoul-Henning Kamp 	if (!Aflag && !Cflag) {
1183d9368b2SPoul-Henning Kamp 		Aflag = aflag;
1193d9368b2SPoul-Henning Kamp 		Cflag = cflag;
1203d9368b2SPoul-Henning Kamp 	}
1213d9368b2SPoul-Henning Kamp 
1223d9368b2SPoul-Henning Kamp 	if (Cflag && !(mode & PPS_CAPTURECLEAR))
1233d9368b2SPoul-Henning Kamp 		errx(1, "-C but cannot capture on clear flank");
1243d9368b2SPoul-Henning Kamp 
1253d9368b2SPoul-Henning Kamp 	if (Aflag && !(mode & PPS_CAPTUREASSERT))
1263d9368b2SPoul-Henning Kamp 		errx(1, "-A but cannot capture on assert flank");
1273d9368b2SPoul-Henning Kamp 
1283d9368b2SPoul-Henning Kamp 	i = time_pps_getparams(ph, &pp);
1293d9368b2SPoul-Henning Kamp 	if (i < 0)
1303d9368b2SPoul-Henning Kamp 		err(1, "time_pps_getparams():");
1313d9368b2SPoul-Henning Kamp 
1323d9368b2SPoul-Henning Kamp 	if (aflag)
1333d9368b2SPoul-Henning Kamp 		pp.mode |= PPS_CAPTUREASSERT;
1343d9368b2SPoul-Henning Kamp 	if (cflag)
1353d9368b2SPoul-Henning Kamp 		pp.mode |= PPS_CAPTURECLEAR;
1363d9368b2SPoul-Henning Kamp 
1373d9368b2SPoul-Henning Kamp 	if (eflag & aflag)
1383d9368b2SPoul-Henning Kamp 		pp.mode |= PPS_ECHOASSERT;
1393d9368b2SPoul-Henning Kamp 
1403d9368b2SPoul-Henning Kamp 	if (eflag & cflag)
1413d9368b2SPoul-Henning Kamp 		pp.mode |= PPS_ECHOCLEAR;
1423d9368b2SPoul-Henning Kamp 
1433d9368b2SPoul-Henning Kamp 	if (!(pp.mode & PPS_TSFMT_TSPEC))
1443d9368b2SPoul-Henning Kamp 		pp.mode |= PPS_TSFMT_TSPEC;
1453d9368b2SPoul-Henning Kamp 
1463d9368b2SPoul-Henning Kamp 	i = time_pps_setparams(ph, &pp);
1473d9368b2SPoul-Henning Kamp 	if (i < 0) {
1483d9368b2SPoul-Henning Kamp 		err(1, "time_pps_setparams(mode %x):", pp.mode);
1493d9368b2SPoul-Henning Kamp 	}
1503d9368b2SPoul-Henning Kamp 
1513d9368b2SPoul-Henning Kamp 	/*
1523d9368b2SPoul-Henning Kamp 	 * Pick up first event outside the loop in order to not
1533d9368b2SPoul-Henning Kamp 	 * get something ancient into the outfile.
1543d9368b2SPoul-Henning Kamp 	 */
1553d9368b2SPoul-Henning Kamp 	to.tv_nsec = 0;
1563d9368b2SPoul-Henning Kamp 	to.tv_sec = 0;
1573d9368b2SPoul-Henning Kamp 	i = time_pps_fetch(ph, PPS_TSFMT_TSPEC, &pi, &to);
1583d9368b2SPoul-Henning Kamp 	if (i < 0)
1593d9368b2SPoul-Henning Kamp 		err(1, "time_pps_fetch()");
1603d9368b2SPoul-Henning Kamp 	olda = pi.assert_sequence;
1613d9368b2SPoul-Henning Kamp 	oldc = pi.clear_sequence;
1623d9368b2SPoul-Henning Kamp 
1633d9368b2SPoul-Henning Kamp 	while (1) {
1643d9368b2SPoul-Henning Kamp 		to.tv_nsec = 0;
1653d9368b2SPoul-Henning Kamp 		to.tv_sec = 0;
1663d9368b2SPoul-Henning Kamp 		i = time_pps_fetch(ph, PPS_TSFMT_TSPEC, &pi, &to);
1673d9368b2SPoul-Henning Kamp 		if (i < 0)
1683d9368b2SPoul-Henning Kamp 			err(1, "time_pps_fetch()");
1693d9368b2SPoul-Henning Kamp 		if (oldc != pi.clear_sequence && Cflag)
1703d9368b2SPoul-Henning Kamp 			;
1713d9368b2SPoul-Henning Kamp 		else if (olda != pi.assert_sequence && Aflag)
1723d9368b2SPoul-Henning Kamp 			;
1733d9368b2SPoul-Henning Kamp 		else {
1743d9368b2SPoul-Henning Kamp 			usleep(10000);
1753d9368b2SPoul-Henning Kamp 			continue;
1763d9368b2SPoul-Henning Kamp 		}
177724e52cdSPoul-Henning Kamp 		if (fdo != NULL) {
178724e52cdSPoul-Henning Kamp 			if (fwrite(&pi, sizeof pi, 1, fdo) != 1)
179724e52cdSPoul-Henning Kamp 				err(1, "Write error on %s", ofn);
180724e52cdSPoul-Henning Kamp 			if (uflag)
181724e52cdSPoul-Henning Kamp 				fflush(fdo);
182724e52cdSPoul-Henning Kamp 		}
1833d9368b2SPoul-Henning Kamp 		Chew(&pi.assert_timestamp, &pi.clear_timestamp,
1843d9368b2SPoul-Henning Kamp 			pi.assert_sequence, pi.clear_sequence);
1853d9368b2SPoul-Henning Kamp 		olda = pi.assert_sequence;
1863d9368b2SPoul-Henning Kamp 		oldc = pi.clear_sequence;
1873d9368b2SPoul-Henning Kamp 	}
1883d9368b2SPoul-Henning Kamp 	return(0);
1893d9368b2SPoul-Henning Kamp }
190