Exemple #1
0
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_report(LOG_PROG,
		    "ITALK: bad SUBFRAME (len %zu, should be 64)\n", len);
	return 0;
    }

    flags = (ushort) getleu16(buf, 7 + 4);
    prn = (ushort) getleu16(buf, 7 + 6);
    sf = (ushort) getleu16(buf, 7 + 8);
    gpsd_report(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);
}
Exemple #2
0
/*@-mustfreefresh@*/
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_report(&session->context->errout, LOG_PROG,
		    "PPS chrony socket %s doesn't exist\n", chrony_path);
    } else {
	session->chronyfd = netlib_localsocket(chrony_path, SOCK_DGRAM);
	if (session->chronyfd < 0)
	    gpsd_report(&session->context->errout, LOG_PROG,
		"PPS connect chrony socket failed: %s, error: %d, errno: %d/%s\n",
		chrony_path, session->chronyfd, errno, strerror(errno));
	else
	    gpsd_report(&session->context->errout, LOG_RAW,
			"PPS using chrony socket: %s\n", chrony_path);
    }
}
Exemple #3
0
void gpsd_time_init(struct gps_context_t *context, time_t starttime)
/* initialize the GPS context's time fields */
{
    /*
     * 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 = LEAPSECOND_NOW;
    context->century = CENTURY_BASE;
    context->start_time = starttime;

    context->rollovers = (int)((context->start_time-GPS_EPOCH) / GPS_ROLLOVER);

    if (context->start_time < GPS_EPOCH)
	gpsd_report(LOG_ERROR, "system time looks bogus, dates may not be reliable.\n");
    else {
	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_report(LOG_INF, "startup at %s (%d)\n", 
		    scr, (int)context->start_time);
    }
}
Exemple #4
0
void ntpshm_link_activate(struct gps_device_t *session)
/* set up ntpshm storage for a session */
{
    /* allocate a shared-memory segment for "NMEA" time data */
    session->shmIndex = ntpshm_alloc(session->context);

    if (0 > session->shmIndex) {
	gpsd_report(&session->context->errout, LOG_INF, 
                    "NTPD ntpshm_alloc() failed\n");
#if defined(PPS_ENABLE)
    } else if (session->sourcetype == source_usb || session->sourcetype == source_rs232) {
	/* 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->shmIndexPPS = ntpshm_alloc(session->context)) < 0) {
	    gpsd_report(&session->context->errout, LOG_INF, 
                        "NTPD ntpshm_alloc(1) failed\n");
	} else {
	    init_hook(session);
	    session->thread_report_hook = report_hook;
	    session->thread_wrap_hook = wrap_hook;
	    pps_thread_activate(session);
	}
#endif /* PPS_ENABLE */
    }
}
Exemple #5
0
static int ntrip_stream_get_req(const struct ntrip_stream_t *stream,
				const int debug)
{
    int dsock;
    char buf[BUFSIZ];

    dsock = netlib_connectsock(AF_UNSPEC, stream->url, stream->port, "tcp");
    if (BAD_SOCKET(dsock)) {
	gpsd_report(debug, LOG_ERROR,
		    "ntrip stream connect error %d\n", dsock);
	return -1;
    }

    gpsd_report(debug, 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_report(debug, LOG_ERROR,
		    "ntrip stream write error %d on fd %d during get request\n", errno,
		    dsock);
	(void)close(dsock);
	return -1;
    }
    return dsock;
}
Exemple #6
0
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_report(LOG_IO, "=> dgps %s\n", buf);
	    else
		gpsd_report(LOG_IO, "write to dgps FAILED\n");
	}
    }
}
Exemple #7
0
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_report(context->debug, LOG_IO, "=> dgps %s\n", buf);
	    } else {
		gpsd_report(context->debug, LOG_IO, "ntrip report write failed\n");
	    }
	}
    }
}
Exemple #8
0
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_report(LOG_PROG,
		    "ITALK: bad UTC_IONO_MODEL (len %zu, should be 64)\n",
		    len);
	return 0;
    }

    flags = (ushort) 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_report(LOG_DATA,
		"UTC_IONO_MODEL: time=%.2f mask={TIME}\n",
		session->newdata.time);
    return TIME_SET | PPSTIME_IS;
}
Exemple #9
0
static int ntrip_stream_req_probe(const struct ntrip_stream_t *stream,
				  const int debug)
{
    int dsock;
    ssize_t r;
    char buf[BUFSIZ];

    dsock = netlib_connectsock(AF_UNSPEC, stream->url, stream->port, "tcp");
    if (dsock < 0) {
	gpsd_report(debug, LOG_ERROR, "ntrip stream connect error %d in req probe\n", dsock);
	return -1;
    }
    gpsd_report(debug, 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_report(debug, 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;
}
Exemple #10
0
int ntpshm_pps(struct gps_device_t *session, struct timeval *tv)
{
    struct shmTime *shmTime = NULL, *shmTimeP = NULL;
    time_t seconds;
    double offset;
    long l_offset;

    if (session->shmindex < 0 || session->shmTimeP < 0 ||
	(shmTime = session->context->shmTime[session->shmindex]) == NULL ||
	(shmTimeP = session->context->shmTime[session->shmTimeP]) == NULL)
	return 0;

    /* check if received time messages are within locking range */

#ifdef S_SPLINT_S	/* avoids an internal error in splint 3.1.1 */
    l_offset = 0;
#else
    l_offset = shmTime->receiveTimeStampSec - shmTime->clockTimeStampSec;
#endif
    /*@ -ignorequals @*/
    l_offset *= 1000000;
    l_offset += shmTime->receiveTimeStampUSec - shmTime->clockTimeStampUSec;
    /*@ +ignorequals @*/
    if (labs( l_offset ) > PUT_MAX_OFFSET) {
        gpsd_report(LOG_RAW, "ntpshm_pps: not in locking range: %ld\n"
		, (long)l_offset);
	return -1;
    }
    /*@ -ignorequals @*/

    if (tv->tv_usec < PPS_MAX_OFFSET) {
	seconds = (time_t)tv->tv_sec;
	offset = (double)tv->tv_usec / 1000000.0;
    } else {
	if (tv->tv_usec > (1000000 - PPS_MAX_OFFSET)) {
	    seconds = (time_t)(tv->tv_sec + 1);
	    offset = 1 - ((double)tv->tv_usec / 1000000.0);
	} else {
	    shmTimeP->precision = -1;	/* lost lock */
	    gpsd_report(LOG_INF, "ntpshm_pps: lost PPS lock\n");
	    return -1;
	}
    }

    shmTimeP->count++;
    shmTimeP->clockTimeStampSec = seconds;
    shmTimeP->clockTimeStampUSec = 0;
    shmTimeP->receiveTimeStampSec = (time_t)tv->tv_sec;
    shmTimeP->receiveTimeStampUSec = tv->tv_usec;
    shmTimeP->precision = offset != 0 ? (int)(ceil(log(offset) / M_LN2)) : -20;
    shmTimeP->count++;
    shmTimeP->valid = 1;

    gpsd_report(LOG_RAW, "ntpshm_pps: clock: %lu @ %lu.%06lu, precision %d\n"
	, (unsigned long)seconds, (unsigned long)tv->tv_sec
        , (unsigned long)tv->tv_usec, shmTimeP->precision);
    return 1;
}
/*@ -branchstate @*/
int ntrip_open(struct gps_context_t *context, char *caster)
/* open a connection to a Ntrip broadcaster */
{
    char *amp, *colon, *slash;
    char *auth = NULL;
    char *port = NULL;
    char *stream = NULL;
    int ret;

    /*@ -boolops @*/
    if ((amp = strchr(caster, '@')) != NULL) {
	if (((colon = strchr(caster, ':')) != NULL) && colon < amp) {
	    auth = caster;
	    *amp = '\0';
	    caster = amp + 1;
	} else {
	    gpsd_report(LOG_ERROR,
			"can't extract user-ID and password from %s\n",
			caster);
	    return -1;
	}
    }
    /*@ +boolops @*/
    if ((slash = strchr(caster, '/')) != NULL) {
	*slash = '\0';
	stream = slash + 1;
    } else {
	/* todo: add autoconnect like in dgpsip.c */
	gpsd_report(LOG_ERROR, "can't extract Ntrip stream from %s\n",
		    caster);
	return -1;
    }
    if ((colon = strchr(caster, ':')) != NULL) {
	port = colon + 1;
	*colon = '\0';
    }
    if (!port) {
	port = "rtcm-sc104";
	if (!getservbyname(port, "tcp"))
	    port = DEFAULT_RTCM_PORT;
    }
    if (ntrip_stream_probe(caster, port, stream, &ntrip_stream)) {
	gpsd_report(LOG_ERROR,
		    "unable to probe for data about stream %s:%s/%s\n",
		    caster, port, stream);
	return -1;
    }
    ret = ntrip_stream_open(caster, port, auth, context, &ntrip_stream);
    if (ret >= 0)
	gpsd_report(LOG_PROG,
		    "connection to Ntrip broadcaster %s established.\n",
		    caster);
    else
	gpsd_report(LOG_ERROR, "can't connect to Ntrip stream %s:%s/%s.\n",
		    caster, port, stream);
    return ret;
}
static void onsig(int sig)
{
    if (sig == SIGALRM) {
	gpsd_report(LOG_ERROR, "packet recognition timed out.\n");
	exit(1);
    } else {
	gpsd_report(LOG_ERROR, "killed by signal %d\n", sig);
	exit(0);
    }
}
Exemple #13
0
static void evermore_configurator(struct gps_device_t *session, unsigned int seq)
{
    gpsd_report(LOG_PROG, "evermore_configurator(%d)\n", seq);
    (void) evermore_nmea_config(session, 1); /* configure NMEA messages for gpsd (GPGSV every 5s) */
    if (seq == 0) {
        if (session->packet.type == NMEA_PACKET) {
	    gpsd_report(LOG_WARN, "NMEA_PACKET packet\n");
        }
        (void) evermore_mode(session, 1); /* switch GPS to binary mode */
        session->back_to_nmea = true;
    }
}
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_report(&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);
	nsv = 0;
	nchan = (unsigned int)getleu16(buf, 7 + 50);
	if (nchan > MAX_NR_VISIBLE_PRNS)
	    nchan = MAX_NR_VISIBLE_PRNS;
	for (i = st = 0; i < nchan; i++) {
	    unsigned int off = 7 + 52 + 10 * i;
	    unsigned short flags;
	    bool used;

	    flags = (unsigned short) getleu16(buf, off);
	    used = flags & PRN_FLAG_USE_IN_NAV;
	    session->gpsdata.skyview[i].ss = (float)(getleu16(buf, off + 2) & 0xff);
	    session->gpsdata.skyview[i].PRN = (int)getleu16(buf, off + 4) & 0xff;
	    session->gpsdata.skyview[i].elevation = (int)getles16(buf, off + 6) & 0xff;
	    session->gpsdata.skyview[i].azimuth = (int)getles16(buf, off + 8) & 0xff;
	    session->gpsdata.skyview[i].used = used;
	    if (session->gpsdata.skyview[i].PRN > 0) {
		st++;
		if (used)
		    session->sats_used[nsv++] = session->gpsdata.skyview[i].PRN;
	    }
	}
	session->gpsdata.satellites_visible = (int)st;
	session->gpsdata.satellites_used = (int)nsv;
	mask = USED_IS | SATELLITE_SET;;

	gpsd_report(&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;
}
Exemple #15
0
static int ntrip_stream_get_parse(const struct ntrip_stream_t *stream,
				  const int dsock, const int debug)
{
/*@-nullpass@*/
    char buf[BUFSIZ];
    int opts;
    memset(buf, 0, sizeof(buf));
    while (read(dsock, buf, sizeof(buf) - 1) == -1) {
	if (errno == EINTR)
	    continue;
	gpsd_report(debug, 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_report(debug, 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_report(debug, 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_report(debug, 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@*/
}
Exemple #16
0
void gpsd_close(struct gps_device_t *session)
{
    if (session->gpsdata.gps_fd != -1) {
	(void)tcdrain(session->gpsdata.gps_fd);
	if (isatty(session->gpsdata.gps_fd) != 0) {
	    /* force hangup on close on systems that don't do HUPCL properly */
	    /*@ ignore @*/
	    (void)cfsetispeed(&session->ttyset, (speed_t) B0);
	    (void)cfsetospeed(&session->ttyset, (speed_t) B0);
	    /*@ end @*/
	    (void)tcsetattr(session->gpsdata.gps_fd, TCSANOW,
			    &session->ttyset);
	}
	/* this is the clean way to do it */
	session->ttyset_old.c_cflag |= HUPCL;
	/* keep the most recent baud rate */
	/*@ ignore @*/
	(void)cfsetispeed(&session->ttyset_old,
			  (speed_t) session->gpsdata.dev.baudrate);
	(void)cfsetospeed(&session->ttyset_old,
			  (speed_t) session->gpsdata.dev.baudrate);
	/*@ end @*/
	(void)tcsetattr(session->gpsdata.gps_fd, TCSANOW,
			&session->ttyset_old);
	gpsd_report(LOG_SPIN, "close(%d) in gpsd_close(%s)\n",
		    session->gpsdata.gps_fd, session->gpsdata.dev.path);
	(void)close(session->gpsdata.gps_fd);
	session->gpsdata.gps_fd = -1;
    }
}
Exemple #17
0
timestamp_t gpsd_utc_resolve(/*@in@*/struct gps_device_t *session)
/* resolve a UTC date, checking for rollovers */
{
    /*
     * We'd like to *correct* for rollover the way we do for GPS week.
     * In theory, comparing extracted UTC against present time should
     * allow us to compute the device's epoch assumption.  In practice,
     * this will be hairy and risky.
     */
    timestamp_t t;

    t = (timestamp_t)mkgmtime(&session->driver.nmea.date) +
	session->driver.nmea.subseconds;
    session->context->valid &=~ GPS_TIME_VALID;

    /*
     * If the system clock is zero or has a small-integer value,
     * no further sanity-checking is possible.
     */
    if (session->context->start_time < GPS_EPOCH)
	return t;

    /*
     * If the GPS is reporting a time from before the daemon started, we've
     * had a rollover event while the daemon was running.
     */
    if (session->newdata.time < (timestamp_t)session->context->start_time) {
	char scr[128];
	(void)unix_to_iso8601(session->newdata.time, scr, sizeof(scr));
	gpsd_report(LOG_WARN, "GPS week rollover makes time %s (%f) invalid\n",
		    scr, session->newdata.time);
    }

    return t;
}
Exemple #18
0
/*@ -branchstate */
int netgnss_uri_open(struct gps_device_t *dev, char *netgnss_service)
/* open a connection to a DGNSS service */
{
#ifdef NTRIP_ENABLE
    if (strncmp(netgnss_service, NETGNSS_NTRIP, strlen(NETGNSS_NTRIP)) == 0) {
	dev->ntrip.conn_state = ntrip_conn_init;
	return ntrip_open(dev, netgnss_service + strlen(NETGNSS_NTRIP));
    }
#endif

    if (strncmp(netgnss_service, NETGNSS_DGPSIP, strlen(NETGNSS_DGPSIP)) == 0)
	return dgpsip_open(dev, netgnss_service + strlen(NETGNSS_DGPSIP));

    if (strncmp(netgnss_service, NETGNSS_UDP, strlen(NETGNSS_UDP)) == 0)
	return udp_open(dev, netgnss_service + strlen(NETGNSS_UDP));

#ifndef REQUIRE_DGNSS_PROTO
    return dgpsip_open(dev, netgnss_service);
#else
    gpsd_report(LOG_ERROR,
		"Unknown or unspecified DGNSS protocol for service %s\n",
		netgnss_service);
    return -1;
#endif
}
Exemple #19
0
/*@ -temptrans -mustfreefresh @*/
static /*@null@*/ char *ntrip_field_iterate( /*@null@ */ char *start,
					     /*@null@*/ char *prev,
					     const char *eol,
					     const int debug)
{
    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_report(debug, LOG_RAW, "Next Ntrip source table field %s\n", s);

    return s;
}
Exemple #20
0
/* offset is actual_ts - clock_ts */
static void chrony_send(struct gps_device_t *session, struct timedrift_t *td)
{
    struct sock_sample sample;

    /* chrony expects tv-sec since Jan 1970 */
    sample.pulse = 0;
    sample.leap = session->context->leap_notify;
    sample.magic = SOCK_MAGIC;
    /*@-type@*//* splint is confused about struct timespec */
    TSTOTV(&sample.tv, &td->clock);
    /*@-compdef@*/
    sample.offset = timespec_diff_ns(td->real, td->clock) / 1e9;
    /*@+compdef@*/
#ifdef __COVERITY__
    sample._pad = 0;
#endif /* __COVERITY__ */
    /*@+type@*/

    /*@-type@*/ /* splint is confused about struct timespec */
    gpsd_report(&session->context->errout, LOG_RAW,
		"PPS chrony_send %lu.%09lu @ %lu.%09lu Offset: %0.9f\n",
		(unsigned long)td->real.tv_sec,
		(unsigned long)td->real.tv_nsec,
		(unsigned long)td->clock.tv_sec,
		(unsigned long)td->clock.tv_nsec,
                sample.offset);
    /*@+type@*/
    (void)send(session->chronyfd, &sample, sizeof (sample), 0);
}
Exemple #21
0
ssize_t gpsd_serial_write(struct gps_device_t * session,
			  const char *buf, const size_t len)
{
    ssize_t status;
    int error = 0;
    bool ok;
/*
    if (session == NULL ||
	session->context == NULL || session->context->readonly)
	return 0;
*/
    status = write(session->gpsdata.gps_fd, buf, len);
    ok = (status == (ssize_t) len);
    session->gpsdata.bytes_send += status;
    if(!ok) error = errno;
    (void)tcdrain(session->gpsdata.gps_fd);
    /* extra guard prevents expensive hexdump calls */
    if (session->context->debug >= LOG_IO) {
	char scratchbuf[MAX_PACKET_LENGTH*2+1];
	gpsd_report(session->context->debug, LOG_IO,
		    "=> GPS: %s%s (%d, %d)\n",
		    gpsd_packetdump(scratchbuf, sizeof(scratchbuf),
				    (char *)buf, len), ok ? "" : " FAILED", status, error);
    }
    return status;
}
Exemple #22
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_report(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_write(session, evrm_nmeaout_config, sizeof(evrm_nmeaout_config));
}
Exemple #23
0
gps_mask_t generic_parse_input(struct gps_device_t *session)
{
    const struct gps_type_t **dp;

    if (session->packet.type == COMMENT_PACKET) {
	gpsd_set_century(session);
	return 0;
#ifdef NMEA_ENABLE
    } else if (session->packet.type == NMEA_PACKET) {
	gps_mask_t st = 0;
	char *sentence = (char *)session->packet.outbuffer;

	if (sentence[strlen(sentence)-1] != '\n')
	    gpsd_report(LOG_IO, "<= GPS: %s\n", sentence);
	else
	    gpsd_report(LOG_IO, "<= GPS: %s", sentence);

	if ((st=nmea_parse(sentence, session)) == 0) {
	    gpsd_report(LOG_WARN, "unknown sentence: \"%s\"\n",	sentence);
	}
	for (dp = gpsd_drivers; *dp; dp++) {
	    char *trigger = (*dp)->trigger;

	    if (trigger!=NULL && strncmp(sentence,trigger,strlen(trigger))==0) {
		gpsd_report(LOG_PROG, "found trigger string %s.\n", trigger);
		if (*dp != session->device_type) {
		    (void)gpsd_switch_driver(session, (*dp)->type_name);
		    if (session->device_type != NULL
			&& session->device_type->event_hook != NULL)
			session->device_type->event_hook(session,
							 event_triggermatch);
		    st |= DEVICEID_SET;
		}
	    }
	}
	return st;
#endif /* NMEA_ENABLE */
    } else {
	for (dp = gpsd_drivers; *dp; dp++) {
	    if (session->packet.type == (*dp)->packet_type) {
		(void)gpsd_switch_driver(session, (*dp)->type_name);
		return (*dp)->parse_packet(session);
	    }
	}
	return 0;
    }
}
Exemple #24
0
static /*@null@*/ struct shmTime *getShmTime(int unit)
{
    int shmid=shmget ((key_t)(NTPD_BASE+unit), 
		      sizeof (struct shmTime), IPC_CREAT|0644);
    if (shmid == -1) {
	gpsd_report(LOG_ERROR, "shmget failed\n");
	return NULL;
    } else {
	struct shmTime *p=(struct shmTime *)shmat (shmid, 0, 0);
	/*@ -mustfreefresh */
	if ((int)(long)p == -1) {
	    gpsd_report(LOG_ERROR, "shmat failed\n");
	    return NULL;
	}
        gpsd_report(LOG_PROG, "shmat(%d,0,0) succeeded\n");
	return p;
	/*@ +mustfreefresh */
    }
}
Exemple #25
0
static bool tnt_send(struct gps_device_t *session, const char *fmt, ...)
/* printf(3)-like TNT command generator */
{
    char buf[BUFSIZ];
    va_list ap;
    ssize_t sent;

    va_start(ap, fmt);
    (void)vsnprintf(buf, sizeof(buf) - 5, fmt, ap);
    va_end(ap);
    sent = tnt_control_send(session, buf, strlen(buf));
    if (sent == (ssize_t) strlen(buf)) {
	gpsd_report(LOG_IO, "=> GPS: %s\n", buf);
	return true;
    } else {
	gpsd_report(LOG_WARN, "=> GPS: %s FAILED\n", buf);
	return false;
    }
}
Exemple #26
0
void pps_thread_activate(struct gps_device_t *session)
/* activate a thread to watch the device's PPS transitions */
{
    int retval;
    pthread_t pt;
#if defined(HAVE_SYS_TIMEPPS_H)
    /* some operations in init_kernel_pps() require root privs */
    (void)init_kernel_pps( session );
    if ( 0 <= session->kernelpps_handle ) {
	gpsd_report(session->context->debug, LOG_WARN,
		    "KPPS kernel PPS will be used\n");
    }
#endif
    /*@-compdef -nullpass@*/
    retval = pthread_create(&pt, NULL, gpsd_ppsmonitor, (void *)session);
    /*@+compdef +nullpass@*/
    gpsd_report(session->context->debug, LOG_PROG, "PPS thread %s\n",
		(retval==0) ? "launched" : "FAILED");
}
Exemple #27
0
static gps_mask_t decode_itk_pseudo(struct gps_device_t *session,
				      unsigned char *buf, size_t len)
{
    unsigned short flags, n, i;
    union long_double l_d;

    n = (ushort) getleu16(buf, 7 + 4);
    if ((n < 1) || (n > MAXCHANNELS)){
	gpsd_report(LOG_INF, "ITALK: bad PSEUDO channel count\n");
	return 0;
    }

    if (len != (size_t)((n+1)*36)) {
	gpsd_report(LOG_PROG,
		    "ITALK: bad PSEUDO len %zu\n", len);
    }

    gpsd_report(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(buf, 7 + 8),
	(unsigned int)getleu32(buf, 7 + 38) / 1000.0);

    /*@-type@*/
    for (i = 0; i < n; i++){
	session->gpsdata.PRN[i] = getleu16(buf, 7 + 26 + (i*36)) & 0xff;
	session->gpsdata.ss[i] = 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] = getled(buf, 7 + 26 + (i*36 + 8));
	session->gpsdata.raw.doppler[i] = getled(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;
    }
    /*@+type@*/
    return RAW_IS;
}
Exemple #28
0
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.
     */
    /*@-observertrans@*/
    (void)putenv("TZ=UTC");
    /*@+observertrans@*/

    /*
     * 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 = LEAPSECOND_NOW;
    context->century = CENTURY_BASE;
    context->start_time = starttime;

    context->rollovers = (int)((context->start_time-GPS_EPOCH) / GPS_ROLLOVER);

    if (context->start_time < GPS_EPOCH)
	gpsd_report(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_report(LOG_INF, "startup at %s (%d)\n",
		    scr, (int)context->start_time);
    }
}
Exemple #29
0
/* Note: you can start gpsd as non-root, and have it work with ntpd.
 * However, it will then only use the ntpshm segments 2 and 3.
 *
 * Ntpd always runs as root (to be able to control the system clock).
 * Its logics for the creation of ntpshm segments are:
 *
 * Segments 0 and 1: permissions 0600, i.e. other programs can only
 *                   read and write as root.
 *
 * Segments 2 and 3: permissions 0666, i.e. other programs can read
 *                   and write as any user.  I.e.: if ntpd has been
 *                   configured to use these segments, any
 *                   unpriviliged user is allowed to provide data
 *                   for synchronisation.
 * * As gpsd can be started as both root and non-root, this behaviour is
 * mimicked by:
 *
 * Started as root: do as ntpd when attaching (creating) the segments.
 * (In contrast to ntpd, which only attaches (creates) configured
 * segments, gpsd creates all segments.)
 *
 * Started as non-root: only attach (create) segments 2 and 3 with
 * permissions 0666.  As the permissions are for any user, the creator
 * does not matter.
 *
 * For each GPS module gpsd controls, it will use the attached ntpshm
 * segments in pairs (for coarse clock and pps source, respectively)
 * starting from the first found segments.  I.e. started as root, one
 * GPS will deliver data on segments 0 and 1, and as non-root data
 * will be delivered on segments 2 and 3.
 *
 * to debug, try looking at the live segments this way
 *
 *  ipcs -m
 * 
 * results  should look like this:
 * ------ Shared Memory Segments --------
 *  key        shmid      owner      perms      bytes      nattch     status
 *  0x4e545030 0          root       700        96         2
 *  0x4e545031 32769      root       700        96         2
 *  0x4e545032 163842     root       666        96         1
 *  0x4e545033 196611     root       666        96         1
 *
 * For a bit more data try this:
 *  cat /proc/sysvipc/shm
 *
 * If gpsd can not open the segments be sure you are not running SELinux
 * or apparmor.
 *
 * if you see the shared segments (keys 1314148400 -- 1314148403), and
 * no gpsd or ntpd is running then try removing them like this:
 *
 * ipcrm  -M 0x4e545030
 * ipcrm  -M 0x4e545031
 * ipcrm  -M 0x4e545032
 * ipcrm  -M 0x4e545033
 */
static /*@null@*/ 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_report(&context->errout, LOG_ERROR,
		    "NTPD 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);
    /*@ -mustfreefresh */
    if ((int)(long)p == -1) {
	gpsd_report(&context->errout, LOG_ERROR,
		    "NTPD shmat failed: %s\n",
		    strerror(errno));
	return NULL;
    }
    gpsd_report(&context->errout, LOG_PROG,
		"NTPD shmat(%d,0,0) succeeded, segment %d\n",
		shmid, unit);
    return p;
    /*@ +mustfreefresh */
}
Exemple #30
0
bool gpsd_set_raw(struct gps_device_t * session)
{
    (void)cfmakeraw(&session->ttyset);
    if (tcsetattr(session->gpsdata.gps_fd, TCIOFLUSH, &session->ttyset) == -1) {
	gpsd_report(LOG_ERROR,
		    "error changing port attributes: %s\n", strerror(errno));
	return false;
    }

    return true;
}