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