summaryrefslogtreecommitdiff
path: root/gpsd.h
diff options
context:
space:
mode:
authorFred Wright <fw@fwright.net>2017-01-24 15:56:17 -0800
committerFred Wright <fw@fwright.net>2017-01-24 16:24:32 -0800
commit744959a2aa3f913e5491c9fe9bac067a670f7de6 (patch)
treef331e32a950f613364cff3b6111fd4870bfc9b2d /gpsd.h
parent2cb17f91607bdfd9cd7ad80f7232db8b1bd23d34 (diff)
downloadgpsd-744959a2aa3f913e5491c9fe9bac067a670f7de6.tar.gz
Eliminates autogeneration of gpsd.h.
The reason for directly including the contents of gpsd_config.h in gpsd.h is long gone, so there's no longer any reason to create the latter by concatenation rather than just making it a normal header which #includes gpsd_config.h. This is a minimal rework of this form. TESTED: Ran "scons build-all check" on OSX 10.9 and Fedora 25 (without Qt in the latter case, where the Qt build needs further work).
Diffstat (limited to 'gpsd.h')
-rw-r--r--gpsd.h1003
1 files changed, 1003 insertions, 0 deletions
diff --git a/gpsd.h b/gpsd.h
new file mode 100644
index 00000000..c69facd0
--- /dev/null
+++ b/gpsd.h
@@ -0,0 +1,1003 @@
+/* gpsd.h -- fundamental types and structures for the gpsd library
+ *
+ * This file is Copyright (c) 2017 by the GPSD project
+ * BSD terms apply: see the file COPYING in the distribution root for details.
+ */
+
+#ifndef _GPSD_H_
+#define _GPSD_H_
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <time.h> /* for time_t */
+
+#include "gpsd_config.h"
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <termios.h>
+
+#include "gps.h"
+#include "compiler.h"
+#include "os_compat.h"
+
+/*
+ * Constants for the VERSION response
+ * 3.1: Base JSON version
+ * 3.2: Added POLL command and response
+ * 3.3: AIS app_id split into DAC and FID
+ * 3.4: Timestamps change from seconds since Unix epoch to ISO8601.
+ * 3.5: POLL subobject name changes: fixes -> tpv, skyview -> sky.
+ * DEVICE::activated becomes ISO8601 rather than real.
+ * 3.6 VERSION, WATCH, and DEVICES from slave gpsds get "remote" attribute.
+ * 3.7 PPS message added to repertoire. SDDBT water depth reported as
+ * negative altitude with Mode 3 set.
+ * 3.8 AIS course member becomes float in scaled mode (bug fix).
+ * 3.9 split24 flag added. Controlled-vocabulary fields are now always
+ * dumped in both numeric and string form, with the string being the
+ * value of a synthesized additional attribute with "_text" appended.
+ * (Thus, the 'scaled' flag no longer affects display of these fields.)
+ * PPS drift message ships nsec rather than msec.
+ * 3.10 The obsolete tag field has been dropped from JSON.
+ * 3.11 A precision field, log2 of the time source jitter, has been added
+ * to the PPS report. See ntpshm.h for more details.
+ * 3.12 OSC message added to repertoire.
+ */
+#define GPSD_PROTO_MAJOR_VERSION 3 /* bump on incompatible changes */
+#define GPSD_PROTO_MINOR_VERSION 12 /* bump on compatible changes */
+
+#define JSON_DATE_MAX 24 /* ISO8601 timestamp with 2 decimal places */
+
+#ifndef DEFAULT_GPSD_SOCKET
+#define DEFAULT_GPSD_SOCKET "/var/run/gpsd.sock"
+#endif
+
+/* Some internal capabilities depend on which drivers we're compiling. */
+#if !defined(AIVDM_ENABLE) && defined(NMEA2000_ENABLE)
+#define AIVDM_ENABLE
+#endif
+#if !defined(NMEA0183_ENABLE) && (defined(ASHTECH_ENABLE) || defined(FV18_ENABLE) || defined(MTK3301_ENABLE) || defined(TNT_ENABLE) || defined(OCEANSERVER_ENABLE) || defined(GPSCLOCK_ENABLE) || defined(FURY_ENABLE) || defined(SKYTRAQ_ENABLE) || defined(TRIPMATE_ENABLE))
+#define NMEA0183_ENABLE
+#endif
+#ifdef EARTHMATE_ENABLE
+#define ZODIAC_ENABLE
+#endif
+#if defined(ZODIAC_ENABLE) || defined(SIRF_ENABLE) || defined(GARMIN_ENABLE) || defined(TSIP_ENABLE) || defined(EVERMORE_ENABLE) || defined(ITRAX_ENABLE) || defined(UBLOX_ENABLE) || defined(SUPERSTAR2_ENABLE) || defined(ONCORE_ENABLE) || defined(GEOSTAR_ENABLE) || defined(NAVCOM_ENABLE) || defined(NMEA2000_ENABLE)
+#define BINARY_ENABLE
+#endif
+#if defined(TRIPMATE_ENABLE) || defined(BINARY_ENABLE)
+#define NON_NMEA0183_ENABLE
+#endif
+#if defined(TNT_ENABLE) || defined(OCEANSERVER_ENABLE)
+#define COMPASS_ENABLE
+#endif
+#ifdef NTPSHM_ENABLE
+#define TIMEHINT_ENABLE
+#endif
+#ifdef ISYNC_ENABLE
+#define STASH_ENABLE
+#endif
+
+/* First, declarations for the packet layer... */
+
+/*
+ * NMEA 3.01, Section 5.3 says the max sentence length shall be
+ * 82 chars, including the leading $ and terminating \r\n.
+ *
+ * Some receivers (TN-200, GSW 2.3.2) emit oversized sentences.
+ * The Trimble BX-960 receiver emits a 91-character GGA message.
+ * The current hog champion is the Skytraq S2525F8 which emits
+ * a 100-character PSTI message.
+ */
+#define NMEA_MAX 102 /* max length of NMEA sentence */
+#define NMEA_BIG_BUF (2*NMEA_MAX+1) /* longer than longest NMEA sentence */
+
+/* a few bits of ISGPS magic */
+enum isgpsstat_t {
+ ISGPS_NO_SYNC, ISGPS_SYNC, ISGPS_SKIP, ISGPS_MESSAGE,
+};
+
+#define RTCM_MAX (RTCM2_WORDS_MAX * sizeof(isgps30bits_t))
+/* RTCM is more variable length than RTCM 2 */
+#define RTCM3_MAX 512
+
+/*
+ * The packet buffers need to be as long than the longest packet we
+ * expect to see in any protocol, because we have to be able to hold
+ * an entire packet for checksumming...
+ * First we thought it had to be big enough for a SiRF Measured Tracker
+ * Data packet (188 bytes). Then it had to be big enough for a UBX SVINFO
+ * packet (206 bytes). Now it turns out that a couple of ITALK messages are
+ * over 512 bytes. I know we like verbose output, but this is ridiculous.
+ */
+#define MAX_PACKET_LENGTH 516 /* 7 + 506 + 3 */
+
+/*
+ * UTC of second 0 of week 0 of the first rollover period of GPS time.
+ * Used to compute UTC from GPS time. Also, the threshold value
+ * under which system clock times are considered unreliable. Often,
+ * embedded systems come up thinking it's early 1970 and the system
+ * clock will report small positive values until the clock is set. By
+ * choosing this as the cutoff, we'll never reject historical GPS logs
+ * that are actually valid.
+ */
+#define GPS_EPOCH 315964800 /* 6 Jan 1981 00:00:00 UTC */
+
+/* time constant */
+#define SECS_PER_DAY (60*60*24) /* seconds per day */
+#define SECS_PER_WEEK (7*SECS_PER_DAY) /* seconds per week */
+#define GPS_ROLLOVER (1024*SECS_PER_WEEK) /* rollover period */
+
+struct gpsd_errout_t {
+ int debug; /* lexer debug level */
+ void (*report)(const char *); /* reporting hook for lexer errors */
+ char *label;
+};
+
+struct gps_lexer_t {
+ /* packet-getter internals */
+ int type;
+#define BAD_PACKET -1
+#define COMMENT_PACKET 0
+#define NMEA_PACKET 1
+#define AIVDM_PACKET 2
+#define GARMINTXT_PACKET 3
+#define MAX_TEXTUAL_TYPE 3 /* increment this as necessary */
+#define SIRF_PACKET 4
+#define ZODIAC_PACKET 5
+#define TSIP_PACKET 6
+#define EVERMORE_PACKET 7
+#define ITALK_PACKET 8
+#define GARMIN_PACKET 9
+#define NAVCOM_PACKET 10
+#define UBX_PACKET 11
+#define SUPERSTAR2_PACKET 12
+#define ONCORE_PACKET 13
+#define GEOSTAR_PACKET 14
+#define NMEA2000_PACKET 15
+#define MAX_GPSPACKET_TYPE 15 /* increment this as necessary */
+#define RTCM2_PACKET 16
+#define RTCM3_PACKET 17
+#define JSON_PACKET 18
+#define PACKET_TYPES 19 /* increment this as necessary */
+#define SKY_PACKET 20
+#define TEXTUAL_PACKET_TYPE(n) ((((n)>=NMEA_PACKET) && ((n)<=MAX_TEXTUAL_TYPE)) || (n)==JSON_PACKET)
+#define GPS_PACKET_TYPE(n) (((n)>=NMEA_PACKET) && ((n)<=MAX_GPSPACKET_TYPE))
+#define LOSSLESS_PACKET_TYPE(n) (((n)>=RTCM2_PACKET) && ((n)<=RTCM3_PACKET))
+#define PACKET_TYPEMASK(n) (1 << (n))
+#define GPS_TYPEMASK (((2<<(MAX_GPSPACKET_TYPE+1))-1) &~ PACKET_TYPEMASK(COMMENT_PACKET))
+ unsigned int state;
+ size_t length;
+ unsigned char inbuffer[MAX_PACKET_LENGTH*2+1];
+ size_t inbuflen;
+ unsigned char *inbufptr;
+ /* outbuffer needs to be able to hold 4 GPGSV records at once */
+ unsigned char outbuffer[MAX_PACKET_LENGTH*2+1];
+ size_t outbuflen;
+ unsigned long char_counter; /* count characters processed */
+ unsigned long retry_counter; /* count sniff retries */
+ unsigned counter; /* packets since last driver switch */
+ struct gpsd_errout_t errout; /* how to report errors */
+#ifdef TIMING_ENABLE
+ timestamp_t start_time; /* timestamp of first input */
+ unsigned long start_char; /* char counter at first input */
+#endif /* TIMING_ENABLE */
+ /*
+ * ISGPS200 decoding context.
+ *
+ * This is not conditionalized on RTCM104_ENABLE because we need to
+ * be able to build gpsdecode even when RTCM support is not
+ * configured in the daemon.
+ */
+ struct {
+ bool locked;
+ int curr_offset;
+ isgps30bits_t curr_word;
+ unsigned int bufindex;
+ /*
+ * Only these should be referenced from elsewhere, and only when
+ * RTCM_MESSAGE has just been returned.
+ */
+ isgps30bits_t buf[RTCM2_WORDS_MAX]; /* packet data */
+ size_t buflen; /* packet length in bytes */
+ } isgps;
+#ifdef PASSTHROUGH_ENABLE
+ unsigned int json_depth;
+ unsigned int json_after;
+#endif /* PASSTHROUGH_ENABLE */
+#ifdef STASH_ENABLE
+ unsigned char stashbuffer[MAX_PACKET_LENGTH];
+ size_t stashbuflen;
+#endif /* STASH_ENABLE */
+};
+
+extern void lexer_init(struct gps_lexer_t *);
+extern void packet_reset(struct gps_lexer_t *);
+extern void packet_pushback(struct gps_lexer_t *);
+extern void packet_parse(struct gps_lexer_t *);
+extern ssize_t packet_get(int, struct gps_lexer_t *);
+extern int packet_sniff(struct gps_lexer_t *);
+#define packet_buffered_input(lexer) ((lexer)->inbuffer + (lexer)->inbuflen - (lexer)->inbufptr)
+
+/* Next, declarations for the core library... */
+
+/* factors for converting among confidence interval units */
+#define CEP50_SIGMA 1.18
+#define DRMS_SIGMA 1.414
+#define CEP95_SIGMA 2.45
+
+/* this is where we choose the confidence level to use in reports */
+#define GPSD_CONFIDENCE CEP95_SIGMA
+
+#define NTPSHMSEGS (MAX_DEVICES * 2) /* number of NTP SHM segments */
+#define NTP_MIN_FIXES 3 /* # fixes to wait for before shipping NTP time */
+
+
+#define AIVDM_CHANNELS 2 /* A, B */
+
+struct gps_device_t;
+
+struct gps_context_t {
+ int valid; /* member validity flags */
+#define LEAP_SECOND_VALID 0x01 /* we have or don't need correction */
+#define GPS_TIME_VALID 0x02 /* GPS week/tow is valid */
+#define CENTURY_VALID 0x04 /* have received ZDA or 4-digit year */
+ struct gpsd_errout_t errout; /* debug verbosity level and hook */
+ bool readonly; /* if true, never write to device */
+ /* DGPS status */
+ int fixcnt; /* count of good fixes seen */
+ /* timekeeping */
+ time_t start_time; /* local time of daemon startup */
+ int leap_seconds; /* Unix seconds to UTC (GPS-UTC offset) */
+ unsigned short gps_week; /* GPS week, actually 10 bits */
+ double gps_tow; /* GPS time of week, actually 19 bits */
+ int century; /* for NMEA-only devices without ZDA */
+ int rollovers; /* rollovers since start of run */
+#ifdef TIMEHINT_ENABLE
+ int leap_notify; /* notification state from subframe */
+#define LEAP_NOWARNING 0x0 /* normal, no leap second warning */
+#define LEAP_ADDSECOND 0x1 /* last minute of day has 60 seconds */
+#define LEAP_DELSECOND 0x2 /* last minute of day has 59 seconds */
+#define LEAP_NOTINSYNC 0x3 /* overload, clock is free running */
+#endif /* TIMEHINT_ENABLE */
+#ifdef NTPSHM_ENABLE
+ /* we need the volatile here to tell the C compiler not to
+ * 'optimize' as 'dead code' the writes to SHM */
+ volatile struct shmTime *shmTime[NTPSHMSEGS];
+ bool shmTimeInuse[NTPSHMSEGS];
+#endif /* NTPSHM_ENABLE */
+#ifdef PPS_ENABLE
+ void (*pps_hook)(struct gps_device_t *, struct timedelta_t *);
+#endif /* PPS_ENABLE */
+#ifdef SHM_EXPORT_ENABLE
+ /* we don't want the compiler to treat writes to shmexport as dead code,
+ * and we don't want them reordered either */
+ volatile void *shmexport;
+#endif
+ ssize_t (*serial_write)(struct gps_device_t *,
+ const char *buf, const size_t len);
+};
+
+/* state for resolving interleaved Type 24 packets */
+struct ais_type24a_t {
+ unsigned int mmsi;
+ char shipname[AIS_SHIPNAME_MAXLEN+1];
+};
+#define MAX_TYPE24_INTERLEAVE 8 /* max number of queued type 24s */
+struct ais_type24_queue_t {
+ struct ais_type24a_t ships[MAX_TYPE24_INTERLEAVE];
+ int index;
+};
+
+/* state for resolving AIVDM decodes */
+struct aivdm_context_t {
+ /* hold context for decoding AIDVM packet sequences */
+ int decoded_frags; /* for tracking AIDVM parts in a multipart sequence */
+ unsigned char bits[2048];
+ size_t bitlen; /* how many valid bits */
+ struct ais_type24_queue_t type24_queue;
+};
+
+#define MODE_NMEA 0
+#define MODE_BINARY 1
+
+typedef enum {ANY, GPS, RTCM2, RTCM3, AIS} gnss_type;
+typedef enum {
+ event_wakeup,
+ event_triggermatch,
+ event_identified,
+ event_configure,
+ event_driver_switch,
+ event_deactivate,
+ event_reactivate,
+} event_t;
+
+
+#define INTERNAL_SET(n) ((gps_mask_t)(1llu<<(SET_HIGH_BIT+(n))))
+#define RAW_IS INTERNAL_SET(1) /* raw pseudoranges available */
+#define USED_IS INTERNAL_SET(2) /* sat-used count available */
+#define DRIVER_IS INTERNAL_SET(3) /* driver type identified */
+#define CLEAR_IS INTERNAL_SET(4) /* starts a reporting cycle */
+#define REPORT_IS INTERNAL_SET(5) /* ends a reporting cycle */
+#define NODATA_IS INTERNAL_SET(6) /* no data read from fd */
+#define NTPTIME_IS INTERNAL_SET(7) /* precision time is available */
+#define PERR_IS INTERNAL_SET(8) /* PDOP set */
+#define PASSTHROUGH_IS INTERNAL_SET(9) /* passthrough mode */
+#define EOF_IS INTERNAL_SET(10) /* synthetic EOF */
+#define GOODTIME_IS INTERNAL_SET(11) /* time good even if no pos fix */
+#define DATA_IS ~(ONLINE_SET|PACKET_SET|CLEAR_IS|REPORT_IS)
+
+typedef unsigned int driver_mask_t;
+#define DRIVER_NOFLAGS 0x00000000u
+#define DRIVER_STICKY 0x00000001u
+
+/*
+ * True if a device type is non-null and has control methods.
+ */
+#define CONTROLLABLE(dp) (((dp) != NULL) && \
+ ((dp)->speed_switcher != NULL \
+ || (dp)->mode_switcher != NULL \
+ || (dp)->rate_switcher != NULL))
+
+/*
+ * True if a driver selection of it should be sticky.
+ */
+#define STICKY(dp) ((dp) != NULL && ((dp)->flags & DRIVER_STICKY) != 0)
+
+struct gps_type_t {
+/* GPS method table, describes how to talk to a particular GPS type */
+ char *type_name;
+ int packet_type;
+ driver_mask_t flags; /* reserved for expansion */
+ char *trigger;
+ int channels;
+ bool (*probe_detect)(struct gps_device_t *session);
+ ssize_t (*get_packet)(struct gps_device_t *session);
+ gps_mask_t (*parse_packet)(struct gps_device_t *session);
+ ssize_t (*rtcm_writer)(struct gps_device_t *session, const char *rtcmbuf, size_t rtcmbytes);
+ void (*init_query)(struct gps_device_t *session);
+ void (*event_hook)(struct gps_device_t *session, event_t event);
+#ifdef RECONFIGURE_ENABLE
+ bool (*speed_switcher)(struct gps_device_t *session,
+ speed_t speed, char parity, int stopbits);
+ void (*mode_switcher)(struct gps_device_t *session, int mode);
+ bool (*rate_switcher)(struct gps_device_t *session, double rate);
+ double min_cycle;
+#endif /* RECONFIGURE_ENABLE */
+#ifdef CONTROLSEND_ENABLE
+ ssize_t (*control_send)(struct gps_device_t *session, char *buf, size_t buflen);
+#endif /* CONTROLSEND_ENABLE */
+#ifdef TIMEHINT_ENABLE
+ double (*time_offset)(struct gps_device_t *session);
+#endif /* TIMEHINT_ENABLE */
+};
+
+/*
+ * Each input source has an associated type. This is currently used in two
+ * ways:
+ *
+ * (1) To determince if we require that gpsd be the only process opening a
+ * device. We make an exception for PTYs because the master side has to be
+ * opened by test code.
+ *
+ * (2) To determine whether it's safe to send wakeup strings. These are
+ * required on some unusual RS-232 devices (such as the TNT compass and
+ * Thales/Ashtech GPSes) but should not be shipped to unidentified USB
+ * or Bluetooth devices as we don't even know in advance those are GPSes;
+ * they might not cope well.
+ *
+ * Where it says "case detected but not used" it means that we can identify
+ * a source type but no behavior is yet contingent on it. A "discoverable"
+ * device is one for which there is discoverable metadata such as a
+ * vendor/product ID.
+ *
+ * We should never see a block device; that would indicate a serious error
+ * in command-line usage or the hotplug system.
+ */
+typedef enum {source_unknown,
+ source_blockdev, /* block devices can't be GPS sources */
+ source_rs232, /* potential GPS source, not discoverable */
+ source_usb, /* potential GPS source, discoverable */
+ source_bluetooth, /* potential GPS source, discoverable */
+ source_can, /* potential GPS source, fixed CAN format */
+ source_pty, /* PTY: we don't require exclusive access */
+ source_tcp, /* TCP/IP stream: case detected but not used */
+ source_udp, /* UDP stream: case detected but not used */
+ source_gpsd, /* Remote gpsd instance over TCP/IP */
+ source_pps, /* PPS-only device, such as /dev/ppsN */
+ source_pipe, /* Unix FIFO; don't use blocking I/O */
+} sourcetype_t;
+
+/*
+ * Each input source also has an associated service type.
+ */
+typedef enum {service_unknown,
+ service_sensor,
+ service_dgpsip,
+ service_ntrip,
+} servicetype_t;
+
+/*
+ * Private state information about an NTRIP stream.
+ */
+struct ntrip_stream_t
+{
+ char mountpoint[101];
+ char credentials[128];
+ char authStr[128];
+ char url[256];
+ char port[32]; /* in my /etc/services 16 was the longest */
+ bool set; /* found and set */
+ enum
+ {
+ fmt_rtcm2,
+ fmt_rtcm2_0,
+ fmt_rtcm2_1,
+ fmt_rtcm2_2,
+ fmt_rtcm2_3,
+ fmt_rtcm3_0,
+ fmt_rtcm3_1,
+ fmt_rtcm3_2,
+ fmt_unknown
+ } format;
+ int carrier;
+ double latitude;
+ double longitude;
+ int nmea;
+ enum
+ { cmp_enc_none, cmp_enc_unknown } compr_encryp;
+ enum
+ { auth_none, auth_basic, auth_digest, auth_unknown } authentication;
+ int fee;
+ int bitrate;
+};
+
+#ifdef PPS_ENABLE
+#include "ppsthread.h"
+#endif /* PPS_ENABLE */
+
+struct gps_device_t {
+/* session object, encapsulates all global state */
+ struct gps_data_t gpsdata;
+ const struct gps_type_t *device_type;
+ unsigned int driver_index; /* numeric index of current driver */
+ unsigned int drivers_identified; /* bitmask; what drivers have we seen? */
+#ifdef RECONFIGURE_ENABLE
+ const struct gps_type_t *last_controller;
+#endif /* RECONFIGURE_ENABLE */
+ struct gps_context_t *context;
+ sourcetype_t sourcetype;
+ servicetype_t servicetype;
+ int mode;
+ struct termios ttyset, ttyset_old;
+#ifndef FIXED_PORT_SPEED
+ unsigned int baudindex;
+#endif /* FIXED_PORT_SPEED */
+ int saved_baud;
+ struct gps_lexer_t lexer;
+ int badcount;
+ int subframe_count;
+ char subtype[64]; /* firmware version or subtype ID */
+ time_t opentime;
+ time_t releasetime;
+ bool zerokill;
+ time_t reawake;
+#ifdef TIMING_ENABLE
+ timestamp_t sor; /* timestamp start of this reporting cycle */
+ unsigned long chars; /* characters in the cycle */
+#endif /* TIMING_ENABLE */
+#ifdef NTP_ENABLE
+ bool ship_to_ntpd;
+#ifdef NTPSHM_ENABLE
+ volatile struct shmTime *shm_clock;
+#endif /* NTPSHM_ENABLE */
+# ifdef PPS_ENABLE
+ volatile struct shmTime *shm_pps;
+ int chronyfd; /* for talking to chrony */
+# endif /* PPS_ENABLE */
+#endif /* NTP_ENABLE */
+#ifdef PPS_ENABLE
+ volatile struct pps_thread_t pps_thread;
+#endif /* PPS_ENABLE */
+ double mag_var; /* magnetic variation in degrees */
+ bool back_to_nmea; /* back to NMEA on revert? */
+ /*
+ * msgbuf needs to hold the hex decode of inbuffer
+ * so msgbuf must be 2x the size of inbuffer
+ */
+ char msgbuf[MAX_PACKET_LENGTH*4+1]; /* command message buffer for sends */
+ size_t msgbuflen;
+ int observed; /* which packet type`s have we seen? */
+ bool cycle_end_reliable; /* does driver signal REPORT_MASK */
+ int fixcnt; /* count of fixes from this device */
+ struct gps_fix_t newdata; /* where drivers put their data */
+ struct gps_fix_t oldfix; /* previous fix for error modeling */
+#ifdef NMEA0183_ENABLE
+ struct {
+ unsigned short sats_used[MAXCHANNELS];
+ int part, await; /* for tracking GSV parts */
+ struct tm date; /* date part of last sentence time */
+ double subseconds; /* subsec part of last sentence time */
+ char *field[NMEA_MAX];
+ unsigned char fieldcopy[NMEA_MAX+1];
+ /* detect receivers that ship GGA with non-advancing timestamp */
+ bool latch_mode;
+ char last_gga_timestamp[16];
+ bool seen_glgsv;
+ bool seen_bdgsv;
+ bool seen_qzss;
+ char last_gsv_talker;
+ bool seen_glgsa;
+ bool seen_gngsa;
+ bool seen_bdgsa;
+ char last_gsa_talker;
+ /*
+ * State for the cycle-tracking machinery.
+ * The reason these timestamps are separate from the
+ * general sentence timestamps is that we can
+ * use the minutes and seconds part of a sentence
+ * with an incomplete timestamp (like GGA) for
+ * end-cycle recognition, even if we don't have a previous
+ * RMC or ZDA that lets us get full time from it.
+ */
+ timestamp_t this_frac_time, last_frac_time;
+ bool latch_frac_time;
+ unsigned int lasttag;
+ unsigned int cycle_enders;
+ bool cycle_continue;
+ } nmea;
+#endif /* NMEA0183_ENABLE */
+ /*
+ * The rest of this structure is driver-specific private storage.
+ * Only put a driver's scratch storage in here if it is never
+ * implemented on the same device that supports any mode already
+ * in this union; otherwise bad things might happen after a device
+ * mode switch.
+ */
+ union {
+#ifdef GARMINTXT_ENABLE
+ struct {
+ struct tm date; /* date part of last sentence time */
+ double subseconds; /* subsec part of last sentence time */
+ } garmintxt;
+#endif /* GARMINTXT_ENABLE */
+#ifdef BINARY_ENABLE
+#ifdef GEOSTAR_ENABLE
+ struct {
+ unsigned int physical_port;
+ } geostar;
+#endif /* GEOSTAR_ENABLE */
+#ifdef SIRF_ENABLE
+ struct {
+ unsigned int need_ack; /* if NZ we're awaiting ACK */
+ unsigned int cfg_stage; /* configuration stage counter */
+ unsigned int driverstate; /* for private use */
+#define SIRF_LT_231 0x01 /* SiRF at firmware rev < 231 */
+#define SIRF_EQ_231 0x02 /* SiRF at firmware rev == 231 */
+#define SIRF_GE_232 0x04 /* SiRF at firmware rev >= 232 */
+#define UBLOX 0x08 /* u-blox firmware with packet 0x62 */
+ unsigned long satcounter;
+ unsigned int time_seen;
+ unsigned char lastid; /* ID with last timestamp seen */
+#define TIME_SEEN_UTC_2 0x08 /* Seen UTC time variant 2? */
+ /* fields from Navigation Parameters message */
+ bool nav_parameters_seen; /* have we seen one? */
+ unsigned char altitude_hold_mode;
+ unsigned char altitude_hold_source;
+ int16_t altitude_source_input;
+ unsigned char degraded_mode;
+ unsigned char degraded_timeout;
+ unsigned char dr_timeout;
+ unsigned char track_smooth_mode;
+ /* fields from DGPS Status */
+ unsigned int dgps_source;
+#define SIRF_DGPS_SOURCE_NONE 0 /* No DGPS correction type have been selected */
+#define SIRF_DGPS_SOURCE_SBAS 1 /* SBAS */
+#define SIRF_DGPS_SOURCE_SERIAL 2 /* RTCM corrections */
+#define SIRF_DGPS_SOURCE_BEACON 3 /* Beacon corrections */
+#define SIRF_DGPS_SOURCE_SOFTWARE 4 /* Software API corrections */
+ } sirf;
+#endif /* SIRF_ENABLE */
+#ifdef SUPERSTAR2_ENABLE
+ struct {
+ time_t last_iono;
+ } superstar2;
+#endif /* SUPERSTAR2_ENABLE */
+#ifdef TSIP_ENABLE
+ struct {
+ unsigned short sats_used[MAXCHANNELS];
+ bool superpkt; /* Super Packet mode requested */
+ time_t last_41; /* Timestamps for packet requests */
+ time_t last_48;
+ time_t last_5c;
+ time_t last_6d;
+ time_t last_46;
+ time_t req_compact;
+ unsigned int stopbits; /* saved RS232 link parameter */
+ char parity;
+ int subtype;
+#define TSIP_UNKNOWN 0
+#define TSIP_ACCUTIME_GOLD 1
+ } tsip;
+#endif /* TSIP_ENABLE */
+#ifdef GARMIN_ENABLE /* private housekeeping stuff for the Garmin driver */
+ struct {
+ unsigned char Buffer[4096+12]; /* Garmin packet buffer */
+ size_t BufferLen; /* current GarminBuffer Length */
+ } garmin;
+#endif /* GARMIN_ENABLE */
+#ifdef ZODIAC_ENABLE /* private housekeeping stuff for the Zodiac driver */
+ struct {
+ unsigned short sn; /* packet sequence number */
+ /*
+ * Zodiac chipset channel status from PRWIZCH. Keep it so
+ * raw-mode translation of Zodiac binary protocol can send
+ * it up to the client.
+ */
+#define ZODIAC_CHANNELS 12
+ unsigned int Zs[ZODIAC_CHANNELS]; /* satellite PRNs */
+ unsigned int Zv[ZODIAC_CHANNELS]; /* signal values (0-7) */
+ } zodiac;
+#endif /* ZODIAC_ENABLE */
+#ifdef UBLOX_ENABLE
+ struct {
+ unsigned char port_id;
+ unsigned char sbas_in_use;
+ /*
+ * NAV-* message order is not defined, thus we handle them isochronously
+ * and store the latest data into these variables rather than expect
+ * some messages to arrive in order. NAV-SOL handler picks up these values
+ * and inserts them into the fix structure in one go.
+ */
+ double last_herr;
+ double last_verr;
+ } ubx;
+#endif /* UBLOX_ENABLE */
+#ifdef NAVCOM_ENABLE
+ struct {
+ uint8_t physical_port;
+ bool warned;
+ } navcom;
+#endif /* NAVCOM_ENABLE */
+#ifdef ONCORE_ENABLE
+ struct {
+#define ONCORE_VISIBLE_CH 12
+ int visible;
+ int PRN[ONCORE_VISIBLE_CH]; /* PRNs of satellite */
+ int elevation[ONCORE_VISIBLE_CH]; /* elevation of satellite */
+ int azimuth[ONCORE_VISIBLE_CH]; /* azimuth */
+ int pps_offset_ns;
+ } oncore;
+#endif /* ONCORE_ENABLE */
+#ifdef NMEA2000_ENABLE
+ struct {
+ unsigned int can_msgcnt;
+ unsigned int can_net;
+ unsigned int unit;
+ bool unit_valid;
+ int mode;
+ unsigned int mode_valid;
+ unsigned int idx;
+// size_t ptr;
+ size_t fast_packet_len;
+ int type;
+ void *workpgn;
+ void *pgnlist;
+ unsigned char sid[8];
+ } nmea2000;
+#endif /* NMEA2000_ENABLE */
+ /*
+ * This is not conditionalized on RTCM104_ENABLE because we need to
+ * be able to build gpsdecode even when RTCM support is not
+ * configured in the daemon. It doesn't take up extra space.
+ */
+ struct {
+ /* ISGPS200 decoding */
+ bool locked;
+ int curr_offset;
+ isgps30bits_t curr_word;
+ isgps30bits_t buf[RTCM2_WORDS_MAX];
+ unsigned int bufindex;
+ } isgps;
+#endif /* BINARY_ENABLE */
+#ifdef AIVDM_ENABLE
+ struct {
+ struct aivdm_context_t context[AIVDM_CHANNELS];
+ char ais_channel;
+ } aivdm;
+#endif /* AIVDM_ENABLE */
+ } driver;
+
+ /*
+ * State of an NTRIP connection. We don't want to zero this on every
+ * activation, otherwise the connection state will get lost. Information
+ * in this substructure is only valid if servicetype is service_ntrip.
+ */
+ struct {
+ /* state information about the stream */
+ struct ntrip_stream_t stream;
+
+ /* state information about our response parsing */
+ enum {
+ ntrip_conn_init,
+ ntrip_conn_sent_probe,
+ ntrip_conn_sent_get,
+ ntrip_conn_established,
+ ntrip_conn_err
+ } conn_state; /* connection state for multi stage connect */
+ bool works; /* marks a working connection, so we try to reconnect once */
+ bool sourcetable_parse; /* have we read the sourcetable header? */
+ } ntrip;
+ /* State of a DGPSIP connection */
+ struct {
+ bool reported;
+ } dgpsip;
+};
+
+/*
+ * These are used where a file descriptor of 0 or greater indicaes open device.
+ */
+#define UNALLOCATED_FD -1 /* this slot is available for reallocation */
+#define PLACEHOLDING_FD -2 /* this slot *not* available for reallocation */
+
+/* logging levels */
+#define LOG_ERROR -1 /* errors, display always */
+#define LOG_SHOUT 0 /* not an error but we should always see it */
+#define LOG_WARN 1 /* not errors but may indicate a problem */
+#define LOG_CLIENT 2 /* log JSON reports to clients */
+#define LOG_INF 3 /* key informative messages */
+#define LOG_PROG 4 /* progress messages */
+#define LOG_IO 5 /* IO to and from devices */
+#define LOG_DATA 6 /* log data management messages */
+#define LOG_SPIN 7 /* logging for catching spin bugs */
+#define LOG_RAW 8 /* raw low-level I/O */
+
+#define ISGPS_ERRLEVEL_BASE LOG_RAW
+
+#define IS_HIGHEST_BIT(v,m) (v & ~((m<<1)-1))==0
+
+/* driver helper functions */
+extern void isgps_init(struct gps_lexer_t *);
+enum isgpsstat_t isgps_decode(struct gps_lexer_t *,
+ bool (*preamble_match)(isgps30bits_t *),
+ bool (*length_check)(struct gps_lexer_t *),
+ size_t,
+ unsigned int);
+extern unsigned int isgps_parity(isgps30bits_t);
+extern void isgps_output_magnavox(const isgps30bits_t *, unsigned int, FILE *);
+
+extern enum isgpsstat_t rtcm2_decode(struct gps_lexer_t *, unsigned int);
+extern void json_rtcm2_dump(const struct rtcm2_t *,
+ const char *, char[], size_t);
+extern void rtcm2_unpack(struct rtcm2_t *, char *);
+extern void json_rtcm3_dump(const struct rtcm3_t *,
+ const char *, char[], size_t);
+extern void rtcm3_unpack(const struct gps_context_t *,
+ struct rtcm3_t *, char *);
+
+/* here are the available GPS drivers */
+extern const struct gps_type_t **gpsd_drivers;
+
+/* gpsd library internal prototypes */
+extern gps_mask_t generic_parse_input(struct gps_device_t *);
+extern ssize_t generic_get(struct gps_device_t *);
+
+extern gps_mask_t nmea_parse(char *, struct gps_device_t *);
+extern ssize_t nmea_write(struct gps_device_t *, char *, size_t);
+extern ssize_t nmea_send(struct gps_device_t *, const char *, ... );
+extern void nmea_add_checksum(char *);
+
+extern gps_mask_t sirf_parse(struct gps_device_t *, unsigned char *, size_t);
+extern gps_mask_t evermore_parse(struct gps_device_t *, unsigned char *, size_t);
+extern gps_mask_t navcom_parse(struct gps_device_t *, unsigned char *, size_t);
+extern gps_mask_t garmin_ser_parse(struct gps_device_t *);
+extern gps_mask_t garmintxt_parse(struct gps_device_t *);
+extern gps_mask_t aivdm_parse(struct gps_device_t *);
+
+extern bool netgnss_uri_check(char *);
+extern int netgnss_uri_open(struct gps_device_t *, char *);
+extern void netgnss_report(struct gps_context_t *,
+ struct gps_device_t *,
+ struct gps_device_t *);
+extern void netgnss_autoconnect(struct gps_context_t *, double, double);
+
+extern int dgpsip_open(struct gps_device_t *, const char *);
+extern void dgpsip_report(struct gps_context_t *,
+ struct gps_device_t *,
+ struct gps_device_t *);
+extern void dgpsip_autoconnect(struct gps_context_t *,
+ double, double, const char *);
+extern int ntrip_open(struct gps_device_t *, char *);
+extern void ntrip_report(struct gps_context_t *,
+ struct gps_device_t *,
+ struct gps_device_t *);
+
+extern void gpsd_tty_init(struct gps_device_t *);
+extern int gpsd_serial_open(struct gps_device_t *);
+extern bool gpsd_set_raw(struct gps_device_t *);
+extern ssize_t gpsd_serial_write(struct gps_device_t *,
+ const char *, const size_t);
+extern bool gpsd_next_hunt_setting(struct gps_device_t *);
+extern int gpsd_switch_driver(struct gps_device_t *, char *);
+extern void gpsd_set_speed(struct gps_device_t *, speed_t, char, unsigned int);
+extern speed_t gpsd_get_speed(const struct gps_device_t *);
+extern speed_t gpsd_get_speed_old(const struct gps_device_t *);
+extern int gpsd_get_stopbits(const struct gps_device_t *);
+extern char gpsd_get_parity(const struct gps_device_t *);
+extern void gpsd_assert_sync(struct gps_device_t *);
+extern void gpsd_close(struct gps_device_t *);
+
+extern ssize_t gpsd_write(struct gps_device_t *, const char *, const size_t);
+
+extern void gpsd_time_init(struct gps_context_t *, time_t);
+extern void gpsd_set_century(struct gps_device_t *);
+extern timestamp_t gpsd_gpstime_resolve(struct gps_device_t *,
+ const unsigned short, const double);
+extern timestamp_t gpsd_utc_resolve(struct gps_device_t *);
+extern void gpsd_century_update(struct gps_device_t *, int);
+
+extern void gpsd_zero_satellites(struct gps_data_t *sp);
+extern gps_mask_t gpsd_interpret_subframe(struct gps_device_t *, unsigned int,
+ uint32_t[]);
+extern gps_mask_t gpsd_interpret_subframe_raw(struct gps_device_t *,
+ unsigned int, uint32_t[]);
+extern const char *gpsd_hexdump(char *, size_t, char *, size_t);
+extern const char *gpsd_packetdump(char *, size_t, char *, size_t);
+extern const char *gpsd_prettydump(struct gps_device_t *);
+# ifdef __cplusplus
+extern "C" {
+# endif
+extern int gpsd_hexpack(const char *, char *, size_t);
+# ifdef __cplusplus
+}
+# endif
+extern ssize_t hex_escapes(char *, const char *);
+extern void gpsd_position_fix_dump(struct gps_device_t *,
+ char[], size_t);
+extern void gpsd_clear_data(struct gps_device_t *);
+extern socket_t netlib_connectsock(int, const char *, const char *, const char *);
+extern socket_t netlib_localsocket(const char *, int);
+extern const char *netlib_errstr(const int);
+extern char *netlib_sock2ip(socket_t);
+
+extern void nmea_tpv_dump(struct gps_device_t *, char[], size_t);
+extern void nmea_sky_dump(struct gps_device_t *, char[], size_t);
+extern void nmea_subframe_dump(struct gps_device_t *, char[], size_t);
+extern void nmea_ais_dump(struct gps_device_t *, char[], size_t);
+extern unsigned int ais_binary_encode(struct ais_t *ais, unsigned char *bits, int flag);
+
+#ifdef NTP_ENABLE
+extern void ntp_latch(struct gps_device_t *device, struct timedelta_t *td);
+#ifdef NTPSHM_ENABLE
+extern void ntpshm_context_init(struct gps_context_t *);
+extern void ntpshm_session_init(struct gps_device_t *);
+extern int ntpshm_put(struct gps_device_t *, volatile struct shmTime *, struct timedelta_t *);
+extern void ntpshm_link_deactivate(struct gps_device_t *);
+extern void ntpshm_link_activate(struct gps_device_t *);
+#endif /* NTPSHM_ENABLE */
+#endif /* NTP_ENABLE */
+
+extern void errout_reset(struct gpsd_errout_t *errout);
+
+extern void gpsd_acquire_reporting_lock(void);
+extern void gpsd_release_reporting_lock(void);
+
+extern void ecef_to_wgs84fix(struct gps_fix_t *,
+ double *,
+ double, double, double,
+ double, double, double);
+extern void clear_dop(struct dop_t *);
+
+/* shmexport.c */
+#define GPSD_SHM_KEY 0x47505344 /* "GPSD" */
+struct shmexport_t
+{
+ int bookend1;
+ struct gps_data_t gpsdata;
+ int bookend2;
+};
+extern bool shm_acquire(struct gps_context_t *);
+extern void shm_release(struct gps_context_t *);
+extern void shm_update(struct gps_context_t *, struct gps_data_t *);
+
+/* dbusexport.c */
+#if defined(DBUS_EXPORT_ENABLE)
+int initialize_dbus_connection (void);
+void send_dbus_fix (struct gps_device_t* channel);
+#endif /* defined(DBUS_EXPORT_ENABLE) */
+
+/* srecord.c */
+extern void hexdump(size_t, unsigned char *, unsigned char *);
+extern unsigned char sr_sum(unsigned int, unsigned int, unsigned char *);
+extern int bin2srec(unsigned int, unsigned int, unsigned int, unsigned char *, unsigned char *);
+extern int srec_hdr(unsigned int, unsigned char *, unsigned char *);
+extern int srec_fin(unsigned int, unsigned char *);
+extern unsigned char hc(unsigned char);
+
+/* a BSD transplant */
+int b64_ntop(unsigned char const *src, size_t srclength, char *target,
+ size_t targsize);
+
+/* application interface */
+extern void gps_context_init(struct gps_context_t *context,
+ const char *label);
+extern void gpsd_init(struct gps_device_t *,
+ struct gps_context_t *,
+ const char *);
+extern void gpsd_clear(struct gps_device_t *);
+extern int gpsd_open(struct gps_device_t *);
+#define O_CONTINUE 0
+#define O_PROBEONLY 1
+#define O_OPTIMIZE 2
+extern int gpsd_activate(struct gps_device_t *, const int);
+extern void gpsd_deactivate(struct gps_device_t *);
+
+#define AWAIT_GOT_INPUT 1
+#define AWAIT_NOT_READY 0
+#define AWAIT_FAILED -1
+extern int gpsd_await_data(fd_set *,
+ fd_set *,
+ const int,
+ fd_set *,
+ struct gpsd_errout_t *errout);
+extern gps_mask_t gpsd_poll(struct gps_device_t *);
+#define DEVICE_EOF -3
+#define DEVICE_ERROR -2
+#define DEVICE_UNREADY -1
+#define DEVICE_READY 1
+#define DEVICE_UNCHANGED 0
+extern int gpsd_multipoll(const bool,
+ struct gps_device_t *,
+ void (*)(struct gps_device_t *, gps_mask_t),
+ float reawake_time);
+extern void gpsd_wrap(struct gps_device_t *);
+extern bool gpsd_add_device(const char *device_name, bool flag_nowait);
+extern const char *gpsd_maskdump(gps_mask_t);
+
+/* exceptional driver methods */
+extern bool ubx_write(struct gps_device_t *, unsigned int, unsigned int,
+ unsigned char *, size_t);
+extern bool ais_binary_decode(const struct gpsd_errout_t *errout,
+ struct ais_t *ais,
+ const unsigned char *, size_t,
+ struct ais_type24_queue_t *);
+
+void gpsd_labeled_report(const int, const int,
+ const char *, const char *, va_list);
+void gpsd_vlog(const struct gpsd_errout_t *,
+ const int, char *, size_t, const char *, va_list ap);
+PRINTF_FUNC(3, 4) void gpsd_log(const struct gpsd_errout_t *, const int, const char *, ...);
+
+/*
+ * How to mix together epx and epy to get a horizontal circular error
+ * eph when reporting requires it. Most devices don't report these;
+ * NMEA 3.x devices reporting $GPGBS are the exception.
+ */
+#define EMIX(x, y) (((x) > (y)) ? (x) : (y))
+
+#define NITEMS(x) ((int) (sizeof(x) / sizeof(x[0]) + COMPILE_CHECK_IS_ARRAY(x)))
+
+/* Ugh - required for build on Solaris */
+#ifndef NAN
+#define NAN (0.0f/0.0f)
+#endif
+
+/* Cygwin, in addition to NAN, doesn't have cfmakeraw */
+#if defined(__CYGWIN__)
+void cfmakeraw(struct termios *);
+#endif /* defined(__CYGWIN__) */
+
+#define DEVICEHOOKPATH "/"SYSCONFDIR"/gpsd/device-hook"
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif /* _GPSD_H_ */
+// Local variables:
+// mode: c
+// end: