123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- /*
- * Watch a specified serial port for transitions that might be 1PPS.
- *
- * Each output line is the second and nanosecond parts of a timestamp
- * followed by the names of handshake signals then asserted. Off
- * transitions may generate lines with no signals asserted.
- *
- * If you don't see output within a second, use gpsmon or some other
- * equivalent tool to check that your device has satellite lock and is
- * getting fixes before giving up on the possibility of 1PPS.
- *
- * Also, check your cable. Cheap DB9 to DB9 cables such as those
- * issued with UPSes often carry TXD/RXD/GND only, omitting handshake
- * lines such as DCD. Suspect this especially if the cable jacket
- * looks too skinny to hold more than three leads!
- *
- * This code requires only ANSI/POSIX. If it doesn't compile and run
- * on your Unix there is something very wrong with your Unix.
- *
- * This code by ESR, Copyright 2013, under BSD terms.
- * This file is Copyright 2013 by the GPSD project
- * SPDX-License-Identifier: BSD-2-clause
- */
- #include "../include/gpsd_config.h" /* must be before all includes */
- #include <errno.h>
- #include <fcntl.h> /* needed for open() and friends */
- #ifdef HAVE_GETOPT_LONG
- #include <getopt.h>
- #endif
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/ioctl.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <time.h>
- #include <unistd.h>
- #include "../include/timespec.h"
- struct assoc {
- int mask;
- char *string;
- };
- /*
- * Possible pins for PPS: DCD, CTS, RI, DSR. Pinouts:
- *
- * DB9 DB25 Name Full name
- * --- ---- ---- --------------------
- * 3 2 TXD --> Transmit Data
- * 2 3 RXD <-- Receive Data
- * 7 4 RTS --> Request To Send
- * 8 5 CTS <-- Clear To Send
- * 6 6 DSR <-- Data Set Ready
- * 4 20 DTR --> Data Terminal Ready
- * 1 8 DCD <-- Data Carrier Detect
- * 9 22 RI <-- Ring Indicator
- * 5 7 GND Signal ground
- *
- * Note that it only makes sense to wait on handshake lines
- * activated from the receive side (DCE->DTE) here; in this
- * context "DCE" is the GPS. {CD,RI,CTS,DSR} is the
- * entire set of these.
- */
- static const struct assoc hlines[] = {
- {TIOCM_CD, "TIOCM_CD"},
- {TIOCM_RI, "TIOCM_RI"},
- {TIOCM_DSR, "TIOCM_DSR"},
- {TIOCM_CTS, "TIOCM_CTS"},
- };
- static void usage(void)
- {
- (void)fprintf(stderr,
- "usage: ppscheck [OPTIONS] <device>\n\n"
- #ifdef HAVE_GETOPT_LONG
- " --help Show this help, then exit.\n"
- " --version Show version, then exit.\n"
- #endif
- " -? Show this help, then exit.\n"
- " -h Show this help, then exit.\n"
- " -V Show version, then exit.\n");
- exit(1);
- }
- int main(int argc, char *argv[])
- {
- struct timespec ts;
- int fd;
- int ch;
- char ts_buf[TIMESPEC_LEN];
- const char *optstring = "?hV";
- #ifdef HAVE_GETOPT_LONG
- int option_index = 0;
- static struct option long_options[] = {
- {"help", no_argument, NULL, 'h'},
- {"version", no_argument, NULL, 'V' },
- {NULL, 0, NULL, 0},
- };
- #endif
- while (1) {
- #ifdef HAVE_GETOPT_LONG
- ch = getopt_long(argc, argv, optstring, long_options, &option_index);
- #else
- ch = getopt(argc, argv, optstring);
- #endif
- if (ch == -1) {
- break;
- }
- switch(ch){
- case '?':
- case 'h':
- default:
- usage();
- exit(0);
- case 'V':
- (void)printf("%s: %s\n", argv[0], REVISION);
- exit(EXIT_SUCCESS);
- }
- }
- argc -= optind;
- argv += optind;
- if (argc != 1)
- usage();
- fd = open(argv[0], O_RDONLY);
- if (fd == -1) {
- (void)fprintf(stderr,
- "open(%s) failed: %d %.40s\n",
- argv[0], errno, strerror(errno));
- exit(1);
- }
- (void)fprintf(stdout, "# Seconds nanoSecs Signals\n");
- for (;;) {
- if (ioctl(fd, TIOCMIWAIT, TIOCM_CD|TIOCM_DSR|TIOCM_RI|TIOCM_CTS) != 0) {
- (void)fprintf(stderr,
- "PPS ioctl(TIOCMIWAIT) failed: %d %.40s\n",
- errno, strerror(errno));
- break;
- } else {
- const struct assoc *sp;
- int handshakes;
- (void)clock_gettime(CLOCK_REALTIME, &ts);
- (void)ioctl(fd, TIOCMGET, &handshakes);
- (void)fprintf(stdout, "%s",
- timespec_str(&ts, ts_buf, sizeof(ts_buf)));
- for (sp = hlines;
- sp < hlines + sizeof(hlines)/sizeof(hlines[0]);
- sp++)
- if ((handshakes & sp->mask) != 0) {
- (void)fputc(' ', stdout);
- (void)fputs(sp->string, stdout);
- }
- (void)fputc('\n', stdout);
- }
- }
- exit(EXIT_SUCCESS);
- }
- /* end */
- // vim: set expandtab shiftwidth=4
|