From d08ab2ed72fb7590739612a7e5d37150a3bf972a Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Sun, 27 Mar 2011 19:09:56 -0400 Subject: Begin splitting apart libgps_core.c into socket-export and generic functions. --- libgps_core.c | 559 +++++++++------------------------------------------------- 1 file changed, 86 insertions(+), 473 deletions(-) (limited to 'libgps_core.c') diff --git a/libgps_core.c b/libgps_core.c index 9983f8a6..19af31d8 100644 --- a/libgps_core.c +++ b/libgps_core.c @@ -56,9 +56,6 @@ struct privdata_t #define DEBUG_JSON 5 /* minimum level for verbose JSON debugging */ static int debuglevel = 0; static FILE *debugfp; -#ifndef USE_QT -static int waitcount = 0; -#endif /* USE_QT */ void gps_enable_debug(int level, FILE * fp) /* control the level and destination of debug trace messages */ @@ -158,376 +155,8 @@ int gps_close(struct gps_data_t *gpsdata) return 0; } - /*@+compdef +usereleased@*/ -#ifdef LIBGPS_DEBUG -static void libgps_dump_state(struct gps_data_t *collect) -{ - const char *status_values[] = { "NO_FIX", "FIX", "DGPS_FIX" }; - const char *mode_values[] = { "", "NO_FIX", "MODE_2D", "MODE_3D" }; - - /* no need to dump the entire state, this is a sanity check */ -#ifndef USE_QT - /* will fail on a 32-bit macine */ - (void)fprintf(debugfp, "flags: (0x%04x) %s\n", - (unsigned int)collect->set, gps_maskdump(collect->set)); -#endif - if (collect->set & ONLINE_SET) - (void)fprintf(debugfp, "ONLINE: %lf\n", collect->online); - if (collect->set & TIME_SET) - (void)fprintf(debugfp, "TIME: %lf\n", collect->fix.time); - if (collect->set & LATLON_SET) - (void)fprintf(debugfp, "LATLON: lat/lon: %lf %lf\n", - collect->fix.latitude, collect->fix.longitude); - if (collect->set & ALTITUDE_SET) - (void)fprintf(debugfp, "ALTITUDE: altitude: %lf U: climb: %lf\n", - collect->fix.altitude, collect->fix.climb); - if (collect->set & SPEED_SET) - (void)fprintf(debugfp, "SPEED: %lf\n", collect->fix.speed); - if (collect->set & TRACK_SET) - (void)fprintf(debugfp, "TRACK: track: %lf\n", collect->fix.track); - if (collect->set & CLIMB_SET) - (void)fprintf(debugfp, "CLIMB: climb: %lf\n", collect->fix.climb); - if (collect->set & STATUS_SET) - (void)fprintf(debugfp, "STATUS: status: %d (%s)\n", - collect->status, status_values[collect->status]); - if (collect->set & MODE_SET) - (void)fprintf(debugfp, "MODE: mode: %d (%s)\n", - collect->fix.mode, mode_values[collect->fix.mode]); - if (collect->set & DOP_SET) - (void)fprintf(debugfp, - "DOP: satellites %d, pdop=%lf, hdop=%lf, vdop=%lf\n", - collect->satellites_used, collect->dop.pdop, - collect->dop.hdop, collect->dop.vdop); - if (collect->set & VERSION_SET) - (void)fprintf(debugfp, "VERSION: release=%s rev=%s proto=%d.%d\n", - collect->version.release, - collect->version.rev, - collect->version.proto_major, - collect->version.proto_minor); - if (collect->set & POLICY_SET) - (void)fprintf(debugfp, - "POLICY: watcher=%s nmea=%s raw=%d scaled=%s timing=%s, devpath=%s\n", - collect->policy.watcher ? "true" : "false", - collect->policy.nmea ? "true" : "false", - collect->policy.raw, - collect->policy.scaled ? "true" : "false", - collect->policy.timing ? "true" : "false", - collect->policy.devpath); - if (collect->set & SATELLITE_SET) { - int i; - - (void)fprintf(debugfp, "SKY: satellites in view: %d\n", - collect->satellites_visible); - for (i = 0; i < collect->satellites_visible; i++) { - (void)fprintf(debugfp, " %2.2d: %2.2d %3.3d %3.0f %c\n", - collect->PRN[i], collect->elevation[i], - collect->azimuth[i], collect->ss[i], - collect->used[i] ? 'Y' : 'N'); - } - } - if (collect->set & DEVICE_SET) - (void)fprintf(debugfp, "DEVICE: Device is '%s', driver is '%s'\n", - collect->dev.path, collect->dev.driver); -#ifdef OLDSTYLE_ENABLE - if (collect->set & DEVICEID_SET) - (void)fprintf(debugfp, "GPSD ID is %s\n", collect->dev.subtype); -#endif /* OLDSTYLE_ENABLE */ - if (collect->set & DEVICELIST_SET) { - int i; - (void)fprintf(debugfp, "DEVICELIST:%d devices:\n", - collect->devices.ndevices); - for (i = 0; i < collect->devices.ndevices; i++) { - (void)fprintf(debugfp, "%d: path='%s' driver='%s'\n", - collect->devices.ndevices, - collect->devices.list[i].path, - collect->devices.list[i].driver); - } - } - -} -#endif /* LIBGPS_DEBUG */ - - -/*@ -branchstate -usereleased -mustfreefresh -nullstate -usedef @*/ -int gps_unpack(char *buf, struct gps_data_t *gpsdata) -/* unpack a gpsd response into a status structure, buf must be writeable. - * gps_unpack() currently returns 0 in all cases, but should it ever need to - * return an error status, it must be < 0. - */ -{ - libgps_debug_trace((DEBUG_CALLS, "gps_unpack(%s)\n", buf)); - - /* detect and process a JSON response */ - if (buf[0] == '{') { - const char *jp = buf, **next = &jp; - while (next != NULL && *next != NULL && next[0][0] != '\0') { - libgps_debug_trace((DEBUG_CALLS, - "gps_unpack() segment parse '%s'\n", *next)); - if (libgps_json_unpack(*next, gpsdata, next) == -1) - break; -#ifdef LIBGPS_DEBUG - if (debuglevel >= 1) - libgps_dump_state(gpsdata); -#endif /* LIBGPS_DEBUG */ - - } -#ifdef OLDSTYLE_ENABLE - if (PRIVATE(gpsdata) != NULL) - PRIVATE(gpsdata)->newstyle = true; -#endif /* OLDSTYLE_ENABLE */ - } -#ifdef OLDSTYLE_ENABLE - else { - /* - * Get the decimal separator for the current application locale. - * This looks thread-unsafe, but it's not. The key is that - * character assignment is atomic. - */ - char *ns, *sp, *tp; - - static char decimal_point = '\0'; - if (decimal_point == '\0') { - struct lconv *locale_data = localeconv(); - if (locale_data != NULL && locale_data->decimal_point[0] != '.') - decimal_point = locale_data->decimal_point[0]; - } - - for (ns = buf; ns; ns = strstr(ns + 1, "GPSD")) { - if ( /*@i1@*/ strncmp(ns, "GPSD", 4) == 0) { - bool eol = false; - /* the following should execute each time we have a good next sp */ - for (sp = ns + 5; *sp != '\0'; sp = tp + 1) { - tp = sp + strcspn(sp, ",\r\n"); - eol = *tp == '\r' || *tp == '\n'; - if (*tp == '\0') - tp--; - else - *tp = '\0'; - - /* - * The daemon always emits the Anglo-American and SI - * decimal point. Hack these into whatever the - * application locale requires if it's not the same. - * This has to happen *after* we grab the next - * comma-delimited response, or we'll lose horribly - * in locales where the decimal separator is comma. - */ - if (decimal_point != '\0') { - char *cp; - for (cp = sp; cp < tp; cp++) - if (*cp == '.') - *cp = decimal_point; - } - - /* note, there's a bit of skip logic after the switch */ - - switch (*sp) { - case 'F': /*@ -mustfreeonly */ - if (sp[2] == '?') - gpsdata->dev.path[0] = '\0'; - else { - /*@ -mayaliasunique @*/ - strncpy(gpsdata->dev.path, sp + 2, - sizeof(gpsdata->dev.path)); - /*@ +mayaliasunique @*/ - gpsdata->set |= DEVICE_SET; - } - /*@ +mustfreeonly */ - break; - case 'I': - /*@ -mustfreeonly */ - if (sp[2] == '?') - gpsdata->dev.subtype[0] = '\0'; - else { - (void)strlcpy(gpsdata->dev.subtype, sp + 2, - sizeof(gpsdata->dev.subtype)); - gpsdata->set |= DEVICEID_SET; - } - /*@ +mustfreeonly */ - break; - case 'O': - if (sp[2] == '?') { - gpsdata->set = MODE_SET | STATUS_SET; - gpsdata->status = STATUS_NO_FIX; - gps_clear_fix(&gpsdata->fix); - } else { - struct gps_fix_t nf; - char tag[MAXTAGLEN + 1], alt[20]; - char eph[20], epv[20], track[20], speed[20], - climb[20]; - char epd[20], eps[20], epc[20], mode[2]; - char timestr[20], ept[20], lat[20], lon[20]; - int st = sscanf(sp + 2, - "%8s %19s %19s %19s %19s %19s %19s %19s %19s %19s %19s %19s %19s %19s %1s", - tag, timestr, ept, lat, lon, - alt, eph, epv, track, speed, - climb, - epd, eps, epc, mode); - if (st >= 14) { -#define DEFAULT(val) (val[0] == '?') ? NAN : atof(val) - /*@ +floatdouble @*/ - nf.time = DEFAULT(timestr); - nf.latitude = DEFAULT(lat); - nf.longitude = DEFAULT(lon); - nf.ept = DEFAULT(ept); - nf.altitude = DEFAULT(alt); - /* designed before we split eph into epx+epy */ - nf.epx = nf.epy = DEFAULT(eph) / sqrt(2); - nf.epv = DEFAULT(epv); - nf.track = DEFAULT(track); - nf.speed = DEFAULT(speed); - nf.climb = DEFAULT(climb); - nf.epd = DEFAULT(epd); - nf.eps = DEFAULT(eps); - nf.epc = DEFAULT(epc); - /*@ -floatdouble @*/ -#undef DEFAULT - if (st >= 15) - nf.mode = - (mode[0] == - '?') ? MODE_NOT_SEEN : atoi(mode); - else - nf.mode = - (alt[0] == '?') ? MODE_2D : MODE_3D; - if (alt[0] != '?') - gpsdata->set |= ALTITUDE_SET | CLIMB_SET; - if (isnan(nf.epx) == 0 && isnan(nf.epy) == 0) - gpsdata->set |= HERR_SET; - if (isnan(nf.epv) == 0) - gpsdata->set |= VERR_SET; - if (isnan(nf.track) == 0) - gpsdata->set |= TRACK_SET | SPEED_SET; - if (isnan(nf.eps) == 0) - gpsdata->set |= SPEEDERR_SET; - if (isnan(nf.epc) == 0) - gpsdata->set |= CLIMBERR_SET; - gpsdata->fix = nf; - (void)strlcpy(gpsdata->tag, tag, - MAXTAGLEN + 1); - gpsdata->set |= - TIME_SET | TIMERR_SET | LATLON_SET | - MODE_SET; - gpsdata->status = STATUS_FIX; - gpsdata->set |= STATUS_SET; - } - } - break; - case 'X': - if (sp[2] == '?') - gpsdata->online = (timestamp_t)-1; - else { - (void)sscanf(sp, "X=%lf", &gpsdata->online); - gpsdata->set |= ONLINE_SET; - } - break; - case 'Y': - if (sp[2] == '?') { - gpsdata->satellites_visible = 0; - } else { - int j, i1, i2, i3, i5; - int PRN[MAXCHANNELS]; - int elevation[MAXCHANNELS], azimuth[MAXCHANNELS]; - int used[MAXCHANNELS]; - double ss[MAXCHANNELS], f4; - char tag[MAXTAGLEN + 1], timestamp[21]; - - (void)sscanf(sp, "Y=%8s %20s %d ", - tag, timestamp, - &gpsdata->satellites_visible); - (void)strncpy(gpsdata->tag, tag, MAXTAGLEN); - if (timestamp[0] != '?') { - gpsdata->set |= TIME_SET; - } - for (j = 0; j < gpsdata->satellites_visible; j++) { - PRN[j] = elevation[j] = azimuth[j] = used[j] = - 0; - ss[j] = 0.0; - } - for (j = 0, gpsdata->satellites_used = 0; - j < gpsdata->satellites_visible; j++) { - if ((sp != NULL) - && ((sp = strchr(sp, ':')) != NULL)) { - sp++; - (void)sscanf(sp, "%d %d %d %lf %d", &i1, - &i2, &i3, &f4, &i5); - PRN[j] = i1; - elevation[j] = i2; - azimuth[j] = i3; - ss[j] = f4; - used[j] = i5; - if (i5 == 1) - gpsdata->satellites_used++; - } - } - /*@ -compdef @*/ - memcpy(gpsdata->PRN, PRN, sizeof(PRN)); - memcpy(gpsdata->elevation, elevation, - sizeof(elevation)); - memcpy(gpsdata->azimuth, azimuth, - sizeof(azimuth)); - memcpy(gpsdata->ss, ss, sizeof(ss)); - memcpy(gpsdata->used, used, sizeof(used)); - /*@ +compdef @*/ - } - gpsdata->set |= SATELLITE_SET; - break; - } - -#ifdef LIBGPS_DEBUG - if (debuglevel >= 1) - libgps_dump_state(gpsdata); -#endif /* LIBGPS_DEBUG */ - - /* - * Skip to next GPSD when we see \r or \n; - * we don't want to try interpreting stuff - * in between that might be raw mode data. - */ - if (eol) - break; - } - } - } - } -#endif /* OLDSTYLE_ENABLE */ - -#ifndef USE_QT - libgps_debug_trace((DEBUG_CALLS, "final flags: (0x%04x) %s\n", gpsdata->set, - gps_maskdump(gpsdata->set))); -#endif - return 0; -} - -/*@ +compdef @*/ -/*@ -branchstate +usereleased +mustfreefresh +nullstate +usedef @*/ - -bool gps_waiting(struct gps_data_t * gpsdata, int timeout) -/* is there input waiting from the GPS? */ -{ -#ifndef USE_QT - fd_set rfds; - struct timeval tv; - - libgps_debug_trace((DEBUG_CALLS, "gps_waiting(%d): %d\n", timeout, waitcount++)); - if (PRIVATE(gpsdata)->waiting > 0) - return true; - - /* we might want to check for EINTR if this returns false */ - errno = 0; - - FD_ZERO(&rfds); - FD_SET(gpsdata->gps_fd, &rfds); - tv.tv_sec = timeout / 1000000; - tv.tv_usec = timeout % 1000000; - /* all error conditions return "not waiting" -- crude but effective */ - return (select(gpsdata->gps_fd + 1, &rfds, NULL, NULL, &tv) == 1); -#else - return ((QTcpSocket *) (gpsdata->gps_fd))->waitForReadyRead(timeout / 1000); -#endif -} - /*@-compdef -usedef -uniondef@*/ int gps_read(/*@out@*/struct gps_data_t *gpsdata) /* wait for and read data being streamed from the daemon */ @@ -606,108 +235,6 @@ int gps_read(/*@out@*/struct gps_data_t *gpsdata) } /*@+compdef -usedef +uniondef@*/ -const char /*@observer@*/ *gps_data(struct gps_data_t *gpsdata) -/* return the contents of the client data buffer */ -{ - return PRIVATE(gpsdata)->buffer; -} - -int gps_send(struct gps_data_t *gpsdata, const char *fmt, ...) -/* send a command to the gpsd instance */ -{ - char buf[BUFSIZ]; - va_list ap; - - va_start(ap, fmt); - (void)vsnprintf(buf, sizeof(buf) - 2, fmt, ap); - va_end(ap); - if (buf[strlen(buf) - 1] != '\n') - (void)strlcat(buf, "\n", BUFSIZ); -#ifndef USE_QT - if (write(gpsdata->gps_fd, buf, strlen(buf)) == (ssize_t) strlen(buf)) - return 0; - else - return -1; -#else - QTcpSocket *sock = (QTcpSocket *) gpsdata->gps_fd; - sock->write(buf, strlen(buf)); - if (sock->waitForBytesWritten()) - return 0; - else { - qDebug() << "libgps::send error: " << sock->errorString(); - return -1; - } -#endif -} - -int gps_stream(struct gps_data_t *gpsdata, unsigned int flags, - /*@null@*/ void *d) -/* ask gpsd to stream reports at you, hiding the command details */ -{ - char buf[GPS_JSON_COMMAND_MAX]; - - if ((flags & (WATCH_JSON | WATCH_OLDSTYLE | WATCH_NMEA | WATCH_RAW)) == 0) { - flags |= WATCH_JSON; - } - if ((flags & WATCH_DISABLE) != 0) { - if ((flags & WATCH_OLDSTYLE) != 0) { - (void)strlcpy(buf, "w-", sizeof(buf)); - if ((flags & WATCH_NMEA) != 0) - (void)strlcat(buf, "r-", sizeof(buf)); - } else { - (void)strlcpy(buf, "?WATCH={\"enable\":false,", sizeof(buf)); - if (flags & WATCH_JSON) - (void)strlcat(buf, "\"json\":false,", sizeof(buf)); - if (flags & WATCH_NMEA) - (void)strlcat(buf, "\"nmea\":false,", sizeof(buf)); - if (flags & WATCH_RAW) - (void)strlcat(buf, "\"raw\":1,", sizeof(buf)); - if (flags & WATCH_RARE) - (void)strlcat(buf, "\"raw\":0,", sizeof(buf)); - if (flags & WATCH_SCALED) - (void)strlcat(buf, "\"scaled\":false,", sizeof(buf)); - if (flags & WATCH_TIMING) - (void)strlcat(buf, "\"timing\":false,", sizeof(buf)); - if (buf[strlen(buf) - 1] == ',') - buf[strlen(buf) - 1] = '\0'; - (void)strlcat(buf, "};", sizeof(buf)); - } - libgps_debug_trace((DEBUG_CALLS, "gps_stream() disable command: %s\n", buf)); - return gps_send(gpsdata, buf); - } else { /* if ((flags & WATCH_ENABLE) != 0) */ - - if ((flags & WATCH_OLDSTYLE) != 0) { - (void)strlcpy(buf, "w+x", sizeof(buf)); - if ((flags & WATCH_NMEA) != 0) - (void)strlcat(buf, "r+", sizeof(buf)); - } else { - (void)strlcpy(buf, "?WATCH={\"enable\":true,", sizeof(buf)); - if (flags & WATCH_JSON) - (void)strlcat(buf, "\"json\":true,", sizeof(buf)); - if (flags & WATCH_NMEA) - (void)strlcat(buf, "\"nmea\":true,", sizeof(buf)); - if (flags & WATCH_RARE) - (void)strlcat(buf, "\"raw\":1,", sizeof(buf)); - if (flags & WATCH_RAW) - (void)strlcat(buf, "\"raw\":2,", sizeof(buf)); - if (flags & WATCH_SCALED) - (void)strlcat(buf, "\"scaled\":true,", sizeof(buf)); - if (flags & WATCH_TIMING) - (void)strlcat(buf, "\"timing\":true,", sizeof(buf)); - /*@-nullpass@*//* shouldn't be needed, splint has a bug */ - if (flags & WATCH_DEVICE) - (void)snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - "\"device\":\"%s\",", (char *)d); - /*@+nullpass@*/ - if (buf[strlen(buf) - 1] == ',') - buf[strlen(buf) - 1] = '\0'; - (void)strlcat(buf, "};", sizeof(buf)); - } - libgps_debug_trace((DEBUG_CALLS, "gps_stream() enable command: %s\n", buf)); - return gps_send(gpsdata, buf); - } -} - extern const char /*@observer@*/ *gps_errstr(const int err) { /* @@ -735,6 +262,92 @@ extern const char /*@observer@*/ *gps_errstr(const int err) #include #include +static void libgps_dump_state(struct gps_data_t *collect) +{ + const char *status_values[] = { "NO_FIX", "FIX", "DGPS_FIX" }; + const char *mode_values[] = { "", "NO_FIX", "MODE_2D", "MODE_3D" }; + + /* no need to dump the entire state, this is a sanity check */ +#ifndef USE_QT + /* will fail on a 32-bit macine */ + (void)fprintf(debugfp, "flags: (0x%04x) %s\n", + (unsigned int)collect->set, gps_maskdump(collect->set)); +#endif + if (collect->set & ONLINE_SET) + (void)fprintf(debugfp, "ONLINE: %lf\n", collect->online); + if (collect->set & TIME_SET) + (void)fprintf(debugfp, "TIME: %lf\n", collect->fix.time); + if (collect->set & LATLON_SET) + (void)fprintf(debugfp, "LATLON: lat/lon: %lf %lf\n", + collect->fix.latitude, collect->fix.longitude); + if (collect->set & ALTITUDE_SET) + (void)fprintf(debugfp, "ALTITUDE: altitude: %lf U: climb: %lf\n", + collect->fix.altitude, collect->fix.climb); + if (collect->set & SPEED_SET) + (void)fprintf(debugfp, "SPEED: %lf\n", collect->fix.speed); + if (collect->set & TRACK_SET) + (void)fprintf(debugfp, "TRACK: track: %lf\n", collect->fix.track); + if (collect->set & CLIMB_SET) + (void)fprintf(debugfp, "CLIMB: climb: %lf\n", collect->fix.climb); + if (collect->set & STATUS_SET) + (void)fprintf(debugfp, "STATUS: status: %d (%s)\n", + collect->status, status_values[collect->status]); + if (collect->set & MODE_SET) + (void)fprintf(debugfp, "MODE: mode: %d (%s)\n", + collect->fix.mode, mode_values[collect->fix.mode]); + if (collect->set & DOP_SET) + (void)fprintf(debugfp, + "DOP: satellites %d, pdop=%lf, hdop=%lf, vdop=%lf\n", + collect->satellites_used, collect->dop.pdop, + collect->dop.hdop, collect->dop.vdop); + if (collect->set & VERSION_SET) + (void)fprintf(debugfp, "VERSION: release=%s rev=%s proto=%d.%d\n", + collect->version.release, + collect->version.rev, + collect->version.proto_major, + collect->version.proto_minor); + if (collect->set & POLICY_SET) + (void)fprintf(debugfp, + "POLICY: watcher=%s nmea=%s raw=%d scaled=%s timing=%s, devpath=%s\n", + collect->policy.watcher ? "true" : "false", + collect->policy.nmea ? "true" : "false", + collect->policy.raw, + collect->policy.scaled ? "true" : "false", + collect->policy.timing ? "true" : "false", + collect->policy.devpath); + if (collect->set & SATELLITE_SET) { + int i; + + (void)fprintf(debugfp, "SKY: satellites in view: %d\n", + collect->satellites_visible); + for (i = 0; i < collect->satellites_visible; i++) { + (void)fprintf(debugfp, " %2.2d: %2.2d %3.3d %3.0f %c\n", + collect->PRN[i], collect->elevation[i], + collect->azimuth[i], collect->ss[i], + collect->used[i] ? 'Y' : 'N'); + } + } + if (collect->set & DEVICE_SET) + (void)fprintf(debugfp, "DEVICE: Device is '%s', driver is '%s'\n", + collect->dev.path, collect->dev.driver); +#ifdef OLDSTYLE_ENABLE + if (collect->set & DEVICEID_SET) + (void)fprintf(debugfp, "GPSD ID is %s\n", collect->dev.subtype); +#endif /* OLDSTYLE_ENABLE */ + if (collect->set & DEVICELIST_SET) { + int i; + (void)fprintf(debugfp, "DEVICELIST:%d devices:\n", + collect->devices.ndevices); + for (i = 0; i < collect->devices.ndevices; i++) { + (void)fprintf(debugfp, "%d: path='%s' driver='%s'\n", + collect->devices.ndevices, + collect->devices.list[i].path, + collect->devices.list[i].driver); + } + } + +} + static void onsig(int sig) { (void)fprintf(stderr, "libgps: died with signal %d\n", sig); -- cgit v1.2.1