1 /*
2  * ppsthread.c - manage PPS watcher threads
3  *
4  * To enable KPPS, this file needs to be compiled with HAVE_SYS_TIMEPPS_H
5  *
6  * If you are not good at threads do not touch this file!
7  * For example: errno is thread safe; strerror() is not.
8  *
9  * It helps to know that there are two PPS measurement methods in
10  * play.  One is defined by RFC2783 and typically implemented in the
11  * kernel.  It is available on FreeBSD, Linux, and NetBSD.  In gpsd it
12  * is referred to as KPPS.  KPPS is accessed on Linux via /dev/ppsN
13  * devices.  On BSD it is accessed via the same device as the serial
14  * port.  This mechanism is preferred as it should provide the smallest
15  * latency and jitter from control line transition to timestamp.
16  *
17  * The other mechanism is user-space PPS, which uses the (not
18  * standardized) TIOCMIWAIT ioctl to wait for PPS transitions on
19  * serial port control lines.  It is implemented on Linux and OpenBSD.
20  *
21  * On Linux, RFC2783 PPS requires root permissions for initialization;
22  * user-space PPS does not.  User-space PPS loses some functionality
23  * when not initialized as root.  In gpsd, user-space PPS is referred
24  * to as "plain PPS".
25  *
26  * On {Free,Net}BSD, RFC2783 PPS should only require access to the
27  * serial port, but details have not yet been tested and documented
28  * here.
29  *
30  * Note that for easy debugging all logging from this file is prefixed
31  * with PPS or KPPS.
32  *
33  * To use the thread manager, you need to first fill in the
34  * devicefd, devicename, and the four hook function members in the thread
35  * context structure. The void *context member is available for your hook
36  * functions to use; the thread-monitor code doesn't touch it.
37  *
38  * After this setup, you can call pps_thread_activate() and the
39  * thread will launch.  It is OK to do this before the device is open,
40  * the thread will wait on that.
41  *
42  * WARNING!  Loss of precision
43  * UNIX time to nanoSec precision is 62 significant bits
44  * UNIX time to nanoSec precision after 2038 is 63 bits
45  * a double is only 53 significant bits.
46  *
47  * You cannot do PPS math with doubles
48  *
49  * This file is Copyright (c)2013-2019 by the GPSD project
50  * SPDX-License-Identifier: BSD-2-clause
51  */
52 
53 #include "gpsd_config.h"  /* must be before all includes */
54 
55 #include <errno.h>
56 #include <inttypes.h>
57 #include <limits.h>
58 #include <math.h>
59 #include <pthread.h>            /* pacifies OpenBSD's compiler */
60 #include <stdbool.h>
61 #include <stdio.h>
62 #include <string.h>
63 #include <sys/socket.h>
64 #include <sys/time.h>
65 #include <unistd.h>
66 
67 /* use RFC 2783 PPS API */
68 /* this needs linux >= 2.6.34 and
69  * CONFIG_PPS=y
70  * CONFIG_PPS_DEBUG=y  [optional to kernel log pulses]
71  * CONFIG_PPS_CLIENT_LDISC=y
72  *
73  * Also beware that setting
74  * CONFIG_PPS_CLIENT_KTIMER=y
75  * adds a fake software-generated PPS intended for testing.  This
76  * doesn't even run at exactly 1Hz, so any attempt to use it for
77  * real timing is disastrous.  Hence we try to avoid it.
78  */
79 #define FAKE_PPS_NAME "ktimer"
80 
81 #if defined(HAVE_SYS_TIMEPPS_H)
82 // include unistd.h here as it is missing on older pps-tools releases.
83 // 'close' is not defined otherwise.
84 #include <unistd.h>
85 #include <sys/timepps.h>
86 #endif
87 
88 #include "timespec.h"
89 #include "ppsthread.h"
90 #include "os_compat.h"
91 
92 /*
93  * Tell GCC that we want thread-safe behavior with _REENTRANT;
94  * in particular, errno must be thread-local.
95  * Tell POSIX-conforming implementations with _POSIX_THREAD_SAFE_FUNCTIONS.
96  * See http://www.unix.org/whitepapers/reentrant.html
97  */
98 #ifndef _REENTRANT
99 #define _REENTRANT
100 #endif
101 #ifndef _POSIX_THREAD_SAFE_FUNCTIONS
102 #define _POSIX_THREAD_SAFE_FUNCTIONS
103 #endif
104 
105 /*
106  * Warning: This is a potential portability problem.
107  * It's needed so that TIOCMIWAIT will be defined and the plain PPS
108  * code will work, but it's not a SuS/POSIX standard header.  We're
109  * going to include it unconditionally here because we expect both
110  * Linux and BSD to have it and we want compilation to break with
111  * an audible snapping sound if it's not present.
112  */
113 #include <sys/ioctl.h>
114 
115 #if defined(HAVE_SYS_TIMEPPS_H)
116 #include <glob.h>
117 #include <fcntl.h>      /* needed for open() and friends */
118 #endif
119 
120 #if defined(TIOCMIWAIT)
121 static int get_edge_tiocmiwait( volatile struct pps_thread_t *,
122                          struct timespec *, int *,
123                          volatile struct timedelta_t *);
124 #endif /* TIOCMIWAIT */
125 
126 struct inner_context_t {
127     volatile struct pps_thread_t        *pps_thread;
128     bool pps_canwait;                   /* can RFC2783 wait? */
129 #if defined(HAVE_SYS_TIMEPPS_H)
130     int pps_caps;                       /* RFC2783 getcaps() */
131     pps_handle_t kernelpps_handle;
132 #endif /* defined(HAVE_SYS_TIMEPPS_H) */
133 };
134 
135 #if defined(HAVE_SYS_TIMEPPS_H)
136 static int get_edge_rfc2783(struct inner_context_t *,
137                          struct timespec *,
138                          int *,
139                          struct timespec *,
140                          int *,
141                          volatile struct timedelta_t *);
142 #endif  /* defined(HAVE_SYS_TIMEPPS_H) */
143 
144 static pthread_mutex_t ppslast_mutex = PTHREAD_MUTEX_INITIALIZER;
145 
146 /*
147  * Version of strerror_r() which explicitly ignores the return value.
148  * This is needed to avoid warnings from some overly pedantic compilers.
149  * Unfortunately, the return type is platform-dependent, making it
150  * impractical to actually use the return value.
151  */
pps_strerror_r(int errnum,char * buf,size_t len)152 static void pps_strerror_r(int errnum, char *buf, size_t len)
153 {
154     if (strerror_r(errnum, buf, len)) {
155         return;
156     } else {
157         return;
158     }
159 }
160 
thread_lock(volatile struct pps_thread_t * pps_thread)161 static void thread_lock(volatile struct pps_thread_t *pps_thread)
162 {
163     int pthread_err = pthread_mutex_lock(&ppslast_mutex);
164     if ( 0 != pthread_err ) {
165         char errbuf[BUFSIZ] = "unknown error";
166         pps_strerror_r(errno, errbuf, sizeof(errbuf));
167         pps_thread->log_hook(pps_thread, THREAD_ERROR,
168                 "PPS:%s pthread_mutex_lock() : %s\n",
169                 pps_thread->devicename, errbuf);
170     }
171 }
172 
thread_unlock(volatile struct pps_thread_t * pps_thread)173 static void thread_unlock(volatile struct pps_thread_t *pps_thread)
174 {
175     int pthread_err = pthread_mutex_unlock(&ppslast_mutex);
176     if ( 0 != pthread_err ) {
177         char errbuf[BUFSIZ] = "unknown error";
178         pps_strerror_r(errno, errbuf, sizeof(errbuf));
179         pps_thread->log_hook(pps_thread, THREAD_ERROR,
180                     "TPPS:%s pthread_mutex_unlock() : %s\n",
181                     pps_thread->devicename, errno, errbuf);
182     }
183 }
184 
185 #if defined(HAVE_SYS_TIMEPPS_H)
186 #ifdef __linux__
187 /* Obtain contents of specified sysfs variable; null string if failure */
get_sysfs_var(const char * path,char * buf,size_t bufsize)188 static void get_sysfs_var(const char *path, char *buf, size_t bufsize)
189 {
190     buf[0] = '\0';
191     int fd = open(path, O_RDONLY);
192     if ( 0 <= fd ) {
193         ssize_t r = read( fd, buf, bufsize -1);
194         if ( 0 < r ) {
195             buf[r - 1] = '\0'; /* remove trailing \x0a */
196         }
197         (void)close(fd);
198     }
199 }
200 
201 /* Check to see whether the named PPS source is the fake one */
pps_check_fake(const char * name)202 int pps_check_fake(const char *name) {
203     char path[PATH_MAX] = "";
204     char buf[32] = "";
205     snprintf(path, sizeof(path), "/sys/devices/virtual/pps/%s/name", name);
206     get_sysfs_var(path, buf, sizeof(buf));
207     return strcmp(buf, FAKE_PPS_NAME) == 0;
208 }
209 
210 /* Get first "real" PPS device, skipping the fake, if any */
pps_get_first(void)211 char *pps_get_first(void)
212 {
213     if (pps_check_fake("pps0"))
214         return "/dev/pps1";
215     return "/dev/pps0";
216 }
217 #endif /* __linux__ */
218 
init_kernel_pps(struct inner_context_t * inner_context)219 static int init_kernel_pps(struct inner_context_t *inner_context)
220 /* return handle for kernel pps, or -1; requires root privileges */
221 {
222     pps_params_t pp;
223     int ret;
224 #ifdef __linux__
225     /* These variables are only needed by Linux to find /dev/ppsN. */
226     int ldisc = 18;   /* the PPS line discipline */
227     glob_t globbuf;
228 #endif
229     char path[PATH_MAX] = "";
230     volatile struct pps_thread_t *pps_thread = inner_context->pps_thread;
231 
232     inner_context->kernelpps_handle = -1;
233     inner_context->pps_canwait = false;
234 
235     /*
236      * This next code block abuses "ret" by storing the filedescriptor
237      * to use for RFC2783 calls.
238      */
239 #ifndef __clang_analyzer__
240     ret = -1;  /* this ret will not be unneeded when the 'else' part
241                 * of the followinng ifdef becomes an #elif */
242 #endif /* __clang_analyzer__ */
243 #ifdef __linux__
244     /*
245      * Some Linuxes, like the RasPi's, have PPS devices preexisting.
246      * Other OS have no way to automatically determine the proper /dev/ppsX.
247      * Allow user to pass in an explicit PPS device path.
248      *
249      * (We use strncpy() here because this might be compiled where
250      * strlcpy() is not available.)
251      */
252     if (strncmp(pps_thread->devicename, "/dev/pps", 8) == 0) {
253         if (pps_check_fake(pps_thread->devicename + 5))
254             pps_thread->log_hook(pps_thread, THREAD_WARN,
255                                  "KPPS:%s is fake PPS,"
256                                  " timing will be inaccurate\n",
257                                  pps_thread->devicename);
258         (void)strncpy(path, pps_thread->devicename, sizeof(path)-1);
259     }
260     else {
261         char pps_num = '\0';  /* /dev/pps[pps_num] is our device */
262         size_t i;             /* to match type of globbuf.gl_pathc */
263         /*
264          * Otherwise one must make calls to associate a serial port with a
265          * /dev/ppsN device and then grovel in system data to determine
266          * the association.
267          */
268 
269         /* Attach the line PPS discipline, so no need to ldattach */
270         /* This activates the magic /dev/pps0 device */
271         /* Note: this ioctl() requires root, and device is a tty */
272         if ( 0 > ioctl(pps_thread->devicefd, TIOCSETD, &ldisc)) {
273             char errbuf[BUFSIZ] = "unknown error";
274             pps_strerror_r(errno, errbuf, sizeof(errbuf));
275             pps_thread->log_hook(pps_thread, THREAD_INF,
276                                  "KPPS:%s cannot set PPS line discipline %s\n",
277                                  pps_thread->devicename, errbuf);
278             return -1;
279         }
280 
281         /* uh, oh, magic file names!, RFC2783 neglects to specify how
282          * to associate the serial device and pps device names */
283         /* need to look in /sys/devices/virtual/pps/pps?/path
284          * (/sys/class/pps/pps?/path is just a link to that)
285          * to find the /dev/pps? that matches our serial port.
286          * this code fails if there are more then 10 pps devices.
287          *
288          * yes, this could be done with libsysfs, but trying to keep
289          * the number of required libs small, and libsysfs would still
290          * be linux only */
291         memset( (void *)&globbuf, 0, sizeof(globbuf));
292         (void)glob("/sys/devices/virtual/pps/pps?/path", 0, NULL, &globbuf);
293 
294         memset( (void *)&path, 0, sizeof(path));
295         for ( i = 0; i < globbuf.gl_pathc; i++ ) {
296             get_sysfs_var(globbuf.gl_pathv[i], path, sizeof(path));
297             pps_thread->log_hook(pps_thread, THREAD_PROG,
298                                  "KPPS:%s checking %s, %s\n",
299                                  pps_thread->devicename,
300                                  globbuf.gl_pathv[i], path);
301             if ( 0 == strncmp( path, pps_thread->devicename, sizeof(path))) {
302                 /* this is the pps we are looking for */
303                 /* FIXME, now build the proper pps device path */
304                 pps_num = globbuf.gl_pathv[i][28];
305                 break;
306             }
307             memset( (void *)&path, 0, sizeof(path));
308         }
309         /* done with blob, clear it */
310         globfree(&globbuf);
311 
312         if ( 0 == (int)pps_num ) {
313             pps_thread->log_hook(pps_thread, THREAD_INF,
314                                  "KPPS:%s device not found.\n",
315                                  pps_thread->devicename);
316             return -1;
317         }
318         /* construct the magic device path */
319         (void)snprintf(path, sizeof(path), "/dev/pps%c", pps_num);
320     }
321 
322     /* root privs are probably required for this device open
323      * do not bother to check uid, just go for the open() */
324 
325     ret = open(path, O_RDWR);
326     if ( 0 > ret ) {
327         char errbuf[BUFSIZ] = "unknown error";
328         pps_strerror_r(errno, errbuf, sizeof(errbuf));
329         pps_thread->log_hook(pps_thread, THREAD_INF,
330                     "KPPS:%s running as %d/%d, cannot open %s: %s\n",
331                     pps_thread->devicename,
332                     getuid(), geteuid(),
333                     path, errbuf);
334         return -1;
335     }
336 #else /* not __linux__ */
337     /*
338      * On BSDs that support RFC2783, one uses the API calls on serial
339      * port file descriptor.
340      *
341      * FIXME! need more specific than 'not linux'
342      */
343     (void)strlcpy(path, pps_thread->devicename, sizeof(path));
344     // cppcheck-suppress redundantAssignment
345     ret  = pps_thread->devicefd;
346 #endif
347     /* assert(ret >= 0); */
348     pps_thread->log_hook(pps_thread, THREAD_INF,
349                 "KPPS:%s RFC2783 path:%s, fd is %d\n",
350                 pps_thread->devicename, path,
351                 ret);
352 
353     /* RFC 2783 implies the time_pps_setcap() needs priviledges *
354      * keep root a tad longer just in case */
355     if ( 0 > time_pps_create(ret, (pps_handle_t *)&inner_context->kernelpps_handle )) {
356         char errbuf[BUFSIZ] = "unknown error";
357         pps_strerror_r(errno, errbuf, sizeof(errbuf));
358         pps_thread->log_hook(pps_thread, THREAD_INF,
359                     "KPPS:%s time_pps_create(%d) failed: %s\n",
360                     pps_thread->devicename,
361                     ret, errbuf);
362         return -1;
363     }
364 
365     /* have kernel PPS handle */
366     /* get RFC2783 features supported */
367     inner_context->pps_caps = 0;
368     if ( 0 > time_pps_getcap(inner_context->kernelpps_handle,
369                                 &inner_context->pps_caps)) {
370         char errbuf[BUFSIZ] = "unknown error";
371         inner_context->pps_caps = 0;
372         pps_strerror_r(errno, errbuf, sizeof(errbuf));
373         pps_thread->log_hook(pps_thread, THREAD_INF,
374                     "KPPS:%s time_pps_getcap() failed: %.100s\n",
375                     pps_thread->devicename, errbuf);
376         return -1;
377     } else {
378         pps_thread->log_hook(pps_thread, THREAD_INF,
379                     "KPPS:%s pps_caps 0x%02X\n",
380                     pps_thread->devicename,
381                     inner_context->pps_caps);
382     }
383 
384     /* construct the setparms structure */
385     memset( (void *)&pp, 0, sizeof(pps_params_t));
386     pp.api_version = PPS_API_VERS_1;  /* version 1 protocol */
387     if ( 0 == (PPS_TSFMT_TSPEC & inner_context->pps_caps ) ) {
388        /* PPS_TSFMT_TSPEC means return a timespec
389         * mandatory for driver to implement, require it */
390         pps_thread->log_hook(pps_thread, THREAD_WARN,
391                     "KPPS:%s fail, missing mandatory PPS_TSFMT_TSPEC\n",
392                     pps_thread->devicename);
393         return -1;
394     }
395     if ( 0 != (PPS_CANWAIT & inner_context->pps_caps ) ) {
396        /* we can wait! so no need for TIOCMIWAIT */
397        pps_thread->log_hook(pps_thread, THREAD_INF,
398                    "KPPS:%s have PPS_CANWAIT\n",
399                    pps_thread->devicename);
400         inner_context->pps_canwait = true;
401     }
402 
403     pp.mode = PPS_TSFMT_TSPEC;
404     switch ( (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR) & inner_context->pps_caps ) {
405     case PPS_CAPTUREASSERT:
406         pps_thread->log_hook(pps_thread, THREAD_WARN,
407                     "KPPS:%s missing PPS_CAPTURECLEAR, pulse may be offset\n",
408                     pps_thread->devicename);
409         pp.mode |= PPS_CAPTUREASSERT;
410         break;
411     case PPS_CAPTURECLEAR:
412         pps_thread->log_hook(pps_thread, THREAD_WARN,
413                     "KPPS:%s missing PPS_CAPTUREASSERT, pulse may be offset\n",
414                     pps_thread->devicename);
415         pp.mode |= PPS_CAPTURECLEAR;
416         break;
417     case PPS_CAPTUREASSERT | PPS_CAPTURECLEAR:
418         pp.mode |= PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
419         break;
420     default:
421         /* THREAD_ERR in the calling routine */
422         pps_thread->log_hook(pps_thread, THREAD_INF,
423                     "KPPS:%s missing PPS_CAPTUREASSERT and CLEAR\n",
424                     pps_thread->devicename);
425         return -1;
426     }
427 
428     if ( 0 > time_pps_setparams(inner_context->kernelpps_handle, &pp)) {
429         char errbuf[BUFSIZ] = "unknown error";
430         pps_strerror_r(errno, errbuf, sizeof(errbuf));
431         pps_thread->log_hook(pps_thread, THREAD_ERROR,
432             "KPPS:%s time_pps_setparams(mode=0x%02X) failed: %s\n",
433             pps_thread->devicename, pp.mode,
434             errbuf);
435         (void)time_pps_destroy(inner_context->kernelpps_handle);
436         return -1;
437     }
438     return 0;
439 }
440 #endif /* defined(HAVE_SYS_TIMEPPS_H) */
441 
442 #if defined(TIOCMIWAIT)
443 /* wait for, and get, an edge using TIOCMIWAIT
444  * return -1 for error
445  *         0 for OK
446  */
get_edge_tiocmiwait(volatile struct pps_thread_t * thread_context,struct timespec * clock_ts,int * state,volatile struct timedelta_t * last_fixtime)447 static int get_edge_tiocmiwait( volatile struct pps_thread_t *thread_context,
448                          struct timespec *clock_ts,
449                          int *state,
450                          volatile struct timedelta_t *last_fixtime)
451 {
452     char ts_str[TIMESPEC_LEN];
453 
454     /* we are lucky to have TIOCMIWAIT, so wait for next edge */
455     #define PPS_LINE_TIOC (TIOCM_CD|TIOCM_RI|TIOCM_CTS|TIOCM_DSR)
456     /*
457      * DB9  DB25  Name      Full name
458      * ---  ----  ----      --------------------
459      *  3     2    TXD  --> Transmit Data
460      *  2     3    RXD  <-- Receive Data
461      *  7     4    RTS  --> Request To Send
462      *  8     5    CTS  <-- Clear To Send
463      *  6     6    DSR  <-- Data Set Ready
464      *  4    20    DTR  --> Data Terminal Ready
465      *  1     8    DCD  <-- Data Carrier Detect
466      *  9    22    RI   <-- Ring Indicator
467      *  5     7    GND      Signal ground
468      *
469      * Wait for status change on any handshake line.  Just one edge,
470      * we do not want to be spinning waiting for the trailing edge of
471      * a pulse. The only assumption here is that no GPS lights up more
472      * than one of these pins.  By waiting on all of them we remove a
473      * configuration switch.
474      *
475      * Note that it only makes sense to wait on handshake lines
476      * activated from the receive side (DCE->DTE) here; in this
477      * context "DCE" is the GPS. {CD,RI,CTS,DSR} is the
478      * entire set of these.
479      *
480      */
481 
482     if (ioctl(thread_context->devicefd, TIOCMIWAIT, PPS_LINE_TIOC) != 0) {
483         char errbuf[BUFSIZ] = "unknown error";
484         pps_strerror_r(errno, errbuf, sizeof(errbuf));
485         thread_context->log_hook(thread_context, THREAD_WARN,
486                 "TPPS:%s ioctl(TIOCMIWAIT) failed: %d %.40s\n",
487                 thread_context->devicename, errno, errbuf);
488         return -1;;
489     }
490 
491     /*
492      * Start of time critical section
493      * Only error reporting, not success reporting in critical section
494      */
495 
496     /* duplicate copy in get_edge_rfc2783 */
497     /* quick, grab a copy of last_fixtime before it changes */
498     thread_lock(thread_context);
499     *last_fixtime = thread_context->fix_in;
500     thread_unlock(thread_context);
501     /* end duplicate copy in get_edge_rfc2783 */
502 
503     /* get the time after we just woke up */
504     if ( 0 > clock_gettime(CLOCK_REALTIME, clock_ts) ) {
505         /* uh, oh, can not get time! */
506         char errbuf[BUFSIZ] = "unknown error";
507         pps_strerror_r(errno, errbuf, sizeof(errbuf));
508         thread_context->log_hook(thread_context, THREAD_ERROR,
509                     "TPPS:%s clock_gettime() failed: %.100s\n",
510                     thread_context->devicename, errbuf);
511         return -1;;
512     }
513 
514     /* got the edge, got the time just after the edge, now quickly
515      * get the edge state */
516     if (ioctl(thread_context->devicefd, (unsigned long)TIOCMGET, state) != 0) {
517         char errbuf[BUFSIZ] = "unknown error";
518         pps_strerror_r(errno, errbuf, sizeof(errbuf));
519         thread_context->log_hook(thread_context, THREAD_ERROR,
520                     "TPPS:%s ioctl(TIOCMGET) failed: %.100s\n",
521                     thread_context->devicename, errbuf);
522         return -1;
523     }
524     /* end of time critical section */
525     /* mask for monitored lines */
526 
527     *state &= PPS_LINE_TIOC;
528 
529     thread_context->log_hook(thread_context, THREAD_PROG,
530                 "TPPS:%s ioctl(TIOCMIWAIT) succeeded, time:%s,  state: %d\n",
531                 thread_context->devicename,
532                 timespec_str(clock_ts, ts_str, sizeof(ts_str)),
533                 *state);
534 
535     return 0;
536 }
537 
538 #endif /* TIOCMIWAIT */
539 
540 #if defined(HAVE_SYS_TIMEPPS_H)
541 /* wait for, and get, last two edges using RFC2783
542  * return -1 for error
543  *         0 for OK
544  *         1 no edge found, continue
545  *
546  * on a quad core 2.4GHz Xeon using KPPS timestamp instead of plain
547  * PPS timestamp removes about 20uS of latency, and about +/-5uS
548  * of jitter
549  */
get_edge_rfc2783(struct inner_context_t * inner_context,struct timespec * prev_clock_ts,int * prev_edge,struct timespec * clock_ts,int * edge,volatile struct timedelta_t * last_fixtime)550 static int get_edge_rfc2783(struct inner_context_t *inner_context,
551                          struct timespec *prev_clock_ts,
552                          int *prev_edge,
553                          struct timespec *clock_ts,
554                          int *edge,
555                          volatile struct timedelta_t *last_fixtime)
556 {
557     pps_info_t pi;
558     char ts_str1[TIMESPEC_LEN], ts_str2[TIMESPEC_LEN];
559     struct timespec kernelpps_tv;
560     volatile struct pps_thread_t *thread_context = inner_context->pps_thread;
561 
562     if ( inner_context->pps_canwait ) {
563         /*
564          * RFC2783 specifies that a NULL timeval means to wait, if
565          * PPS_CANWAIT is available.
566          *
567          * since we pps_canwait, we skipped the TIOMCIWAIT
568          *
569          * 3 second time out, some GPS output 0.5Hz and some RFC2783
570          * can only trigger on one edge
571          * a better and more complex solution would be to wait
572          * for 1/20 second and suffer the cycles
573          */
574         kernelpps_tv.tv_sec = 3;
575         kernelpps_tv.tv_nsec = 0;
576     } else {
577         /*
578          * We use of a non-NULL zero timespec here,
579          * which means to return immediately with -1 (section
580          * 3.4.3).  This is because we know we just got a pulse because
581          * TIOCMIWAIT just woke up.
582          * The timestamp has already been captured in the kernel, and we
583          * are merely fetching it here.
584          */
585         memset( (void *)&kernelpps_tv, 0, sizeof(kernelpps_tv));
586     }
587     memset( (void *)&pi, 0, sizeof(pi)); /* paranoia */
588     if ( 0 > time_pps_fetch(inner_context->kernelpps_handle, PPS_TSFMT_TSPEC
589         , &pi, &kernelpps_tv)) {
590 
591         char errbuf[BUFSIZ] = "unknown error";
592         pps_strerror_r(errno, errbuf, sizeof(errbuf));
593         if ( ETIMEDOUT == errno || EINTR == errno ) {
594                 /* just a timeout */
595                 thread_context->log_hook(thread_context, THREAD_INF,
596                             "KPPS:%s kernel PPS timeout %s\n",
597                             thread_context->devicename, errbuf);
598                 return 1;
599         }
600         thread_context->log_hook(thread_context, THREAD_WARN,
601                     "KPPS:%s kernel PPS failed %s\n",
602                     thread_context->devicename, errbuf);
603         return 0;
604     }
605     if ( inner_context->pps_canwait ) {
606         /* get_edge_tiocmiwait() got this if !pps_canwait */
607 
608         /* quick, grab a copy of last fixtime before it changes */
609         thread_lock(thread_context);
610         *last_fixtime = thread_context->fix_in;
611         thread_unlock(thread_context);
612     }
613 
614 
615     // find the last edge
616     if ( pi.assert_timestamp.tv_sec > pi.clear_timestamp.tv_sec ) {
617         /* assert 1 sec or more after than clear */
618         *edge = 1;
619     } else if ( pi.assert_timestamp.tv_sec < pi.clear_timestamp.tv_sec ) {
620         /* assert 1 sec or more before than clear */
621         *edge = 0;
622     } else if ( pi.assert_timestamp.tv_nsec > pi.clear_timestamp.tv_nsec ) {
623         /* assert less than 1 sec after clear */
624         *edge = 1;
625     } else {
626         /* assert less than 1 sec before clear */
627         *edge = 0;
628     }
629     if ( 1 == *edge ) {
630         /* assert after clear */
631         *prev_edge = 0;
632         if ( 0 == pi.clear_timestamp.tv_sec ) {
633                 /* brain damaged pps-gpio sometimes never fills in clear
634                  * so make it look like an invisible pulse
635                  * if clear is the leading edge, then we are off by the
636                  * pulse width */
637                 *prev_clock_ts = pi.assert_timestamp;
638         } else {
639                 *prev_clock_ts = pi.clear_timestamp;
640         }
641         *clock_ts = pi.assert_timestamp;
642     } else {
643         /* assert before clear */
644         *prev_edge = 1;
645         *prev_clock_ts = pi.assert_timestamp;
646         *clock_ts = pi.clear_timestamp;
647     }
648     /*
649      * pps_seq_t is uint32_t on NetBSD, so cast to
650      * unsigned long as a wider-or-equal type to
651      * accomodate Linux's type.
652      */
653     thread_context->log_hook(thread_context, THREAD_PROG,
654                 "KPPS:%s assert %s, sequence: %lu, "
655                 "clear  %s, sequence: %lu - using: %.10s\n",
656                 thread_context->devicename,
657                 timespec_str(&pi.assert_timestamp, ts_str1, sizeof(ts_str1)),
658                 (unsigned long) pi.assert_sequence,
659                 timespec_str(&pi.clear_timestamp, ts_str2, sizeof(ts_str2)),
660                 (unsigned long) pi.clear_sequence,
661                 *edge ? "assert" : "clear");
662 
663     return 0;
664 }
665 #endif  /* defined(HAVE_SYS_TIMEPPS_H) */
666 
667 /* gpsd_ppsmonitor()
668  *
669  * the core loop of the PPS thread.
670  * All else is initialization, cleanup or subroutine
671  */
gpsd_ppsmonitor(void * arg)672 static void *gpsd_ppsmonitor(void *arg)
673 {
674     char ts_str1[TIMESPEC_LEN], ts_str2[TIMESPEC_LEN];
675     struct inner_context_t inner_context = *((struct inner_context_t *)arg);
676     volatile struct pps_thread_t *thread_context = inner_context.pps_thread;
677     /* the GPS time and system clock timme, to the nSec,
678      * when the last fix received
679      * using a double would cause loss of precision */
680     volatile struct timedelta_t last_fixtime = {{0, 0}, {0, 0}};
681     struct timespec clock_ts = {0, 0};
682     time_t last_second_used = 0;
683     int64_t cycle = 0, duration = 0;
684     /* state is the last state of the tty control signals */
685     int state = 0;
686     /* count of how many cycles unchanged data */
687     int  unchanged = 0;
688     /* state_last is previous state */
689     int state_last = 0;
690     /* edge, used as index into pulse to find previous edges */
691     int edge = 0;       /* 0 = clear edge, 1 = assert edge */
692 
693 #if defined(TIOCMIWAIT)
694     int edge_tio = 0;
695     int64_t cycle_tio = 0;
696     int64_t duration_tio = 0;
697     int state_tio = 0;
698     int state_last_tio = 0;
699     struct timespec clock_ts_tio = {0, 0};
700     /* pulse stores the time of the last two edges */
701     struct timespec pulse_tio[2] = { {0, 0}, {0, 0} };
702 #endif /* TIOCMIWAIT */
703 
704 #if defined(HAVE_SYS_TIMEPPS_H)
705     int64_t cycle_kpps = 0, duration_kpps = 0;
706     /* kpps_pulse stores the time of the last two edges */
707     struct timespec pulse_kpps[2] = { {0, 0}, {0, 0} };
708 #endif /* defined(HAVE_SYS_TIMEPPS_H) */
709     bool not_a_tty = false;
710 
711     /* Acknowledge that we've grabbed the inner_context data */
712     ((volatile struct inner_context_t *)arg)->pps_thread = NULL;
713 
714     /* before the loop, figure out how we can detect edges:
715      * TIOMCIWAIT, which is linux specifix
716      * RFC2783, a.k.a kernel PPS (KPPS)
717      * or if KPPS is deficient a combination of the two */
718     if ( 0 > thread_context->devicefd
719       || 0 == isatty(thread_context->devicefd) ) {
720         thread_context->log_hook(thread_context, THREAD_PROG,
721             "KPPS:%s gps_fd:%d not a tty, can not use TIOMCIWAIT\n",
722             thread_context->devicename,
723             thread_context->devicefd);
724         /* why do we care the device is a tty? so as not to ioctl(TIO..)
725         * /dev/pps0 is not a tty and we need to use it */
726         not_a_tty = true;
727     }
728     /* if no TIOCMIWAIT, we hope to have PPS_CANWAIT */
729 
730     if ( not_a_tty && !inner_context.pps_canwait ) {
731         /* for now, no way to wait for an edge, in the future maybe figure out
732          * a sleep */
733     }
734 
735     /*
736      * this is the main loop, exit and never any further PPS processing.
737      *
738      * Four stages to the loop,
739      * an unwanted condition at any point and the loop restarts
740      * an error condition and we exit for all time.
741      *
742      * Stage One: wait for the next edge.
743      *      If we have KPPS
744      *         If we have PPS_CANWAIT
745      *             use KPPS and PPS_CANWAIT - this is the most accurate
746      *         else
747      *             use KPPS and TIOMCIWAIT together - this is pretty accurate
748      *      else If we have TIOMCIWAIT
749      *         use TIOMCIWAIT - this is the least accurate
750      *      else
751      *         give up
752      *
753      * Success is we have a good edge, otherwise loop some more
754      *
755      * On a successul stage one, we know this about the exact moment
756      * of current pulse:
757      *      GPS (real) time
758      *      system (clock) time
759      *      edge type: Assert (rising) or Clear (falling)
760      *
761      * From the above 3 items, we can compute:
762      *      cycle length - elapsed time from the previous edge of the same type
763      *      pulse length (duration) - elapsed time from the previous edge
764      *                            (the previous edge would be the opposite type)
765      *
766      * Stage Two:  Categorize the current edge
767      *      Decide if we have 0.5Hz, 1Hz, 5 Hz cycle time
768      *      knowing cycle time determine if we have the leading or trailing edge
769      *      restart the loop if the edge looks dodgy
770      *
771      * Stage Three: Calculate
772      *      Calculate the offset (difference) between the system time
773      *      and the GPS time at the pulse moment
774      *      restart the loop if the offset looks dodgy
775      *
776      * Stage Four: Tell ntpd, chronyd, or gpsmon what we learned
777      *       a few more sanity checks
778      *       call the report hook with our PPS report
779      */
780     while (thread_context->report_hook != NULL) {
781         bool ok = false;
782         char *log = NULL;
783         char *edge_str = "";
784 
785         if (++unchanged == 10) {
786             /* last ten edges no good, stop spinning, just wait 10 seconds */
787             unchanged = 0;
788             thread_context->log_hook(thread_context, THREAD_WARN,
789                     "PPS:%s unchanged state, ppsmonitor sleeps 10\n",
790                     thread_context->devicename);
791             (void)sleep(10);
792         }
793 
794         /* Stage One; wait for the next edge */
795 #if defined(TIOCMIWAIT)
796         if ( !not_a_tty && !inner_context.pps_canwait ) {
797             int ret;
798 
799             /* we are a tty, so can TIOCMIWAIT */
800             /* we have no PPS_CANWAIT, so must TIOCMIWAIT */
801 
802             ret = get_edge_tiocmiwait( thread_context, &clock_ts_tio,
803                         &state_tio, &last_fixtime );
804             if ( 0 != ret ) {
805                 thread_context->log_hook(thread_context, THREAD_PROG,
806                             "PPS:%s die: TIOCMIWAIT Error\n",
807                             thread_context->devicename);
808                 break;
809             }
810 
811             edge_tio = (state_tio > state_last_tio) ? 1 : 0;
812 
813             state_last_tio = state_tio;
814 
815             /* three things now known about the current edge:
816              * clock_ts - time of the edge
817              * state - the serial line input states
818              * edge - rising edge (1), falling edge (0) or invisble edge (0)
819              */
820 
821             /* calculate cycle and duration from previous edges */
822             cycle_tio = timespec_diff_ns(clock_ts_tio, pulse_tio[edge_tio]);
823             cycle_tio /= 1000;  /* nsec to usec */
824             duration_tio = timespec_diff_ns(clock_ts_tio,
825                                             pulse_tio[edge_tio ? 0 : 1]) / 1000;
826 
827             /* save this edge so we know next cycle time */
828             pulse_tio[edge_tio] = clock_ts_tio;
829 
830             /* use this data */
831             ok = true;
832             clock_ts = clock_ts_tio;
833             state = edge_tio;
834             edge = edge_tio;
835             edge_str = edge ? "Assert" : "Clear";
836             cycle = cycle_tio;
837             duration = duration_tio;
838 
839             // (long long) for 32-bit compat.  PRId64 segfaults
840             thread_context->log_hook(thread_context, THREAD_PROG,
841                     "TPPS:%s %.10s, cycle: %lld, duration: %lld @ %s\n",
842                     thread_context->devicename, edge_str,
843                     (long long)cycle, (long long)duration,
844                     timespec_str(&clock_ts, ts_str1, sizeof(ts_str1)));
845 
846         }
847 #endif /* TIOCMIWAIT */
848 
849         /* ok and log used by KPPS and TIOCMIWAIT */
850         log = NULL;
851 #if defined(HAVE_SYS_TIMEPPS_H)
852         if ( 0 <= inner_context.kernelpps_handle ) {
853             int ret;
854             int edge_kpps = 0;       /* 0 = clear edge, 1 = assert edge */
855             /* time of the last edge */
856             struct timespec clock_ts_kpps = {0, 0};
857             /* time of the edge before the last edge */
858             struct timespec prev_clock_ts = {0, 0};
859             /* direction of next to last edge 1 = assert, 0 = clear */
860             int prev_edge = 0;
861 
862             /* get last and previous edges, in order
863              * optionally wait for goood data
864              */
865             ret = get_edge_rfc2783(&inner_context,
866                          &prev_clock_ts,
867                          &prev_edge,
868                          &clock_ts_kpps,
869                          &edge_kpps,
870                          &last_fixtime);
871 
872             if ( -1 == ret ) {
873                 /* error, so break */
874                 thread_context->log_hook(thread_context, THREAD_ERROR,
875                             "PPS:%s die: RFC2783 Error\n",
876                             thread_context->devicename);
877                 break;
878             }
879 
880             if ( 1 == ret ) {
881                 /* no edge found, so continue */
882                 /* maybe use TIOCMIWAIT edge instead?? */
883                 continue;
884             }
885             /* for now, as we have been doing all of gpsd 3.x, just
886              *use the last edge, not the previous edge */
887 
888             /* compute time from previous saved similar edge */
889             cycle_kpps = timespec_diff_ns(clock_ts_kpps, pulse_kpps[edge_kpps]);
890             cycle_kpps /= 1000;
891             /* compute time from previous saved dis-similar edge */
892             duration_kpps = timespec_diff_ns(clock_ts_kpps, prev_clock_ts) /
893                             1000;
894 
895             /* save for later */
896             pulse_kpps[edge_kpps] = clock_ts_kpps;
897             pulse_kpps[edge_kpps ? 0 : 1] = prev_clock_ts;
898             /* sanity checks are later */
899 
900             /* use this data */
901             state = edge_kpps;
902             edge = edge_kpps;
903             edge_str = edge ? "Assert" : "Clear";
904             clock_ts = clock_ts_kpps;
905             cycle = cycle_kpps;
906             duration = duration_kpps;
907 
908             // (long long) for 32-bit compat.  PRId64 segfaults
909             thread_context->log_hook(thread_context, THREAD_PROG,
910                 "KPPS:%s %.10s cycle: %lld, duration: %lld @ %s\n",
911                 thread_context->devicename,
912                 edge_str,
913                 (long long)cycle_kpps, (long long)duration_kpps,
914                 timespec_str(&clock_ts_kpps, ts_str1, sizeof(ts_str1)));
915 
916         }
917 #endif /* defined(HAVE_SYS_TIMEPPS_H) */
918 
919         if ( not_a_tty && !inner_context.pps_canwait ) {
920             /* uh, oh, no TIOMCIWAIT, nor RFC2783, die */
921             thread_context->log_hook(thread_context, THREAD_WARN,
922                         "PPS:%s die: no TIOMCIWAIT, nor RFC2783 CANWAIT\n",
923                         thread_context->devicename);
924             break;
925         }
926         /*
927          * End of Stge One
928          * we now know this about the exact moment of current pulse:
929          *      GPS (real) time
930          *      system (clock) time
931          *      edge type: Assert (rising) or Clear (falling)
932          *
933          * we have computed:
934          *      cycle length
935          *      pulse length (duration)
936          */
937 
938         /*
939          * Stage Two:  Categorize the current edge
940          *      Decide if we have 0.5Hz, 1Hz, 5 Hz cycle time
941          *      determine if we have the leading or trailing edge
942          */
943 
944         /* FIXME! this block duplicates a lot of the next block
945          * of cycle detetion code */
946         if (state != state_last) {
947             thread_context->log_hook(thread_context, THREAD_RAW,
948                         "PPS:%s %.10s pps-detect changed to %d\n",
949                         thread_context->devicename, edge_str, state);
950             unchanged = 0;
951         } else if ( (180000 < cycle &&  220000 > cycle)      /* 5Hz */
952                 ||  (900000 < cycle && 1100000 > cycle)      /* 1Hz */
953                 || (1800000 < cycle && 2200000 > cycle) ) {  /* 0.5Hz */
954 
955             /* some pulses may be so short that state never changes
956              * and some RFC2783 only can detect one edge */
957 
958             duration = 0;
959             unchanged = 0;
960             thread_context->log_hook(thread_context, THREAD_RAW,
961                         "PPS:%s %.10s pps-detect invisible pulse\n",
962                         thread_context->devicename, edge_str);
963         }
964         /* else, unchannged state, and weird cycle time */
965 
966         state_last = state;
967         // (long long) for 32-bit compat.  PRId64 segfaults
968         thread_context->log_hook(thread_context, THREAD_PROG,
969             "PPS:%s %.10s cycle: %lld, duration: %lld @ %s\n",
970             thread_context->devicename,
971             edge_str,
972             (long long)cycle, (long long)duration,
973             timespec_str(&clock_ts, ts_str1, sizeof(ts_str1)));
974         if (unchanged) {
975             // strange, try again
976             continue;
977         }
978 
979         /*
980          * The PPS pulse is normally a short pulse with a frequency of
981          * 1 Hz, and the UTC second is defined by the front edge. But we
982          * don't know the polarity of the pulse (different receivers
983          * emit different polarities). The duration variable is used to
984          * determine which way the pulse is going.  When the duration
985          * is less than 1/2 the cycle we are on the trailing edge.
986          *
987          * Some GPSes instead output a square wave that is 0.5 Hz and each
988          * edge denotes the start of a second.
989          *
990          * Some GPSes, like the Globalsat MR-350P, output a 1uS pulse.
991          * The pulse is so short that TIOCMIWAIT sees a state change
992          * but by the time TIOCMGET is called the pulse is gone.  gpsd
993          * calls that an invisible pulse.
994          *
995          * A few stupid GPSes, like the Furuno GPSClock, output a 1.0 Hz
996          * square wave where the leading edge is the start of a second
997          * gpsd can only guess the correct edge.
998          *
999          * 5Hz GPS (Garmin 18-5Hz) pulses at 5Hz. Set the pulse length to
1000          * 40ms which gives a 160ms pulse before going high.
1001          *
1002          * You may think that PPS is very accurate, so the cycle time
1003          * valid window should be very small.  This is not the case,
1004          * The Raspberry Pi clock is very coarse when it starts and/or chronyd
1005          * may be doing a fast slew.  chronyd by default will slew up
1006          * to 8.334%!  So the cycle time as measured by the system clock
1007          * may be almost +/- 9%. Therefore, gpsd uses a 10% window.
1008          * Don't worry, ntpd and chronyd will do further validation.
1009          */
1010 
1011         log = "Unknown error";
1012         if ( 0 > cycle ) {
1013             log = "Rejecting negative cycle\n";
1014         } else if (180000 > cycle) {
1015             /* shorter than 200 milliSec - 10%
1016              * too short to even be a 5Hz pulse */
1017             log = "Too short for 5Hz\n";
1018         } else if (201000 > cycle) {
1019             /* longer than 200 milliSec - 10%
1020              * shorter than 200 milliSec + 10%
1021              * about 200 milliSec cycle */
1022             /* looks like 5hz PPS pulse */
1023             if (100000 > duration) {
1024                 /* this is the end of the long part */
1025                 /* BUG: how does the code know to tell ntpd
1026                  * which 1/5 of a second to use?? */
1027                 ok = true;
1028                 log = "5Hz PPS pulse\n";
1029             }
1030         } else if (900000 > cycle) {
1031             /* longer than 200 milliSec + 10%
1032              * shorter than 1.000 Sec - 10% */
1033             /* Yes, 10% window.  The Raspberry Pi clock is very coarse
1034              * when it starts and chronyd may be doing a fast slew.
1035              * chronyd by default will slew up to 8.334% ! */
1036             log = "Too long for 5Hz, too short for 1Hz\n";
1037         } else if (1100000 > cycle) {
1038             /* longer than 1.000 Sec - 10%
1039              * shorter than 1.000 Sec + 10% */
1040             /* Yes, 10% window.  */
1041             /* looks like 1Hz PPS pulse or square wave */
1042             if (0 == duration) {
1043                 ok = true;
1044                 log = "invisible pulse\n";
1045             } else if (450000 > duration) {
1046                 /* pulse shorter than 500 milliSec - 10%
1047                  * end of the short "half" of the cycle
1048                  * aka the trailing edge */
1049                 log = "1Hz trailing edge\n";
1050             } else if (555000 > duration) {
1051                 /* pulse longer than 500 milliSec - 10%
1052                  * pulse shorter than 500 milliSec + 10%
1053                  * looks like 1.0 Hz square wave, ignore trailing edge
1054                  * except we can't tell which is which, so we guess */
1055                 // cppcheck-suppress knownConditionTrueFalse
1056                 if (edge == 1) {
1057                     ok = true;
1058                     log = "square\n";
1059                 }
1060             } else {
1061                 /* pulse longer than 500 milliSec + 10%
1062                  * end of the long "half" of the cycle
1063                  * aka the leading edge,
1064                  * the edge that marks the start of the second */
1065                 ok = true;
1066                 log = "1Hz leading edge\n";
1067             }
1068         } else if (1800000 > cycle) {
1069             /* cycle longer than 1.000 Sec + 10%
1070              * cycle shorter than 2.000 Sec - 10%
1071              * Too long for 1Hz, too short for 2Hz */
1072             log = "Too long for 1Hz, too short for 2Hz\n";
1073         } else if (2200000 > cycle) {
1074             /* cycle longer than 2.000 Sec - 10%
1075              * cycle shorter than 2.000 Sec + 10%
1076              * looks like 0.5 Hz square wave */
1077             if (990000 > duration) {
1078                  /* pulse shorter than 1.000 Sec - 10%
1079                   * too short to be a 2Hx square wave */
1080                 log = "0.5 Hz square too short duration\n";
1081             } else if (1100000 > duration) {
1082                  /* pulse longer than 1.000 Sec - 10%
1083                   * pulse shorter than 1.000 Sec + 10%
1084                   * and nice 0.5Hz square wave */
1085                 ok = true;
1086                 log = "0.5 Hz square wave\n";
1087             } else {
1088                 log = "0.5 Hz square too long duration\n";
1089             }
1090         } else {
1091             /* cycle longer than 2.000 Sec + 10%
1092              * can't be anything */
1093             log = "Too long for 0.5Hz\n";
1094         }
1095 
1096         /* end of Stage two
1097          * we now know what type of PPS pulse, and if we have  a good
1098          * leading edge or not
1099          */
1100 
1101         /* Stage Three: Calculate
1102          *      Calculate the offset (difference) between the system time
1103          *      and the GPS time at the pulse moment
1104          */
1105 
1106         /*
1107          * If there has not yet been any valid in-band time stashed
1108          * from the GPS when the PPS event was asserted, we can do
1109          * nothing further.  gpsd can not tell what second this pulse is
1110          * in reference to.
1111          *
1112          * Some GPSes like Garmin always send a PPS, valid or not.
1113          * Other GPSes like some uBlox may only send PPS when time is valid.
1114          * It is common to get PPS, and no fixtime, while autobauding.
1115          */
1116         /* FIXME, some GPS, like Skytraq, may output a the fixtime so
1117          * late in the cycle as to be ambiguous. */
1118         if (last_fixtime.real.tv_sec == 0) {
1119             /* probably should log computed offset just for grins here */
1120             ok = false;
1121             log = "missing last_fixtime\n";
1122         } else if ( ok && last_second_used >= last_fixtime.real.tv_sec ) {
1123             /* uh, oh, this second already handled */
1124             ok = false;
1125             log = "this second already handled\n";
1126         }
1127 
1128         if ( !ok ) {
1129             /* can not use this pulse, reject and retry */
1130             thread_context->log_hook(thread_context, THREAD_PROG,
1131                         "PPS:%s %.10s ignored %.100s",
1132                         thread_context->devicename, edge_str,  log);
1133             continue;
1134         }
1135 
1136         /* we have validated a goood cycle, mark it */
1137         unchanged = 0;
1138         /* offset is the skew from expected to observed pulse time */
1139         struct timespec offset;
1140         /* offset as a printable string */
1141         char offset_str[TIMESPEC_LEN];
1142         /* delay after last fix */
1143         struct timespec  delay;
1144         /* delay as a printable string */
1145         char delay_str[TIMESPEC_LEN];
1146         char *log1 = "";
1147         /* ppstimes.real is the time we think the pulse represents  */
1148         struct timedelta_t ppstimes;
1149         thread_context->log_hook(thread_context, THREAD_RAW,
1150                     "PPS:%s %.10s categorized %.100s",
1151                     thread_context->devicename, edge_str, log);
1152 
1153         /* FIXME! The GR-601W at 38,400 or faster can send the
1154          * serial fix before the interrupt event carrying the PPS
1155          * line assertion by about 10 mSec!
1156          */
1157 
1158         /*
1159          * We get the time of the last fix recorded before the PPS came in,
1160          * which is for the previous cycle.  Only works for integral cycle
1161          * times, but more than 1Hz is pointless.
1162          */
1163 
1164         ppstimes.real.tv_sec = (time_t)last_fixtime.real.tv_sec + 1;
1165         ppstimes.real.tv_nsec = 0;  /* need to be fixed for 5Hz */
1166         ppstimes.clock = clock_ts;
1167 
1168         // Here would be a good place to apply qErr
1169 
1170         TS_SUB( &offset, &ppstimes.real, &ppstimes.clock);
1171         TS_SUB( &delay, &ppstimes.clock, &last_fixtime.clock);
1172         timespec_str(&delay, delay_str, sizeof(delay_str));
1173 
1174         /* end Stage Three: now known about the exact edge moment:
1175          *      UTC time of PPS edge
1176          *      offset of system time to PS time
1177          */
1178 
1179         /* Stage Four: Tell ntpd, chronyd, or gpsmon what we learned
1180          *       a few more sanity checks
1181          *       call the report hook with our PPS report
1182          */
1183 
1184         if (0 > delay.tv_sec || 0 > delay.tv_nsec) {
1185             thread_context->log_hook(thread_context, THREAD_RAW,
1186                         "PPS:%s %.10s system clock went backwards: %.20s\n",
1187                         thread_context->devicename,
1188                         edge_str,
1189                         delay_str);
1190             log1 = "system clock went backwards";
1191         } else if ((2 < delay.tv_sec)
1192           || (1 == delay.tv_sec && 100000000 < delay.tv_nsec)) {
1193             /* system clock could be slewing so allow up to 1.1 sec delay */
1194             /* chronyd can slew +/-8.33% */
1195             thread_context->log_hook(thread_context, THREAD_RAW,
1196                         "PPS:%s %.10s no current GPS seconds: %.20s\n",
1197                         thread_context->devicename,
1198                         edge_str,
1199                         delay_str);
1200             log1 = "timestamp out of range";
1201         } else {
1202             last_second_used = last_fixtime.real.tv_sec;
1203             if (thread_context->report_hook != NULL)
1204                 log1 = thread_context->report_hook(thread_context, &ppstimes);
1205             else
1206                 log1 = "no report hook";
1207             thread_lock(thread_context);
1208             thread_context->pps_out = ppstimes;
1209             thread_context->ppsout_count++;
1210             thread_unlock(thread_context);
1211             thread_context->log_hook(thread_context, THREAD_INF,
1212                 "PPS:%s %.10s hooks called clock: %s real: %s: %.20s\n",
1213                 thread_context->devicename,
1214                 edge_str,
1215                 timespec_str(&ppstimes.clock, ts_str1, sizeof(ts_str1)),
1216                 timespec_str(&ppstimes.real, ts_str2, sizeof(ts_str2)),
1217                 log1);
1218         }
1219         thread_context->log_hook(thread_context, THREAD_PROG,
1220                 "PPS:%s %.10s %.30s @ %s offset %.20s\n",
1221                 thread_context->devicename,
1222                 edge_str,
1223                 log1,
1224                 timespec_str(&clock_ts, ts_str1, sizeof(ts_str1)),
1225                 timespec_str(&offset, offset_str, sizeof(offset_str)));
1226         /* end Stage four, end of the loop, do it again */
1227     }
1228 #if defined(HAVE_SYS_TIMEPPS_H)
1229     if (inner_context.kernelpps_handle > 0) {
1230         thread_context->log_hook(thread_context, THREAD_PROG,
1231             "KPPS:%s descriptor cleaned up\n",
1232             thread_context->devicename);
1233         (void)time_pps_destroy(inner_context.kernelpps_handle);
1234     }
1235 #endif
1236     thread_context->log_hook(thread_context, THREAD_PROG,
1237                 "PPS:%s gpsd_ppsmonitor exited.\n",
1238                 thread_context->devicename);
1239     return NULL;
1240 }
1241 
1242 /*
1243  * Entry points begin here.
1244  */
1245 
pps_thread_activate(volatile struct pps_thread_t * pps_thread)1246 void pps_thread_activate(volatile struct pps_thread_t *pps_thread)
1247 /* activate a thread to watch the device's PPS transitions */
1248 {
1249     int retval;
1250     pthread_t pt;
1251     struct timespec start_delay = {0, 1000000};  /* 1 ms */
1252     /*
1253      * FIXME: this launch code is not itself thread-safe!
1254      * It would be if inner_context could be auto, but the monitor
1255      * routine gets garbage when we try that.  Ideally the body
1256      * of this function would be guarded by a separate mutex.
1257      * Either that, or this should be an exception to the no-malloc rule.
1258      */
1259     static struct inner_context_t       inner_context;
1260 
1261     inner_context.pps_thread = pps_thread;
1262 #if defined(HAVE_SYS_TIMEPPS_H)
1263     /* some operations in init_kernel_pps() require root privs */
1264     (void)init_kernel_pps(&inner_context);
1265     if ( 0 <= inner_context.kernelpps_handle ) {
1266         pps_thread->log_hook(pps_thread, THREAD_INF,
1267                     "KPPS:%s kernel PPS will be used\n",
1268                     pps_thread->devicename);
1269     } else {
1270         pps_thread->log_hook(pps_thread, THREAD_WARN,
1271                     "KPPS:%s kernel PPS unavailable, PPS accuracy will suffer\n",
1272                     pps_thread->devicename);
1273     }
1274 #else
1275     pps_thread->log_hook(pps_thread, THREAD_WARN,
1276                 "KPPS:%s no HAVE_SYS_TIMEPPS_H, PPS accuracy will suffer\n",
1277                 pps_thread->devicename);
1278 #endif
1279 
1280     memset( &pt, 0, sizeof(pt));
1281     retval = pthread_create(&pt, NULL, gpsd_ppsmonitor, (void *)&inner_context);
1282     pps_thread->log_hook(pps_thread, THREAD_PROG, "PPS:%s thread %s\n",
1283                 pps_thread->devicename,
1284                 (retval==0) ? "launched" : "FAILED");
1285     /* The monitor thread may not run immediately, particularly on a single-
1286      * core machine, so we need to wait for it to acknowledge its copying
1287      * of the inner_context struct before proceeding.
1288      */
1289     while (inner_context.pps_thread)
1290         (void) nanosleep(&start_delay, NULL);
1291 }
1292 
pps_thread_deactivate(volatile struct pps_thread_t * pps_thread)1293 void pps_thread_deactivate(volatile struct pps_thread_t *pps_thread)
1294 /* cleanly terminate PPS thread */
1295 {
1296     pps_thread->report_hook = NULL;
1297 }
1298 
1299 /* thread-safe update of last fix time - only way we pass data in */
pps_thread_fixin(volatile struct pps_thread_t * pps_thread,volatile struct timedelta_t * fix_in)1300 void pps_thread_fixin(volatile struct pps_thread_t *pps_thread,
1301                       volatile struct timedelta_t *fix_in)
1302 {
1303     thread_lock(pps_thread);
1304     pps_thread->fix_in = *fix_in;
1305     thread_unlock(pps_thread);
1306 }
1307 
1308 /* thread-safe update of qErr and qErr_time - only way we pass data in */
pps_thread_qErrin(volatile struct pps_thread_t * pps_thread,long qErr,struct timespec qErr_time)1309 void pps_thread_qErrin(volatile struct pps_thread_t *pps_thread,
1310                        long qErr, struct timespec qErr_time)
1311 {
1312     thread_lock(pps_thread);
1313     pps_thread->qErr = qErr;
1314     pps_thread->qErr_time = qErr_time;
1315     thread_unlock(pps_thread);
1316 }
1317 
pps_thread_ppsout(volatile struct pps_thread_t * pps_thread,volatile struct timedelta_t * td)1318 int pps_thread_ppsout(volatile struct pps_thread_t *pps_thread,
1319                        volatile struct timedelta_t *td)
1320 /* return the delta at the time of the last PPS - only way we pass data out */
1321 {
1322     volatile int ret;
1323 
1324     thread_lock(pps_thread);
1325     *td = pps_thread->pps_out;
1326     ret = pps_thread->ppsout_count;
1327     thread_unlock(pps_thread);
1328 
1329     return ret;
1330 }
1331 
1332 /* end */
1333 
1334 // vim: set expandtab shiftwidth=4
1335