diff options
author | Eric S. Raymond <esr@thyrsus.com> | 2013-11-19 04:19:17 -0500 |
---|---|---|
committer | Eric S. Raymond <esr@thyrsus.com> | 2013-11-19 04:19:17 -0500 |
commit | d1645133ee3aecb02f1f8f61a1e0854eb5c712da (patch) | |
tree | bb830c53d9bed842bfa0c3a2d74ebbd278266f0e | |
parent | 08198ac8b5d745cf678d0eb7c34e99deb0dc894d (diff) | |
download | gpsd-d1645133ee3aecb02f1f8f61a1e0854eb5c712da.tar.gz |
Add timeout on wait-for-ACK to SiRF driver.
Correct initialization observed oon SiRF-III. All regression tests pass.
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | driver_sirf.c | 23 | ||||
-rw-r--r-- | gpsd.h-tail | 3 | ||||
-rw-r--r-- | gpsmon.c | 8 |
4 files changed, 28 insertions, 8 deletions
@@ -20,7 +20,7 @@ month is quite low. **** In gpsmon's PPS Offset field -Presently PPS Offset is displayed in direct mode for NMEA, SiRF, and +resently PPS Offset is displayed in direct mode for NMEA, SiRF, and UBX devices. Others should probably do likewise, notably the Motorola Oncore and Garmin drivers. diff --git a/driver_sirf.c b/driver_sirf.c index 942915d2..d9bcbbd5 100644 --- a/driver_sirf.c +++ b/driver_sirf.c @@ -46,6 +46,12 @@ #define HI(n) ((n) >> 8) #define LO(n) ((n) & 0xff) +/* + * According to the protocol reference, if you don't get ACK/NACK in response + * to a control send withing 6 seconds, you should just retry. + */ +#define SIRF_RETRY_TIME 6 + /*@ +charint @*/ /* Poll Software Version MID 132 */ static unsigned char versionprobe[] = { @@ -237,7 +243,10 @@ static bool sirf_write(struct gps_device_t *session, unsigned char *msg) * lower-powered processor that apparently has trouble keeping up. * Now you have to wait for the ACK, otherwise chaos ensues. */ - if (session->driver.sirf.ack_await > 0) { + if (time(NULL) - session->driver.sirf.last_send > SIRF_RETRY_TIME) + session->driver.sirf.need_ack = false; + /* can also be false because ACK was received after last send */ + if (session->driver.sirf.need_ack) { gpsd_report(session->context->debug, LOG_WARN, "SiRF: write of control type %02x failed, awaiting ACK.\n", msg[4]); @@ -260,7 +269,8 @@ static bool sirf_write(struct gps_device_t *session, unsigned char *msg) "SiRF: Writing control type %02x:\n", msg[4]); ok = (gpsd_write(session, (const char *)msg, len+8) == (ssize_t) (len+8)); - session->driver.sirf.ack_await++; + session->driver.sirf.need_ack = true; + session->driver.sirf.last_send = time(NULL); return (ok); } @@ -1230,14 +1240,14 @@ gps_mask_t sirf_parse(struct gps_device_t * session, unsigned char *buf, case 0x0b: /* Command Acknowledgement MID 11 */ gpsd_report(session->context->debug, LOG_PROG, "SiRF: ACK 0x0b: %02x\n", getub(buf, 1)); - session->driver.sirf.ack_await--; + session->driver.sirf.need_ack = false; return 0; case 0x0c: /* Command NAcknowledgement MID 12 */ gpsd_report(session->context->debug, LOG_PROG, "SiRF: NAK 0x0c: %02x\n", getub(buf, 1)); /* ugh -- there's no alternative but silent failure here */ - session->driver.sirf.ack_await--; + session->driver.sirf.need_ack = false; return 0; case 0x0d: /* Visible List MID 13 */ @@ -1391,7 +1401,10 @@ static void sirfbin_event_hook(struct gps_device_t *session, event_t event) if (event == event_configure) { /* might not be time for the next init string yet */ - if (session->driver.sirf.ack_await > 0) + if (time(NULL) - session->driver.sirf.last_send > SIRF_RETRY_TIME) + session->driver.sirf.need_ack = false; + /* can also be false because ACK was received after last send */ + if (session->driver.sirf.need_ack) return; switch (session->driver.sirf.cfg_stage++) { diff --git a/gpsd.h-tail b/gpsd.h-tail index b9b1ea67..a2604d7b 100644 --- a/gpsd.h-tail +++ b/gpsd.h-tail @@ -545,7 +545,8 @@ struct gps_device_t { #endif /* GEOSTAR_ENABLE */ #ifdef SIRF_ENABLE struct { - int ack_await; /* if NZ we're awaiting ACK */ + bool need_ack; /* if NZ we're awaiting ACK */ + time_t last_send; /* for tracking send timeouts */ unsigned int cfg_stage; /* configuration stage counter */ unsigned int driverstate; /* for private use */ #define SIRF_LT_231 0x01 /* SiRF at firmware rev < 231 */ @@ -1158,7 +1158,13 @@ int main(int argc, char **argv) else devicename = argv[optind]; - (void)strlcpy(session.gpsdata.dev.path, devicename, + /* backward compatibilty: accept a bare server name */ + if (strchr(devicename, ':') == NULL && devicename[0] != '/') + (void) strlcpy(session.gpsdata.dev.path, + "tcp://", sizeof(session.gpsdata.dev.path)); + else + session.gpsdata.dev.path[0] = '\0'; + (void)strlcat(session.gpsdata.dev.path, devicename, sizeof(session.gpsdata.dev.path)); if (gpsd_activate(&session, O_PROBEONLY) == -1) { |