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