diff options
author | Eric S. Raymond <esr@thyrsus.com> | 2005-06-29 16:18:42 +0000 |
---|---|---|
committer | Eric S. Raymond <esr@thyrsus.com> | 2005-06-29 16:18:42 +0000 |
commit | 1391a44aa66d71f74fa2513c16c8ae61e6a4e2ee (patch) | |
tree | af5fd7bd59e98984d0f15beba50018de4d491cf7 | |
parent | 08a04efa887261803bc7717bd5e60882349aa131 (diff) | |
download | gpsd-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.am | 1 | ||||
-rw-r--r-- | dgpsip.c | 87 | ||||
-rw-r--r-- | gpsd.c | 28 | ||||
-rw-r--r-- | gpsd.h | 20 | ||||
-rw-r--r-- | libgpsd_core.c | 58 | ||||
-rw-r--r-- | serial.c | 2 |
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); + } + } +} + @@ -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)) @@ -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; } @@ -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 |