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 FILE *fdo; 35 pps_info_t pi; 36 pps_params_t pp; 37 pps_handle_t ph; 38 int i, mode; 39 u_int olda, oldc; 40 struct timespec to; 41 char const *ofn; 42 43 ofn = NULL; 44 while ((i = getopt(argc, argv, "aAbBcCeo:uv")) != -1) { 45 switch (i) { 46 case 'a': aflag = 1; break; 47 case 'A': Aflag = 1; break; 48 case 'b': aflag = 1; cflag = 1; break; 49 case 'B': Aflag = 1; Cflag = 1; break; 50 case 'c': cflag = 1; break; 51 case 'C': Cflag = 1; break; 52 case 'e': eflag = 1; break; 53 case 'o': ofn = optarg; break; 54 case 'u': uflag = 1; break; 55 case 'v': vflag = 1; break; 56 case '?': 57 default: 58 fprintf(stderr, 59 "Usage: ppsapitest [-aAcC] device\n"); 60 exit (1); 61 } 62 } 63 if (ofn != NULL) { 64 fdo = fopen(ofn, "w"); 65 if (fdo == NULL) 66 err(1, "Cannot open %s", ofn); 67 } else { 68 fdo = NULL; 69 } 70 argc -= optind; 71 argv += optind; 72 if (argc > 0) { 73 fd = open(argv[0], O_RDONLY); 74 if (fd < 0) 75 err(1, argv[0]); 76 } else { 77 fd = 0; 78 } 79 i = time_pps_create(fd, &ph); 80 if (i < 0) 81 err(1, "time_pps_create"); 82 83 i = time_pps_getcap(ph, &mode); 84 if (i < 0) 85 err(1, "time_pps_getcap"); 86 if (vflag) { 87 fprintf(stderr, "Supported modebits:"); 88 if (mode & PPS_CAPTUREASSERT) 89 fprintf(stderr, " CAPTUREASSERT"); 90 if (mode & PPS_CAPTURECLEAR) 91 fprintf(stderr, " CAPTURECLEAR"); 92 if (mode & PPS_OFFSETASSERT) 93 fprintf(stderr, " OFFSETASSERT"); 94 if (mode & PPS_OFFSETCLEAR) 95 fprintf(stderr, " OFFSETCLEAR"); 96 if (mode & PPS_ECHOASSERT) 97 fprintf(stderr, " ECHOASSERT"); 98 if (mode & PPS_ECHOCLEAR) 99 fprintf(stderr, " ECHOCLEAR"); 100 if (mode & PPS_CANWAIT) 101 fprintf(stderr, " CANWAIT"); 102 if (mode & PPS_CANPOLL) 103 fprintf(stderr, " CANPOLL"); 104 if (mode & PPS_TSFMT_TSPEC) 105 fprintf(stderr, " TSPEC"); 106 if (mode & PPS_TSFMT_NTPFP) 107 fprintf(stderr, " NTPFP"); 108 fprintf(stderr, "\n"); 109 } 110 111 if (!aflag && !cflag) { 112 if (mode & PPS_CAPTUREASSERT) 113 aflag = 1; 114 if (mode & PPS_CAPTURECLEAR) 115 cflag = 1; 116 } 117 if (!Aflag && !Cflag) { 118 Aflag = aflag; 119 Cflag = cflag; 120 } 121 122 if (Cflag && !(mode & PPS_CAPTURECLEAR)) 123 errx(1, "-C but cannot capture on clear flank"); 124 125 if (Aflag && !(mode & PPS_CAPTUREASSERT)) 126 errx(1, "-A but cannot capture on assert flank"); 127 128 i = time_pps_getparams(ph, &pp); 129 if (i < 0) 130 err(1, "time_pps_getparams():"); 131 132 if (aflag) 133 pp.mode |= PPS_CAPTUREASSERT; 134 if (cflag) 135 pp.mode |= PPS_CAPTURECLEAR; 136 137 if (eflag & aflag) 138 pp.mode |= PPS_ECHOASSERT; 139 140 if (eflag & cflag) 141 pp.mode |= PPS_ECHOCLEAR; 142 143 if (!(pp.mode & PPS_TSFMT_TSPEC)) 144 pp.mode |= PPS_TSFMT_TSPEC; 145 146 i = time_pps_setparams(ph, &pp); 147 if (i < 0) { 148 err(1, "time_pps_setparams(mode %x):", pp.mode); 149 } 150 151 /* 152 * Pick up first event outside the loop in order to not 153 * get something ancient into the outfile. 154 */ 155 to.tv_nsec = 0; 156 to.tv_sec = 0; 157 i = time_pps_fetch(ph, PPS_TSFMT_TSPEC, &pi, &to); 158 if (i < 0) 159 err(1, "time_pps_fetch()"); 160 olda = pi.assert_sequence; 161 oldc = pi.clear_sequence; 162 163 while (1) { 164 to.tv_nsec = 0; 165 to.tv_sec = 0; 166 i = time_pps_fetch(ph, PPS_TSFMT_TSPEC, &pi, &to); 167 if (i < 0) 168 err(1, "time_pps_fetch()"); 169 if (oldc != pi.clear_sequence && Cflag) 170 ; 171 else if (olda != pi.assert_sequence && Aflag) 172 ; 173 else { 174 usleep(10000); 175 continue; 176 } 177 if (fdo != NULL) { 178 if (fwrite(&pi, sizeof pi, 1, fdo) != 1) 179 err(1, "Write error on %s", ofn); 180 if (uflag) 181 fflush(fdo); 182 } 183 Chew(&pi.assert_timestamp, &pi.clear_timestamp, 184 pi.assert_sequence, pi.clear_sequence); 185 olda = pi.assert_sequence; 186 oldc = pi.clear_sequence; 187 } 188 return(0); 189 } 190