xref: /freebsd/tools/test/ppsapi/ppsapitest.c (revision 3d9368b2d03926ad079a2eb910f1a423df925dd5)
1 /*-
2  * Copyright (c) 1998-2003 Poul-Henning Kamp
3  *
4  * Please see src/share/examples/etc/bsd-style-copyright.
5  *
6  */
7 
8 #include <sys/cdefs.h>
9 __FBSDID("$FreeBSD$");
10 
11 #include <stdio.h>
12 #include <stdint.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <fcntl.h>
16 #include <err.h>
17 #include <sys/timepps.h>
18 
19 static int aflag, Aflag, cflag, Cflag, eflag, uflag, vflag;
20 
21 static void
22 Chew(struct timespec *tsa, struct timespec *tsc, unsigned sa, unsigned sc)
23 {
24 	printf("%jd .%09ld %u", (intmax_t)tsa->tv_sec, tsa->tv_nsec, sa);
25 	printf(" %jd .%09ld %u\n", (intmax_t)tsc->tv_sec, tsc->tv_nsec, sc);
26 	if (uflag)
27 		fflush(stdout);
28 }
29 
30 int
31 main(int argc, char **argv)
32 {
33 	int fd;
34 	pps_info_t pi;
35 	pps_params_t pp;
36 	pps_handle_t ph;
37 	int i, mode;
38 	u_int olda, oldc;
39 	struct timespec to;
40 
41 	while ((i = getopt(argc, argv, "aAbBcCeuv")) != -1) {
42 		switch (i) {
43 		case 'a': aflag = 1; break;
44 		case 'A': Aflag = 1; break;
45 		case 'b': aflag = 1; cflag = 1; break;
46 		case 'B': Aflag = 1; Cflag = 1; break;
47 		case 'c': cflag = 1; break;
48 		case 'C': Cflag = 1; break;
49 		case 'e': eflag = 1; break;
50 		case 'u': uflag = 1; break;
51 		case 'v': vflag = 1; break;
52 		case '?':
53 		default:
54 			fprintf(stderr,
55 			    "Usage: ppsapitest [-aAcC] device\n");
56 			exit (1);
57 		}
58 	}
59 	argc -= optind;
60 	argv += optind;
61 	if (argc > 0) {
62 		fd = open(argv[0], O_RDONLY);
63 		if (fd < 0)
64 			err(1, argv[0]);
65 	} else {
66 		fd = 0;
67 	}
68 	i = time_pps_create(fd, &ph);
69 	if (i < 0)
70 		err(1, "time_pps_create");
71 
72 	i = time_pps_getcap(ph, &mode);
73 	if (i < 0)
74 		err(1, "time_pps_getcap");
75 	if (vflag) {
76 		fprintf(stderr, "Supported modebits:");
77 		if (mode & PPS_CAPTUREASSERT)
78 			fprintf(stderr, " CAPTUREASSERT");
79 		if (mode & PPS_CAPTURECLEAR)
80 			fprintf(stderr, " CAPTURECLEAR");
81 		if (mode & PPS_OFFSETASSERT)
82 			fprintf(stderr, " OFFSETASSERT");
83 		if (mode & PPS_OFFSETCLEAR)
84 			fprintf(stderr, " OFFSETCLEAR");
85 		if (mode & PPS_ECHOASSERT)
86 			fprintf(stderr, " ECHOASSERT");
87 		if (mode & PPS_ECHOCLEAR)
88 			fprintf(stderr, " ECHOCLEAR");
89 		if (mode & PPS_CANWAIT)
90 			fprintf(stderr, " CANWAIT");
91 		if (mode & PPS_CANPOLL)
92 			fprintf(stderr, " CANPOLL");
93 		if (mode & PPS_TSFMT_TSPEC)
94 			fprintf(stderr, " TSPEC");
95 		if (mode & PPS_TSFMT_NTPFP)
96 			fprintf(stderr, " NTPFP");
97 		fprintf(stderr, "\n");
98 	}
99 
100 	if (!aflag && !cflag) {
101 		if (mode & PPS_CAPTUREASSERT)
102 			aflag = 1;
103 		if (mode & PPS_CAPTURECLEAR)
104 			cflag = 1;
105 	}
106 	if (!Aflag && !Cflag) {
107 		Aflag = aflag;
108 		Cflag = cflag;
109 	}
110 
111 	if (Cflag && !(mode & PPS_CAPTURECLEAR))
112 		errx(1, "-C but cannot capture on clear flank");
113 
114 	if (Aflag && !(mode & PPS_CAPTUREASSERT))
115 		errx(1, "-A but cannot capture on assert flank");
116 
117 	i = time_pps_getparams(ph, &pp);
118 	if (i < 0)
119 		err(1, "time_pps_getparams():");
120 
121 	if (aflag)
122 		pp.mode |= PPS_CAPTUREASSERT;
123 	if (cflag)
124 		pp.mode |= PPS_CAPTURECLEAR;
125 
126 	if (eflag & aflag)
127 		pp.mode |= PPS_ECHOASSERT;
128 
129 	if (eflag & cflag)
130 		pp.mode |= PPS_ECHOCLEAR;
131 
132 	if (!(pp.mode & PPS_TSFMT_TSPEC))
133 		pp.mode |= PPS_TSFMT_TSPEC;
134 
135 	i = time_pps_setparams(ph, &pp);
136 	if (i < 0) {
137 		err(1, "time_pps_setparams(mode %x):", pp.mode);
138 	}
139 
140 	/*
141 	 * Pick up first event outside the loop in order to not
142 	 * get something ancient into the outfile.
143 	 */
144 	to.tv_nsec = 0;
145 	to.tv_sec = 0;
146 	i = time_pps_fetch(ph, PPS_TSFMT_TSPEC, &pi, &to);
147 	if (i < 0)
148 		err(1, "time_pps_fetch()");
149 	olda = pi.assert_sequence;
150 	oldc = pi.clear_sequence;
151 
152 	while (1) {
153 		to.tv_nsec = 0;
154 		to.tv_sec = 0;
155 		i = time_pps_fetch(ph, PPS_TSFMT_TSPEC, &pi, &to);
156 		if (i < 0)
157 			err(1, "time_pps_fetch()");
158 		if (oldc != pi.clear_sequence && Cflag)
159 			;
160 		else if (olda != pi.assert_sequence && Aflag)
161 			;
162 		else {
163 			usleep(10000);
164 			continue;
165 		}
166 		Chew(&pi.assert_timestamp, &pi.clear_timestamp,
167 			pi.assert_sequence, pi.clear_sequence);
168 		olda = pi.assert_sequence;
169 		oldc = pi.clear_sequence;
170 	}
171 	return(0);
172 }
173