[gpsd] fix PPS with large offsets
Miroslav Lichvar
mlichvar at fedoraproject.org
Wed Jul 2 17:05:23 UTC 2014
commit 3f55d2db18fa8db1a9b868c3ed86b212efe0f88f
Author: Miroslav Lichvar <mlichvar at redhat.com>
Date: Wed Jul 2 17:55:07 2014 +0200
fix PPS with large offsets
gpsd-ppsoffset.patch | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++
gpsd.spec | 4 ++
2 files changed, 144 insertions(+), 0 deletions(-)
---
diff --git a/gpsd-ppsoffset.patch b/gpsd-ppsoffset.patch
new file mode 100644
index 0000000..a140386
--- /dev/null
+++ b/gpsd-ppsoffset.patch
@@ -0,0 +1,140 @@
+commit f2357b3fbf3b242f3998d2ce6b5e1ecce1f65125
+Author: Miroslav Lichvar <mlichvar at redhat.com>
+Date: Tue May 27 18:08:19 2014 +0200
+
+ Fix PPS with large offsets.
+
+ This was broken by commit 575444. The check if the PPS time isn't
+ referenced with an old message time used PPS offset instead of the
+ difference between local PPS time and local time of the last message.
+ The PPS sample was reported via SHM or chrony socket only if the offset
+ was between -1 and 1000001 seconds.
+
+ Keep the local timestamp of the last fix in struct gps_device_t in
+ addition to the real timestamp and use it to check the PPS delay.
+ Rename the l_offset variable to delay to avoid further confusion.
+
+diff --git a/gpsd.c b/gpsd.c
+index 53d68d1..ffaf680 100644
+--- a/gpsd.c
++++ b/gpsd.c
+@@ -1557,7 +1557,7 @@ static void all_reports(struct gps_device_t *device, gps_mask_t changed)
+ //gpsd_report(context.debug, LOG_PROG, "NTP: No time this packet\n");
+ } else if (isnan(device->newdata.time)) {
+ //gpsd_report(context.debug, LOG_PROG, "NTP: bad new time\n");
+- } else if (device->newdata.time == device->last_fixtime) {
++ } else if (device->newdata.time == device->last_fixtime.real) {
+ //gpsd_report(context.debug, LOG_PROG, "NTP: Not a new time\n");
+ } else if (!device->ship_to_ntpd) {
+ //gpsd_report(context.debug, LOG_PROG, "NTP: No precision time report\n");
+@@ -1588,7 +1588,8 @@ static void all_reports(struct gps_device_t *device, gps_mask_t changed)
+ /*@-compdef@*/
+ (void)ntpshm_put(device, device->shmIndex, &td);
+ /*@+compdef@*/
+- device->last_fixtime = device->newdata.time;
++ device->last_fixtime.real = device->newdata.time;
++ device->last_fixtime.clock = td.clock.tv_sec + td.clock.tv_nsec / 1e9;
+ }
+ #endif /* NTPSHM_ENABLE */
+
+diff --git a/gpsd.h-tail b/gpsd.h-tail
+index 8040094..08e0d59 100644
+--- a/gpsd.h-tail
++++ b/gpsd.h-tail
+@@ -475,7 +475,10 @@ struct gps_device_t {
+ int shmIndexPPS;
+ # endif /* PPS_ENABLE */
+ #endif /* NTPSHM_ENABLE */
+- volatile timestamp_t last_fixtime; /* so updates happen once */
++ volatile struct {
++ timestamp_t real;
++ timestamp_t clock;
++ } last_fixtime; /* so updates happen once */
+ #ifdef PPS_ENABLE
+ #if defined(HAVE_SYS_TIMEPPS_H)
+ pps_handle_t kernelpps_handle;
+diff --git a/gpsmon.c b/gpsmon.c
+index b030979..77b6558 100644
+--- a/gpsmon.c
++++ b/gpsmon.c
+@@ -770,7 +770,7 @@ static void gpsmon_hook(struct gps_device_t *device, gps_mask_t changed UNUSED)
+ report_unlock();
+
+ /* Update the last fix time seen for PPS. FIXME: do this here? */
+- device->last_fixtime = device->newdata.time;
++ device->last_fixtime.real = device->newdata.time;
+ }
+ /*@+observertrans +nullpass +globstate +compdef +uniondef@*/
+
+diff --git a/ppsthread.c b/ppsthread.c
+index d9e431e..ed5c7ef 100644
+--- a/ppsthread.c
++++ b/ppsthread.c
+@@ -238,7 +238,7 @@ static int init_kernel_pps(struct gps_device_t *session)
+ static /*@null@*/ void *gpsd_ppsmonitor(void *arg)
+ {
+ struct gps_device_t *session = (struct gps_device_t *)arg;
+- double last_fixtime = 0;
++ double last_fixtime_real = 0, last_fixtime_clock = 0;
+ #ifndef HAVE_CLOCK_GETTIME
+ struct timeval clock_tv = {0, 0};
+ #endif /* HAVE_CLOCK_GETTIME */
+@@ -299,7 +299,8 @@ static /*@null@*/ void *gpsd_ppsmonitor(void *arg)
+ break;
+ }
+ /* quick, grab a copy of last_fixtime before it changes */
+- last_fixtime = session->last_fixtime;
++ last_fixtime_real = session->last_fixtime.real;
++ last_fixtime_clock = session->last_fixtime.clock;
+
+ /*@-noeffect@*/
+ /* get the time after we just woke up */
+@@ -541,7 +542,7 @@ static /*@null@*/ void *gpsd_ppsmonitor(void *arg)
+ log = "Too long for 0.5Hz\n";
+ }
+ #endif /* TIOCMIWAIT */
+- if ( ok && last_second_used >= last_fixtime ) {
++ if ( ok && last_second_used >= last_fixtime_real ) {
+ /* uh, oh, this second already handled */
+ ok = 0;
+ log = "this second already handled\n";
+@@ -550,7 +551,8 @@ static /*@null@*/ void *gpsd_ppsmonitor(void *arg)
+ if (ok) {
+ /* offset is the skew from expected to observed pulse time */
+ double offset;
+- long l_offset;
++ /* delay after last fix */
++ double delay;
+ char *log1 = NULL;
+ /* drift.real is the time we think the pulse represents */
+ struct timedrift_t drift;
+@@ -580,7 +582,7 @@ static /*@null@*/ void *gpsd_ppsmonitor(void *arg)
+ */
+
+ /*@+relaxtypes@*/
+- drift.real.tv_sec = last_fixtime + 1;
++ drift.real.tv_sec = last_fixtime_real + 1;
+ drift.real.tv_nsec = 0; /* need to be fixed for 5Hz */
+ drift.clock = clock_ts;
+ /*@-relaxtypes@*/
+@@ -589,15 +591,15 @@ static /*@null@*/ void *gpsd_ppsmonitor(void *arg)
+ * GPS serial input then use that */
+ offset = (drift.real.tv_sec - drift.clock.tv_sec);
+ offset += ((drift.real.tv_nsec - drift.clock.tv_nsec) / 1e9);
+- l_offset = (long) offset;
+- if (0 > l_offset || 1000000 < l_offset) {
++ delay = (drift.clock.tv_sec + drift.clock.tv_nsec / 1e9) - last_fixtime_clock;
++ if (0.0 > delay || 1.0 < delay) {
+ gpsd_report(session->context->debug, LOG_RAW,
+- "PPS: no current GPS seconds: %ld\n",
+- (long)l_offset);
++ "PPS: no current GPS seconds: %f\n",
++ delay);
+ log1 = "timestamp out of range";
+ } else {
+ /*@-compdef@*/
+- last_second_used = last_fixtime;
++ last_second_used = last_fixtime_real;
+ if (session->thread_report_hook != NULL)
+ log1 = session->thread_report_hook(session, &drift);
+ else
diff --git a/gpsd.spec b/gpsd.spec
index f67be78..faa3797 100644
--- a/gpsd.spec
+++ b/gpsd.spec
@@ -15,6 +15,9 @@ Source10: gpsd.service
Source11: gpsd.sysconfig
Source12: gpsdctl.service
+# Fix PPS with large offsets
+Patch1: gpsd-ppsoffset.patch
+
BuildRequires: dbus-devel dbus-glib-devel ncurses-devel xmlto python-devel
BuildRequires: scons desktop-file-utils bluez-libs-devel pps-tools-devel
%ifnarch s390 s390x
@@ -75,6 +78,7 @@ can run on a serial terminal or terminal emulator.
%prep
%setup -q -n %{name}
+%patch1 -p1 -b .ppsoffset
# fix RPATH
sed -i 's|sysrpath =.*|sysrpath = ["%{_libdir}"]|' SConstruct
More information about the scm-commits
mailing list