1123303Sphk/*-
2123303Sphk * Copyright (c) 1998-2003 Poul-Henning Kamp
3123303Sphk *
4123303Sphk * Please see src/share/examples/etc/bsd-style-copyright.
5123303Sphk *
6123303Sphk */
7123303Sphk
8123303Sphk#include <sys/cdefs.h>
9123303Sphk__FBSDID("$FreeBSD: stable/11/tools/test/ppsapi/ppsapitest.c 323406 2017-09-11 00:19:09Z ian $");
10123303Sphk
11123303Sphk#include <stdio.h>
12123303Sphk#include <stdint.h>
13123303Sphk#include <stdlib.h>
14123303Sphk#include <unistd.h>
15123303Sphk#include <fcntl.h>
16123303Sphk#include <err.h>
17123303Sphk#include <sys/timepps.h>
18123303Sphk
19123303Sphkstatic int aflag, Aflag, cflag, Cflag, eflag, uflag, vflag;
20123303Sphk
21123303Sphkstatic void
22123303SphkChew(struct timespec *tsa, struct timespec *tsc, unsigned sa, unsigned sc)
23123303Sphk{
24123303Sphk	printf("%jd .%09ld %u", (intmax_t)tsa->tv_sec, tsa->tv_nsec, sa);
25123303Sphk	printf(" %jd .%09ld %u\n", (intmax_t)tsc->tv_sec, tsc->tv_nsec, sc);
26123303Sphk	if (uflag)
27123303Sphk		fflush(stdout);
28123303Sphk}
29123303Sphk
30123303Sphkint
31123303Sphkmain(int argc, char **argv)
32123303Sphk{
33123303Sphk	int fd;
34126820Sphk	FILE *fdo;
35123303Sphk	pps_info_t pi;
36123303Sphk	pps_params_t pp;
37123303Sphk	pps_handle_t ph;
38123303Sphk	int i, mode;
39123303Sphk	u_int olda, oldc;
40123303Sphk	struct timespec to;
41126820Sphk	char const *ofn;
42123303Sphk
43126820Sphk	ofn = NULL;
44126820Sphk	while ((i = getopt(argc, argv, "aAbBcCeo:uv")) != -1) {
45123303Sphk		switch (i) {
46123303Sphk		case 'a': aflag = 1; break;
47123303Sphk		case 'A': Aflag = 1; break;
48123303Sphk		case 'b': aflag = 1; cflag = 1; break;
49123303Sphk		case 'B': Aflag = 1; Cflag = 1; break;
50123303Sphk		case 'c': cflag = 1; break;
51123303Sphk		case 'C': Cflag = 1; break;
52123303Sphk		case 'e': eflag = 1; break;
53126820Sphk		case 'o': ofn = optarg; break;
54123303Sphk		case 'u': uflag = 1; break;
55123303Sphk		case 'v': vflag = 1; break;
56123303Sphk		case '?':
57123303Sphk		default:
58123303Sphk			fprintf(stderr,
59123303Sphk			    "Usage: ppsapitest [-aAcC] device\n");
60123303Sphk			exit (1);
61123303Sphk		}
62123303Sphk	}
63126820Sphk	if (ofn != NULL) {
64126820Sphk		fdo = fopen(ofn, "w");
65126820Sphk		if (fdo == NULL)
66126820Sphk			err(1, "Cannot open %s", ofn);
67126820Sphk	} else {
68126820Sphk		fdo = NULL;
69126820Sphk	}
70123303Sphk	argc -= optind;
71123303Sphk	argv += optind;
72123303Sphk	if (argc > 0) {
73123303Sphk		fd = open(argv[0], O_RDONLY);
74123303Sphk		if (fd < 0)
75323406Sian			err(1, "%s", argv[0]);
76123303Sphk	} else {
77123303Sphk		fd = 0;
78123303Sphk	}
79123303Sphk	i = time_pps_create(fd, &ph);
80123303Sphk	if (i < 0)
81123303Sphk		err(1, "time_pps_create");
82123303Sphk
83123303Sphk	i = time_pps_getcap(ph, &mode);
84123303Sphk	if (i < 0)
85123303Sphk		err(1, "time_pps_getcap");
86123303Sphk	if (vflag) {
87123303Sphk		fprintf(stderr, "Supported modebits:");
88123303Sphk		if (mode & PPS_CAPTUREASSERT)
89123303Sphk			fprintf(stderr, " CAPTUREASSERT");
90123303Sphk		if (mode & PPS_CAPTURECLEAR)
91123303Sphk			fprintf(stderr, " CAPTURECLEAR");
92123303Sphk		if (mode & PPS_OFFSETASSERT)
93123303Sphk			fprintf(stderr, " OFFSETASSERT");
94123303Sphk		if (mode & PPS_OFFSETCLEAR)
95123303Sphk			fprintf(stderr, " OFFSETCLEAR");
96123303Sphk		if (mode & PPS_ECHOASSERT)
97123303Sphk			fprintf(stderr, " ECHOASSERT");
98123303Sphk		if (mode & PPS_ECHOCLEAR)
99123303Sphk			fprintf(stderr, " ECHOCLEAR");
100123303Sphk		if (mode & PPS_CANWAIT)
101123303Sphk			fprintf(stderr, " CANWAIT");
102123303Sphk		if (mode & PPS_CANPOLL)
103123303Sphk			fprintf(stderr, " CANPOLL");
104123303Sphk		if (mode & PPS_TSFMT_TSPEC)
105123303Sphk			fprintf(stderr, " TSPEC");
106123303Sphk		if (mode & PPS_TSFMT_NTPFP)
107123303Sphk			fprintf(stderr, " NTPFP");
108123303Sphk		fprintf(stderr, "\n");
109123303Sphk	}
110123303Sphk
111123303Sphk	if (!aflag && !cflag) {
112123303Sphk		if (mode & PPS_CAPTUREASSERT)
113123303Sphk			aflag = 1;
114123303Sphk		if (mode & PPS_CAPTURECLEAR)
115123303Sphk			cflag = 1;
116123303Sphk	}
117123303Sphk	if (!Aflag && !Cflag) {
118123303Sphk		Aflag = aflag;
119123303Sphk		Cflag = cflag;
120123303Sphk	}
121123303Sphk
122123303Sphk	if (Cflag && !(mode & PPS_CAPTURECLEAR))
123123303Sphk		errx(1, "-C but cannot capture on clear flank");
124123303Sphk
125123303Sphk	if (Aflag && !(mode & PPS_CAPTUREASSERT))
126123303Sphk		errx(1, "-A but cannot capture on assert flank");
127123303Sphk
128123303Sphk	i = time_pps_getparams(ph, &pp);
129123303Sphk	if (i < 0)
130123303Sphk		err(1, "time_pps_getparams():");
131123303Sphk
132123303Sphk	if (aflag)
133123303Sphk		pp.mode |= PPS_CAPTUREASSERT;
134123303Sphk	if (cflag)
135123303Sphk		pp.mode |= PPS_CAPTURECLEAR;
136123303Sphk
137123303Sphk	if (eflag & aflag)
138123303Sphk		pp.mode |= PPS_ECHOASSERT;
139123303Sphk
140123303Sphk	if (eflag & cflag)
141123303Sphk		pp.mode |= PPS_ECHOCLEAR;
142123303Sphk
143123303Sphk	if (!(pp.mode & PPS_TSFMT_TSPEC))
144123303Sphk		pp.mode |= PPS_TSFMT_TSPEC;
145123303Sphk
146123303Sphk	i = time_pps_setparams(ph, &pp);
147123303Sphk	if (i < 0) {
148123303Sphk		err(1, "time_pps_setparams(mode %x):", pp.mode);
149123303Sphk	}
150123303Sphk
151123303Sphk	/*
152123303Sphk	 * Pick up first event outside the loop in order to not
153123303Sphk	 * get something ancient into the outfile.
154123303Sphk	 */
155123303Sphk	to.tv_nsec = 0;
156123303Sphk	to.tv_sec = 0;
157123303Sphk	i = time_pps_fetch(ph, PPS_TSFMT_TSPEC, &pi, &to);
158123303Sphk	if (i < 0)
159123303Sphk		err(1, "time_pps_fetch()");
160123303Sphk	olda = pi.assert_sequence;
161123303Sphk	oldc = pi.clear_sequence;
162123303Sphk
163123303Sphk	while (1) {
164123303Sphk		to.tv_nsec = 0;
165123303Sphk		to.tv_sec = 0;
166123303Sphk		i = time_pps_fetch(ph, PPS_TSFMT_TSPEC, &pi, &to);
167123303Sphk		if (i < 0)
168123303Sphk			err(1, "time_pps_fetch()");
169123303Sphk		if (oldc != pi.clear_sequence && Cflag)
170123303Sphk			;
171123303Sphk		else if (olda != pi.assert_sequence && Aflag)
172123303Sphk			;
173123303Sphk		else {
174123303Sphk			usleep(10000);
175123303Sphk			continue;
176123303Sphk		}
177126820Sphk		if (fdo != NULL) {
178126820Sphk			if (fwrite(&pi, sizeof pi, 1, fdo) != 1)
179126820Sphk				err(1, "Write error on %s", ofn);
180126820Sphk			if (uflag)
181126820Sphk				fflush(fdo);
182126820Sphk		}
183123303Sphk		Chew(&pi.assert_timestamp, &pi.clear_timestamp,
184123303Sphk			pi.assert_sequence, pi.clear_sequence);
185123303Sphk		olda = pi.assert_sequence;
186123303Sphk		oldc = pi.clear_sequence;
187123303Sphk	}
188123303Sphk	return(0);
189123303Sphk}
190