diff options
-rw-r--r-- | cgps.c | 2 | ||||
-rw-r--r-- | gps.h | 6 | ||||
-rw-r--r-- | gps_json.h | 2 | ||||
-rw-r--r-- | libgps.xml | 8 | ||||
-rw-r--r-- | libgps_core.c | 50 | ||||
-rw-r--r-- | www/client-howto.txt | 4 |
6 files changed, 42 insertions, 30 deletions
@@ -693,7 +693,7 @@ static void update_gps_panel(struct gps_data_t *gpsdata) /* Be quiet if the user requests silence. */ if (!silent_flag && raw_flag) { - (void)waddstr(messages, gpsdata->buffer); + (void)waddstr(messages, gps_data(gpsdata)); } /* Reset the status_timer if the state has changed. */ @@ -49,7 +49,6 @@ extern "C" { #define MAXCHANNELS 72 /* must be > 12 GPS + 12 GLONASS + 2 WAAS */ #define GPS_PRNMAX 32 /* above this number are SBAS satellites */ #define GPS_PATH_MAX 64 /* dev files usually have short names */ -#define GPS_BUFFER_MAX 3072 /* enough for two maximun-size JSON objects */ #define MAXUSERDEVS 4 /* max devices per user */ /* @@ -1403,10 +1402,6 @@ struct gps_data_t { char tag[MAXTAGLEN+1]; /* tag of last sentence processed */ - /* data buffered from the last read */ - ssize_t waiting; - char buffer[GPS_BUFFER_MAX * 2]; - /* pack things never reported together to reduce structure size */ #define UNION_SET (RTCM2_SET|RTCM3_SET|SUBFRAME_SET|AIS_SET|VERSION_SET|DEVICELIST_SET|LOGMESSAGE_SET|ERROR_SET|GST_SET) union { @@ -1439,6 +1434,7 @@ extern int gps_send(struct gps_data_t *, const char *, ... ); extern int gps_read(/*@out@*/struct gps_data_t *); extern bool gps_waiting(struct gps_data_t *, int); extern int gps_stream(struct gps_data_t *, unsigned int, /*@null@*/void *); +extern const char /*@observer@*/ *gps_data(struct gps_data_t *); extern const char /*@observer@*/ *gps_errstr(const int); /* this only needs to be visible for the unit tests */ @@ -8,7 +8,7 @@ #include "json.h" #define GPS_JSON_COMMAND_MAX 80 -#define GPS_JSON_RESPONSE_MAX 1536 +#define GPS_JSON_RESPONSE_MAX 4096 #ifdef __cplusplus extern "C" { @@ -47,6 +47,10 @@ C: <paramdef>int <parameter>timeout</parameter></paramdef> </funcprototype> <funcprototype> +<funcdef>void <function>gps_data</function></funcdef> + <paramdef>struct gps_data_t *<parameter>gpsdata</parameter></paramdef> +</funcprototype> +<funcprototype> <funcdef>void <function>gps_close</function></funcdef> <paramdef>struct gps_data_t *<parameter>gpsdata</parameter></paramdef> </funcprototype> @@ -140,6 +144,10 @@ will not supply input often enough to prevent a spurious error indication. For the typical 1-second cycle time of GPSes this implies a minimum 2-second timeout.</para> +<para><function>gps_data()</function> returns the contents of the +client data buffer. Use with care; this may fail to be a NUL-terminated +string if WATCH_RAW is enabled.</para> + <para><function>gps_stream()</function> asks <application>gpsd</application> to stream the reports it has at you, to be made available when you poll. It is preferable to the diff --git a/libgps_core.c b/libgps_core.c index d59f3839..23f3e999 100644 --- a/libgps_core.c +++ b/libgps_core.c @@ -44,6 +44,10 @@ extern char *strtok_r(char *, const char *, char **); struct privdata_t { bool newstyle; + /* data buffered from the last read */ + ssize_t waiting; + char buffer[GPS_JSON_RESPONSE_MAX * 2]; + }; #define PRIVATE(gpsdata) ((struct privdata_t *)gpsdata->privdata) @@ -129,9 +133,7 @@ int gps_open(/*@null@*/const char *host, /*@null@*/const char *port, if (gpsdata->privdata == NULL) return -1; PRIVATE(gpsdata)->newstyle = false; - gpsdata->waiting = 0; - /*@i1@*/ gpsdata->buffer[0] = '\0'; - + PRIVATE(gpsdata)->waiting = 0; return 0; /*@ +branchstate @*/ } @@ -507,7 +509,7 @@ bool gps_waiting(struct gps_data_t * gpsdata, int timeout) struct timeval tv; libgps_debug_trace((DEBUG_CALLS, "gps_waiting(%d): %d\n", timeout, waitcount++)); - if (gpsdata->waiting > 0) + if (PRIVATE(gpsdata)->waiting > 0) return true; /* we might want to check for EINTR if this returns false */ @@ -534,8 +536,8 @@ int gps_read(/*@out@*/struct gps_data_t *gpsdata) int status = -1; gpsdata->set &= ~PACKET_SET; - for (eol = gpsdata->buffer; - *eol != '\n' && eol < gpsdata->buffer + gpsdata->waiting; eol++) + for (eol = PRIVATE(gpsdata)->buffer; + *eol != '\n' && eol < PRIVATE(gpsdata)->buffer + PRIVATE(gpsdata)->waiting; eol++) continue; if (*eol != '\n') eol = NULL; @@ -546,21 +548,21 @@ int gps_read(/*@out@*/struct gps_data_t *gpsdata) #ifndef USE_QT /* read data: return -1 if no data waiting or buffered, 0 otherwise */ status = (int)recv(gpsdata->gps_fd, - gpsdata->buffer + gpsdata->waiting, - sizeof(gpsdata->buffer) - gpsdata->waiting, 0); + PRIVATE(gpsdata)->buffer + PRIVATE(gpsdata)->waiting, + sizeof(PRIVATE(gpsdata)->buffer) - PRIVATE(gpsdata)->waiting, 0); #else status = - ((QTcpSocket *) (gpsdata->gps_fd))->read(gpsdata->buffer + - gpsdata->waiting, - sizeof(gpsdata->buffer) - - gpsdata->waiting); + ((QTcpSocket *) (gpsdata->gps_fd))->read(PRIVATE(gpsdata)->buffer + + PRIVATE(gpsdata)->waiting, + sizeof(PRIVATE(gpsdata)->buffer) - + PRIVATE(gpsdata)->waiting); #endif /* if we just received data from the socket, it's in the buffer */ if (status > -1) - gpsdata->waiting += status; + PRIVATE(gpsdata)->waiting += status; /* buffer is empty - implies no data was read */ - if (gpsdata->waiting == 0) { + if (PRIVATE(gpsdata)->waiting == 0) { /* * If we received 0 bytes, other side of socket is closing. * Return -1 as end-of-data indication. @@ -578,8 +580,8 @@ int gps_read(/*@out@*/struct gps_data_t *gpsdata) return -1; } /* there's buffered data waiting to be returned */ - for (eol = gpsdata->buffer; - *eol != '\n' && eol < gpsdata->buffer + gpsdata->waiting; eol++) + for (eol = PRIVATE(gpsdata)->buffer; + *eol != '\n' && eol < PRIVATE(gpsdata)->buffer + PRIVATE(gpsdata)->waiting; eol++) continue; if (*eol != '\n') eol = NULL; @@ -589,20 +591,26 @@ int gps_read(/*@out@*/struct gps_data_t *gpsdata) assert(eol != NULL); *eol = '\0'; - response_length = eol - gpsdata->buffer + 1; + response_length = eol - PRIVATE(gpsdata)->buffer + 1; received = gpsdata->online = timestamp(); - status = gps_unpack(gpsdata->buffer, gpsdata); + status = gps_unpack(PRIVATE(gpsdata)->buffer, gpsdata); /*@+matchanyintegral@*/ - memmove(gpsdata->buffer, - gpsdata->buffer + response_length, gpsdata->waiting - response_length); + memmove(PRIVATE(gpsdata)->buffer, + PRIVATE(gpsdata)->buffer + response_length, PRIVATE(gpsdata)->waiting - response_length); /*@-matchanyintegral@*/ - gpsdata->waiting -= response_length; + PRIVATE(gpsdata)->waiting -= response_length; gpsdata->set |= PACKET_SET; return (status == 0) ? (int)response_length : status; } /*@+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 */ { diff --git a/www/client-howto.txt b/www/client-howto.txt index 9d5a9ffc..3dbf341f 100644 --- a/www/client-howto.txt +++ b/www/client-howto.txt @@ -1,6 +1,6 @@ = GPSD Client HOWTO = Eric S. Raymond <esr@thyrsus.com> -v1.7, March 2011 +v1.8, March 2011 This document is mastered in asciidoc format. If you are reading it in HTML, you can find the original at @@ -507,7 +507,7 @@ In major versions before 5: send messages to stderr. This requirement is now gone. * There was a set_raw_hook() method in the C and Python bindings, now gone. - Clients can simply look at the response buffer. + C clients should call gps_data(); the buffer is available directly in Python. See http://gpsd.berlios.de/future.html#api_cleanup[Client API Cleanup] for details. |