summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2014-08-25 07:35:41 -0400
committerEric S. Raymond <esr@thyrsus.com>2014-08-25 07:35:41 -0400
commit2f7a78002f012c7ed322767cf3e413b961a640b4 (patch)
tree50d95ee10f3a8e972489e5502a75dd970483a15f
parent3517cd53afabac201b3563f58a33dc15fd35bfdd (diff)
downloadgpsd-2f7a78002f012c7ed322767cf3e413b961a640b4.tar.gz
Split firmwqre version query out of the init method.
This enables us to force readonly off while it's being called. The practical effect is that gpsmon can get a firmware version (if this is possible) without reconfiguring the device.
-rw-r--r--TODO5
-rw-r--r--driver_evermore.c1
-rw-r--r--driver_garmin.c3
-rw-r--r--driver_geostar.c11
-rw-r--r--driver_italk.c1
-rw-r--r--driver_navcom.c1
-rw-r--r--driver_nmea2000.c1
-rw-r--r--driver_oncore.c3
-rw-r--r--driver_proto.c2
-rw-r--r--driver_sirf.c22
-rw-r--r--driver_superstar2.c4
-rw-r--r--driver_tsip.c24
-rw-r--r--driver_ubx.c14
-rw-r--r--driver_zodiac.c1
-rw-r--r--drivers.c21
-rw-r--r--gpsd.h-tail1
-rw-r--r--libgpsd_core.c14
-rw-r--r--www/writing-a-driver.xml13
18 files changed, 110 insertions, 32 deletions
diff --git a/TODO b/TODO
index aee80655..4184320c 100644
--- a/TODO
+++ b/TODO
@@ -39,11 +39,6 @@ uncertainty in output JSON.
*** Client bugs
-*** gpsmon on a SiRF doesn't get firmware version ***
-
-For this to work, the firmware probe needs to be split out of the
-configure method so gpsmon can call it separately.
-
**** In gpsmon's PPS Offset field
Presently PPS Offset is displayed in direct mode for NMEA, SiRF, and
diff --git a/driver_evermore.c b/driver_evermore.c
index d8ec713c..ea315643 100644
--- a/driver_evermore.c
+++ b/driver_evermore.c
@@ -623,6 +623,7 @@ const struct gps_type_t driver_evermore =
.get_packet = generic_get, /* use generic one */
.parse_packet = generic_parse_input, /* parse message packets */
.rtcm_writer = gpsd_write, /* send RTCM data straight */
+ .init_query = NULL, /* non-perturbing query */
.event_hook = evermore_event_hook, /* lifetime event handler */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = evermore_speed, /* we can change baud rates */
diff --git a/driver_garmin.c b/driver_garmin.c
index 4ecdad49..acdbc90b 100644
--- a/driver_garmin.c
+++ b/driver_garmin.c
@@ -1384,6 +1384,7 @@ const struct gps_type_t driver_garmin_usb_binary_old =
.get_packet = garmin_get_packet,/* how to grab a packet */
.parse_packet = garmin_usb_parse, /* parse message packets */
.rtcm_writer = NULL, /* don't send DGPS corrections */
+ .init_query = NULL, /* non-perturbing initial query */
.event_hook = garmin_event_hook,/* lifetime event handler */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = NULL, /* no speed switcher */
@@ -1413,6 +1414,7 @@ const struct gps_type_t driver_garmin_usb_binary =
.get_packet = generic_get, /* how to grab a packet */
.parse_packet = garmin_ser_parse, /* parse message packets */
.rtcm_writer = NULL, /* don't send DGPS corrections */
+ .init_query = NULL, /* non-perturbing initial query */
.event_hook = garmin_event_hook,/* lifetime ebent handler */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = NULL, /* no speed switcher */
@@ -1441,6 +1443,7 @@ const struct gps_type_t driver_garmin_ser_binary =
.get_packet = generic_get, /* how to grab a packet */
.parse_packet = garmin_ser_parse, /* parse message packets */
.rtcm_writer = NULL, /* don't send DGPS corrections */
+ .init_query = NULL, /* non-perturbing initial query */
.event_hook = NULL, /* lifetime event handler */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = NULL, /* no speed switcher */
diff --git a/driver_geostar.c b/driver_geostar.c
index e2f5899e..a7c37689 100644
--- a/driver_geostar.c
+++ b/driver_geostar.c
@@ -502,6 +502,14 @@ static ssize_t geostar_control_send(struct gps_device_t *session,
}
#endif /* CONTROLSEND_ENABLE */
+
+static void geostar_init_query(struct gps_device_t *session)
+{
+ unsigned char buf[2 * 4];
+ /* Poll Software Version */
+ (void)geostar_write(session, 0xc1, buf, 1);
+}
+
static void geostar_event_hook(struct gps_device_t *session, event_t event)
{
unsigned char buf[2 * 4];
@@ -537,8 +545,6 @@ static void geostar_event_hook(struct gps_device_t *session, event_t event)
(void)geostar_write(session, 0x8e, buf, 1);
/* Poll binary packets selected */
(void)geostar_write(session, 0x8f, buf, 1);
- /* Poll Software Version */
- (void)geostar_write(session, 0xc1, buf, 1);
}
if (event == event_deactivate) {
@@ -620,6 +626,7 @@ const struct gps_type_t driver_geostar =
.get_packet = generic_get, /* use the generic packet getter */
.parse_packet = geostar_parse_input, /* parse message packets */
.rtcm_writer = NULL, /* doesn't accept DGPS corrections */
+ .init_query = geostar_init_query, /* non-perturbing initial query */
.event_hook = geostar_event_hook, /* fire on various lifetime events */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = geostar_speed_switch,/* change baud rate */
diff --git a/driver_italk.c b/driver_italk.c
index 75f8e738..94f78118 100644
--- a/driver_italk.c
+++ b/driver_italk.c
@@ -416,6 +416,7 @@ const struct gps_type_t driver_italk =
.get_packet = generic_get, /* use generic packet grabber */
.parse_packet = italk_parse_input,/* parse message packets */
.rtcm_writer = gpsd_write, /* send RTCM data straight */
+ .init_query = NULL, /* non-perturbing initial query */
.event_hook = NULL, /* lifetime event handler */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = NULL, /* no speed switcher */
diff --git a/driver_navcom.c b/driver_navcom.c
index fdecf661..213b6d25 100644
--- a/driver_navcom.c
+++ b/driver_navcom.c
@@ -1285,6 +1285,7 @@ const struct gps_type_t driver_navcom =
.get_packet = generic_get, /* use generic one */
.parse_packet = navcom_parse_input, /* parse message packets */
.rtcm_writer = gpsd_write, /* send RTCM data straight */
+ .init_query = NULL, /* non-perturbing query */
.event_hook = navcom_event_hook, /* lifetime event handler */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = navcom_speed, /* we do change baud rates */
diff --git a/driver_nmea2000.c b/driver_nmea2000.c
index 147eba57..dc6eb474 100644
--- a/driver_nmea2000.c
+++ b/driver_nmea2000.c
@@ -1675,6 +1675,7 @@ const struct gps_type_t driver_nmea2000 = {
.get_packet = nmea2000_get, /* how to get a packet */
.parse_packet = nmea2000_parse_input, /* how to interpret a packet */
.rtcm_writer = NULL, /* Don't send RTCM to this */
+ .init_query = NULL, /* non-perturbing query */
.event_hook = NULL,
#ifdef RECONFIGURE_ENABLE
.speed_switcher = NULL, /* no speed switcher */
diff --git a/driver_oncore.c b/driver_oncore.c
index d745b476..e9dbecfd 100644
--- a/driver_oncore.c
+++ b/driver_oncore.c
@@ -498,7 +498,8 @@ const struct gps_type_t driver_oncore = {
.get_packet = generic_get, /* packet getter */
.parse_packet = oncore_parse_input, /* packet parser */
.rtcm_writer = gpsd_write, /* device accepts RTCM */
- .event_hook = oncore_event_hook, /* lifetime event hook */
+ .init_query = NULL, /* non-perturbing query */
+ .event_hook = oncore_event_hook, /* lifetime event hook */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = NULL, /* no speed setter */
.mode_switcher = NULL, /* no mode setter */
diff --git a/driver_proto.c b/driver_proto.c
index d0de2410..10fb05ac 100644
--- a/driver_proto.c
+++ b/driver_proto.c
@@ -512,6 +512,8 @@ const struct gps_type_t driver__proto__binary = {
.parse_packet = _proto__parse_input,
/* RTCM handler (using default routine) */
.rtcm_writer = pass_rtcm,
+ /* non-perturbing initial query (e.g. for version) */
+ .init_query = NULL,
/* fire on various lifetime events */
.event_hook = _proto__event_hook,
#ifdef RECONFIGURE_ENABLE
diff --git a/driver_sirf.c b/driver_sirf.c
index d0506e7f..0a81781c 100644
--- a/driver_sirf.c
+++ b/driver_sirf.c
@@ -1373,6 +1373,13 @@ static gps_mask_t sirfbin_parse_input(struct gps_device_t *session)
return 0;
}
+static void sirfbin_init_query(struct gps_device_t *session)
+{
+ gpsd_report(session->context->debug, LOG_PROG,
+ "SiRF: Probing for firmware version.\n");
+ (void)sirf_write(session, versionprobe);
+}
+
static void sirfbin_event_hook(struct gps_device_t *session, event_t event)
{
if (session->context->readonly)
@@ -1401,9 +1408,11 @@ static void sirfbin_event_hook(struct gps_device_t *session, event_t event)
return;
case 1:
+ /* disable navigation debug messages (the value 5 is magic) */
gpsd_report(session->context->debug, LOG_PROG,
- "SiRF: Probing for firmware version.\n");
- (void)sirf_write(session, versionprobe);
+ "SiRF: disable MID 7, 28, 29, 30, 31.\n");
+ putbyte(unsetmidXX, 5, 0x05);
+ (void)sirf_write(session, unsetmidXX);
break;
case 2:
@@ -1484,14 +1493,6 @@ static void sirfbin_event_hook(struct gps_device_t *session, event_t event)
}
break;
- case 12:
- /* disable navigation debug messages (the value 5 is magic) */
- gpsd_report(session->context->debug, LOG_PROG,
- "SiRF: disable MID 7, 28, 29, 30, 31.\n");
- putbyte(unsetmidXX, 5, 0x05);
- (void)sirf_write(session, unsetmidXX);
- break;
-
#endif /* RECONFIGURE_ENABLE */
default:
/* initialization is done */
@@ -1546,6 +1547,7 @@ const struct gps_type_t driver_sirf =
.get_packet = generic_get, /* be prepared for SiRF or NMEA */
.parse_packet = sirfbin_parse_input,/* parse message packets */
.rtcm_writer = gpsd_write, /* send RTCM data straight */
+ .init_query = sirfbin_init_query,/* non-perturbing initial qury */
.event_hook = sirfbin_event_hook,/* lifetime event handler */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = sirfbin_speed, /* we can change baud rate */
diff --git a/driver_superstar2.c b/driver_superstar2.c
index ff151f6d..9db21e02 100644
--- a/driver_superstar2.c
+++ b/driver_superstar2.c
@@ -430,6 +430,8 @@ superstar2_dispatch(struct gps_device_t * session, unsigned char *buf,
*
**********************************************************/
+/* FIXME: factor out Superstar init_query for version */
+
static void superstar2_event_hook(struct gps_device_t *session, event_t event)
{
if (session->context->readonly)
@@ -556,6 +558,8 @@ const struct gps_type_t driver_superstar2 = {
.parse_packet = superstar2_parse_input,
/* RTCM handler (using default routine) */
.rtcm_writer = gpsd_write,
+ /* non-perturbing initial query */
+ .init_query = NULL,
/* Fire on various lifetime events */
.event_hook = superstar2_event_hook,
#ifdef RECONFIGURE_ENABLE
diff --git a/driver_tsip.c b/driver_tsip.c
index ea29145e..d8736736 100644
--- a/driver_tsip.c
+++ b/driver_tsip.c
@@ -1012,6 +1012,19 @@ static ssize_t tsip_control_send(struct gps_device_t *session,
}
#endif /* CONTROLSEND_ENABLE */
+static void tsip_init_query(struct gps_device_t *session)
+{
+ unsigned char buf[100];
+
+ /* Request Hardware Version Information */
+ putbyte(buf, 0, 0x03); /* Subcode */
+ (void)tsip_write(session, 0x1c, buf, 1);
+ /*
+ * After HW information packet is received, a
+ * decision is made how to configure the device.
+ */
+}
+
static void tsip_event_hook(struct gps_device_t *session, event_t event)
{
if (session->context->readonly)
@@ -1020,7 +1033,7 @@ static void tsip_event_hook(struct gps_device_t *session, event_t event)
unsigned char buf[100];
/*
- * Set basic configuration, in case no hardware config resonse
+ * Set basic configuration, in case no hardware config response
* comes back.
*/
putbyte(buf, 0, 0x1e); /* Position: DP, MSL, LLA */
@@ -1028,14 +1041,6 @@ static void tsip_event_hook(struct gps_device_t *session, event_t event)
putbyte(buf, 2, 0x00); /* Time: GPS */
putbyte(buf, 3, 0x08); /* Aux: dBHz */
(void)tsip_write(session, 0x35, buf, 4);
-
- /* Request Hardware Version Information */
- putbyte(buf, 0, 0x03); /* Subcode */
- (void)tsip_write(session, 0x1c, buf, 1);
- /*
- * After HW information packet is received, a
- * decision is made how to configure the device.
- */
}
if (event == event_configure && session->packet.counter == 0) {
/*
@@ -1256,6 +1261,7 @@ const struct gps_type_t driver_tsip =
.get_packet = generic_get, /* use the generic packet getter */
.parse_packet = tsip_parse_input, /* parse message packets */
.rtcm_writer = NULL, /* doesn't accept DGPS corrections */
+ .init_query = tsip_init_query, /* non-perturbing initial query */
.event_hook = tsip_event_hook, /* fire on various lifetime events */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = tsip_speed_switch,/* change baud rate */
diff --git a/driver_ubx.c b/driver_ubx.c
index 88633919..cf51afd0 100644
--- a/driver_ubx.c
+++ b/driver_ubx.c
@@ -619,6 +619,16 @@ static ssize_t ubx_control_send(struct gps_device_t *session, char *msg,
}
#endif /* CONTROLSEND_ENABLE */
+static void ubx_init_query(struct gps_device_t *session)
+{
+ unsigned char msg[32];
+
+ /*@ -type @*/
+ /* MON_VER: query for version information */
+ (void)ubx_write(session, UBX_CLASS_MON, 0x04, msg, 0);
+ /*@ +type @*/
+}
+
static void ubx_event_hook(struct gps_device_t *session, event_t event)
{
if (session->context->readonly)
@@ -638,9 +648,6 @@ static void ubx_event_hook(struct gps_device_t *session, event_t event)
msg[6] = 0x00;
msg[7] = 0x00;
(void)ubx_write(session, 0x06u, 0x16, msg, 8);
-
- /* MON_VER: query for version information */
- (void)ubx_write(session, UBX_CLASS_MON, 0x04, msg, 0);
/*@ +type @*/
#ifdef RECONFIGURE_ENABLE
@@ -969,6 +976,7 @@ const struct gps_type_t driver_ubx = {
.get_packet = generic_get, /* Packet getter (using default routine) */
.parse_packet = parse_input, /* Parse message packets */
.rtcm_writer = gpsd_write, /* RTCM handler (using default routine) */
+ .init_query = ubx_init_query, /* non-perturbing initial query */
.event_hook = ubx_event_hook, /* Fire on various lifetime events */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = ubx_speed, /* Speed (baudrate) switch */
diff --git a/driver_zodiac.c b/driver_zodiac.c
index 240c7909..be7d8b54 100644
--- a/driver_zodiac.c
+++ b/driver_zodiac.c
@@ -474,6 +474,7 @@ const struct gps_type_t driver_zodiac =
.get_packet = generic_get, /* use the generic packet getter */
.parse_packet = zodiac_analyze, /* parse message packets */
.rtcm_writer = zodiac_send_rtcm, /* send DGPS correction */
+ .init_query = NULL, /* non-perturbing initial query */
.event_hook = NULL, /* no configuration */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = zodiac_speed_switch,/* we can change baud rate */
diff --git a/drivers.c b/drivers.c
index 13cf4ef8..725fb709 100644
--- a/drivers.c
+++ b/drivers.c
@@ -87,6 +87,7 @@ const struct gps_type_t driver_unknown = {
.get_packet = generic_get, /* use generic packet getter */
.parse_packet = generic_parse_input, /* how to interpret a packet */
.rtcm_writer = NULL, /* write RTCM data straight */
+ .init_query = NULL, /* non-perturbing initial query */
.event_hook = NULL, /* lifetime event handler */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = NULL, /* no speed switcher */
@@ -252,6 +253,7 @@ const struct gps_type_t driver_nmea0183 = {
.get_packet = generic_get, /* use generic packet getter */
.parse_packet = generic_parse_input, /* how to interpret a packet */
.rtcm_writer = gpsd_write, /* write RTCM data straight */
+ .init_query = NULL, /* non-perturbing initial query */
.event_hook = nmea_event_hook, /* lifetime event handler */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = NULL, /* no speed switcher */
@@ -357,6 +359,7 @@ const struct gps_type_t driver_garmin = {
.get_packet = generic_get, /* use generic packet getter */
.parse_packet = generic_parse_input, /* how to interpret a packet */
.rtcm_writer = NULL, /* some do, some don't, skip for now */
+ .init_query = NULL, /* non-perturbing initial query */
.event_hook = garmin_nmea_event_hook, /* lifetime event handler */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = NULL, /* no speed switcher */
@@ -419,6 +422,7 @@ const struct gps_type_t driver_ashtech = {
.get_packet = generic_get, /* how to get a packet */
.parse_packet = generic_parse_input, /* how to interpret a packet */
.rtcm_writer = gpsd_write, /* write RTCM data straight */
+ .init_query = NULL, /* non-perturbing initial query */
.event_hook = ashtech_event_hook, /* lifetime event handler */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = NULL, /* no speed switcher */
@@ -470,6 +474,7 @@ const struct gps_type_t driver_fv18 = {
.get_packet = generic_get, /* how to get a packet */
.parse_packet = generic_parse_input, /* how to interpret a packet */
.rtcm_writer = gpsd_write, /* write RTCM data straight */
+ .init_query = NULL, /* non-perturbing initial query */
.event_hook = fv18_event_hook, /* lifetime event handler */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = NULL, /* no speed switcher */
@@ -524,6 +529,7 @@ const struct gps_type_t driver_gpsclock = {
.get_packet = generic_get, /* how to get a packet */
.parse_packet = generic_parse_input, /* how to interpret a packet */
.rtcm_writer = gpsd_write, /* write RTCM data straight */
+ .init_query = NULL, /* non-perturbing initial query */
.event_hook = gpsclock_event_hook, /* lifetime event handler */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = NULL, /* no speed switcher */
@@ -577,8 +583,9 @@ static const struct gps_type_t driver_tripmate = {
.channels = 12, /* consumer-grade GPS */
.probe_detect = NULL, /* no probe */
.get_packet = generic_get, /* how to get a packet */
- .parse_packet = generic_parse_input, /* how to interpret a packet */
- .rtcm_writer = gpsd_write, /* send RTCM data straight */
+ .parse_packet = generic_parse_input, /* how to interpret a packet */
+ .rtcm_writer = gpsd_write, /* send RTCM data straight */
+ .init_query = NULL, /* non-perturbing query */
.event_hook = tripmate_event_hook, /* lifetime event handler */
#ifdef RECONFIGURE_ENABLE
.speed_switcher= NULL, /* no speed switcher */
@@ -630,6 +637,7 @@ static const struct gps_type_t driver_earthmate = {
.get_packet = generic_get, /* how to get a packet */
.parse_packet = generic_parse_input, /* how to interpret a packet */
.rtcm_writer = NULL, /* don't send RTCM data */
+ .init_query = NULL, /* non-perturbing query */
.event_hook = earthmate_event_hook, /* lifetime event handler */
#ifdef RECONFIGURE_ENABLE
.speed_switcher= NULL, /* no speed switcher */
@@ -755,6 +763,7 @@ const struct gps_type_t driver_trueNorth = {
.get_packet = generic_get, /* how to get a packet */
.parse_packet = generic_parse_input, /* how to interpret a packet */
.rtcm_writer = NULL, /* Don't send */
+ .init_query = NULL, /* non-perturbing initial query */
.event_hook = tnt_event_hook, /* lifetime event handler */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = tnt_speed, /* no speed switcher */
@@ -833,6 +842,7 @@ static const struct gps_type_t driver_oceanServer = {
.get_packet = generic_get, /* how to get a packet */
.parse_packet = generic_parse_input, /* how to interpret a packet */
.rtcm_writer = NULL, /* Don't send */
+ .init_query = NULL, /* non-perturbing initial query */
.event_hook = oceanserver_event_hook,
#ifdef RECONFIGURE_ENABLE
.speed_switcher = NULL, /* no speed switcher */
@@ -900,6 +910,7 @@ static const struct gps_type_t driver_fury = {
.get_packet = generic_get, /* how to get a packet */
.parse_packet = generic_parse_input, /* how to interpret a packet */
.rtcm_writer = NULL, /* Don't send */
+ .init_query = NULL, /* non-perturbing initial query */
.event_hook = fury_event_hook,
#ifdef RECONFIGURE_ENABLE
.speed_switcher = NULL, /* no speed switcher */
@@ -954,6 +965,7 @@ static const struct gps_type_t driver_rtcm104v2 = {
.get_packet = generic_get, /* how to get a packet */
.parse_packet = rtcm104v2_analyze, /* */
.rtcm_writer = NULL, /* don't send RTCM data, */
+ .init_query = NULL, /* non-perturbing initial query */
.event_hook = NULL, /* no event_hook */
#ifdef RECONFIGURE_ENABLE
.speed_switcher= NULL, /* no speed switcher */
@@ -1000,6 +1012,7 @@ static const struct gps_type_t driver_rtcm104v3 = {
.get_packet = generic_get, /* how to get a packet */
.parse_packet = rtcm104v3_analyze, /* */
.rtcm_writer = NULL, /* don't send RTCM data, */
+ .init_query = NULL, /* non-perturbing initial query */
.event_hook = NULL, /* no event hook */
#ifdef RECONFIGURE_ENABLE
.speed_switcher= NULL, /* no speed switcher */
@@ -1035,6 +1048,7 @@ static const struct gps_type_t driver_garmintxt = {
.get_packet = generic_get, /* how to get a packet */
.parse_packet = garmintxt_parse, /* how to parse one */
.rtcm_writer = NULL, /* don't send RTCM data, */
+ .init_query = NULL, /* non-perturbing initial query */
.event_hook = NULL, /* no event hook */
#ifdef RECONFIGURE_ENABLE
.speed_switcher= NULL, /* no speed switcher */
@@ -1130,6 +1144,7 @@ const struct gps_type_t driver_mtk3301 = {
.get_packet = generic_get, /* how to get a packet */
.parse_packet = generic_parse_input, /* how to interpret a packet */
.rtcm_writer = gpsd_write, /* write RTCM data straight */
+ .init_query = NULL, /* non-perturbing initial query */
.event_hook = mtk3301_event_hook, /* lifetime event handler */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = NULL, /* no speed switcher */
@@ -1372,6 +1387,7 @@ const struct gps_type_t driver_aivdm = {
.get_packet = generic_get, /* how to get a packet */
.parse_packet = aivdm_analyze, /* how to analyze a packet */
.rtcm_writer = NULL, /* don't send RTCM data, */
+ .init_query = NULL, /* non-perturbing initial query */
.event_hook = NULL, /* lifetime event handler */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = NULL, /* no speed switcher */
@@ -1475,6 +1491,7 @@ const struct gps_type_t driver_json_passthrough = {
.get_packet = generic_get, /* use generic packet getter */
.parse_packet = json_pass_packet, /* how to interpret a packet */
.rtcm_writer = NULL, /* write RTCM data straight */
+ .init_query = NULL, /* non-perturbing initial query */
.event_hook = NULL, /* lifetime event handler */
#ifdef RECONFIGURE_ENABLE
.speed_switcher = NULL, /* no speed switcher */
diff --git a/gpsd.h-tail b/gpsd.h-tail
index 34bfe71e..f28152b8 100644
--- a/gpsd.h-tail
+++ b/gpsd.h-tail
@@ -345,6 +345,7 @@ struct gps_type_t {
/*@null@*/ssize_t (*get_packet)(struct gps_device_t *session);
/*@null@*/gps_mask_t (*parse_packet)(struct gps_device_t *session);
/*@null@*/ssize_t (*rtcm_writer)(struct gps_device_t *session, const char *rtcmbuf, size_t rtcmbytes);
+ /*@null@*/void (*init_query)(struct gps_device_t *session);
/*@null@*/void (*event_hook)(struct gps_device_t *session, event_t event);
#ifdef RECONFIGURE_ENABLE
/*@null@*/bool (*speed_switcher)(struct gps_device_t *session,
diff --git a/libgpsd_core.c b/libgpsd_core.c
index f7e8075c..f11e4831 100644
--- a/libgpsd_core.c
+++ b/libgpsd_core.c
@@ -1325,6 +1325,20 @@ gps_mask_t gpsd_poll(struct gps_device_t *session)
timestamp() - session->opentime,
(unsigned int)speed);
/*@+nullderef@*/
+
+ /* fire the init_query method */
+ if (session->device_type != NULL
+ && session->device_type->init_query != NULL) {
+ /*
+ * We can force readonly off knowing this method does
+ * not alter device state.
+ */
+ bool saved = session->context->readonly;
+ session->context->readonly = false;
+ session->device_type->init_query(session);
+ session->context->readonly = saved;
+ }
+
/* fire the identified hook */
if (session->device_type != NULL
&& session->device_type->event_hook != NULL)
diff --git a/www/writing-a-driver.xml b/www/writing-a-driver.xml
index 91e751b4..9cac39b3 100644
--- a/www/writing-a-driver.xml
+++ b/www/writing-a-driver.xml
@@ -15,6 +15,14 @@
<revhistory>
<revision>
+ <revnumber>1.13</revnumber>
+ <date>25 Aug 2014</date>
+ <authorinitials>er</authorinitials>
+ <revremark>
+ Updated by esr; added init_query method.
+ </revremark>
+ </revision>
+ <revision>
<revnumber>1.12</revnumber>
<date>31 Oct 2013</date>
<authorinitials>er</authorinitials>
@@ -639,6 +647,11 @@ original settings for later restoration, probably by
<structfield>.wrapup</structfield> mentioned below. Later in this
document I discuss my work to implement this function.</para>
+<!-- added by ESR, 2014 -->
+<para><structfield>.init_query</structfield> points to a block of code
+that will be called to query the firmware version of the device. This
+code <emphasis>must not</emphasis> alter device state or settings.</para>
+
<para><structfield>.event_hook</structfield> points to a block of code
that will be executed on and after various events, distinguished by a
second argument that specifies the event type. The event_hook hook is