diff --git a/gpsd/gpsd.c b/gpsd/gpsd.c index 9151a6124..cfb7a92cc 100644 --- a/gpsd/gpsd.c +++ b/gpsd/gpsd.c @@ -2428,6 +2428,7 @@ int main(int argc, char *argv[]) switch(gpsd_await_data(&rfds, &efds, maxfd, &all_fds, &context.errout)) { case AWAIT_GOT_INPUT: + case AWAIT_TIMEOUT: break; case AWAIT_NOT_READY: for (device = devices; device < devices + MAX_DEVICES; device++) @@ -2567,6 +2568,17 @@ int main(int argc, char *argv[]) case DEVICE_EOF: deactivate_device(device); break; + // If a driver hasn't been determined yet (ie. we don't have enough data to + // determine the GPS receiver type) then check if we should + // change the baud rate. + // Changing the baud rate of the GPS Receiver may allow us to read data from it + // properly and therefore determine its type (ie. driver_index) + case DEVICE_UNCHANGED: + if (device->driver_index == 0) + { + gpsd_next_hunt_setting(device); + } + break; default: break; } diff --git a/gpsd/libgpsd_core.c b/gpsd/libgpsd_core.c index 2aa3537b8..3a9f7d8dc 100644 --- a/gpsd/libgpsd_core.c +++ b/gpsd/libgpsd_core.c @@ -1301,7 +1301,7 @@ int gpsd_await_data(fd_set *rfds, struct gpsd_errout_t *errout) { int status; - timespec_t ts_timeout = {3, 0}; // timeout for pselect() + struct timespec tv; FD_ZERO(efds); *rfds = *all_fds; @@ -1315,12 +1315,17 @@ int gpsd_await_data(fd_set *rfds, * low-clock-rate SBCs and the like). * * As used here, there is no difference between pselect() - * or select(). A 3 second timeout is used, this adds a bit - * of power consumption, but prevents infinite hang during autobaud. + * or select(). */ errno = 0; - status = pselect(maxfd + 1, rfds, NULL, NULL, &ts_timeout, NULL); + // Timeout after 5 seconds. + // If we're set to the wrong baud rate then there's a chance this call + // to pselect can hang forever. + tv.tv_sec = 5; + tv.tv_nsec = 0; + + status = pselect(maxfd + 1, rfds, NULL, NULL, &tv, NULL); if (-1 == status) { if (errno == EINTR) return AWAIT_NOT_READY; @@ -1342,6 +1347,9 @@ int gpsd_await_data(fd_set *rfds, GPSD_LOG(LOG_ERROR, errout, "select: %s\n", strerror(errno)); return AWAIT_FAILED; } + else if (0 == status) { + return AWAIT_TIMEOUT; + } if (errout->debug >= LOG_SPIN) { int i; @@ -1466,15 +1474,12 @@ gps_mask_t gpsd_poll(struct gps_device_t *session) gap = TS_SUB_D(&ts_now, &session->lexer.start_time); - // used to comare gap > min_cycle, but min_cycle is now - // so variable as to be not helpful. Some GPS models can - // vary from 20Hz to 1Hz. - if (gap > quiet_time) { - // quiet_time is getting less useful as GNSS receivers - // have more data to send. + if (gap > min_cycle) + GPSD_LOG(LOG_WARN, &session->context->errout, + "cycle-start detector failed.\n"); + else if (gap > quiet_time) { GPSD_LOG(LOG_PROG, &session->context->errout, - "transmission pause. gap %f quiet_time %f\n", - gap, quiet_time); + "transmission pause of %f\n", gap); session->sor = ts_now; session->lexer.start_char = session->lexer.char_counter; } diff --git a/gpsd/serial.c b/gpsd/serial.c index 3803d4675..a9f50423e 100644 --- a/gpsd/serial.c +++ b/gpsd/serial.c @@ -556,6 +556,8 @@ void gpsd_set_speed(struct gps_device_t *session, } } packet_reset(&session->lexer); + + clock_gettime(CLOCK_MONOTONIC, &session->ts_startCurrentBaud); } /* open a device for access to its data @@ -816,7 +818,13 @@ bool gpsd_next_hunt_setting(struct gps_device_t * session) return false; } - if (session->lexer.retry_counter++ >= SNIFF_RETRIES) { + struct timespec ts_now; + clock_gettime(CLOCK_MONOTONIC, &ts_now); + + if (session->lexer.retry_counter++ >= SNIFF_RETRIES || + // If we've been communicating to the GPS Receiver for over 5 seconds and we still don't know + // the GPS Receiver type then switch baud rates. + ((ts_now.tv_sec - session->ts_startCurrentBaud.tv_sec >= 5) && (session->driver_index == 0))) { char new_parity; // E, N, O unsigned int new_stop; // u-blox 9 can do 921600 diff --git a/include/gpsd.h b/include/gpsd.h index 531ef822c..3788e7c29 100644 --- a/include/gpsd.h +++ b/include/gpsd.h @@ -532,6 +532,7 @@ struct gps_device_t { unsigned int baudindex; int saved_baud; struct gps_lexer_t lexer; + struct timespec ts_startCurrentBaud; int badcount; int subframe_count; /* firmware version or subtype ID, 96 too small for ZED-F9 */ @@ -1019,6 +1020,7 @@ extern int gpsd_open(struct gps_device_t *); extern int gpsd_activate(struct gps_device_t *, const int); extern void gpsd_deactivate(struct gps_device_t *); +#define AWAIT_TIMEOUT 2 #define AWAIT_GOT_INPUT 1 #define AWAIT_NOT_READY 0 #define AWAIT_FAILED -1