Coverage Report

Created: 2026-10-12 06:10

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