int serOpenDev ( serDevT* dev ) { #ifdef ENABLE_TIMEPPS pps_params_t ppsparams; int ppsmode; #endif dev->fd = open ( dev->dev, O_RDONLY|O_NOCTTY ); switch ( dev->mode ) { #ifdef ENABLE_TIMEPPS case SERPORT_MODE_TIMEPPS: if ( time_pps_create ( dev->fd, &dev->ppshandle ) == -1 ) return -1; if ( time_pps_getparams ( dev->ppshandle, &ppsparams ) == -1 ) return -1; ppsparams.mode |= PPS_TSFMT_TSPEC | PPS_CAPTUREBOTH; if ( time_pps_setparams ( dev->ppshandle, &ppsparams ) == -1 ) return -1; if ( time_pps_getcap ( dev->ppshandle, &ppsmode ) == -1 ) return -1; //NOTE: these should probably be error cases, but the code is still experimental and //the PPS support I've used also seems to have problems if ( ! (ppsmode | PPS_CAPTUREASSERT) ) loggerf ( LOGGER_NOTE, "Warning: PPS_CAPTUREASSERT not supported\n" ); if ( ! (ppsmode | PPS_CAPTURECLEAR) ) loggerf ( LOGGER_NOTE, "Warning: PPS_CAPTURECLEAR not supported\n" ); //!!! no point using this - too many problems //1. linux doesn't report PPS_CANWAIT, but can //2. FreeBSD does report PPS_CANWAIT, but can't //(unless its me reading the docs backwards?) // if ( ! (ppsmode | PPS_CANWAIT) ) // loggerf ( LOGGER_NOTE, "Warning: PPS_CANWAIT not supported (linux lies)\n" ); #endif } return dev->fd; }
PPS::PPS(const std::string& dev) { // Linux v2.6 (LinuxPPS) implementation. #if defined(DUNE_SYS_HAS_TIMEPPS_H) // Try to find the source by using the supplied "path" name int rv = open(dev.c_str(), O_RDWR); if (rv < 0) throw std::runtime_error(Utils::String::str("unable to open PPS device '%s'\n", dev.c_str())); // Open the PPS source (and check the file descriptor) rv = time_pps_create(rv, &m_handle); if (rv < 0) throw std::runtime_error(Utils::String::str("cannot create a PPS source from device '%s'\n", dev.c_str())); // Find out what features are supported int mode = 0; rv = time_pps_getcap(m_handle, &mode); if (rv < 0) throw std::runtime_error(Utils::String::str("cannot get capabilities of device '%s'\n", dev.c_str())); if ((mode & PPS_CAPTUREASSERT) == 0) throw std::runtime_error("device does not support CAPTUREASSERT"); if ((mode & PPS_OFFSETASSERT) == 0) throw std::runtime_error("device does not support OFFSETASSERT"); // Capture assert timestamps, and compensate for a 675 nsec // propagation delay. pps_params_t params; rv = time_pps_getparams(m_handle, ¶ms); if (rv < 0) throw std::runtime_error("unable to retrieve parameters"); params.assert_offset.tv_sec = 0; params.assert_offset.tv_nsec = 675; params.mode |= PPS_CAPTUREASSERT | PPS_OFFSETASSERT; params.mode &= ~(PPS_CAPTURECLEAR | PPS_OFFSETCLEAR); rv = time_pps_setparams(m_handle, ¶ms); if (rv < 0) throw std::runtime_error("unable to set parameters"); // Not yet implemented. #else (void)dev; #endif }
int set_pps_parameters(pps_handle_t ph, int capability, int tsclock, pps_params_t *ppsparams) { int mode; int err; mode = 0; if (capability & PPS_CAPTUREASSERT) mode |= PPS_CAPTUREASSERT; if (capability & PPS_CAPTURECLEAR) mode |= PPS_CAPTURECLEAR; if (capability & tsclock) mode |= tsclock; else { fprintf(stdout, "Warning: PPS-API does not support this tsclock: %d\n", tsclock); return (-1); } ppsparams->mode = mode; err = time_pps_setparams(ph, ppsparams); if (err < 0) { fprintf(stderr, "time_pps_setparams\n"); return (err); } err = time_pps_getparams(ph, ppsparams); if (err < 0) { fprintf(stderr, "time_pps_getparams\n"); return (err); } if (mode != ppsparams->mode) { fprintf(stderr, "Inconsistent parameters: mode = %d, pps = %d\n", mode, ppsparams->mode); return (-1); } return (0); }
int main(int argc, char **argv) { int fd; FILE *fdo; pps_info_t pi; pps_params_t pp; pps_handle_t ph; int i, mode; u_int olda, oldc; struct timespec to; char const *ofn; ofn = NULL; while ((i = getopt(argc, argv, "aAbBcCeo:uv")) != -1) { switch (i) { case 'a': aflag = 1; break; case 'A': Aflag = 1; break; case 'b': aflag = 1; cflag = 1; break; case 'B': Aflag = 1; Cflag = 1; break; case 'c': cflag = 1; break; case 'C': Cflag = 1; break; case 'e': eflag = 1; break; case 'o': ofn = optarg; break; case 'u': uflag = 1; break; case 'v': vflag = 1; break; case '?': default: fprintf(stderr, "Usage: ppsapitest [-aAcC] device\n"); exit (1); } } if (ofn != NULL) { fdo = fopen(ofn, "w"); if (fdo == NULL) err(1, "Cannot open %s", ofn); } else { fdo = NULL; } argc -= optind; argv += optind; if (argc > 0) { fd = open(argv[0], O_RDONLY); if (fd < 0) err(1, argv[0]); } else { fd = 0; } i = time_pps_create(fd, &ph); if (i < 0) err(1, "time_pps_create"); i = time_pps_getcap(ph, &mode); if (i < 0) err(1, "time_pps_getcap"); if (vflag) { fprintf(stderr, "Supported modebits:"); if (mode & PPS_CAPTUREASSERT) fprintf(stderr, " CAPTUREASSERT"); if (mode & PPS_CAPTURECLEAR) fprintf(stderr, " CAPTURECLEAR"); if (mode & PPS_OFFSETASSERT) fprintf(stderr, " OFFSETASSERT"); if (mode & PPS_OFFSETCLEAR) fprintf(stderr, " OFFSETCLEAR"); if (mode & PPS_ECHOASSERT) fprintf(stderr, " ECHOASSERT"); if (mode & PPS_ECHOCLEAR) fprintf(stderr, " ECHOCLEAR"); if (mode & PPS_CANWAIT) fprintf(stderr, " CANWAIT"); if (mode & PPS_CANPOLL) fprintf(stderr, " CANPOLL"); if (mode & PPS_TSFMT_TSPEC) fprintf(stderr, " TSPEC"); if (mode & PPS_TSFMT_NTPFP) fprintf(stderr, " NTPFP"); fprintf(stderr, "\n"); } if (!aflag && !cflag) { if (mode & PPS_CAPTUREASSERT) aflag = 1; if (mode & PPS_CAPTURECLEAR) cflag = 1; } if (!Aflag && !Cflag) { Aflag = aflag; Cflag = cflag; } if (Cflag && !(mode & PPS_CAPTURECLEAR)) errx(1, "-C but cannot capture on clear flank"); if (Aflag && !(mode & PPS_CAPTUREASSERT)) errx(1, "-A but cannot capture on assert flank"); i = time_pps_getparams(ph, &pp); if (i < 0) err(1, "time_pps_getparams():"); if (aflag) pp.mode |= PPS_CAPTUREASSERT; if (cflag) pp.mode |= PPS_CAPTURECLEAR; if (eflag & aflag) pp.mode |= PPS_ECHOASSERT; if (eflag & cflag) pp.mode |= PPS_ECHOCLEAR; if (!(pp.mode & PPS_TSFMT_TSPEC)) pp.mode |= PPS_TSFMT_TSPEC; i = time_pps_setparams(ph, &pp); if (i < 0) { err(1, "time_pps_setparams(mode %x):", pp.mode); } /* * Pick up first event outside the loop in order to not * get something ancient into the outfile. */ to.tv_nsec = 0; to.tv_sec = 0; i = time_pps_fetch(ph, PPS_TSFMT_TSPEC, &pi, &to); if (i < 0) err(1, "time_pps_fetch()"); olda = pi.assert_sequence; oldc = pi.clear_sequence; while (1) { to.tv_nsec = 0; to.tv_sec = 0; i = time_pps_fetch(ph, PPS_TSFMT_TSPEC, &pi, &to); if (i < 0) err(1, "time_pps_fetch()"); if (oldc != pi.clear_sequence && Cflag) ; else if (olda != pi.assert_sequence && Aflag) ; else { usleep(10000); continue; } if (fdo != NULL) { if (fwrite(&pi, sizeof pi, 1, fdo) != 1) err(1, "Write error on %s", ofn); if (uflag) fflush(fdo); } Chew(&pi.assert_timestamp, &pi.clear_timestamp, pi.assert_sequence, pi.clear_sequence); olda = pi.assert_sequence; oldc = pi.clear_sequence; } return(0); }