diff options
author | Eric S. Raymond <esr@thyrsus.com> | 2005-03-14 23:58:01 +0000 |
---|---|---|
committer | Eric S. Raymond <esr@thyrsus.com> | 2005-03-14 23:58:01 +0000 |
commit | 8c7ea306a6e7b5a1e78bd139f7413f81bce08132 (patch) | |
tree | 9988b6c5c4becd2b6dcf6fc9ce7f5d4978fe1217 | |
parent | 997706c85198692fc1cf1545f8aff8ef88dc55b7 (diff) | |
download | gpsd-8c7ea306a6e7b5a1e78bd139f7413f81bce08132.tar.gz |
gps_poll now handles multi-line resonses.
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | gps.h | 2 | ||||
-rw-r--r-- | gpsd.spec.in | 3 | ||||
-rw-r--r-- | libgps.c | 306 | ||||
-rw-r--r-- | libgps.xml | 20 |
5 files changed, 167 insertions, 166 deletions
@@ -3,8 +3,6 @@ doing Ctl-C Ctl-t and browsing through the outline headers. ** Finish implementing the N command -** Make sure gps_poll can handle multiple-sentence returns - ** Rate-limiting SiRF sentence 4. The SiRF binary driver works nicely now, but it's a bit annoying that @@ -143,7 +143,7 @@ struct gps_data_t *gps_open(const char *host, const char *port); int gps_close(struct gps_data_t *); int gps_query(struct gps_data_t *gpsdata, const char *requests); int gps_poll(struct gps_data_t *gpsdata); - void gps_set_raw_hook(struct gps_data_t *gpsdata, void (*hook)(struct gps_data_t *sentence, char *buf)); +void gps_set_raw_hook(struct gps_data_t *gpsdata, void (*hook)(struct gps_data_t *sentence, char *buf)); /* some multipliers for interpreting GPS output */ #define METERS_TO_FEET 3.2808399 /* Imperial (U.S./British) feet */ diff --git a/gpsd.spec.in b/gpsd.spec.in index bf5e1ae1..4e4c8446 100644 --- a/gpsd.spec.in +++ b/gpsd.spec.in @@ -106,7 +106,8 @@ cp gps.py gpsd.py "$RPM_BUILD_ROOT"%{_libdir}/python${PYVERSION}/site-packages (important!). Fix bonehead error in interpretation of PGRME. We don't use O_SYNC (it turned out not to be reliable) so remove it to make life easier under Mac OS X. Allow gpsfake to accept subsecond cycle times. - Add a FAQ to the HTML documentation. + Add a FAQ to the HTML documentation. gps_poll() now handles multi-line + responses. * Fri Mar 11 2005 Eric S. Raymond <esr@snark.thyrsus.com> - 2.16-1 - New F command allows changing the GPS device after startup time. @@ -53,166 +53,164 @@ void gps_set_raw_hook(struct gps_data_t *gpsdata, void (*hook)(struct gps_data_t static int gps_unpack(char *buf, struct gps_data_t *gpsdata) /* unpack a daemon response into a status structure */ { - char *sp, *tp; + char *ns, *sp, *tp; double d1, d2, d3; - int i1, i2; + int i1, i2, changed = 0; - if (!strncmp(buf, "GPSD", 4)) { - for (sp = buf + 5; ; sp = tp+1) { - if (!(tp = strchr(sp, ','))) - tp = strchr(sp, '\r'); - if (!tp) break; - *tp = '\0'; + for (ns = buf; ns; ns = strstr(ns+1, "GPSD")) { + if (!strncmp(ns, "GPSD", 4)) { + for (sp = ns + 5; ; sp = tp+1) { + if (!(tp = strchr(sp, ','))) + tp = strchr(sp, '\r'); + if (!tp) break; + *tp = '\0'; - if (sp[2] == '?') - continue; + if (sp[2] == '?') + continue; - switch (*sp) { - case 'A': - sscanf(sp, "A=%lf", &d1); - gpsdata->altitude_stamp.changed = (gpsdata->altitude != d1); - gpsdata->altitude = d1; - REFRESH(gpsdata->altitude_stamp); - break; - case 'B': - sscanf(sp, "B=%d %*d %*s %d", &gpsdata->baudrate, &gpsdata->stopbits); - break; - case 'C': - sscanf(sp, "C=%d", &gpsdata->cycle); - break; - case 'D': - strcpy(gpsdata->utc, sp+2); - break; - case 'E': - sscanf(sp, "E=%lf %lf %lf", &d1, &d2, &d3); - gpsdata->fix_quality_stamp.changed = \ - (gpsdata->epe != d1) || (gpsdata->eph != d2) || (gpsdata->epv != d3); - gpsdata->epe = d1; gpsdata->eph = d2; gpsdata->epv = d3; - REFRESH(gpsdata->epe_quality_stamp); - break; - case 'I': - if (gpsdata->gps_id) - free(gpsdata->gps_id); - gpsdata->gps_id = strdup(sp+2); - case 'M': - i1 = atoi(sp+2); - gpsdata->mode_stamp.changed = (gpsdata->mode != i1); - gpsdata->mode = i1; - REFRESH(gpsdata->mode_stamp); - break; - case 'P': - sscanf(sp, "P=%lf %lf", &d1, &d2); - gpsdata->latlon_stamp.changed = (gpsdata->latitude != d1) || (gpsdata->longitude != d2); - gpsdata->latitude = d1; gpsdata->longitude = d2; - REFRESH(gpsdata->latlon_stamp); - break; - case 'Q': - sscanf(sp, "Q=%d %lf %lf %lf", &i1, &d1, &d2, &d3); - gpsdata->fix_quality_stamp.changed = \ - (gpsdata->satellites_used != i1) - || (gpsdata->pdop != d1) - || (gpsdata->hdop != d2) - || (gpsdata->vdop != d3); - gpsdata->satellites_used = i1; - gpsdata->pdop = d1; gpsdata->hdop = d2; gpsdata->vdop = d3; - REFRESH(gpsdata->fix_quality_stamp); - break; - case 'S': - i1 = atoi(sp+2); - gpsdata->status_stamp.changed = (gpsdata->status != i1); - gpsdata->status = i1; - REFRESH(gpsdata->status_stamp); - break; - case 'T': - sscanf(sp, "T=%lf", &d1); - gpsdata->track_stamp.changed = (gpsdata->track != d1); - gpsdata->track = d1; - REFRESH(gpsdata->track_stamp); - break; - case 'U': - sscanf(sp, "U=%lf", &d1); - gpsdata->climb_stamp.changed = (gpsdata->climb != d1); - gpsdata->climb = d1; - REFRESH(gpsdata->climb_stamp); - break; - case 'V': - sscanf(sp, "V=%lf", &d1); - gpsdata->speed_stamp.changed = (gpsdata->speed != d1); - gpsdata->speed = d1; - REFRESH(gpsdata->speed_stamp); - break; - case 'X': - if (!strncmp(sp, "X=1", 3)) { - gpsdata->online_stamp.changed = gpsdata->online != 1; - gpsdata->online = 1; - REFRESH(gpsdata->online_stamp); - } - else if (!strncmp(sp, "X=0", 3)) { - gpsdata->online_stamp.changed = gpsdata->online != 0; - gpsdata->online = 0; - REFRESH(gpsdata->online_stamp); - } - break; - case 'Y': - i1 = atoi(sp+2); - gpsdata->satellite_stamp.changed = (gpsdata->satellites != i1); - gpsdata->satellites = i1; - if (gpsdata->satellites) { - int j, i3, i4, i5; - int PRN[MAXCHANNELS]; - int elevation[MAXCHANNELS], azimuth[MAXCHANNELS]; - int ss[MAXCHANNELS], used[MAXCHANNELS]; - - for (j = 0; j < gpsdata->satellites; j++) { - PRN[j]=elevation[j]=azimuth[j]=ss[j]=used[j]=0; + switch (*sp) { + case 'A': + sscanf(sp, "A=%lf", &d1); + gpsdata->altitude_stamp.changed = (gpsdata->altitude != d1); + gpsdata->altitude = d1; + REFRESH(gpsdata->altitude_stamp); + break; + case 'B': + sscanf(sp, "B=%d %*d %*s %d", &gpsdata->baudrate, &gpsdata->stopbits); + break; + case 'C': + sscanf(sp, "C=%d", &gpsdata->cycle); + break; + case 'D': + strcpy(gpsdata->utc, sp+2); + break; + case 'E': + sscanf(sp, "E=%lf %lf %lf", &d1, &d2, &d3); + gpsdata->fix_quality_stamp.changed = \ + (gpsdata->epe != d1) || (gpsdata->eph != d2) || (gpsdata->epv != d3); + gpsdata->epe = d1; gpsdata->eph = d2; gpsdata->epv = d3; + REFRESH(gpsdata->epe_quality_stamp); + break; + case 'I': + if (gpsdata->gps_id) + free(gpsdata->gps_id); + gpsdata->gps_id = strdup(sp+2); + case 'M': + i1 = atoi(sp+2); + gpsdata->mode_stamp.changed = (gpsdata->mode != i1); + gpsdata->mode = i1; + REFRESH(gpsdata->mode_stamp); + break; + case 'P': + sscanf(sp, "P=%lf %lf", &d1, &d2); + gpsdata->latlon_stamp.changed = (gpsdata->latitude != d1) || (gpsdata->longitude != d2); + gpsdata->latitude = d1; gpsdata->longitude = d2; + REFRESH(gpsdata->latlon_stamp); + break; + case 'Q': + sscanf(sp, "Q=%d %lf %lf %lf", &i1, &d1, &d2, &d3); + gpsdata->fix_quality_stamp.changed = \ + (gpsdata->satellites_used != i1) + || (gpsdata->pdop != d1) + || (gpsdata->hdop != d2) + || (gpsdata->vdop != d3); + gpsdata->satellites_used = i1; + gpsdata->pdop = d1; gpsdata->hdop = d2; gpsdata->vdop = d3; + REFRESH(gpsdata->fix_quality_stamp); + break; + case 'S': + i1 = atoi(sp+2); + gpsdata->status_stamp.changed = (gpsdata->status != i1); + gpsdata->status = i1; + REFRESH(gpsdata->status_stamp); + break; + case 'T': + sscanf(sp, "T=%lf", &d1); + gpsdata->track_stamp.changed = (gpsdata->track != d1); + gpsdata->track = d1; + REFRESH(gpsdata->track_stamp); + break; + case 'U': + sscanf(sp, "U=%lf", &d1); + gpsdata->climb_stamp.changed = (gpsdata->climb != d1); + gpsdata->climb = d1; + REFRESH(gpsdata->climb_stamp); + break; + case 'V': + sscanf(sp, "V=%lf", &d1); + gpsdata->speed_stamp.changed = (gpsdata->speed != d1); + gpsdata->speed = d1; + REFRESH(gpsdata->speed_stamp); + break; + case 'X': + if (!strncmp(sp, "X=1", 3)) { + gpsdata->online_stamp.changed = gpsdata->online != 1; + gpsdata->online = 1; + REFRESH(gpsdata->online_stamp); } - for (j = 0; j < gpsdata->satellites; j++) { - sp = strchr(sp, ':') + 1; - sscanf(sp, "%d %d %d %d %d", &i1, &i2, &i3, &i4, &i5); - PRN[j] = i1; - elevation[j] = i2; azimuth[j] = i3; - ss[j] = i4; used[j] = i5; + else if (!strncmp(sp, "X=0", 3)) { + gpsdata->online_stamp.changed = gpsdata->online != 0; + gpsdata->online = 0; + REFRESH(gpsdata->online_stamp); } - /* - * This won't catch the case where all values are identical - * but rearranged. We can live with that. - */ - gpsdata->satellite_stamp.changed |= \ - memcmp(gpsdata->PRN, PRN, sizeof(PRN)) || - memcmp(gpsdata->elevation, elevation, sizeof(elevation)) || - memcmp(gpsdata->azimuth, azimuth,sizeof(azimuth)) || - memcmp(gpsdata->ss, ss, sizeof(ss)) || - memcmp(gpsdata->used, used, sizeof(used)); - 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)); + break; + case 'Y': + i1 = atoi(sp+2); + gpsdata->satellite_stamp.changed = (gpsdata->satellites != i1); + gpsdata->satellites = i1; + if (gpsdata->satellites) { + int j, i3, i4, i5; + int PRN[MAXCHANNELS]; + int elevation[MAXCHANNELS], azimuth[MAXCHANNELS]; + int ss[MAXCHANNELS], used[MAXCHANNELS]; + + for (j = 0; j < gpsdata->satellites; j++) { + PRN[j]=elevation[j]=azimuth[j]=ss[j]=used[j]=0; + } + for (j = 0; j < gpsdata->satellites; j++) { + sp = strchr(sp, ':') + 1; + sscanf(sp, "%d %d %d %d %d", &i1, &i2, &i3, &i4, &i5); + PRN[j] = i1; + elevation[j] = i2; azimuth[j] = i3; + ss[j] = i4; used[j] = i5; + } + /* + * This won't catch the case where all values are identical + * but rearranged. We can live with that. + */ + gpsdata->satellite_stamp.changed |= \ + memcmp(gpsdata->PRN, PRN, sizeof(PRN)) || + memcmp(gpsdata->elevation, elevation, sizeof(elevation)) || + memcmp(gpsdata->azimuth, azimuth,sizeof(azimuth)) || + memcmp(gpsdata->ss, ss, sizeof(ss)) || + memcmp(gpsdata->used, used, sizeof(used)); + 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)); + } + REFRESH(gpsdata->satellite_stamp); + break; + case 'Z': + sscanf(sp, "Z=%d", &gpsdata->profiling); + break; + case '$': + sscanf(sp, "$=%s %d %lf %lf %lf %lf %lf %lf", + gpsdata->tag, + &gpsdata->sentence_length, + &gpsdata->gps_time, + &gpsdata->d_xmit_time, + &gpsdata->d_recv_time, + &gpsdata->d_decode_time, + &gpsdata->poll_time, + &gpsdata->emit_time); + break; } - REFRESH(gpsdata->satellite_stamp); - break; - case 'Z': - sscanf(sp, "Z=%d", &gpsdata->profiling); - break; - case '$': - sscanf(sp, "$=%s %d %lf %lf %lf %lf %lf %lf", - gpsdata->tag, - &gpsdata->sentence_length, - &gpsdata->gps_time, - &gpsdata->d_xmit_time, - &gpsdata->d_recv_time, - &gpsdata->d_decode_time, - &gpsdata->poll_time, - &gpsdata->emit_time); - break; } } - } - - if (gpsdata->raw_hook) - gpsdata->raw_hook(gpsdata, buf); - - return gpsdata->online_stamp.changed + changed |= + gpsdata->online_stamp.changed || gpsdata->latlon_stamp.changed || gpsdata->altitude_stamp.changed || gpsdata->climb_stamp.changed @@ -224,6 +222,12 @@ static int gps_unpack(char *buf, struct gps_data_t *gpsdata) || gpsdata->epe_quality_stamp.changed || gpsdata->satellite_stamp.changed ; + } + + if (gpsdata->raw_hook) + gpsdata->raw_hook(gpsdata, buf); + + return changed; } /* @@ -39,8 +39,7 @@ C: </funcprototype> <funcprototype> <funcdef>int <function>gps_poll</function></funcdef> - <paramdef>struct gps_data_t * <parameter>gpsdata</parameter></paramdef> - <paramdef>void *<parameter>raw_hook</parameter>(char *buf)</paramdef> + <paramdef>struct gps_data_t *<parameter>gpsdata</parameter></paramdef> </funcprototype> <funcprototype> <funcdef>void <function>gps_close</function></funcdef> @@ -99,15 +98,14 @@ must be a string containing letters from the command set documented at This function returns a 1 if any data changed since the last query, a 0 if no data changed, or a -1 if there was a Unix-level read error.</para> -<para><function>gpsd_poll()</function> accepts a one-line response from -the daemon and interprets it as though it were a query response (the -return value is as for a query). It is meant to be used after the -user has issued an 'R' or 'W' command with -<function>gpsd_query()</function>, telling the daemon to stream updates -to the client. If the third argument is non-NULL, it is used as a -hook function to be called on each line of streamed data. -<function>gpsd_poll()</function> returns -1 if there was an error, 0 -if no data was read or no changes or 1 if gpsdata has changes.</para> +<para><function>gpsd_poll()</function> accepts a response, or sequence +of responses, from the daemon and interprets it as though it were a +query response (the return value is as for a query). It is meant to +be used after the user has issued an 'R' or 'W' command with +<function>gpsd_query()</function>, telling the daemon to stream +updates to the client. <function>gpsd_poll()</function> returns -1 if +there was an error, 0 if no data was read or no changes or 1 if +gpsdata has changes.</para> <para>Several member groups within the GPS-data structure have last-modified timestamps and change-flag members associated with them; |