summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2005-06-29 16:18:42 +0000
committerEric S. Raymond <esr@thyrsus.com>2005-06-29 16:18:42 +0000
commit1391a44aa66d71f74fa2513c16c8ae61e6a4e2ee (patch)
treeaf5fd7bd59e98984d0f15beba50018de4d491cf7
parent08a04efa887261803bc7717bd5e60882349aa131 (diff)
downloadgpsd-1391a44aa66d71f74fa2513c16c8ae61e6a4e2ee.tar.gz
Pull the DGPSIP code into its own module.
The DGPSIP socket is now part of the session context; it's guarded by the same select as all other socket reads. The latest RTCM104 report from it is relayed to each attached GPS when appropriate. (The old code only passed a correction to the first GPS to be polled after the report came in from the server.)
-rw-r--r--Makefile.am1
-rw-r--r--dgpsip.c87
-rw-r--r--gpsd.c28
-rw-r--r--gpsd.h20
-rw-r--r--libgpsd_core.c58
-rw-r--r--serial.c2
6 files changed, 123 insertions, 73 deletions
diff --git a/Makefile.am b/Makefile.am
index 7a322b94..c940f0c4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -80,6 +80,7 @@ libgps_c_sources = \
packet.c \
gpsutils.c \
geoid.c \
+ dgpsip.c \
sirf.c \
report.c \
bits.h \
diff --git a/dgpsip.c b/dgpsip.c
new file mode 100644
index 00000000..36164544
--- /dev/null
+++ b/dgpsip.c
@@ -0,0 +1,87 @@
+/* dgpsip.c -- gather and dispatch DGPS data from DGPSIP servers */
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include "gpsd.h"
+
+/*@ -branchstate */
+int dgpsip_open(struct gps_context_t *context, const char *dgpsserver)
+/* open a connection to a DGPSIP server */
+{
+ char hn[256], buf[BUFSIZ];
+ char *colon, *dgpsport = "rtcm-sc104";
+ int opts;
+
+ if ((colon = strchr(dgpsserver, ':'))) {
+ dgpsport = colon+1;
+ *colon = '\0';
+ }
+ if (!getservbyname(dgpsport, "tcp"))
+ dgpsport = "2101";
+
+ context->dsock = netlib_connectsock(dgpsserver, dgpsport, "tcp");
+ if (context->dsock >= 0) {
+ (void)gethostname(hn, sizeof(hn));
+ (void)snprintf(buf,sizeof(buf), "HELO %s gpsd %s\r\nR\r\n",hn,VERSION);
+ (void)write(context->dsock, buf, strlen(buf));
+ }
+ opts = fcntl(context->dsock, F_GETFL);
+
+ if (opts >= 0)
+ (void)fcntl(context->dsock, F_SETFL, opts | O_NONBLOCK);
+ return context->dsock;
+}
+/*@ +branchstate */
+
+void dgpsip_poll(struct gps_context_t *context)
+/* poll the DGPSIP server for a correction report */
+{
+ if (context->dsock > -1) {
+ context->rtcmbytes = read(context->dsock, context->rtcmbuf, sizeof(context->rtcmbuf));
+ if (context->rtcmbytes < 0 && errno != EAGAIN)
+ gpsd_report(1, "Read from rtcm source failed\n");
+ else
+ context->rtcmtime = timestamp();
+ }
+}
+
+void dgpsip_relay(struct gps_device_t *session)
+/* pass a DGPSIP connection report to a session */
+{
+ if (session->gpsdata.gps_fd !=-1 && session->context->rtcmbytes > -1
+ && session->rtcmtime < session->context->rtcmtime) {
+ if (session->device_type->rtcm_writer(session,
+ session->context->rtcmbuf,
+ (size_t)session->context->rtcmbytes) == 0)
+ gpsd_report(1, "Write to rtcm sink failed\n");
+ else {
+ session->rtcmtime = timestamp();
+ gpsd_report(2, "<= DGPS: %d bytes of RTCM relayed.\n", session->context->rtcmbytes);
+ }
+ }
+}
+
+void dgpsip_report(struct gps_device_t *session)
+/* may be time to ship a usage report to the DGPSIP server */
+{
+ if (session->fixcnt > 10 && !session->sentdgps) {
+ session->sentdgps = true;
+ if (session->context->dsock > -1) {
+ char buf[BUFSIZ];
+ (void)snprintf(buf, sizeof(buf), "R %0.8f %0.8f %0.2f\r\n",
+ session->gpsdata.fix.latitude,
+ session->gpsdata.fix.longitude,
+ session->gpsdata.fix.altitude);
+ (void)write(session->context->dsock, buf, strlen(buf));
+ gpsd_report(2, "=> dgps %s", buf);
+ }
+ }
+}
+
diff --git a/gpsd.c b/gpsd.c
index cf64f4ab..0fda316b 100644
--- a/gpsd.c
+++ b/gpsd.c
@@ -59,7 +59,8 @@ static int debuglevel;
static bool in_background = false;
static jmp_buf restartbuf;
/*@ -initallelements -nullassign -nullderef @*/
-static struct gps_context_t context = {0, LEAP_SECONDS, CENTURY_BASE,
+static struct gps_context_t context = {0, LEAP_SECONDS, CENTURY_BASE,
+ 0, 0, {'\0'}, 0,
#ifdef NTPSHM_ENABLE
{0},
{0},
@@ -936,7 +937,7 @@ int main(int argc, char *argv[])
{
static char *pid_file = NULL;
static bool nowait = false;
- static int st, dsock = -1, csock = -1;
+ static int st, csock = -1;
static gps_mask_t changed;
static char *dgpsserver = NULL;
static char *service = NULL;
@@ -1034,11 +1035,11 @@ int main(int argc, char *argv[])
gpsd_report(1, "listening on port %s\n", service);
if (dgpsserver) {
- dsock = gpsd_open_dgps(dgpsserver);
- if (dsock >= 0)
+ int dsock = dgpsip_open(&context, dgpsserver);
+ if (dsock >= 0) {
FD_SET(dsock, &all_fds);
- else
- gpsd_report(1, "Can't connect to DGPS server, netlib error %d\n",dsock);
+ } else
+ gpsd_report(1, "Can't connect to DGPS server, netlib error %d\n", dsock);
}
#ifdef NTPSHM_ENABLE
@@ -1120,15 +1121,11 @@ int main(int argc, char *argv[])
device = open_device(argv[i], nowait);
if (!device) {
gpsd_report(0, "GPS device %s nonexistent or can't be read\n", argv[i]);
- } else if (dsock >= 0)
- device->dsock = dsock;
+ }
}
for (;;) {
(void)memcpy((char *)&rfds, (char *)&all_fds, sizeof(rfds));
- for (channel = channels; channel < channels + MAXDEVICES; channel++)
- if (allocated_channel(channel) && channel->dsock > -1)
- FD_CLR(channel->dsock, &rfds);
/*
* Poll for user commands or GPS data. The timeout doesn't
@@ -1193,6 +1190,11 @@ int main(int argc, char *argv[])
FD_CLR(csock, &rfds);
}
+ /* be ready for DGPSIP reports */
+ if (FD_ISSET(context.dsock, &rfds)) {
+ dgpsip_poll(&context);
+ }
+
/* read any commands that came in over control sockets */
for (cfd = 0; cfd < FD_SETSIZE; cfd++)
if (FD_ISSET(cfd, &control_fds)) {
@@ -1212,6 +1214,7 @@ int main(int argc, char *argv[])
if (!allocated_channel(channel))
continue;
+
/* we may need to force the GPS open */
if (nowait && channel->gpsdata.gps_fd == -1) {
gpsd_deactivate(channel);
@@ -1221,6 +1224,9 @@ int main(int argc, char *argv[])
}
}
+ /* pass the current DGPSIP coorection to the GPS if new */
+ dgpsip_relay(channel);
+
/* get data from the device */
changed = 0;
if (channel->gpsdata.gps_fd >= 0 && FD_ISSET(channel->gpsdata.gps_fd, &rfds))
diff --git a/gpsd.h b/gpsd.h
index feb0db7d..b1511b34 100644
--- a/gpsd.h
+++ b/gpsd.h
@@ -25,7 +25,7 @@
/* only used if the GPS doesn't report estimated position error itself */
#define UERE_NO_DGPS 8 /* meters */
#define UERE_WITH_DGPS 2 /* meters */
-#define UERE(session) ((session->dsock==-1) ? UERE_NO_DGPS : UERE_WITH_DGPS)
+#define UERE(session) ((session->context->dsock==-1) ? UERE_NO_DGPS : UERE_WITH_DGPS)
#define NTPSHMSEGS 4 /* number of NTP SHM segments */
@@ -34,6 +34,10 @@ struct gps_context_t {
#define LEAP_SECOND_VALID 0x01 /* we have or don't need correction */
int leap_seconds;
int century; /* for NMEA-only devices without ZDA */
+ int dsock; /* socket to DGPS server */
+ ssize_t rtcmbytes; /* byte count of last RTCM104 report */
+ char rtcmbuf[40]; /* last RTCM104 report */
+ double rtcmtime; /* timestamp of last RTCM104 report */
#ifdef NTPSHM_ENABLE
/*@reldef@*/struct shmTime *shmTime[NTPSHMSEGS];
bool shmTimeInuse[NTPSHMSEGS];
@@ -81,8 +85,8 @@ struct gps_device_t {
/* session object, encapsulates all global state */
struct gps_data_t gpsdata;
/*@relnull@*/struct gps_type_t *device_type;
- int dsock; /* socket to DGPS server */
- int sentdgps; /* have we sent a DGPS correction? */
+ double rtcmtime; /* timestamp of last RTCM104 correction to GPS */
+ bool sentdgps; /* have we sent a DGPSIP usage report? */
int fixcnt; /* count of good fixes seen */
struct termios ttyset, ttyset_old;
/* packet-getter internals */
@@ -164,11 +168,16 @@ extern void nmea_add_checksum(char *);
extern gps_mask_t sirf_parse(struct gps_device_t *, unsigned char *, size_t);
-extern void packet_reset(struct gps_device_t *session);
-extern void packet_pushback(struct gps_device_t *session);
+extern void packet_reset(struct gps_device_t *);
+extern void packet_pushback(struct gps_device_t *);
extern ssize_t packet_get(struct gps_device_t *);
extern int packet_sniff(struct gps_device_t *);
+extern int dgpsip_open(struct gps_context_t *, const char *);
+extern void dgpsip_poll(struct gps_context_t *);
+extern void dgpsip_relay(struct gps_device_t *);
+extern void dgpsip_report(struct gps_device_t *);
+
extern int gpsd_open(struct gps_device_t *);
extern bool gpsd_next_hunt_setting(struct gps_device_t *);
extern int gpsd_switch_driver(struct gps_device_t *, char *);
@@ -191,7 +200,6 @@ extern void ecef_to_wgs84fix(struct gps_data_t *,
extern gps_mask_t dop(struct gps_data_t *);
/* External interface */
-extern int gpsd_open_dgps(char *);
extern void gpsd_init(struct gps_device_t *,
struct gps_context_t *, char *device);
extern int gpsd_activate(struct gps_device_t *);
diff --git a/libgpsd_core.c b/libgpsd_core.c
index 07715e9a..f9447c26 100644
--- a/libgpsd_core.c
+++ b/libgpsd_core.c
@@ -18,34 +18,6 @@
#include "gpsd.h"
-/*@ -branchstate */
-int gpsd_open_dgps(char *dgpsserver)
-{
- char hn[256], buf[BUFSIZ];
- char *colon, *dgpsport = "rtcm-sc104";
- int dsock, opts;
-
- if ((colon = strchr(dgpsserver, ':'))) {
- dgpsport = colon+1;
- *colon = '\0';
- }
- if (!getservbyname(dgpsport, "tcp"))
- dgpsport = "2101";
-
- dsock = netlib_connectsock(dgpsserver, dgpsport, "tcp");
- if (dsock >= 0) {
- (void)gethostname(hn, sizeof(hn));
- (void)snprintf(buf,sizeof(buf), "HELO %s gpsd %s\r\nR\r\n",hn,VERSION);
- (void)write(dsock, buf, strlen(buf));
- }
- opts = fcntl(dsock, F_GETFL);
-
- if (opts >= 0)
- (void)fcntl(dsock, F_SETFL, opts | O_NONBLOCK);
- return dsock;
-}
-/*@ +branchstate */
-
int gpsd_switch_driver(struct gps_device_t *session, char* typename)
{
struct gps_type_t **dp;
@@ -70,7 +42,7 @@ void gpsd_init(struct gps_device_t *session, struct gps_context_t *context, char
strncpy(session->gpsdata.gps_device, device, PATH_MAX);
/*@ -mustfreeonly @*/
session->device_type = NULL; /* start by hunting packets */
- session->dsock = -1;
+ session->rtcmtime = 0;
/*@ -temptrans @*/
session->context = context;
/*@ +temptrans @*/
@@ -392,20 +364,6 @@ gps_mask_t gpsd_poll(struct gps_device_t *session)
{
ssize_t packet_length;
- if (session->dsock > -1) {
- char buf[BUFSIZ];
- int rtcmbytes;
-
- /* accept a DGPS correction if one is pending */
- if ((rtcmbytes=(int)read(session->dsock,buf,sizeof(buf)))>0 && (session->gpsdata.gps_fd !=-1)) {
- if (session->device_type->rtcm_writer(session, buf, (size_t)rtcmbytes) == 0)
- gpsd_report(1, "Write to rtcm sink failed\n");
- else
- gpsd_report(2, "<= DGPS: %d bytes of RTCM relayed.\n", rtcmbytes);
- } else if (errno != EAGAIN)
- gpsd_report(1, "Read from rtcm source failed\n");
- }
-
if (session->inbuflen==0)
session->gpsdata.d_xmit_time = timestamp();
@@ -578,19 +536,7 @@ gps_mask_t gpsd_poll(struct gps_device_t *session)
}
}
- /* may< be time to ship a DGPS correction to the GPS */
- if (session->fixcnt > 10 && session->sentdgps==0) {
- session->sentdgps++;
- if (session->dsock > -1) {
- char buf[BUFSIZ];
- (void)snprintf(buf, sizeof(buf), "R %0.8f %0.8f %0.2f\r\n",
- session->gpsdata.fix.latitude,
- session->gpsdata.fix.longitude,
- session->gpsdata.fix.altitude);
- (void)write(session->dsock, buf, strlen(buf));
- gpsd_report(2, "=> dgps %s", buf);
- }
- }
+ dgpsip_report(session);
return session->gpsdata.set;
}
diff --git a/serial.c b/serial.c
index 42d67a63..405f5b7f 100644
--- a/serial.c
+++ b/serial.c
@@ -128,8 +128,10 @@ int gpsd_open(struct gps_device_t *session)
* Only block until we get at least one character, whatever the
* third arg of read(2) says.
*/
+ /*@ ignore @*/
memset(session->ttyset.c_cc,0,sizeof(session->ttyset.c_cc));
session->ttyset.c_cc[VMIN] = 1;
+ /*@ end @*/
/*
* Tip from Chris Kuethe: the FIDI chip used in the Trip-Nav
* 200 (and possibly other USB GPSes) gets completely hosed