static int ntrip_stream_req_probe(const struct ntrip_stream_t *stream, struct gpsd_errout_t *errout) { int dsock; ssize_t r; char buf[BUFSIZ]; dsock = netlib_connectsock(AF_UNSPEC, stream->url, stream->port, "tcp"); if (dsock < 0) { gpsd_log(errout, LOG_ERROR, "ntrip stream connect error %d in req probe\n", dsock); return -1; } gpsd_log(errout, LOG_SPIN, "ntrip stream for req probe connected on fd %d\n", dsock); (void)snprintf(buf, sizeof(buf), "GET / HTTP/1.1\r\n" "User-Agent: NTRIP gpsd/%s\r\n" "Host: %s\r\n" "Connection: close\r\n" "\r\n", VERSION, stream->url); r = write(dsock, buf, strlen(buf)); if (r != (ssize_t)strlen(buf)) { gpsd_log(errout, LOG_ERROR, "ntrip stream write error %d on fd %d during probe request %zd\n", errno, dsock, r); (void)close(dsock); return -1; } /* coverity[leaked_handle] This is an intentional allocation */ return dsock; }
static gps_mask_t decode_itk_utcionomodel(struct gps_device_t *session, unsigned char *buf, size_t len) { int leap; unsigned short flags; if (len != 64) { gpsd_log(&session->context->errout, LOG_PROG, "ITALK: bad UTC_IONO_MODEL (len %zu, should be 64)\n", len); return 0; } flags = (unsigned short) getleu16(buf, 7); if (0 == (flags & UTC_IONO_MODEL_UTCVALID)) return 0; leap = (int)getleu16(buf, 7 + 24); if (session->context->leap_seconds < leap) session->context->leap_seconds = leap; session->newdata.time = gpsd_gpstime_resolve(session, (unsigned short) getleu16(buf, 7 + 36), (unsigned int)getleu32(buf, 7 + 38) / 1000.0); gpsd_log(&session->context->errout, LOG_DATA, "UTC_IONO_MODEL: time=%.2f mask={TIME}\n", session->newdata.time); return TIME_SET | NTPTIME_IS; }
static gps_mask_t decode_itk_subframe(struct gps_device_t *session, unsigned char *buf, size_t len) { unsigned short flags, prn, sf; unsigned int i; uint32_t words[10]; if (len != 64) { gpsd_log(&session->context->errout, LOG_PROG, "ITALK: bad SUBFRAME (len %zu, should be 64)\n", len); return 0; } flags = (unsigned short) getleu16(buf, 7 + 4); prn = (unsigned short) getleu16(buf, 7 + 6); sf = (unsigned short) getleu16(buf, 7 + 8); gpsd_log(&session->context->errout, LOG_PROG, "iTalk 50B SUBFRAME prn %u sf %u - decode %s %s\n", prn, sf, (flags & SUBFRAME_WORD_FLAG_MASK) ? "error" : "ok", (flags & SUBFRAME_GPS_PREAMBLE_INVERTED) ? "(inverted)" : ""); if (flags & SUBFRAME_WORD_FLAG_MASK) return 0; // don't try decode an erroneous packet /* * Timo says "SUBRAME message contains decoded navigation message subframe * words with parity checking done but parity bits still present." */ for (i = 0; i < 10; i++) words[i] = (uint32_t)(getleu32(buf, 7 + 14 + 4 * i) >> 6) & 0xffffff; return gpsd_interpret_subframe(session, prn, words); }
static int ntrip_stream_get_req(const struct ntrip_stream_t *stream, const struct gpsd_errout_t *errout) { int dsock; char buf[BUFSIZ]; dsock = netlib_connectsock(AF_UNSPEC, stream->url, stream->port, "tcp"); if (BAD_SOCKET(dsock)) { gpsd_log(errout, LOG_ERROR, "ntrip stream connect error %d\n", dsock); return -1; } gpsd_log(errout, LOG_SPIN, "netlib_connectsock() returns socket on fd %d\n", dsock); (void)snprintf(buf, sizeof(buf), "GET /%s HTTP/1.1\r\n" "User-Agent: NTRIP gpsd/%s\r\n" "Host: %s\r\n" "Accept: rtk/rtcm, dgps/rtcm\r\n" "%s" "Connection: close\r\n" "\r\n", stream->mountpoint, VERSION, stream->url, stream->authStr); if (write(dsock, buf, strlen(buf)) != (ssize_t) strlen(buf)) { gpsd_log(errout, LOG_ERROR, "ntrip stream write error %d on fd %d during get request\n", errno, dsock); (void)close(dsock); return -1; } return dsock; }
void ntrip_report(struct gps_context_t *context, struct gps_device_t *gps, struct gps_device_t *caster) /* may be time to ship a usage report to the Ntrip caster */ { static int count; /* * 10 is an arbitrary number, the point is to have gotten several good * fixes before reporting usage to our Ntrip caster. * * count % 5 is as arbitrary a number as the fixcnt. But some delay * was needed here */ count ++; if (caster->ntrip.stream.nmea != 0 && context->fixcnt > 10 && (count % 5)==0) { if (caster->gpsdata.gps_fd > -1) { char buf[BUFSIZ]; gpsd_position_fix_dump(gps, buf, sizeof(buf)); if (write(caster->gpsdata.gps_fd, buf, strlen(buf)) == (ssize_t) strlen(buf)) { gpsd_log(&context->errout, LOG_IO, "=> dgps %s\n", buf); } else { gpsd_log(&context->errout, LOG_IO, "ntrip report write failed\n"); } } } }
bool shm_acquire(struct gps_context_t *context) /* initialize the shared-memory segment to be used for export */ { /*@-nullpass@*/ long shmkey = getenv("GPSD_SHM_KEY") ? strtol(getenv("GPSD_SHM_KEY"), NULL, 0) : GPSD_SHM_KEY; /*@+nullpass@*/ int shmid = shmget((key_t)shmkey, sizeof(struct gps_data_t), (int)(IPC_CREAT|0666)); if (shmid == -1) { gpsd_log(&context->errout, LOG_ERROR, "shmget(0x%lx, %zd, 0666) for SHM export failed: %s\n", shmkey, sizeof(struct gps_data_t), strerror(errno)); return false; } else gpsd_log(&context->errout, LOG_PROG, "shmget(0x%lx, %zd, 0666) for SHM export succeeded\n", shmkey, sizeof(struct gps_data_t)); context->shmexport = (void *)shmat(shmid, 0, 0); if ((int)(long)context->shmexport == -1) { gpsd_log(&context->errout, LOG_ERROR, "shmat failed: %s\n", strerror(errno)); context->shmexport = NULL; return false; } gpsd_log(&context->errout, LOG_PROG, "shmat() for SHM export succeeded, segment %d\n", shmid); return true; }
void dgpsip_report(struct gps_context_t *context, struct gps_device_t *gps, struct gps_device_t *dgpsip) /* may be time to ship a usage report to the DGPSIP server */ { /* * 10 is an arbitrary number, the point is to have gotten several good * fixes before reporting usage to our DGPSIP server. */ if (context->fixcnt > 10 && !dgpsip->dgpsip.reported) { dgpsip->dgpsip.reported = true; if (dgpsip->gpsdata.gps_fd > -1) { char buf[BUFSIZ]; (void)snprintf(buf, sizeof(buf), "R %0.8f %0.8f %0.2f\r\n", gps->gpsdata.fix.latitude, gps->gpsdata.fix.longitude, gps->gpsdata.fix.altitude); if (write(dgpsip->gpsdata.gps_fd, buf, strlen(buf)) == (ssize_t) strlen(buf)) gpsd_log(&context->errout, LOG_IO, "=> dgps %s\n", buf); else gpsd_log(&context->errout, LOG_IO, "write to dgps FAILED\n"); } } }
static void onsig(int sig) { if (sig == SIGALRM) { gpsd_log(&context.errout, LOG_ERROR, "packet recognition timed out.\n"); exit(EXIT_FAILURE); } else { gpsd_log(&context.errout, LOG_ERROR, "killed by signal %d\n", sig); exit(EXIT_SUCCESS); } }
static gps_mask_t decode_itk_prnstatus(struct gps_device_t *session, unsigned char *buf, size_t len) { gps_mask_t mask; if (len < 62) { gpsd_log(&session->context->errout, LOG_PROG, "ITALK: runt PRN_STATUS (len=%zu)\n", len); mask = 0; } else { unsigned int i, nsv, nchan, st; session->gpsdata.skyview_time = gpsd_gpstime_resolve(session, (unsigned short)getleu16(buf, 7 + 4), (unsigned int)getleu32(buf, 7 + 6) / 1000.0), gpsd_zero_satellites(&session->gpsdata); nchan = (unsigned int)getleu16(buf, 7 + 50); if (nchan > MAX_NR_VISIBLE_PRNS) nchan = MAX_NR_VISIBLE_PRNS; for (i = st = nsv = 0; i < nchan; i++) { unsigned int off = 7 + 52 + 10 * i; unsigned short flags; bool used; flags = (unsigned short) getleu16(buf, off); used = (bool)(flags & PRN_FLAG_USE_IN_NAV); session->gpsdata.skyview[st].ss = (float)(getleu16(buf, off + 2) & 0xff); session->gpsdata.skyview[st].PRN = (short)(getleu16(buf, off + 4) & 0xff); session->gpsdata.skyview[st].elevation = (short)(getles16(buf, off + 6) & 0xff); session->gpsdata.skyview[st].azimuth = (short)(getles16(buf, off + 8) & 0xff); session->gpsdata.skyview[st].used = used; if (session->gpsdata.skyview[st].PRN > 0) { st++; if (used) nsv++; } } session->gpsdata.satellites_visible = (int)st; session->gpsdata.satellites_used = (int)nsv; mask = USED_IS | SATELLITE_SET;; gpsd_log(&session->context->errout, LOG_DATA, "PRN_STATUS: time=%.2f visible=%d used=%d mask={USED|SATELLITE}\n", session->newdata.time, session->gpsdata.satellites_visible, session->gpsdata.satellites_used); } return mask; }
static int ntrip_stream_get_parse(const struct ntrip_stream_t *stream, const int dsock, const struct gpsd_errout_t *errout) { /*@-nullpass@*/ char buf[BUFSIZ]; int opts; memset(buf, 0, sizeof(buf)); while (read(dsock, buf, sizeof(buf) - 1) == -1) { if (errno == EINTR) continue; gpsd_log(errout, LOG_ERROR, "ntrip stream read error %d on fd %d during get rsp\n", errno, dsock); goto close; } /* parse 401 Unauthorized */ /* coverity[string_null] - guaranteed terminated by the memset above */ if (strstr(buf, NTRIP_UNAUTH)!=NULL) { gpsd_log(errout, LOG_ERROR, "not authorized for Ntrip stream %s/%s\n", stream->url, stream->mountpoint); goto close; } /* parse SOURCETABLE */ if (strstr(buf, NTRIP_SOURCETABLE)!=NULL) { gpsd_log(errout, LOG_ERROR, "Broadcaster doesn't recognize Ntrip stream %s:%s/%s\n", stream->url, stream->port, stream->mountpoint); goto close; } /* parse ICY 200 OK */ if (strstr(buf, NTRIP_ICY)==NULL) { gpsd_log(errout, LOG_ERROR, "Unknown reply %s from Ntrip service %s:%s/%s\n", buf, stream->url, stream->port, stream->mountpoint); goto close; } opts = fcntl(dsock, F_GETFL); if (opts >= 0) (void)fcntl(dsock, F_SETFL, opts | O_NONBLOCK); return dsock; close: (void)close(dsock); return -1; /*@+nullpass@*/ }
/* * pretend to decode MID 0xE3, Beiduo D2 Subframe data * * from Beidou Standard BDS-SIS-ICD-2.0 * D2, with the data rate of 500 bps, is broadcasted by the GEO satellites. * * len 31 bytes * */ static gps_mask_t sky_msg_E3(struct gps_device_t *session, unsigned char *buf, size_t len) { int i; unsigned int prn; /* BeidouPS sat PRN 201-205 */ unsigned int subf; /* subframe 1-5 */ /* the words are preprocessed, not raw, just the 28 bytes of data */ uint8_t bytes[28]; /* raw data */ if ( 31 != len) return 0; prn = (unsigned int)getub(buf, 1); subf = (unsigned int)getub(buf, 2); for ( i = 0; i < 28; i++ ) { bytes[i] = getub(buf, 3 + i); } /* extra guard prevents expensive hexdump calls */ if (session->context->errout.debug >= LOG_PROG) { gpsd_log(&session->context->errout, LOG_PROG, "Skytraq: Beidou D2 subframe PRN %d Subframe %d " "length %zd byte:%s\n", prn, subf, len, gpsd_hexdump(session->msgbuf, sizeof(session->msgbuf), (char *)bytes, 28)); } return ONLINE_SET; }
/* * decode MID 0xDC, Measurement Time * * 10 bytes */ static gps_mask_t sky_msg_DC(struct gps_device_t *session, unsigned char *buf, size_t len) { unsigned int iod; /* Issue of data 0 - 255 */ unsigned int wn; /* week number 0 - 65535 */ unsigned int tow; /* receiver tow 0 - 604799999 in mS */ unsigned int mp; /* measurement period 1 - 1000 ms */ /* calculated */ double f_tow; /* tow in seconds */ unsigned int msec; /* mSec part of tow */ if ( 10 != len) return 0; iod = (unsigned int)getub(buf, 1); wn = getbeu16(buf, 2); tow = getbeu32(buf, 4); f_tow = (double)(tow / 1000); msec = tow % 1000; mp = getbeu16(buf, 8); /* should this be newdata.skyview_time? */ session->gpsdata.skyview_time = gpsd_gpstime_resolve(session, wn, f_tow ); gpsd_log(&session->context->errout, LOG_DATA, "Skytraq: MID 0xDC: iod=%u, wn=%u, tow=%u, mp=%u, t=%lld.%03u\n", iod, wn, tow, mp, (long long)session->gpsdata.skyview_time, msec); return 0; }
static bool evermore_nmea_config(struct gps_device_t *session, int mode) /* mode = 0 : EverMore default */ /* mode = 1 : gpsd best */ /* mode = 2 : EverMore search, activate PEMT101 message */ { unsigned char tmp8; /*@ +charint */ unsigned char evrm_nmeaout_config[] = { 0x8e, /* 0: msg ID, NMEA Message Control */ 0xff, /* 1: NMEA sentence bitmask, GGA(0), GLL(1), GSA(2), GSV(3), ... */ 0x01, /* 2: nmea checksum no(0), yes(1) */ 1, /* 3: GPGGA, interval 0-255s */ 0, /* 4: GPGLL, interval 0-255s */ 1, /* 5: GPGSA, interval 0-255s */ 1, /* 6: GPGSV, interval 0-255s */ 1, /* 7: GPRMC, interval 0-255s */ 0, /* 8: GPVTG, interval 0-255s */ 0, /* 9: PEMT,101, interval 0-255s */ 0, 0, 0, 0, 0, 0, /* 10-15: reserved */ }; /*@ -charint */ gpsd_log(&session->context->errout, LOG_PROG, "evermore_nmea_config(%d)\n", mode); /*@i1@*/ tmp8 = (mode == 1) ? 5 : 1; /* NMEA GPGSV, gpsd */ evrm_nmeaout_config[6] = tmp8; /* GPGSV, 1s or 5s */ /*@i1@*/ tmp8 = (mode == 2) ? 1 : 0; /* NMEA PEMT101 */ evrm_nmeaout_config[9] = tmp8; /* PEMT101, 1s or 0s */ return (evermore_control_send(session, (char *)evrm_nmeaout_config, sizeof(evrm_nmeaout_config)) != -1); }
static char *ntrip_field_iterate(char *start, char *prev, const char *eol, const struct gpsd_errout_t *errout) { char *s, *t, *u; if (start) s = start; else { if (!prev) return NULL; s = prev + strlen(prev) + 1; if (s >= eol) return NULL; } /* ignore any quoted ; chars as they are part of the field content */ t = s; while ((u = strstr(t, NTRIP_QSC))) t = u + strlen(NTRIP_QSC); if ((t = strstr(t, ";"))) *t = '\0'; gpsd_log(errout, LOG_RAW, "Next Ntrip source table field %s\n", s); return s; }
void ntpshm_link_activate(struct gps_device_t *session) /* set up ntpshm storage for a session */ { /* don't talk to NTP when we're running inside the test harness */ if (session->sourcetype == source_pty) return; if (session->sourcetype != source_pps ) { /* allocate a shared-memory segment for "NMEA" time data */ session->shm_clock = ntpshm_alloc(session->context); if (session->shm_clock == NULL) { gpsd_log(&session->context->errout, LOG_WARN, "NTP: ntpshm_alloc() failed\n"); return; } } #if defined(PPS_ENABLE) if (session->sourcetype == source_usb || session->sourcetype == source_rs232 || session->sourcetype == source_pps) { /* We also have the 1pps capability, allocate a shared-memory segment * for the 1pps time data and launch a thread to capture the 1pps * transitions */ if ((session->shm_pps = ntpshm_alloc(session->context)) == NULL) { gpsd_log(&session->context->errout, LOG_WARN, "PPS: ntpshm_alloc(1) failed\n"); } else { init_hook(session); session->pps_thread.report_hook = report_hook; /* * The HAT kludge. If we're using the HAT GPS on a * Raspberry Pi or a workalike like the ODROIDC2, and * there is a static /dev/pps0, and we have access because * we're root, assume we want to use KPPS. */ if ((strcmp(session->pps_thread.devicename, MAGIC_HAT_GPS) == 0 || strcmp(session->pps_thread.devicename, MAGIC_LINK_GPS) == 0) && access("/dev/pps0", R_OK | W_OK) == 0) session->pps_thread.devicename = "/dev/pps0"; pps_thread_activate(&session->pps_thread); } } #endif /* PPS_ENABLE */ }
/** * GPS Satellite Info */ static gps_mask_t oncore_msg_svinfo(struct gps_device_t *session, unsigned char *buf, size_t data_len) { unsigned int i, nchan; int j; if (data_len != 92) return 0; gpsd_log(&session->context->errout, LOG_DATA, "oncore SVINFO - satellite data\n"); nchan = (unsigned int)getub(buf, 4); gpsd_log(&session->context->errout, LOG_DATA, "oncore SVINFO - %d satellites:\n", nchan); /* Then we clamp the value to not read outside the table. */ if (nchan > 12) nchan = 12; session->driver.oncore.visible = (int)nchan; for (i = 0; i < nchan; i++) { /* get info for one channel/satellite */ unsigned int off = 5 + 7 * i; int sv = (int)getub(buf, off); int el = (int)getub(buf, off + 3); int az = (int)getbeu16(buf, off + 4); gpsd_log(&session->context->errout, LOG_DATA, "%2d %2d %2d %3d\n", i, sv, el, az); /* Store for use when Ea messages come. */ session->driver.oncore.PRN[i] = sv; session->driver.oncore.elevation[i] = el; session->driver.oncore.azimuth[i] = az; /* If it has an entry in the satellite list, update it! */ for (j = 0; j < session->gpsdata.satellites_visible; j++) if (session->gpsdata.skyview[j].PRN == (short)sv) { session->gpsdata.skyview[j].elevation = (short)el; session->gpsdata.skyview[j].azimuth = (short)az; } } gpsd_log(&session->context->errout, LOG_DATA, "SVINFO: mask={SATELLITE}\n"); return SATELLITE_SET; }
void gpsd_time_init(struct gps_context_t *context, time_t starttime) /* initialize the GPS context's time fields */ { /* * gpsd can't work with 'right' timezones (leapseconds inserted in * the timezone offset). Avoid this and all manner of other local * time issues by telling the system we want times returned in UTC. */ (void)putenv("TZ=UTC"); /* * Provides a start time for getting the century. Do this, just * in case one of our embedded deployments is still in place in * the year 2.1K. Still likely to fail if we bring up the daemon * just before a century mark, but that case is probably doomed * anyhow because of 2-digit years. */ context->leap_seconds = BUILD_LEAPSECONDS; context->century = BUILD_CENTURY; context->start_time = starttime; context->rollovers = (int)((context->start_time-GPS_EPOCH) / GPS_ROLLOVER); if (context->start_time < GPS_EPOCH) gpsd_log(&context->errout, LOG_ERROR, "system time looks bogus, dates may not be reliable.\n"); else { /* we've forced the UTC timezone, so this is actually UTC */ struct tm *now = localtime(&context->start_time); char scr[128]; /* * This is going to break our regression-test suite once a century. * I think we can live with that consequence. */ now->tm_year += 1900; context->century = now->tm_year - (now->tm_year % 100); (void)unix_to_iso8601((timestamp_t)context->start_time, scr, sizeof(scr)); gpsd_log(&context->errout, LOG_INF, "startup at %s (%d)\n", scr, (int)context->start_time); } }
bool gpsd_set_raw(struct gps_device_t * session) { (void)cfmakeraw(&session->ttyset); if (tcsetattr(session->gpsdata.gps_fd, TCIOFLUSH, &session->ttyset) == -1) { gpsd_log(&session->context->errout, LOG_ERROR, "error changing port attributes: %s\n", strerror(errno)); return false; } return true; }
int dgpsip_open(struct gps_device_t *device, const char *dgpsserver) /* open a connection to a DGPSIP server */ { char *colon, *dgpsport = "rtcm-sc104"; int opts; device->dgpsip.reported = false; if ((colon = strchr(dgpsserver, ':')) != NULL) { dgpsport = colon + 1; *colon = '\0'; } if (!getservbyname(dgpsport, "tcp")) dgpsport = DEFAULT_RTCM_PORT; device->gpsdata.gps_fd = netlib_connectsock(AF_UNSPEC, dgpsserver, dgpsport, "tcp"); // cppcheck-suppress pointerPositive if (device->gpsdata.gps_fd >= 0) { char hn[256], buf[BUFSIZ]; gpsd_log(&device->context->errout, LOG_PROG, "connection to DGPS server %s established.\n", dgpsserver); (void)gethostname(hn, sizeof(hn)); /* greeting required by some RTCM104 servers; others will ignore it */ (void)snprintf(buf, sizeof(buf), "HELO %s gpsd %s\r\nR\r\n", hn, VERSION); if (write(device->gpsdata.gps_fd, buf, strlen(buf)) != (ssize_t) strlen(buf)) gpsd_log(&device->context->errout, LOG_ERROR, "hello to DGPS server %s failed\n", dgpsserver); } else gpsd_log(&device->context->errout, LOG_ERROR, "can't connect to DGPS server %s, netlib error %d.\n", dgpsserver, device->gpsdata.gps_fd); opts = fcntl(device->gpsdata.gps_fd, F_GETFL); if (opts >= 0) (void)fcntl(device->gpsdata.gps_fd, F_SETFL, opts | O_NONBLOCK); device->servicetype = service_dgpsip; return device->gpsdata.gps_fd; }
static volatile struct shmTime *getShmTime(struct gps_context_t *context, int unit) { int shmid; unsigned int perms; volatile struct shmTime *p; // set the SHM perms the way ntpd does if (unit < 2) { // we are root, be careful perms = 0600; } else { // we are not root, try to work anyway perms = 0666; } /* * Note: this call requires root under BSD, and possibly on * well-secured Linux systems. This is why ntpshm_context_init() has to be * called before privilege-dropping. */ shmid = shmget((key_t) (NTPD_BASE + unit), sizeof(struct shmTime), (int)(IPC_CREAT | perms)); if (shmid == -1) { gpsd_log(&context->errout, LOG_ERROR, "NTP: shmget(%ld, %zd, %o) fail: %s\n", (long int)(NTPD_BASE + unit), sizeof(struct shmTime), (int)perms, strerror(errno)); return NULL; } p = (struct shmTime *)shmat(shmid, 0, 0); if ((int)(long)p == -1) { gpsd_log(&context->errout, LOG_ERROR, "NTP: shmat failed: %s\n", strerror(errno)); return NULL; } gpsd_log(&context->errout, LOG_PROG, "NTP: shmat(%d,0,0) succeeded, segment %d\n", shmid, unit); return p; }
static gps_mask_t decode_itk_pseudo(struct gps_device_t *session, unsigned char *buf, size_t len) { unsigned short flags, n, i; n = (unsigned short) getleu16(buf, 7 + 4); if ((n < 1) || (n > MAXCHANNELS)){ gpsd_log(&session->context->errout, LOG_INF, "ITALK: bad PSEUDO channel count\n"); return 0; } if (len != (size_t)((n+1)*36)) { gpsd_log(&session->context->errout, LOG_PROG, "ITALK: bad PSEUDO len %zu\n", len); } gpsd_log(&session->context->errout, LOG_PROG, "iTalk PSEUDO [%u]\n", n); flags = (unsigned short)getleu16(buf, 7 + 6); if ((flags & 0x3) != 0x3) return 0; // bail if measurement time not valid. session->newdata.time = gpsd_gpstime_resolve(session, (unsigned short int)getleu16((char *)buf, 7 + 8), (unsigned int)getleu32(buf, 7 + 38) / 1000.0); for (i = 0; i < n; i++){ session->gpsdata.skyview[i].PRN = getleu16(buf, 7 + 26 + (i*36)) & 0xff; session->gpsdata.skyview[i].ss = getleu16(buf, 7 + 26 + (i*36 + 2)) & 0x3f; session->gpsdata.raw.satstat[i] = getleu32(buf, 7 + 26 + (i*36 + 4)); session->gpsdata.raw.pseudorange[i] = getled64((char *)buf, 7 + 26 + (i*36 + 8)); session->gpsdata.raw.doppler[i] = getled64((char *)buf, 7 + 26 + (i*36 + 16)); session->gpsdata.raw.carrierphase[i] = getleu16(buf, 7 + 26 + (i*36 + 28)); session->gpsdata.raw.mtime[i] = session->newdata.time; session->gpsdata.raw.codephase[i] = NAN; session->gpsdata.raw.deltarange[i] = NAN; } return RAW_IS; }
int ntpshm_put(struct gps_device_t *session, volatile struct shmTime *shmseg, struct timedelta_t *td) /* put a received fix time into shared memory for NTP */ { char real_str[TIMESPEC_LEN]; char clock_str[TIMESPEC_LEN]; /* Any NMEA will be about -1 or -2. Garmin GPS-18/USB is around -6 or -7. */ int precision = -20; /* default precision, 1 micro sec */ if (shmseg == NULL) { gpsd_log(&session->context->errout, LOG_RAW, "NTP:PPS: missing shm\n"); return 0; } #ifdef PPS_ENABLE if (shmseg == session->shm_pps) { /* precision is a floor so do not make it tight */ if ( source_usb == session->sourcetype ) { /* if PPS over USB, then precision = -20, 1 micro sec */ precision = -20; } else { /* likely PPS over serial, precision = -30, 1 nano sec */ precision = -30; } } #endif /* PPS_ENABLE */ ntp_write(shmseg, td, precision, session->context->leap_notify); timespec_str( &td->real, real_str, sizeof(real_str) ); timespec_str( &td->clock, clock_str, sizeof(clock_str) ); gpsd_log(&session->context->errout, LOG_PROG, "NTP: ntpshm_put(%s,%s) %s @ %s\n", session->gpsdata.dev.path, precision, real_str, clock_str); return 1; }
/************************************************************************** * decode integer from string, check if the result is in expected range * return 0: OK * -1: data error * -2: data not valid **************************************************************************/ static int gar_int_decode(const struct gps_context_t *context, const char *data, const size_t length, const unsigned int min, const unsigned int max, unsigned int *result) { char buf[6]; unsigned int res; if (length >= sizeof(buf)) { gpsd_log(&context->errout, LOG_ERROR, "internal buffer too small\n"); return -1; } memset(buf, 0, (int)sizeof(buf)); (void)strlcpy(buf, data, length); gpsd_log(&context->errout, LOG_RAW + 2, "Decoded string: %s\n", buf); if (strchr(buf, '_') != NULL) { /* value is not valid, ignore it */ return -2; } if (strspn(buf, "0123456789") != length) { gpsd_log(&context->errout, LOG_WARN, "Invalid value %s\n", buf); return -1; } res = (unsigned)atoi(buf); if ((res >= min) && (res <= max)) { *result = res; return 0; /* SUCCESS */ } else { gpsd_log(&context->errout, LOG_WARN, "Value %u out of range <%u, %u>\n", res, min, max); return -1; } }
/* * decode MID 0xDD, Raw Measurements * */ static gps_mask_t sky_msg_DD(struct gps_device_t *session, unsigned char *buf, size_t len UNUSED) { unsigned int iod; /* Issue of data 0 - 255 */ unsigned int nmeas; /* number of measurements */ iod = (unsigned int)getub(buf, 1); nmeas = (unsigned int)getub(buf, 2); gpsd_log(&session->context->errout, LOG_DATA, "Skytraq: MID 0xDD: iod=%u, nmeas=%u\n", iod, nmeas); return 0; }
/* zodiac_spew - Takes a message type, an array of data words, and a length * for the array, and prepends a 5 word header (including checksum). * The data words are expected to be checksummed. */ static ssize_t zodiac_spew(struct gps_device_t *session, unsigned short type, unsigned short *dat, int dlen) { struct header h; int i; char buf[BUFSIZ]; h.sync = 0x81ff; h.id = (unsigned short)type; h.ndata = (unsigned short)(dlen - 1); h.flags = 0; h.csum = zodiac_checksum((unsigned short *)&h, 4); if (!BAD_SOCKET(session->gpsdata.gps_fd)) { size_t hlen, datlen; hlen = sizeof(h); datlen = sizeof(unsigned short) * dlen; if (end_write(session->gpsdata.gps_fd, &h, hlen) != (ssize_t) hlen || end_write(session->gpsdata.gps_fd, dat, datlen) != (ssize_t) datlen) { gpsd_log(&session->context->errout, LOG_RAW, "Reconfigure write failed\n"); return -1; } } (void)snprintf(buf, sizeof(buf), "%04x %04x %04x %04x %04x", h.sync, h.id, h.ndata, h.flags, h.csum); for (i = 0; i < dlen; i++) str_appendf(buf, sizeof(buf), " %04x", dat[i]); gpsd_log(&session->context->errout, LOG_RAW, "Sent Zodiac packet: %s\n", buf); return 0; }
static gps_mask_t handle1003(struct gps_device_t *session) /* skyview report */ { int i, n; /* The Polaris (and probably the DAGR) emit some strange variant of * this message which causes gpsd to crash filtering on impossible * number of satellites avoids this */ n = (int)getzword(14); if ((n < 0) || (n > 12)) return 0; gpsd_zero_satellites(&session->gpsdata); /* ticks = getzlong(6); */ /* sequence = getzword(8); */ session->gpsdata.dop.gdop = (unsigned int)getzword(9) * 1e-2; session->gpsdata.dop.pdop = (unsigned int)getzword(10) * 1e-2; session->gpsdata.dop.hdop = (unsigned int)getzword(11) * 1e-2; session->gpsdata.dop.vdop = (unsigned int)getzword(12) * 1e-2; session->gpsdata.dop.tdop = (unsigned int)getzword(13) * 1e-2; session->gpsdata.satellites_visible = n; for (i = 0; i < ZODIAC_CHANNELS; i++) { if (i < session->gpsdata.satellites_visible) { session->gpsdata.skyview[i].PRN = (short)getzword(15 + (3 * i)); session->gpsdata.skyview[i].azimuth = (short)(((short)getzword(16 + (3 * i))) * RAD_2_DEG * 1e-4); if (session->gpsdata.skyview[i].azimuth < 0) session->gpsdata.skyview[i].azimuth += 360; session->gpsdata.skyview[i].elevation = (short)(((short)getzword(17 + (3 * i))) * RAD_2_DEG * 1e-4); } else { session->gpsdata.skyview[i].PRN = 0; session->gpsdata.skyview[i].azimuth = 0; session->gpsdata.skyview[i].elevation = 0; } } session->gpsdata.skyview_time = NAN; gpsd_log(&session->context->errout, LOG_DATA, "NAVDOP: visible=%d gdop=%.2f pdop=%.2f " "hdop=%.2f vdop=%.2f tdop=%.2f mask={SATELLITE|DOP}\n", session->gpsdata.satellites_visible, session->gpsdata.dop.gdop, session->gpsdata.dop.hdop, session->gpsdata.dop.vdop, session->gpsdata.dop.pdop, session->gpsdata.dop.tdop); return SATELLITE_SET | DOP_SET; }
static void init_hook(struct gps_device_t *session) /* for chrony SOCK interface, which allows nSec timekeeping */ { /* open the chrony socket */ char chrony_path[GPS_PATH_MAX]; session->chronyfd = -1; if ( 0 == getuid() ) { /* this case will fire on command-line devices; * they're opened before priv-dropping. Matters because * only root can use /var/run. */ (void)snprintf(chrony_path, sizeof (chrony_path), "/var/run/chrony.%s.sock", basename(session->gpsdata.dev.path)); } else { (void)snprintf(chrony_path, sizeof (chrony_path), "/tmp/chrony.%s.sock", basename(session->gpsdata.dev.path)); } if (access(chrony_path, F_OK) != 0) { gpsd_log(&session->context->errout, LOG_PROG, "PPS:%s chrony socket %s doesn't exist\n", session->gpsdata.dev.path, chrony_path); } else { session->chronyfd = netlib_localsocket(chrony_path, SOCK_DGRAM); if (session->chronyfd < 0) gpsd_log(&session->context->errout, LOG_PROG, "PPS:%s connect chrony socket failed: %s, error: %d, errno: %d/%s\n", session->gpsdata.dev.path, chrony_path, session->chronyfd, errno, strerror(errno)); else gpsd_log(&session->context->errout, LOG_RAW, "PPS:%s using chrony socket: %s\n", session->gpsdata.dev.path, chrony_path); } }
/** * PPS offset */ static gps_mask_t oncore_msg_pps_offset(struct gps_device_t *session, unsigned char *buf, size_t data_len) { int pps_offset_ns; if (data_len != 11) return 0; gpsd_log(&session->context->errout, LOG_DATA, "oncore PPS offset\n"); pps_offset_ns = (int)getbes32(buf, 4); session->driver.oncore.pps_offset_ns = pps_offset_ns; return 0; }
static void evermore_mode(struct gps_device_t *session, int mode) { gpsd_log(&session->context->errout, LOG_PROG, "evermore_mode(%d), %d\n", mode, session->back_to_nmea ? 1 : 0); if (mode == MODE_NMEA) { /* NMEA */ (void)evermore_protocol(session, 1); (void)evermore_nmea_config(session, 1); /* configure NMEA messages for gpsd */ } else { /* binary */ (void)evermore_protocol(session, 0); session->back_to_nmea = false; } }
void gpsd_century_update(struct gps_device_t *session, int century) { session->context->valid |= CENTURY_VALID; if (century > session->context->century) { /* * This mismatch is almost certainly not due to a GPS week * rollover, because that would throw the ZDA report backward * into the last rollover period instead of forward. Almost * certainly it means that a century mark has passed while * gpsd was running, and we should trust the new ZDA year. */ gpsd_log(&session->context->errout, LOG_WARN, "century rollover detected.\n"); session->context->century = century; } else if (session->context->start_time >= GPS_EPOCH && century < session->context->century) { /* * This looks like a GPS week-counter rollover. */ gpsd_log(&session->context->errout, LOG_WARN, "ZDA year less than clock year, " "probable GPS week rollover lossage\n"); session->context->valid &=~ CENTURY_VALID; } }