"Initial commit to Gerrit"
[profile/ivi/gpsd.git] / libgpsd_core.c
1 /* libgpsd_core.c -- direct access to GPSes on serial or USB devices.
2  *
3  * This file is Copyright (c) 2010 by the GPSD project
4  * BSD terms apply: see the file COPYING in the distribution root for details.
5  */
6 #include <stdlib.h>
7 #include "gpsd_config.h"
8 #include <sys/time.h>
9 #ifdef HAVE_SYS_IOCTL_H
10 #include <sys/ioctl.h>
11 #endif /* HAVE_SYS_IOCTL_H */
12 #ifndef S_SPLINT_S
13 #ifdef HAVE_SYS_SOCKET_H
14 #include <sys/socket.h>
15 #else
16 #define AF_UNSPEC 0
17 #endif /* HAVE_SYS_SOCKET_H */
18 #include <unistd.h>
19 #endif /* S_SPLINT_S */
20 #include <sys/time.h>
21 #include <stdio.h>
22 #include <math.h>
23 #ifndef S_SPLINT_S
24 #ifdef HAVE_NETDB_H
25 #include <netdb.h>
26 #endif /* HAVE_NETDB_H */
27 #endif /* S_SPLINT_S */
28 #include <string.h>
29 #include <errno.h>
30 #include <fcntl.h>
31
32 #include "gpsd.h"
33
34 #if defined(PPS_ENABLE) && defined(TIOCMIWAIT)
35 #ifndef S_SPLINT_S
36 #include <pthread.h>            /* pacifies OpenBSD's compiler */
37 #endif
38 #endif
39
40 int gpsd_switch_driver(struct gps_device_t *session, char *type_name)
41 {
42     const struct gps_type_t **dp;
43     bool identified = (session->device_type != NULL);
44
45     gpsd_report(LOG_PROG, "switch_driver(%s) called...\n", type_name);
46     if (identified && strcmp(session->device_type->type_name, type_name) == 0)
47         return 0;
48
49     /*@ -compmempass @*/
50     for (dp = gpsd_drivers; *dp; dp++)
51         if (strcmp((*dp)->type_name, type_name) == 0) {
52             gpsd_report(LOG_PROG, "selecting %s driver...\n",
53                         (*dp)->type_name);
54             gpsd_assert_sync(session);
55             /*@i@*/ session->device_type = *dp;
56 #ifdef ALLOW_RECONFIGURE
57             session->gpsdata.dev.mincycle = session->device_type->min_cycle;
58 #endif /* ALLOW_RECONFIGURE */
59             /* reconfiguration might be required */
60             if (identified && session->device_type->event_hook != NULL)
61                 session->device_type->event_hook(session,
62                                                  event_driver_switch);
63             /* clients should be notified */
64             session->notify_clients = true;
65             return 1;
66         }
67     gpsd_report(LOG_ERROR, "invalid GPS type \"%s\".\n", type_name);
68     return 0;
69     /*@ +compmempass @*/
70 }
71
72
73 void gpsd_init(struct gps_device_t *session, struct gps_context_t *context,
74                char *device)
75 /* initialize GPS polling */
76 {
77     /*@ -mayaliasunique @*/
78     if (device != NULL)
79         (void)strlcpy(session->gpsdata.dev.path, device,
80                       sizeof(session->gpsdata.dev.path));
81     /*@ -mustfreeonly @*/
82     session->device_type = NULL;        /* start by hunting packets */
83     session->observed = 0;
84     session->rtcmtime = 0;
85     session->is_serial = false; /* gpsd_open() sets this */
86     session->sourcetype = source_unknown;       /* gpsd_open() sets this */
87     /*@ -temptrans @*/
88     session->context = context;
89     /*@ +temptrans @*/
90     /*@ +mayaliasunique @*/
91     /*@ +mustfreeonly @*/
92     gps_clear_fix(&session->gpsdata.fix);
93     gps_clear_fix(&session->newdata);
94     gps_clear_fix(&session->oldfix);
95     session->gpsdata.set = 0;
96     session->gpsdata.dop.hdop = NAN;
97     session->gpsdata.dop.vdop = NAN;
98     session->gpsdata.dop.pdop = NAN;
99     session->gpsdata.dop.tdop = NAN;
100     session->gpsdata.dop.gdop = NAN;
101     session->gpsdata.epe = NAN;
102     session->mag_var = NAN;
103     session->gpsdata.dev.cycle = session->gpsdata.dev.mincycle = 1;
104
105     /* tty-level initialization */
106     gpsd_tty_init(session);
107     /* necessary in case we start reading in the middle of a GPGSV sequence */
108     gpsd_zero_satellites(&session->gpsdata);
109
110     /* initialize things for the packet parser */
111     packet_reset(&session->packet);
112 }
113
114 void gpsd_deactivate(struct gps_device_t *session)
115 /* temporarily release the GPS device */
116 {
117 #ifdef NTPSHM_ENABLE
118     (void)ntpshm_free(session->context, session->shmindex);
119     session->shmindex = -1;
120 # ifdef PPS_ENABLE
121     (void)ntpshm_free(session->context, session->shmTimeP);
122     session->shmTimeP = -1;
123 # endif /* PPS_ENABLE */
124 #endif /* NTPSHM_ENABLE */
125 #ifdef ALLOW_RECONFIGURE
126     if (!session->context->readonly
127         && session->device_type != NULL
128         && session->device_type->event_hook != NULL) {
129         session->device_type->event_hook(session, event_deactivate);
130     }
131     if (session->device_type != NULL) {
132         if (session->back_to_nmea
133             && session->device_type->mode_switcher != NULL)
134             session->device_type->mode_switcher(session, 0);
135     }
136 #endif /* ALLOW_RECONFIGURE */
137     gpsd_report(LOG_INF, "closing GPS=%s (%d)\n",
138                 session->gpsdata.dev.path, session->gpsdata.gps_fd);
139     (void)gpsd_close(session);
140 }
141
142 #if defined(PPS_ENABLE) && defined(TIOCMIWAIT)
143 static /*@null@*/ void *gpsd_ppsmonitor(void *arg)
144 {
145     struct gps_device_t *session = (struct gps_device_t *)arg;
146     int cycle, duration, state = 0, laststate = -1, unchanged = 0;
147     struct timeval tv;
148     struct timeval pulse[2] = { {0, 0}, {0, 0} };
149
150 #if defined(PPS_ON_CTS)
151     int pps_device = TIOCM_CTS;
152 #define pps_device_str "CTS"
153 #else
154     int pps_device = TIOCM_CAR;
155 #define pps_device_str "DCD"
156 #endif
157
158     gpsd_report(LOG_PROG, "PPS Create Thread gpsd_ppsmonitor\n");
159
160     /* wait for status change on the device's carrier-detect line */
161     while (ioctl(session->gpsdata.gps_fd, TIOCMIWAIT, pps_device) == 0) {
162         int ok = 0;
163         char *log = NULL;
164
165         (void)gettimeofday(&tv, NULL);
166
167         ok = 0;
168         log = NULL;
169
170         /*@ +ignoresigns */
171         if (ioctl(session->gpsdata.gps_fd, TIOCMGET, &state) != 0)
172             break;
173         /*@ -ignoresigns */
174
175         state = (int)((state & pps_device) != 0);
176         /*@ +boolint @*/
177 #define timediff(x, y)  (int)((x.tv_sec-y.tv_sec)*1000000+x.tv_usec-y.tv_usec)
178         cycle = timediff(tv, pulse[state]);
179         duration = timediff(tv, pulse[(int)(state == 0)]);
180 #undef timediff
181         /*@ -boolint @*/
182
183         if (state == laststate) {
184             /* some pulses may be so short that state never changes */
185             if (999000 < cycle && 1001000 > cycle) {
186                 duration = 0;
187                 unchanged = 0;
188                 gpsd_report(LOG_RAW,
189                             "PPS pps-detect (%s) on %s invisible pulse\n",
190                             pps_device_str, session->gpsdata.dev.path);
191             } else if (++unchanged == 10) {
192                 unchanged = 1;
193                 gpsd_report(LOG_WARN,
194                             "PPS TIOCMIWAIT returns unchanged state, ppsmonitor sleeps 10\n");
195                 (void)sleep(10);
196             }
197         } else {
198             gpsd_report(LOG_RAW, "PPS pps-detect (%s) on %s changed to %d\n",
199                         pps_device_str, session->gpsdata.dev.path, state);
200             laststate = state;
201             unchanged = 0;
202         }
203         pulse[state] = tv;
204         if (unchanged) {
205             // strange, try again
206             continue;
207         }
208         gpsd_report(LOG_INF, "PPS cycle: %d, duration: %d @ %lu.%06lu\n",
209                     cycle, duration,
210                     (unsigned long)tv.tv_sec, (unsigned long)tv.tv_usec);
211
212         /*@ +boolint @*/
213         if (3 < session->context->fixcnt) {
214             /* Garmin doc says PPS is valid after four good fixes. */
215             /*
216              * The PPS pulse is normally a short pulse with a frequency of
217              * 1 Hz, and the UTC second is defined by the front edge. But we
218              * don't know the polarity of the pulse (different receivers
219              * emit different polarities). The duration variable is used to
220              * determine which way the pulse is going. The code assumes
221              * that the UTC second is changing when the signal has not
222              * been changing for at least 800ms, i.e. it assumes the duty
223              * cycle is at most 20%.
224              *
225              * Some GPS instead output a square wave that is 0.5 Hz and each
226              * edge denotes the start of a second.
227              *
228              * Some GPS, like the Globalsat MR-350P, output a 1uS pulse.
229              * The pulse is so short that TIOCMIWAIT sees a state change
230              * but by the time TIOCMGET is called the pulse is gone.
231              *
232              * A few stupid GPS, like the Furuno GPSClock, output a 1.0 Hz
233              * square wave where the leading edge is the start of a second
234              *
235              * 5Hz GPS (Garmin 18-5Hz) pulses at 5Hz. Set the pulse length to
236              * 40ms which gives a 160ms pulse before going high.
237              *
238              */
239
240             if (199000 > cycle) {
241                 // too short to even be a 5Hz pulse
242                 log = "Too short for 5Hz\n";
243             } else if (201000 > cycle) {
244                 /* 5Hz cycle */
245                 /* looks like 5hz PPS pulse */
246                 if (100000 > duration) {
247                     /* BUG: how does the code know to tell ntpd
248                      * which 1/5 of a second to use?? */
249                     ok = 1;
250                     log = "5Hz PPS pulse\n";
251                 }
252             } else if (999000 > cycle) {
253                 log = "Too long for 5Hz, too short for 1Hz\n";
254             } else if (1001000 > cycle) {
255                 /* looks like PPS pulse or square wave */
256                 if (0 == duration) {
257                     ok = 1;
258                     log = "PPS invisible pulse\n";
259                 } else if (499000 > duration) {
260                     /* end of the short "half" of the cycle */
261                     /* aka the trailing edge */
262                     log = "PPS 1Hz trailing edge\n";
263                 } else if (501000 > duration) {
264                     /* looks like 1.0 Hz square wave, ignore trailing edge */
265                     if (state == 1) {
266                         ok = 1;
267                         log = "PPS square\n";
268                     }
269                 } else {
270                     /* end of the long "half" of the cycle */
271                     /* aka the leading edge */
272                     ok = 1;
273                     log = "PPS 1Hz leading edge\n";
274                 }
275             } else if (1999000 > cycle) {
276                 log = "Too long for 1Hz, too short for 2Hz\n";
277             } else if (2001000 > cycle) {
278                 /* looks like 0.5 Hz square wave */
279                 if (999000 > duration) {
280                     log = "PPS 0.5 Hz square too short duration\n";
281                 } else if (1001000 > duration) {
282                     ok = 1;
283                     log = "PPS 0.5 Hz square wave\n";
284                 } else {
285                     log = "PPS 0.5 Hz square too long duration\n";
286                 }
287             } else {
288                 log = "Too long for 0.5Hz\n";
289             }
290         } else {
291             /* not a good fix, but a test for an otherwise good PPS
292              * would go here */
293             log = "PPS no fix.\n";
294         }
295         /*@ -boolint @*/
296         if (NULL != log) {
297             gpsd_report(LOG_RAW, "%s\n", log);
298         }
299         if (0 != ok) {
300             (void)ntpshm_pps(session, &tv);
301         } else {
302             gpsd_report(LOG_INF, "PPS pulse rejected\n");
303         }
304
305     }
306
307     return NULL;
308 }
309 #endif /* PPS_ENABLE */
310
311 /*@ -branchstate @*/
312 int gpsd_activate(struct gps_device_t *session)
313 /* acquire a connection to the GPS device */
314 {
315     /* special case: source may be a URI to a remote GNSS or DGPS service */
316     if (netgnss_uri_check(session->gpsdata.dev.path)) {
317         session->gpsdata.gps_fd = netgnss_uri_open(session->context,
318                                                    session->gpsdata.dev.path);
319         session->sourcetype = source_tcp;
320         gpsd_report(LOG_SPIN,
321                     "netgnss_uri_open(%s) returns socket on fd %d\n",
322                     session->gpsdata.dev.path, session->gpsdata.gps_fd);
323         /* otherwise, could be an TCP data feed */
324     } else if (strncmp(session->gpsdata.dev.path, "tcp://", 6) == 0) {
325         char server[GPS_PATH_MAX], *port;
326         socket_t dsock;
327         (void)strlcpy(server, session->gpsdata.dev.path + 6, sizeof(server));
328         session->gpsdata.gps_fd = -1;
329         port = strchr(server, ':');
330         if (port == NULL) {
331             gpsd_report(LOG_ERROR, "Missing colon in TCP feed spec.\n");
332             return -1;
333         }
334         *port++ = '\0';
335         gpsd_report(LOG_INF, "opening TCP feed at %s, port %s.\n", server,
336                     port);
337         if ((dsock = netlib_connectsock(AF_UNSPEC, server, port, "tcp")) < 0) {
338             gpsd_report(LOG_ERROR, "TCP device open error %s.\n",
339                         netlib_errstr(dsock));
340             return -1;
341         }
342         session->gpsdata.gps_fd = dsock;
343         session->sourcetype = source_tcp;
344     } else if (strncmp(session->gpsdata.dev.path, "udp://", 6) == 0) {
345         char server[GPS_PATH_MAX], *port;
346         socket_t dsock;
347         (void)strlcpy(server, session->gpsdata.dev.path + 6, sizeof(server));
348         session->gpsdata.gps_fd = -1;
349         port = strchr(server, ':');
350         if (port == NULL) {
351             gpsd_report(LOG_ERROR, "Missing colon in UDP feed spec.\n");
352             return -1;
353         }
354         *port++ = '\0';
355         gpsd_report(LOG_INF, "opening UDP feed at %s, port %s.\n", server,
356                     port);
357         if ((dsock = netlib_connectsock(AF_UNSPEC, server, port, "udp")) < 0) {
358             gpsd_report(LOG_ERROR, "UDP device open error %s.\n",
359                         netlib_errstr(dsock));
360             return -1;
361         }
362         session->gpsdata.gps_fd = dsock;
363         session->sourcetype = source_udp;
364     }
365     /* otherwise, ordinary serial device */
366     else
367         session->gpsdata.gps_fd = gpsd_open(session);
368
369     if (session->gpsdata.gps_fd < 0)
370         return -1;
371     else {
372 #ifdef NON_NMEA_ENABLE
373         const struct gps_type_t **dp;
374
375         /*@ -mustfreeonly @*/
376         for (dp = gpsd_drivers; *dp; dp++) {
377             (void)tcflush(session->gpsdata.gps_fd, TCIOFLUSH);  /* toss stale data */
378             if ((*dp)->probe_detect != NULL
379                 && (*dp)->probe_detect(session) != 0) {
380                 gpsd_report(LOG_PROG, "probe found %s driver...\n",
381                             (*dp)->type_name);
382                 session->device_type = *dp;
383                 gpsd_assert_sync(session);
384                 goto foundit;
385             }
386         }
387         /*@ +mustfreeonly @*/
388         gpsd_report(LOG_PROG, "no probe matched...\n");
389       foundit:
390 #endif /* NON_NMEA_ENABLE */
391         session->gpsdata.online = timestamp();
392 #ifdef SIRF_ENABLE
393         session->driver.sirf.satcounter = 0;
394 #endif /* SIRF_ENABLE */
395         packet_init(&session->packet);
396         gpsd_report(LOG_INF,
397                     "gpsd_activate(): opened GPS (fd %d)\n",
398                     session->gpsdata.gps_fd);
399         // session->gpsdata.online = 0;
400         session->gpsdata.fix.mode = MODE_NOT_SEEN;
401         session->gpsdata.status = STATUS_NO_FIX;
402         session->gpsdata.fix.track = NAN;
403         session->gpsdata.separation = NAN;
404         session->mag_var = NAN;
405         session->releasetime = 0;
406         session->getcount = 0;
407
408         /* clear the private data union */
409         memset(&session->driver, '\0', sizeof(session->driver));
410         /*
411          * We might know the device's type, but we shoudn't assume it has
412          * retained its settings.  A revert hook might well have undone
413          * them on the previous close.  Fire a reactivate event so drivers
414          * can do something about this if they choose.
415          */
416         if (session->device_type != NULL
417             && session->device_type->event_hook != NULL)
418             session->device_type->event_hook(session, event_reactivate);
419     }
420
421     session->opentime = timestamp();
422     return session->gpsdata.gps_fd;
423 }
424
425 /*@ +branchstate @*/
426
427 void ntpd_link_activate(struct gps_device_t *session)
428 {
429 #if defined(PPS_ENABLE) && defined(TIOCMIWAIT)
430     pthread_t pt;
431 #endif /* defined(PPS_ENABLE) && defined(TIOCMIWAIT) */
432
433 #ifdef NTPSHM_ENABLE
434     /* If we are talking to ntpd, allocate a shared-memory segment for "NMEA" time data */
435     if (session->context->enable_ntpshm)
436         session->shmindex = ntpshm_alloc(session->context);
437
438     if (0 > session->shmindex) {
439         gpsd_report(LOG_INF, "NTPD ntpshm_alloc() failed\n");
440 #if defined(PPS_ENABLE) && defined(TIOCMIWAIT)
441     } else if (session->context->shmTimePPS) {
442         /* We also have the 1pps capability, allocate a shared-memory segment
443          * for the 1pps time data and launch a thread to capture the 1pps
444          * transitions
445          */
446         if ((session->shmTimeP = ntpshm_alloc(session->context)) >= 0) {
447             /*@-unrecog@*/
448             (void)pthread_create(&pt, NULL, gpsd_ppsmonitor, (void *)session);
449             /*@+unrecog@*/
450         } else {
451             gpsd_report(LOG_INF, "NTPD ntpshm_alloc(1) failed\n");
452         }
453
454 #endif /* defined(PPS_ENABLE) && defined(TIOCMIWAIT) */
455     }
456 #endif /* NTPSHM_ENABLE */
457 }
458
459 char /*@observer@*/ *gpsd_id( /*@in@ */ struct gps_device_t *session)
460 /* full ID of the device for reports, including subtype */
461 {
462     static char buf[128];
463     if ((session == NULL) || (session->device_type == NULL) ||
464         (session->device_type->type_name == NULL))
465         return "unknown,";
466     (void)strlcpy(buf, session->device_type->type_name, sizeof(buf));
467     if (session->subtype[0] != '\0') {
468         (void)strlcat(buf, " ", sizeof(buf));
469         (void)strlcat(buf, session->subtype, sizeof(buf));
470     }
471     return (buf);
472 }
473
474 static void gpsd_error_model(struct gps_device_t *session,
475                              struct gps_fix_t *fix, struct gps_fix_t *oldfix)
476 /* compute errors and derived quantities */
477 {
478     /*
479      * Now we compute derived quantities.  This is where the tricky error-
480      * modeling stuff goes. Presently we don't know how to derive
481      * time error.
482      *
483      * Some drivers set the position-error fields.  Only the Zodiacs
484      * report speed error.  Nobody reports track error or climb error.
485      *
486      * The UERE constants are our assumption about the base error of
487      * GPS fixes in different directions.
488      */
489 #define H_UERE_NO_DGPS          15.0    /* meters, 95% confidence */
490 #define H_UERE_WITH_DGPS        3.75    /* meters, 95% confidence */
491 #define V_UERE_NO_DGPS          23.0    /* meters, 95% confidence */
492 #define V_UERE_WITH_DGPS        5.75    /* meters, 95% confidence */
493 #define P_UERE_NO_DGPS          19.0    /* meters, 95% confidence */
494 #define P_UERE_WITH_DGPS        4.75    /* meters, 95% confidence */
495     double h_uere, v_uere, p_uere;
496
497     if (NULL == session)
498         return;
499
500     h_uere =
501         (session->gpsdata.status ==
502          STATUS_DGPS_FIX ? H_UERE_WITH_DGPS : H_UERE_NO_DGPS);
503     v_uere =
504         (session->gpsdata.status ==
505          STATUS_DGPS_FIX ? V_UERE_WITH_DGPS : V_UERE_NO_DGPS);
506     p_uere =
507         (session->gpsdata.status ==
508          STATUS_DGPS_FIX ? P_UERE_WITH_DGPS : P_UERE_NO_DGPS);
509
510     /*
511      * OK, this is not an error computation, but we're at the right
512      * place in the architecture for it.  Compute speed over ground
513      * and climb/sink in the simplest possible way.
514      */
515     if (fix->mode >= MODE_2D && oldfix->mode >= MODE_2D
516         && isnan(fix->speed) != 0) {
517         if (fix->time == oldfix->time)
518             fix->speed = 0;
519         else
520             fix->speed =
521                 earth_distance(fix->latitude, fix->longitude,
522                                oldfix->latitude, oldfix->longitude)
523                 / (fix->time - oldfix->time);
524     }
525     if (fix->mode >= MODE_3D && oldfix->mode >= MODE_3D
526         && isnan(fix->climb) != 0) {
527         if (fix->time == oldfix->time)
528             fix->climb = 0;
529         else if (isnan(fix->altitude) == 0 && isnan(oldfix->altitude) == 0) {
530             fix->climb =
531                 (fix->altitude - oldfix->altitude) / (fix->time -
532                                                       oldfix->time);
533         }
534     }
535
536     /*
537      * Field reports match the theoretical prediction that
538      * expected time error should be half the resolution of
539      * the GPS clock, so we put the bound of the error
540      * in as a constant pending getting it from each driver.
541      */
542     if (isnan(fix->time) == 0 && isnan(fix->ept) != 0)
543         fix->ept = 0.005;
544     /* Other error computations depend on having a valid fix */
545     gpsd_report(LOG_DATA, "modeling errors: mode=%d, masks=%s\n",
546                 fix->mode, gpsd_maskdump(session->gpsdata.set));
547     if (fix->mode >= MODE_2D) {
548         if (isnan(fix->epx) != 0 && finite(session->gpsdata.dop.hdop) != 0)
549             fix->epx = session->gpsdata.dop.xdop * h_uere;
550
551         if (isnan(fix->epy) != 0 && finite(session->gpsdata.dop.hdop) != 0)
552             fix->epy = session->gpsdata.dop.ydop * h_uere;
553
554         if ((fix->mode >= MODE_3D)
555             && isnan(fix->epv) != 0 && finite(session->gpsdata.dop.vdop) != 0)
556             fix->epv = session->gpsdata.dop.vdop * v_uere;
557
558         if (isnan(session->gpsdata.epe) != 0
559             && finite(session->gpsdata.dop.pdop) != 0)
560             session->gpsdata.epe = session->gpsdata.dop.pdop * p_uere;
561         else
562             session->gpsdata.epe = NAN;
563
564         /*
565          * If we have a current fix and an old fix, and the packet handler
566          * didn't set the speed error and climb error members itself,
567          * try to compute them now.
568          */
569         if (isnan(fix->eps) != 0) {
570             if (oldfix->mode > MODE_NO_FIX && fix->mode > MODE_NO_FIX
571                 && isnan(oldfix->epx) == 0 && isnan(oldfix->epy) == 0
572                 && isnan(oldfix->time) == 0 && isnan(oldfix->time) == 0
573                 && fix->time > oldfix->time) {
574                 double t = fix->time - oldfix->time;
575                 double e =
576                     EMIX(oldfix->epx, oldfix->epy) + EMIX(fix->epx, fix->epy);
577                 fix->eps = e / t;
578             } else
579                 fix->eps = NAN;
580         }
581         if ((fix->mode >= MODE_3D)
582             && isnan(fix->epc) != 0 && fix->time > oldfix->time) {
583             if (oldfix->mode > MODE_3D && fix->mode > MODE_3D) {
584                 double t = fix->time - oldfix->time;
585                 double e = oldfix->epv + fix->epv;
586                 /* if vertical uncertainties are zero this will be too */
587                 fix->epc = e / t;
588             }
589             /*
590              * We compute a track error estimate solely from the
591              * position of this fix and the last one.  The maximum
592              * track error, as seen from the position of last fix, is
593              * the angle subtended by the two most extreme possible
594              * error positions of the current fix; the expected track
595              * error is half that.  Let the position of the old fix be
596              * A and of the new fix B.  We model the view from A as
597              * two right triangles ABC and ABD with BC and BD both
598              * having the length of the new fix's estimated error.
599              * adj = len(AB), opp = len(BC) = len(BD), hyp = len(AC) =
600              * len(AD). This leads to spurious uncertainties
601              * near 180 when we're moving slowly; to avoid reporting
602              * garbage, throw back NaN if the distance from the previous
603              * fix is less than the error estimate.
604              */
605             fix->epd = NAN;
606             if (oldfix->mode >= MODE_2D) {
607                 double adj =
608                     earth_distance(oldfix->latitude, oldfix->longitude,
609                                    fix->latitude, fix->longitude);
610                 if (isnan(adj) == 0 && adj > EMIX(fix->epx, fix->epy)) {
611                     double opp = EMIX(fix->epx, fix->epy);
612                     double hyp = sqrt(adj * adj + opp * opp);
613                     fix->epd = RAD_2_DEG * 2 * asin(opp / hyp);
614                 }
615             }
616         }
617     }
618
619     /* save old fix for later error computations */
620     /*@ -mayaliasunique @*/
621     if (fix->mode >= MODE_2D)
622         (void)memcpy(oldfix, fix, sizeof(struct gps_fix_t));
623     /*@ +mayaliasunique @*/
624 }
625
626 gps_mask_t gpsd_poll(struct gps_device_t *session)
627 /* update the stuff in the scoreboard structure */
628 {
629     ssize_t newlen;
630     bool first_sync = false;
631
632     gps_clear_fix(&session->newdata);
633
634 #ifdef TIMING_ENABLE
635     if (session->packet.outbuflen == 0)
636         session->d_xmit_time = timestamp();
637 #endif /* TIMING_ENABLE */
638
639     if (session->packet.type >= COMMENT_PACKET) {
640         /*@-shiftnegative@*/
641         session->observed |= PACKET_TYPEMASK(session->packet.type);
642         /*@+shiftnegative@*/
643     }
644
645     /* can we get a full packet from the device? */
646     if (session->device_type) {
647         newlen = session->device_type->get_packet(session);
648         gpsd_report(LOG_RAW,
649                     "%s is known to be %s\n",
650                     session->gpsdata.dev.path,
651                     session->device_type->type_name);
652     } else {
653         const struct gps_type_t **dp;
654
655         newlen = generic_get(session);
656         gpsd_report(LOG_RAW,
657                     "packet sniff on %s finds type %d\n",
658                     session->gpsdata.dev.path, session->packet.type);
659         if (session->packet.type == COMMENT_PACKET) {
660             gpsd_report (LOG_PROG, "comment, sync lock deferred\n");
661         } else if (session->packet.type > COMMENT_PACKET) {
662             first_sync = (session->device_type == NULL);
663             for (dp = gpsd_drivers; *dp; dp++)
664                 if (session->packet.type == (*dp)->packet_type) {
665                     (void)gpsd_switch_driver(session, (*dp)->type_name);
666                     break;
667                 }
668         } else if (session->getcount++ > 1 && !gpsd_next_hunt_setting(session))
669             return ERROR_IS;
670     }
671
672     /* update the scoreboard structure from the GPS */
673     gpsd_report(LOG_RAW + 2, "%s sent %zd new characters\n",
674                 session->gpsdata.dev.path, newlen);
675     if (newlen < 0) {           /* read error */
676         gpsd_report(LOG_INF, "GPS on %s returned error %zd (%lf sec since data)\n",
677                     session->gpsdata.dev.path, newlen,
678                     timestamp() - session->gpsdata.online);
679         session->gpsdata.online = 0;
680         return ERROR_IS;
681     } else if (newlen == 0) {           /* zero length read, possible EOF */
682         gpsd_report(LOG_INF, "GPS on %s is offline (%lf sec since data)\n",
683                     session->gpsdata.dev.path,
684                     timestamp() - session->gpsdata.online);
685         session->gpsdata.online = 0;
686         return NODATA_IS;
687     } else if (session->packet.outbuflen == 0) {        /* got new data, but no packet */
688         gpsd_report(LOG_RAW + 3, "New data on %s, not yet a packet\n",
689                     session->gpsdata.dev.path);
690         return ONLINE_IS;
691     } else {                    /* we have recognized a packet */
692         gps_mask_t received = PACKET_IS, dopmask = 0;
693         session->gpsdata.online = timestamp();
694
695         gpsd_report(LOG_RAW + 3, "Accepted packet on %s.\n",
696                     session->gpsdata.dev.path);
697
698 #ifdef TIMING_ENABLE
699         session->d_recv_time = timestamp();
700 #endif /* TIMING_ENABLE */
701
702         /* track the packet count since achieving sync on the device */
703         if (first_sync) {
704             /*@-nullderef@*/
705             gpsd_report(LOG_INF,
706                         "%s identified as type %s (%f sec @ %dbps)\n",
707                         session->gpsdata.dev.path,
708                         session->device_type->type_name,
709                         timestamp() - session->opentime,
710                         gpsd_get_speed(&session->ttyset));
711             /*@+nullderef@*/
712             /* fire the identified hook */
713             if (session->device_type != NULL
714                 && session->device_type->event_hook != NULL)
715                 session->device_type->event_hook(session, event_identified);
716             session->packet.counter = 0;
717         } else
718             session->packet.counter++;
719
720         /* fire the configure hook */
721         if (session->device_type != NULL
722             && session->device_type->event_hook != NULL)
723             session->device_type->event_hook(session, event_configure);
724
725         /*
726          * If this is the first time we've achieved sync on this
727          * device, or the driver type has changed for any other
728          * reason, that's a significant event that the caller needs to
729          * know about.
730          */
731         if (first_sync || session->notify_clients) {
732             session->notify_clients = false;
733             received |= DRIVER_IS;
734         }
735
736         /* Get data from current packet into the fix structure */
737         if (session->packet.type != COMMENT_PACKET)
738             if (session->device_type != NULL
739                 && session->device_type->parse_packet != NULL)
740                 received |= session->device_type->parse_packet(session);
741
742 #ifdef NTPSHM_ENABLE
743         /*
744          * Only update the NTP time if we've seen the leap-seconds data. 
745          * Else we may be providing GPS time.
746          */
747         if (session->context->enable_ntpshm == 0) {
748             //gpsd_report(LOG_PROG, "NTP: off\n");
749         } else if ((received & TIME_IS) == 0) {
750             //gpsd_report(LOG_PROG, "NTP: No time this packet\n");
751         } else if (isnan(session->newdata.time)) {
752             //gpsd_report(LOG_PROG, "NTP: bad new time\n");
753         } else if (session->newdata.time == session->last_fixtime) {
754             //gpsd_report(LOG_PROG, "NTP: Not a new time\n");
755         } else if (session->newdata.mode == MODE_NO_FIX) {
756             //gpsd_report(LOG_PROG, "NTP: No fix\n");
757         } else {
758             double offset;
759             //gpsd_report(LOG_PROG, "NTP: Got one\n");
760             /* assume zero when there's no offset method */
761             if (session->device_type == NULL
762                 || session->device_type->ntp_offset == NULL)
763                 offset = 0.0;
764             else
765                 offset = session->device_type->ntp_offset(session);
766             (void)ntpshm_put(session, session->newdata.time, offset);
767             session->last_fixtime = session->newdata.time;
768         }
769 #endif /* NTPSHM_ENABLE */
770
771         /*
772          * Compute fix-quality data from the satellite positions.
773          * These will not overwrite any DOPs reported from the packet
774          * we just got.
775          */
776         if ((received & SATELLITE_IS) != 0
777             && session->gpsdata.satellites_visible > 0) {
778             dopmask = fill_dop(&session->gpsdata, &session->gpsdata.dop);
779             session->gpsdata.epe = NAN;
780         }
781         session->gpsdata.set = ONLINE_IS | dopmask | received;
782
783         /* copy/merge device data into staging buffers */
784         /*@-nullderef -nullpass@*/
785         if ((session->gpsdata.set & CLEAR_IS) != 0)
786             gps_clear_fix(&session->gpsdata.fix);
787         /* don't downgrade mode if holding previous fix */
788         if (session->gpsdata.fix.mode > session->newdata.mode)
789             session->gpsdata.set &= ~MODE_IS;
790         //gpsd_report(LOG_PROG,
791         //              "transfer mask on %s: %02x\n", session->gpsdata.tag, session->gpsdata.set);
792         gps_merge_fix(&session->gpsdata.fix,
793                       session->gpsdata.set, &session->newdata);
794         gpsd_error_model(session, &session->gpsdata.fix, &session->oldfix);
795         /*@+nullderef -nullpass@*/
796
797         /*
798          * Count good fixes. We used to check
799          *      session->gpsdata.status > STATUS_NO_FIX
800          * here, but that wasn't quite right.  That tells us whether
801          * we think we have a valid fix for the current cycle, but remains
802          * true while following non-fix packets are received.  What we
803          * really want to know is whether the last packet received was a
804          * fix packet AND held a valid fix. We must ignore non-fix packets
805          * AND packets which have fix data but are flagged as invalid. Some
806          * devices output fix packets on a regular basis, even when unable
807          * to derive a good fix. Such packets should set STATUS_NO_FIX.
808          */
809         if ((session->gpsdata.set & LATLON_IS) != 0
810             && session->gpsdata.status > STATUS_NO_FIX)
811             session->context->fixcnt++;
812
813 #ifdef TIMING_ENABLE
814         session->d_decode_time = timestamp();
815 #endif /* TIMING_ENABLE */
816
817         /*
818          * Sanity check.  This catches a surprising number of port and
819          * driver errors, including 32-vs.-64-bit problems.
820          */
821         /*@+relaxtypes +longunsignedintegral@*/
822         if ((session->gpsdata.set & TIME_IS) != 0) {
823             if (session->newdata.time > time(NULL) + (60 * 60 * 24 * 365))
824                 gpsd_report(LOG_ERROR,
825                             "date more than a year in the future!\n");
826             else if (session->newdata.time < 0)
827                 gpsd_report(LOG_ERROR, "date is negative!\n");
828         }
829         /*@-relaxtypes -longunsignedintegral@*/
830
831         return session->gpsdata.set;
832     }
833 }
834
835 void gpsd_wrap(struct gps_device_t *session)
836 /* end-of-session wrapup */
837 {
838     if (session->gpsdata.gps_fd != -1)
839         gpsd_deactivate(session);
840 }
841
842 void gpsd_zero_satellites( /*@out@*/ struct gps_data_t *out)
843 {
844     (void)memset(out->PRN, 0, sizeof(out->PRN));
845     (void)memset(out->elevation, 0, sizeof(out->elevation));
846     (void)memset(out->azimuth, 0, sizeof(out->azimuth));
847     (void)memset(out->ss, 0, sizeof(out->ss));
848     out->satellites_visible = 0;
849     clear_dop(&out->dop);
850 }