summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2009-09-13 03:30:05 +0000
committerEric S. Raymond <esr@thyrsus.com>2009-09-13 03:30:05 +0000
commit00cd07ffcaa670709bc492e01d5c97be0262580b (patch)
tree4f21deae21586a533b279d272d74af3a0899b5e1
parentbff151b7897e75612f871d44087c6f90cf412b52 (diff)
downloadgpsd-00cd07ffcaa670709bc492e01d5c97be0262580b.tar.gz
Merge the configurator and probe_subtype methods.
They're now distinguished by an event argument passed to the common hook function. This is a refactoring step - later, we'll define more and different events for finer-grained control. All regression tests pass.
-rw-r--r--driver_evermore.c8
-rw-r--r--driver_garmin.c12
-rw-r--r--driver_italk.c12
-rw-r--r--driver_navcom.c8
-rw-r--r--driver_oncore.c21
-rw-r--r--driver_proto.c45
-rw-r--r--driver_sirf.c6
-rw-r--r--driver_superstar2.c56
-rw-r--r--driver_tsip.c72
-rw-r--r--driver_ubx.c83
-rw-r--r--driver_zodiac.c1
-rw-r--r--drivers.c336
-rw-r--r--gpsd.h-tail5
-rw-r--r--gpsmon.c2
-rw-r--r--libgpsd_core.c24
-rw-r--r--www/writing-a-driver.xml74
16 files changed, 399 insertions, 366 deletions
diff --git a/driver_evermore.c b/driver_evermore.c
index f24495e1..454781f9 100644
--- a/driver_evermore.c
+++ b/driver_evermore.c
@@ -483,12 +483,13 @@ static void evermore_mode(struct gps_device_t *session, int mode)
}
}
-static void evermore_configurator(struct gps_device_t *session, unsigned int seq)
+static void evermore_configurator(struct gps_device_t *session,
+ event_t event, unsigned int seq)
{
gpsd_report(LOG_PROG, "evermore_configurator(%d)\n", seq);
- (void) evermore_nmea_config(session, 1); /* configure NMEA messages for gpsd (GPGSV every 5s) */
- if (seq == 0) {
+ if (event == event_configure && seq == 0) {
if (session->packet.type == NMEA_PACKET) {
+ (void) evermore_nmea_config(session, 1); /* configure NMEA messages for gpsd (GPGSV every 5s) */
gpsd_report(LOG_WARN, "NMEA_PACKET packet\n");
}
(void) evermore_mode(session, 1); /* switch GPS to binary mode */
@@ -535,7 +536,6 @@ const struct gps_type_t evermore_binary =
.channels = EVERMORE_CHANNELS, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
.probe_detect = NULL, /* no probe */
- .probe_subtype = NULL, /* no subtype probing */
.get_packet = generic_get, /* use generic one */
.parse_packet = evermore_parse_input, /* parse message packets */
.rtcm_writer = pass_rtcm, /* send RTCM data straight */
diff --git a/driver_garmin.c b/driver_garmin.c
index 40b7cc9b..a196def4 100644
--- a/driver_garmin.c
+++ b/driver_garmin.c
@@ -854,9 +854,10 @@ static bool garmin_detect(struct gps_device_t *session)
return true;
}
-static void garmin_probe_subtype(struct gps_device_t *session, unsigned int seq)
+static void garmin_configurator(struct gps_device_t *session,
+ event_t event, unsigned int seq)
{
- if (seq == 0) {
+ if (event == event_probe_subtype && seq == 0) {
// Tell the device to send product data
gpsd_report(LOG_PROG, "Get Garmin Product Data\n");
Build_Send_SER_Packet(session, GARMIN_LAYERID_APPL
@@ -1212,7 +1213,6 @@ const struct gps_type_t garmin_usb_binary_old =
.channels = GARMIN_CHANNELS, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
.probe_detect = garmin_detect, /* how to detect at startup time */
- .probe_subtype = garmin_probe_subtype, /* get subtype info */
.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 */
@@ -1220,7 +1220,7 @@ const struct gps_type_t garmin_usb_binary_old =
.control_send = garmin_control_send, /* send raw bytes */
#endif /* ALLOW_CONTROLSEND */
#ifdef ALLOW_RECONFIGURE
- .configurator = NULL, /* does not allow reconfiguration */
+ .configurator = garmin_configurator, /* enable what we need */
.speed_switcher = NULL, /* no speed switcher */
.mode_switcher = NULL, /* no mode switcher */
.rate_switcher = NULL, /* no sample-rate switcher */
@@ -1239,7 +1239,6 @@ const struct gps_type_t garmin_usb_binary =
.channels = GARMIN_CHANNELS, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
.probe_detect = garmin_detect, /* how to detect at startup time */
- .probe_subtype = garmin_probe_subtype, /* get subtype info */
.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 */
@@ -1247,7 +1246,7 @@ const struct gps_type_t garmin_usb_binary =
.control_send = garmin_control_send, /* send raw bytes */
#endif /* ALLOW_CONTROLSEND */
#ifdef ALLOW_RECONFIGURE
- .configurator = NULL, /* enable what we need */
+ .configurator = garmin_configurator, /* enable what we need */
.speed_switcher = NULL, /* no speed switcher */
.mode_switcher = garmin_switcher, /* how to change modes */
.rate_switcher = NULL, /* no sample-rate switcher */
@@ -1265,7 +1264,6 @@ const struct gps_type_t garmin_ser_binary =
.channels = GARMIN_CHANNELS, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
.probe_detect = NULL, /* how to detect at startup time */
- .probe_subtype = NULL, /* initialize the device */
.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 */
diff --git a/driver_italk.c b/driver_italk.c
index 9e692ab9..f220e820 100644
--- a/driver_italk.c
+++ b/driver_italk.c
@@ -393,9 +393,10 @@ static void italk_mode(struct gps_device_t *session, int mode)
}
}
-static void italk_configurator(struct gps_device_t *session, unsigned int seq)
+static void italk_configurator(struct gps_device_t *session,
+ event_t event, unsigned int seq)
{
- if (seq == 0 && session->packet.type == NMEA_PACKET)
+ if (event == event_configure && seq == 0 && session->packet.type == NMEA_PACKET)
(void)italk_set_mode(session,
session->gpsdata.dev.baudrate,
(char)session->gpsdata.dev.parity,
@@ -422,7 +423,6 @@ const struct gps_type_t italk_binary =
.channels = 12, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
.probe_detect = NULL, /* how to detect at startup time */
- .probe_subtype = NULL, /* initialize the device */
.get_packet = generic_get, /* use generic packet grabber */
.parse_packet = italk_parse_input,/* parse message packets */
.rtcm_writer = pass_rtcm, /* send RTCM data straight */
@@ -506,10 +506,11 @@ static void itrax_probe_subtype(struct gps_device_t *session, unsigned int seq)
}
#ifdef ALLOW_RECONFIGURE
-static void itrax_configurator(struct gps_device_t *session, int seq)
+static void itrax_configurator(struct gps_device_t
+ event_t event, *session, int seq)
/* set synchronous mode */
{
- if (seq == 0) {
+ if (event == event_configure && seq == 0) {
(void)literal_send(session->gpsdata.gps_fd, "$PFST,SYNCMODE,1\r\n");
(void)literal_send(session->gpsdata.gps_fd,
ITRAX_MODESTRING, session->gpsdata.baudrate);
@@ -548,7 +549,6 @@ const static struct gps_type_t itrax = {
.channels = 12, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
.probe_detect = NULL, /* no probe */
- .probe_subtype = itrax_probe_subtype, /* initialize */
.get_packet = generic_get, /* how to get a packet */
.parse_packet = nmea_parse_input, /* how to interpret a packet */
.rtcm_writer = NULL, /* iTrax doesn't support DGPS/WAAS/EGNOS */
diff --git a/driver_navcom.c b/driver_navcom.c
index 7bb9a432..51f0aa61 100644
--- a/driver_navcom.c
+++ b/driver_navcom.c
@@ -186,10 +186,11 @@ static void navcom_cmd_0x11(struct gps_device_t *session, u_int8_t port_selectio
}
#endif /* ALLOW_RECONFIGURE */
-static void navcom_probe_subtype(struct gps_device_t *session, unsigned int seq)
+static void navcom_configurator(struct gps_device_t *session,
+ event_t event, unsigned int seq)
{
/* Request the following messages: */
- if (seq==0) {
+ if (event == event_probe_subtype && seq==0) {
/*@ +charint @*/
navcom_cmd_0x1c(session, 0x01, 5); /* Blink LEDs on receiver */
navcom_cmd_0x20(session, 0xae, 0x1770); /* Identification Block - send every 10 min*/
@@ -1269,7 +1270,6 @@ const struct gps_type_t navcom_binary =
.channels = NAVCOM_CHANNELS, /* 12 L1 + 12 L2 + 2 Inmarsat L-Band */
.probe_wakeup = navcom_ping, /* wakeup to be done before hunt */
.probe_detect = NULL, /* no probe */
- .probe_subtype = navcom_probe_subtype, /* subtype probing */
.get_packet = generic_get, /* use generic one */
.parse_packet = navcom_parse_input, /* parse message packets */
.rtcm_writer = pass_rtcm, /* send RTCM data straight */
@@ -1277,7 +1277,7 @@ const struct gps_type_t navcom_binary =
.control_send = navcom_control_send, /* how to send a control string */
#endif /* ALLOW_CONTROLSEND */
#ifdef ALLOW_RECONFIGURE
- .configurator = NULL, /* no reconfigure */
+ .configurator = navcom_configurator, /* configuration logic */
.speed_switcher = navcom_speed, /* we do change baud rates */
.mode_switcher = NULL, /* there is not a mode switcher */
.rate_switcher = NULL, /* no sample-rate switcher */
diff --git a/driver_oncore.c b/driver_oncore.c
index fec40671..b71f3214 100644
--- a/driver_oncore.c
+++ b/driver_oncore.c
@@ -46,7 +46,7 @@ static gps_mask_t oncore_msg_firmware(struct gps_device_t *, unsigned char *, si
*/
static ssize_t oncore_control_send(struct gps_device_t *, char *, size_t );
static void oncore_probe_wakeup(struct gps_device_t *);
-static void oncore_configurator(struct gps_device_t *, unsigned int );
+static void oncore_configurator(struct gps_device_t *, event_t, unsigned int );
static bool oncore_set_speed(struct gps_device_t *, speed_t, char, int );
static void oncore_set_mode(struct gps_device_t *, int );
static void oncore_revert(struct gps_device_t *);
@@ -393,14 +393,17 @@ static ssize_t oncore_control_send(struct gps_device_t *session,
#endif /* ALLOW_CONTROLSEND */
#ifdef ALLOW_RECONFIGURE
-static void oncore_configurator(struct gps_device_t *session, unsigned int seq UNUSED)
+static void oncore_configurator(struct gps_device_t *session,
+ event_t event, unsigned int seq UNUSED)
{
- (void)oncore_control_send(session,enableEa,sizeof(enableEa));
- (void)oncore_control_send(session,enableBb,sizeof(enableBb));
- (void)oncore_control_send(session,enableEn,sizeof(enableEn));
- /*(void)oncore_control_send(session,enableAt2,sizeof(enableAt2));*/
- /*(void)oncore_control_send(session,pollAs,sizeof(pollAs));*/
- (void)oncore_control_send(session,pollBo,sizeof(pollBo));
+ if (event == event_configure) {
+ (void)oncore_control_send(session,enableEa,sizeof(enableEa));
+ (void)oncore_control_send(session,enableBb,sizeof(enableBb));
+ (void)oncore_control_send(session,enableEn,sizeof(enableEn));
+ /*(void)oncore_control_send(session,enableAt2,sizeof(enableAt2));*/
+ /*(void)oncore_control_send(session,pollAs,sizeof(pollAs));*/
+ (void)oncore_control_send(session,pollBo,sizeof(pollBo));
+ }
}
/*
@@ -490,8 +493,6 @@ const struct gps_type_t oncore_binary = {
.probe_detect = NULL,
/* Wakeup to be done before each baud hunt */
.probe_wakeup = oncore_probe_wakeup,
- /* Initialize the device and get subtype */
- .probe_subtype = NULL,
/* Packet getter (using default routine) */
.get_packet = generic_get,
/* Parse message packets */
diff --git a/driver_proto.c b/driver_proto.c
index 9f3517dc..2e34f0a7 100644
--- a/driver_proto.c
+++ b/driver_proto.c
@@ -66,13 +66,12 @@ static gps_mask_t _proto__msg_svinfo(struct gps_device_t *, unsigned char *, siz
/*
* These methods may be called elsewhere in gpsd
*/
-static ssize_t _proto__control_send(struct gps_device_t *, char *, size_t );
+static ssize_t _proto__control_send(struct gps_device_t *, char *, size_t);
static bool _proto__probe_detect(struct gps_device_t *);
static void _proto__probe_wakeup(struct gps_device_t *);
-static void _proto__probe_subtype(struct gps_device_t *, unsigned int );
-static void _proto__configurator(struct gps_device_t *, unsigned int );
-static bool _proto__set_speed(struct gps_device_t *, speed_t, char, int );
-static void _proto__set_mode(struct gps_device_t *, int );
+static void _proto__configurator(struct gps_device_t *, event_t, unsigned int);
+static bool _proto__set_speed(struct gps_device_t *, speed_t, char, int);
+static void _proto__set_mode(struct gps_device_t *, int);
static void _proto__revert(struct gps_device_t *);
static void _proto__wrapup(struct gps_device_t *);
@@ -284,16 +283,6 @@ static void _proto__probe_wakeup(struct gps_device_t *session)
*/
}
-static void _proto__probe_subtype(struct gps_device_t *session, unsigned int seq)
-{
- /*
- * Probe for subtypes here. If possible, get the software version and
- * store it in session->subtype. The seq values don't actually mean
- * anything, but conditionalizing probes on them gives the device
- * time to respond to each one.
- */
-}
-
#ifdef ALLOW_CONTROLSEND
/**
* Write data to the device, doing any required padding or checksumming
@@ -324,13 +313,23 @@ static ssize_t _proto__control_send(struct gps_device_t *session,
#endif /* ALLOW_CONTROLSEND */
#ifdef ALLOW_RECONFIGURE
-static void _proto__configurator(struct gps_device_t *session, unsigned int seq)
+static void _proto__configurator(struct gps_device_t *session,
+ event_t event, unsigned int seq)
{
- /*
- * Change sentence mix and set reporting modes as needed.
- * If your device has a default cycle time other than 1 second,
- * set session->device->gpsdata.cycle here.
- */
+ if (event == event_configure) {
+ /*
+ * Change sentence mix and set reporting modes as needed.
+ * If your device has a default cycle time other than 1 second,
+ * set session->device->gpsdata.cycle here.
+ */
+ } else if (event == event_probe_subtype) {
+ /*
+ * Probe for subtypes here. If possible, get the software version and
+ * store it in session->subtype. The seq values don't actually mean
+ * anything, but conditionalizing probes on them gives the device
+ * time to respond to each one.
+ */
+ }
}
/*
@@ -430,8 +429,6 @@ const struct gps_type_t _proto__binary = {
.probe_detect = _proto__probe_detect,
/* Wakeup to be done before each baud hunt */
.probe_wakeup = _proto__probe_wakeup,
- /* Initialize the device and get subtype */
- .probe_subtype = _proto__probe_subtype,
/* Packet getter (using default routine) */
.get_packet = generic_get,
/* Parse message packets */
@@ -443,7 +440,7 @@ const struct gps_type_t _proto__binary = {
.control_send = _proto__control_send,
#endif /* ALLOW_CONTROLSEND */
#ifdef ALLOW_RECONFIGURE
- /* Enable what reports we need */
+ /* configuration hook for various events */
.configurator = _proto__configurator,
/* Speed (baudrate) switch */
.speed_switcher = _proto__set_speed,
diff --git a/driver_sirf.c b/driver_sirf.c
index ddf4c463..9cd78e8a 100644
--- a/driver_sirf.c
+++ b/driver_sirf.c
@@ -937,9 +937,10 @@ static gps_mask_t sirfbin_parse_input(struct gps_device_t *session)
}
#ifdef ALLOW_RECONFIGURE
-static void sirfbin_configure(struct gps_device_t *session, unsigned int seq)
+static void sirfbin_configure(struct gps_device_t *session,
+ event_t event, unsigned int seq)
{
- if (seq != 0)
+ if (event != event_configure || seq != 0)
return;
if (session->packet.type == NMEA_PACKET) {
gpsd_report(LOG_PROG, "Switching chip mode to SiRF binary.\n");
@@ -1032,7 +1033,6 @@ const struct gps_type_t sirf_binary =
.channels = SIRF_CHANNELS, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
.probe_detect = NULL, /* no probe */
- .probe_subtype = NULL, /* can't probe more in NMEA mode */
.get_packet = sirf_get, /* be prepared for SiRF or NMEA */
.parse_packet = sirfbin_parse_input,/* parse message packets */
.rtcm_writer = pass_rtcm, /* send RTCM data straight */
diff --git a/driver_superstar2.c b/driver_superstar2.c
index b78f8600..3ecd961c 100644
--- a/driver_superstar2.c
+++ b/driver_superstar2.c
@@ -45,13 +45,13 @@ static gps_mask_t superstar2_msg_ephemeris(struct gps_device_t *,
/*
* These methods may be called elsewhere in gpsd
*/
-static ssize_t superstar2_control_send(struct gps_device_t *, char *, size_t );
+static ssize_t superstar2_control_send(struct gps_device_t *, char *, size_t);
static void superstar2_probe_wakeup(struct gps_device_t *);
-static void superstar2_configurator(struct gps_device_t *, unsigned int );
+static void superstar2_configurator(struct gps_device_t *,
+ event_t, unsigned int);
static bool superstar2_set_speed(struct gps_device_t *, speed_t, char, int);
-static void superstar2_set_mode(struct gps_device_t *, int );
+static void superstar2_set_mode(struct gps_device_t *, int);
static void superstar2_probe_wakeup(struct gps_device_t *);
-static void superstar2_probe_subtype(struct gps_device_t *, unsigned int );
static ssize_t superstar2_write(struct gps_device_t *, char *, size_t);
@@ -517,37 +517,33 @@ superstar2_probe_wakeup(struct gps_device_t *session)
return;
}
-static void
-superstar2_probe_subtype(struct gps_device_t *session,
- unsigned int seq)
-{
- if (seq == 0)
- (void)superstar2_write(session, version_msg, sizeof(version_msg));
- return;
-}
-
static void superstar2_configurator(struct gps_device_t *session,
+ event_t event,
unsigned int seq)
{
- /*@ +charint @*/
- char svinfo_msg[] = {0x01, 0xa1, 0x5e, 0x00, 0x00, 0x01};
- char timing_msg[] = {0x01, 0xf1, 0x0e, 0x00, 0x00, 0x01};
- char navsol_lla_msg[] = {0x01, 0x94, 0x6b, 0x00, 0x00, 0x01};
- char ephemeris_msg[] = {0x01, 0x96, 0x69, 0x00, 0x00, 0x01};
- char measurement_msg[] = {0x01, 0x97, 0x68, 0x01, 0x00, 0x01, 0x01};
- /*@ -charint @*/
-
if (seq != 0)
return;
- (void)superstar2_write(session, timing_msg, sizeof(timing_msg));
- (void)superstar2_write(session, measurement_msg, sizeof(measurement_msg));
- (void)superstar2_write(session, svinfo_msg, sizeof(svinfo_msg));
- (void)superstar2_write(session, navsol_lla_msg, sizeof(navsol_lla_msg));
- (void)superstar2_write(session, version_msg, sizeof(version_msg));
- (void)superstar2_write(session, ephemeris_msg, sizeof(ephemeris_msg));
- (void)superstar2_write(session, iono_utc_msg, sizeof(iono_utc_msg));
- session->driver.superstar2.last_iono = time(NULL);
+ if (event == event_configure) {
+ /*@ +charint @*/
+ char svinfo_msg[] = {0x01, 0xa1, 0x5e, 0x00, 0x00, 0x01};
+ char timing_msg[] = {0x01, 0xf1, 0x0e, 0x00, 0x00, 0x01};
+ char navsol_lla_msg[] = {0x01, 0x94, 0x6b, 0x00, 0x00, 0x01};
+ char ephemeris_msg[] = {0x01, 0x96, 0x69, 0x00, 0x00, 0x01};
+ char measurement_msg[] = {0x01, 0x97, 0x68, 0x01, 0x00, 0x01, 0x01};
+ /*@ -charint @*/
+
+ (void)superstar2_write(session, timing_msg, sizeof(timing_msg));
+ (void)superstar2_write(session, measurement_msg, sizeof(measurement_msg));
+ (void)superstar2_write(session, svinfo_msg, sizeof(svinfo_msg));
+ (void)superstar2_write(session, navsol_lla_msg, sizeof(navsol_lla_msg));
+ (void)superstar2_write(session, version_msg, sizeof(version_msg));
+ (void)superstar2_write(session, ephemeris_msg, sizeof(ephemeris_msg));
+ (void)superstar2_write(session, iono_utc_msg, sizeof(iono_utc_msg));
+ session->driver.superstar2.last_iono = time(NULL);
+ }
+ if (event == event_probe_subtype)
+ (void)superstar2_write(session, version_msg, sizeof(version_msg));
}
/*
@@ -638,8 +634,6 @@ const struct gps_type_t superstar2_binary = {
.probe_detect = NULL,
/* Wakeup to be done before each baud hunt */
.probe_wakeup = superstar2_probe_wakeup,
- /* Initialize the device and get subtype */
- .probe_subtype = superstar2_probe_subtype,
/* Packet getter (using default routine) */
.get_packet = generic_get,
/* Parse message packets */
diff --git a/driver_tsip.c b/driver_tsip.c
index e021921f..a6275338 100644
--- a/driver_tsip.c
+++ b/driver_tsip.c
@@ -51,38 +51,6 @@ static int tsip_write(struct gps_device_t *session,
return 0;
}
-static void tsip_probe_subtype(struct gps_device_t *session, unsigned int seq)
-{
- unsigned char buf[100];
-
- switch (seq) {
- case 0:
- /* TSIP is ODD parity 1 stopbit, save original values and change it */
- /* XXX Thunderbolts and Copernicus use 8N1... which isn't exactly a */
- /* XXX good idea due to the fragile wire format. We must divine a */
- /* XXX clever heuristic to decide if the parity change is required. */
- session->driver.tsip.parity = session->gpsdata.dev.parity;
- session->driver.tsip.stopbits = (uint)session->gpsdata.dev.stopbits;
- gpsd_set_speed(session, session->gpsdata.dev.baudrate, 'O', 1);
- break;
-
- case 1:
- /* Request Software Versions */
- (void)tsip_write(session, 0x1f, NULL, 0);
- /* Request Current Time */
- (void)tsip_write(session, 0x21, NULL, 0);
- /* Request GPS Systems Message */
- (void)tsip_write(session, 0x28, NULL, 0);
- /* Request Current Datum Values */
- putbyte(buf,0,0x15);
- (void)tsip_write(session, 0x8e, buf, 1);
- /* Request Navigation Configuration */
- putbyte(buf,0,0x03);
- (void)tsip_write(session, 0xbb, buf, 1);
- break;
- }
-}
-
static void tsip_wrapup(struct gps_device_t *session)
{
/* restore saved parity and stopbits when leaving TSIP mode */
@@ -795,9 +763,11 @@ static ssize_t tsip_control_send(struct gps_device_t *session,
#endif /* ALLOW_CONTROLSEND */
#ifdef ALLOW_RECONFIGURE
-static void tsip_configurator(struct gps_device_t *session, unsigned int seq)
+static void tsip_configurator(struct gps_device_t *session,
+ event_t event,
+ unsigned int seq)
{
- if (seq == 0) {
+ if (event == event_configure && seq == 0) {
unsigned char buf[100];
/* I/O Options */
@@ -807,6 +777,39 @@ static void tsip_configurator(struct gps_device_t *session, unsigned int seq)
putbyte(buf,3,0x08); /* Aux: dBHz */
(void)tsip_write(session, 0x35, buf, 4);
}
+ if (event == event_probe_subtype && seq == 0) {
+ unsigned char buf[100];
+
+ switch (seq) {
+ case 0:
+ /*
+ * TSIP is ODD parity 1 stopbit, save original values and
+ * change it XXX Thunderbolts and Copernicus use
+ * 8N1... which isn't exactly a XXX good idea due to the
+ * fragile wire format. We must divine a XXX clever
+ * heuristic to decide if the parity change is required.
+ */
+ session->driver.tsip.parity = session->gpsdata.dev.parity;
+ session->driver.tsip.stopbits = (uint)session->gpsdata.dev.stopbits;
+ gpsd_set_speed(session, session->gpsdata.dev.baudrate, 'O', 1);
+ break;
+
+ case 1:
+ /* Request Software Versions */
+ (void)tsip_write(session, 0x1f, NULL, 0);
+ /* Request Current Time */
+ (void)tsip_write(session, 0x21, NULL, 0);
+ /* Request GPS Systems Message */
+ (void)tsip_write(session, 0x28, NULL, 0);
+ /* Request Current Datum Values */
+ putbyte(buf,0,0x15);
+ (void)tsip_write(session, 0x8e, buf, 1);
+ /* Request Navigation Configuration */
+ putbyte(buf,0,0x03);
+ (void)tsip_write(session, 0xbb, buf, 1);
+ break;
+ }
+ }
}
static bool tsip_speed_switch(struct gps_device_t *session,
@@ -901,7 +904,6 @@ const struct gps_type_t tsip_binary =
.channels = TSIP_CHANNELS, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
.probe_detect = NULL, /* no probe */
- .probe_subtype = tsip_probe_subtype, /* no more subtype discovery */
.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 */
diff --git a/driver_ubx.c b/driver_ubx.c
index 9ee3f7cb..347629de 100644
--- a/driver_ubx.c
+++ b/driver_ubx.c
@@ -568,47 +568,49 @@ static ssize_t ubx_control_send(struct gps_device_t *session, char *msg, size_t
#endif /* ALLOW_CONTROLSEND */
#ifdef ALLOW_RECONFIGURE
-static void ubx_configure(struct gps_device_t *session, unsigned int seq)
+static void ubx_configure(struct gps_device_t *session,
+ event_t event, unsigned int seq)
{
- unsigned char msg[32];
-
- gpsd_report(LOG_IO, "UBX configure: %d\n",seq);
-
- (void)ubx_write(session, 0x06u, 0x00, NULL, 0); /* get this port's settings */
-
- /*@ -type @*/
- msg[0] = 0x03; /* SBAS mode enabled, accept testbed mode */
- msg[1] = 0x07; /* SBAS usage: range, differential corrections and integrity */
- msg[2] = 0x03; /* use the maximun search range: 3 channels */
- msg[3] = 0x00; /* PRN numbers to search for all set to 0 => auto scan */
- msg[4] = 0x00;
- msg[5] = 0x00;
- msg[6] = 0x00;
- msg[7] = 0x00;
- (void)ubx_write(session, 0x06u, 0x16, msg, 8);
-
- msg[0] = 0x01; /* class */
- msg[1] = 0x04; /* msg id = UBX_NAV_DOP */
- msg[2] = 0x01; /* rate */
- (void)ubx_write(session, 0x06u, 0x01, msg, 3);
- msg[0] = 0x01; /* class */
- msg[1] = 0x06; /* msg id = NAV-SOL */
- msg[2] = 0x01; /* rate */
- (void)ubx_write(session, 0x06u, 0x01, msg, 3);
- msg[0] = 0x01; /* class */
- msg[1] = 0x20; /* msg id = UBX_NAV_TIMEGPS */
- msg[2] = 0x01; /* rate */
- (void)ubx_write(session, 0x06u, 0x01, msg, 3);
- msg[0] = 0x01; /* class */
- msg[1] = 0x30; /* msg id = NAV-SVINFO */
- msg[2] = 0x0a; /* rate */
- (void)ubx_write(session, 0x06u, 0x01, msg, 3);
- msg[0] = 0x01; /* class */
- msg[1] = 0x32; /* msg id = NAV-SBAS */
- msg[2] = 0x0a; /* rate */
- (void)ubx_write(session, 0x06u, 0x01, msg, 3);
- /*@ +type @*/
-
+ if (event == event_configure) {
+ unsigned char msg[32];
+
+ gpsd_report(LOG_IO, "UBX configure: %d\n",seq);
+
+ (void)ubx_write(session, 0x06u, 0x00, NULL, 0); /* get this port's settings */
+
+ /*@ -type @*/
+ msg[0] = 0x03; /* SBAS mode enabled, accept testbed mode */
+ msg[1] = 0x07; /* SBAS usage: range, differential corrections and integrity */
+ msg[2] = 0x03; /* use the maximun search range: 3 channels */
+ msg[3] = 0x00; /* PRN numbers to search for all set to 0 => auto scan */
+ msg[4] = 0x00;
+ msg[5] = 0x00;
+ msg[6] = 0x00;
+ msg[7] = 0x00;
+ (void)ubx_write(session, 0x06u, 0x16, msg, 8);
+
+ msg[0] = 0x01; /* class */
+ msg[1] = 0x04; /* msg id = UBX_NAV_DOP */
+ msg[2] = 0x01; /* rate */
+ (void)ubx_write(session, 0x06u, 0x01, msg, 3);
+ msg[0] = 0x01; /* class */
+ msg[1] = 0x06; /* msg id = NAV-SOL */
+ msg[2] = 0x01; /* rate */
+ (void)ubx_write(session, 0x06u, 0x01, msg, 3);
+ msg[0] = 0x01; /* class */
+ msg[1] = 0x20; /* msg id = UBX_NAV_TIMEGPS */
+ msg[2] = 0x01; /* rate */
+ (void)ubx_write(session, 0x06u, 0x01, msg, 3);
+ msg[0] = 0x01; /* class */
+ msg[1] = 0x30; /* msg id = NAV-SVINFO */
+ msg[2] = 0x0a; /* rate */
+ (void)ubx_write(session, 0x06u, 0x01, msg, 3);
+ msg[0] = 0x01; /* class */
+ msg[1] = 0x32; /* msg id = NAV-SBAS */
+ msg[2] = 0x0a; /* rate */
+ (void)ubx_write(session, 0x06u, 0x01, msg, 3);
+ /*@ +type @*/
+ }
}
static void ubx_revert(struct gps_device_t *session)
@@ -726,7 +728,6 @@ const struct gps_type_t ubx_binary = {
.channels = 50, /* Number of satellite channels supported by the device */
.probe_detect = NULL, /* Startup-time device detector */
.probe_wakeup = NULL, /* Wakeup to be done before each baud hunt */
- .probe_subtype = NULL, /* Initialize the device and get subtype */
.get_packet = generic_get, /* Packet getter (using default routine) */
.parse_packet = parse_input, /* Parse message packets */
.rtcm_writer = NULL, /* RTCM handler (using default routine) */
diff --git a/driver_zodiac.c b/driver_zodiac.c
index 0956038c..10d2e6c7 100644
--- a/driver_zodiac.c
+++ b/driver_zodiac.c
@@ -498,7 +498,6 @@ const struct gps_type_t zodiac_binary =
.channels = 12, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no probe on baud rate change */
.probe_detect = NULL, /* no probe */
- .probe_subtype = NULL, /* no initialization */
.get_packet = generic_get, /* use the generic packet getter */
.parse_packet = zodiac_analyze, /* parse message packets */
.rtcm_writer = zodiac_send_rtcm, /* send DGPS correction */
diff --git a/drivers.c b/drivers.c
index 7ad100b9..eb4d1218 100644
--- a/drivers.c
+++ b/drivers.c
@@ -111,105 +111,108 @@ gps_mask_t nmea_parse_input(struct gps_device_t *session)
}
}
-static void nmea_probe_subtype(struct gps_device_t *session, unsigned int seq)
+static void nmea_configurator(struct gps_device_t *session,
+ event_t event, unsigned int seq)
{
- /* change this guard if the probe count goes up */
- if (seq <= 8)
- gpsd_report(LOG_WARN, "=> Probing device subtype %d\n", seq);
- /*
- * The reason for splitting these probes up by packet sequence
- * number, interleaving them with the first few packet receives,
- * is because many generic-NMEA devices get confused if you send
- * too much at them in one go.
- *
- * A fast response to an early probe will change drivers so the
- * later ones won't be sent at all. Thus, for best overall
- * performance, order these to probe for the most popular types
- * soonest.
- *
- * Note: don't make the trigger strings identical to the probe,
- * because some NMEA devices (notably SiRFs) will just echo
- * unknown strings right back at you. A useful dodge is to append
- * a comma to the trigger, because that won't be in the response
- * unless there is actual following data.
- */
- switch (seq) {
-#ifdef SIRF_ENABLE
- case 0:
- /* probe for Garmin serial GPS -- expect $PGRMC followed by data*/
- (void)nmea_send(session, "$PGRMCE");
- break;
-#endif /* SIRF_ENABLE */
-#ifdef NMEA_ENABLE
- case 1:
+ if (event == event_probe_subtype) {
+ /* change this guard if the probe count goes up */
+ if (seq <= 8)
+ gpsd_report(LOG_WARN, "=> Probing device subtype %d\n", seq);
/*
- * We used to try to probe for SiRF by issuing "$PSRF105,1"
- * and expecting "$Ack Input105.". But it turns out this
- * only works for SiRF-IIs; SiRF-I and SiRF-III don't respond.
- * Thus the only reliable probe is to try to flip the SiRF into
- * binary mode, cluing in the library to revert it on close.
+ * The reason for splitting these probes up by packet sequence
+ * number, interleaving them with the first few packet receives,
+ * is because many generic-NMEA devices get confused if you send
+ * too much at them in one go.
+ *
+ * A fast response to an early probe will change drivers so the
+ * later ones won't be sent at all. Thus, for best overall
+ * performance, order these to probe for the most popular types
+ * soonest.
*
- * SiRFs dominate the GPS-mouse market, so we used to put this test
- * first. Unfortunately this causes problems for gpsctl, as it cannot
- * select the NMEA driver without switching the device back to
- * binary mode! Fix this if we ever find a nondisruptive probe string.
+ * Note: don't make the trigger strings identical to the probe,
+ * because some NMEA devices (notably SiRFs) will just echo
+ * unknown strings right back at you. A useful dodge is to append
+ * a comma to the trigger, because that won't be in the response
+ * unless there is actual following data.
*/
- (void)nmea_send(session,
- "$PSRF100,0,%d,%d,%d,0",
- session->gpsdata.dev.baudrate,
- 9-session->gpsdata.dev.stopbits,
- session->gpsdata.dev.stopbits);
- session->back_to_nmea = true;
- break;
- case 2:
- /* probe for the FV-18 -- expect $PFEC,GPint followed by data */
- (void)nmea_send(session, "$PFEC,GPint");
- break;
- case 3:
- /* probe for the Trimble Copernicus */
- (void)nmea_send(session, "$PTNLSNM,0139,01");
- break;
+ switch (seq) {
+#ifdef SIRF_ENABLE
+ case 0:
+ /* probe for Garmin serial GPS -- expect $PGRMC followed by data*/
+ (void)nmea_send(session, "$PGRMCE");
+ break;
+#endif /* SIRF_ENABLE */
+#ifdef NMEA_ENABLE
+ case 1:
+ /*
+ * We used to try to probe for SiRF by issuing "$PSRF105,1"
+ * and expecting "$Ack Input105.". But it turns out this
+ * only works for SiRF-IIs; SiRF-I and SiRF-III don't respond.
+ * Thus the only reliable probe is to try to flip the SiRF into
+ * binary mode, cluing in the library to revert it on close.
+ *
+ * SiRFs dominate the GPS-mouse market, so we used to put this test
+ * first. Unfortunately this causes problems for gpsctl, as it cannot
+ * select the NMEA driver without switching the device back to
+ * binary mode! Fix this if we ever find a nondisruptive probe string.
+ */
+ (void)nmea_send(session,
+ "$PSRF100,0,%d,%d,%d,0",
+ session->gpsdata.dev.baudrate,
+ 9-session->gpsdata.dev.stopbits,
+ session->gpsdata.dev.stopbits);
+ session->back_to_nmea = true;
+ break;
+ case 2:
+ /* probe for the FV-18 -- expect $PFEC,GPint followed by data */
+ (void)nmea_send(session, "$PFEC,GPint");
+ break;
+ case 3:
+ /* probe for the Trimble Copernicus */
+ (void)nmea_send(session, "$PTNLSNM,0139,01");
+ break;
#endif /* NMEA_ENABLE */
#ifdef EVERMORE_ENABLE
- case 4:
- /* Enable checksum and GGA(1s), GLL(0s), GSA(1s), GSV(1s), RMC(1s), VTG(0s), PEMT101(1s) */
- /* EverMore will reply with: \x10\x02\x04\x38\x8E\xC6\x10\x03 */
- (void)gpsd_write(session,
- "\x10\x02\x12\x8E\x7F\x01\x01\x00\x01\x01\x01\x00\x01\x00\x00\x00\x00\x00\x00\x13\x10\x03", 22);
- break;
+ case 4:
+ /* Enable checksum and GGA(1s), GLL(0s), GSA(1s), GSV(1s), RMC(1s), VTG(0s), PEMT101(1s) */
+ /* EverMore will reply with: \x10\x02\x04\x38\x8E\xC6\x10\x03 */
+ (void)gpsd_write(session,
+ "\x10\x02\x12\x8E\x7F\x01\x01\x00\x01\x01\x01\x00\x01\x00\x00\x00\x00\x00\x00\x13\x10\x03", 22);
+ break;
#endif /* EVERMORE_ENABLE */
#ifdef ITRAX_ENABLE
- case 5:
- /* probe for iTrax, looking for "$PFST,OK" */
- (void)nmea_send(session, "$PFST");
- break;
+ case 5:
+ /* probe for iTrax, looking for "$PFST,OK" */
+ (void)nmea_send(session, "$PFST");
+ break;
#endif /* ITRAX_ENABLE */
#ifdef GPSCLOCK_ENABLE
- case 6:
- /* probe for Furuno Electric GH-79L4-N (GPSClock); expect $PFEC,GPssd */
- (void)nmea_send(session, "$PFEC,GPsrq");
- break;
+ case 6:
+ /* probe for Furuno Electric GH-79L4-N (GPSClock); expect $PFEC,GPssd */
+ (void)nmea_send(session, "$PFEC,GPsrq");
+ break;
#endif /* GPSCLOCK_ENABLE */
#ifdef ASHTECH_ENABLE
- case 7:
- /* probe for Ashtech -- expect $PASHR,RID */
- (void)nmea_send(session, "$PASHQ,RID");
- break;
+ case 7:
+ /* probe for Ashtech -- expect $PASHR,RID */
+ (void)nmea_send(session, "$PASHQ,RID");
+ break;
#endif /* ASHTECH_ENABLE */
#ifdef UBX_ENABLE
- case 8:
- /* probe for UBX -- query software version */
- (void)ubx_write(session, 0x0au, 0x04, NULL, 0);
- break;
+ case 8:
+ /* probe for UBX -- query software version */
+ (void)ubx_write(session, 0x0au, 0x04, NULL, 0);
+ break;
#endif /* UBX_ENABLE */
#ifdef MKT3301_ENABLE
- case 9:
- /* probe for MKT-3301 -- expect $PMTK705 */
- (void)nmea_send(session, "$PMTK605");
- break;
+ case 9:
+ /* probe for MKT-3301 -- expect $PMTK705 */
+ (void)nmea_send(session, "$PMTK605");
+ break;
#endif /* MKT3301_ENABLE */
- default:
- break;
+ default:
+ break;
+ }
}
}
@@ -220,7 +223,6 @@ const struct gps_type_t nmea = {
.channels = 12, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
.probe_detect = NULL, /* no probe */
- .probe_subtype = nmea_probe_subtype, /* probe for special types */
.get_packet = generic_get, /* use generic packet getter */
.parse_packet = nmea_parse_input, /* how to interpret a packet */
.rtcm_writer = pass_rtcm, /* write RTCM data straight */
@@ -228,7 +230,7 @@ const struct gps_type_t nmea = {
.control_send = nmea_write, /* how to send control strings */
#endif /* ALLOW_CONTROLSEND */
#ifdef ALLOW_RECONFIGURE
- .configurator = NULL, /* enable what we need */
+ .configurator = nmea_configurator, /* enable what we need */
.speed_switcher = NULL, /* no speed switcher */
.mode_switcher = NULL, /* no mode switcher */
.rate_switcher = NULL, /* no sample-rate switcher */
@@ -257,47 +259,50 @@ static void garmin_mode_switch(struct gps_device_t *session, int mode)
}
}
-static void garmin_nmea_configurator(struct gps_device_t *session, unsigned int seq)
+static void garmin_nmea_configurator(struct gps_device_t *session,
+ event_t event, unsigned int seq)
{
- /*
- * Receivers like the Garmin GPS-10 don't handle having having a lot of
- * probes shoved at them very well.
- */
- switch (seq) {
- case 0:
- /* reset some config, AutoFix, WGS84, PPS
- * Set the PPS pulse length to 40ms which leaves the Garmin 18-5hz
- * with a 160ms low state.
- * NOTE: new PPS only takes effect after next power cycle
- */
- (void)nmea_send(session, "$PGRMC,A,,100,,,,,,A,,1,2,1,30");
- break;
- case 1:
- /* once a sec, no averaging, NMEA 2.3, WAAS */
- (void)nmea_send(session, "$PGRMC1,1,1,1,,,,2,W,N");
- break;
- case 2:
- /* get some more config info */
- (void)nmea_send(session, "$PGRMC1E");
- break;
- case 3:
- /* turn off all output except GGA */
- (void)nmea_send(session, "$PGRMO,,2");
- (void)nmea_send(session, "$PGRMO,GPGGA,1");
- break;
- case 4:
- /* enable GPGGA, GPGSA, GPGSV, GPRMC on Garmin serial GPS */
- (void)nmea_send(session, "$PGRMO,GPGSA,1");
- break;
- case 5:
- (void)nmea_send(session, "$PGRMO,GPGSV,1");
- break;
- case 6:
- (void)nmea_send(session, "$PGRMO,GPRMC,1");
- break;
- case 7:
- (void)nmea_send(session, "$PGRMO,PGRME,1");
- break;
+ if (event == event_configure) {
+ /*
+ * Receivers like the Garmin GPS-10 don't handle having having a lot of
+ * probes shoved at them very well.
+ */
+ switch (seq) {
+ case 0:
+ /* reset some config, AutoFix, WGS84, PPS
+ * Set the PPS pulse length to 40ms which leaves the Garmin 18-5hz
+ * with a 160ms low state.
+ * NOTE: new PPS only takes effect after next power cycle
+ */
+ (void)nmea_send(session, "$PGRMC,A,,100,,,,,,A,,1,2,1,30");
+ break;
+ case 1:
+ /* once a sec, no averaging, NMEA 2.3, WAAS */
+ (void)nmea_send(session, "$PGRMC1,1,1,1,,,,2,W,N");
+ break;
+ case 2:
+ /* get some more config info */
+ (void)nmea_send(session, "$PGRMC1E");
+ break;
+ case 3:
+ /* turn off all output except GGA */
+ (void)nmea_send(session, "$PGRMO,,2");
+ (void)nmea_send(session, "$PGRMO,GPGGA,1");
+ break;
+ case 4:
+ /* enable GPGGA, GPGSA, GPGSV, GPRMC on Garmin serial GPS */
+ (void)nmea_send(session, "$PGRMO,GPGSA,1");
+ break;
+ case 5:
+ (void)nmea_send(session, "$PGRMO,GPGSV,1");
+ break;
+ case 6:
+ (void)nmea_send(session, "$PGRMO,GPRMC,1");
+ break;
+ case 7:
+ (void)nmea_send(session, "$PGRMO,PGRME,1");
+ break;
+ }
}
}
#endif /* ALLOW_RECONFIGURE */
@@ -309,7 +314,6 @@ const struct gps_type_t garmin = {
.channels = 12, /* not used by this driver */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
.probe_detect = NULL, /* no probe */
- .probe_subtype = NULL, /* no further querying */
.get_packet = generic_get, /* use generic packet getter */
.parse_packet = nmea_parse_input, /* how to interpret a packet */
.rtcm_writer = NULL, /* some do, some don't, skip for now */
@@ -336,9 +340,10 @@ const struct gps_type_t garmin = {
**************************************************************************/
#ifdef ALLOW_RECONFIGURE
-static void ashtech_configure(struct gps_device_t *session, unsigned int seq)
+static void ashtech_configure(struct gps_device_t *session,
+ event_t event, unsigned int seq)
{
- if (seq == 0){
+ if (event == event_configure && seq == 0){
/* turn WAAS on. can't hurt... */
(void)nmea_send(session, "$PASHS,WAS,ON");
/* reset to known output state */
@@ -371,7 +376,6 @@ const struct gps_type_t ashtech = {
.channels = 24, /* not used, GG24 has 24 channels */
.probe_wakeup = ashtech_ping, /* wakeup to be done before hunt */
.probe_detect = NULL, /* no probe */
- .probe_subtype = NULL, /* to be sent unconditionally */
.get_packet = generic_get, /* how to get a packet */
.parse_packet = nmea_parse_input, /* how to interpret a packet */
.rtcm_writer = pass_rtcm, /* write RTCM data straight */
@@ -398,13 +402,14 @@ const struct gps_type_t ashtech = {
**************************************************************************/
#ifdef ALLOW_RECONFIGURE
-static void fv18_configure(struct gps_device_t *session, unsigned int seq)
+static void fv18_configure(struct gps_device_t *session,
+ event_t event, unsigned int seq)
{
/*
* Tell an FV18 to send GSAs so we'll know if 3D is accurate.
* Suppress GLL and VTG. Enable ZDA so dates will be accurate for replay.
*/
- if (seq == 0)
+ if (event == event_configure && seq == 0)
(void)nmea_send(session,
"$PFEC,GPint,GSA01,DTM00,ZDA01,RMC01,GLL00,VTG00,GSV05");
}
@@ -417,7 +422,6 @@ const struct gps_type_t fv18 = {
.channels = 12, /* not used by this driver */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
.probe_detect = NULL, /* no probe */
- .probe_subtype = NULL, /* to be sent unconditionally */
.get_packet = generic_get, /* how to get a packet */
.parse_packet = nmea_parse_input, /* how to interpret a packet */
.rtcm_writer = pass_rtcm, /* write RTCM data straight */
@@ -447,13 +451,14 @@ const struct gps_type_t fv18 = {
* Based on http://www.tecsys.de/fileadmin/user_upload/pdf/gh79_1an_intant.pdf
*/
-static void gpsclock_probe_subtype(struct gps_device_t *session, unsigned int seq)
+static void gpsclock_configurator(struct gps_device_t *session,
+ event_t event, unsigned int seq)
{
/*
* Michael St. Laurent <mikes@hartwellcorp.com> reports that you have to
* ignore the trailing PPS edge when extracting time from this chip.
*/
- if (seq == 0) {
+ if (event == event_probe_subtype && seq == 0) {
gpsd_report(LOG_INF, "PPS trailing edge will be ignored");
session->driver.nmea.ignore_trailing_edge = true;
}
@@ -466,7 +471,6 @@ const struct gps_type_t gpsclock = {
.channels = 12, /* not used by this driver */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
.probe_detect = NULL, /* no probe */
- .probe_subtype = gpsclock_probe_subtype, /* to be sent unconditionally */
.get_packet = generic_get, /* how to get a packet */
.parse_packet = nmea_parse_input, /* how to interpret a packet */
.rtcm_writer = pass_rtcm, /* write RTCM data straight */
@@ -474,7 +478,7 @@ const struct gps_type_t gpsclock = {
.control_send = nmea_write, /* how to send control strings */
#endif /* ALLOW_CONTROLSEND */
#ifdef ALLOW_RECONFIGURE
- .configurator = NULL, /* change its sentence set */
+ .configurator = gpsclock_configurator, /* change its sentence set */
.speed_switcher = NULL, /* no speed switcher */
.mode_switcher = NULL, /* no mode switcher */
.rate_switcher = NULL, /* sample rate is fixed */
@@ -500,19 +504,16 @@ const struct gps_type_t gpsclock = {
* and was replaced by the Zodiac EarthMate.
*/
-static void tripmate_probe_subtype(struct gps_device_t *session, unsigned int seq)
-{
- /* TripMate requires this response to the ASTRAL it sends at boot time */
- if (seq == 0)
- (void)nmea_send(session, "$IIGPQ,ASTRAL");
-}
-
#ifdef ALLOW_RECONFIGURE
-static void tripmate_configurator(struct gps_device_t *session, unsigned int seq)
+static void tripmate_configurator(struct gps_device_t *session,
+ event_t event, unsigned int seq)
{
/* stop it sending PRWIZCH */
- if (seq == 0)
+ if (event == event_configure && seq == 0)
(void)nmea_send(session, "$PRWIILOG,ZCH,V,,");
+ /* TripMate requires this response to the ASTRAL it sends at boot time */
+ if (event == event_probe_subtype && seq == 0)
+ (void)nmea_send(session, "$IIGPQ,ASTRAL");
}
#endif /* ALLOW_RECONFIGURE */
@@ -523,7 +524,6 @@ static const struct gps_type_t tripmate = {
.channels = 12, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no wakeup before hunt */
.probe_detect = NULL, /* no probe */
- .probe_subtype = tripmate_probe_subtype, /* send unconditionally */
.get_packet = generic_get, /* how to get a packet */
.parse_packet = nmea_parse_input, /* how to interpret a packet */
.rtcm_writer = pass_rtcm, /* send RTCM data straight */
@@ -553,9 +553,10 @@ static const struct gps_type_t tripmate = {
*
**************************************************************************/
-static void earthmate_probe_subtype(struct gps_device_t *session, unsigned int seq)
+static void earthmate_configurator(struct gps_device_t *session,
+ event_t event, unsigned int seq)
{
- if (seq == 0) {
+ if (event == event_probe_subtype && seq == 0) {
(void)gpsd_write(session, "EARTHA\r\n", 8);
(void)usleep(10000);
(void)gpsd_switch_driver(session, "Zodiac Binary");
@@ -570,7 +571,6 @@ static const struct gps_type_t earthmate = {
.channels = 12, /* not used by NMEA parser */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
.probe_detect = NULL, /* no probe */
- .probe_subtype = earthmate_probe_subtype, /* switch us to Zodiac mode */
.get_packet = generic_get, /* how to get a packet */
.parse_packet = nmea_parse_input, /* how to interpret a packet */
.rtcm_writer = NULL, /* don't send RTCM data */
@@ -578,7 +578,7 @@ static const struct gps_type_t earthmate = {
.control_send = nmea_write, /* how to send control strings */
#endif /* ALLOW_CONTROLSEND */
#ifdef ALLOW_RECONFIGURE
- .configurator = NULL, /* no configuration here */
+ .configurator = earthmate_configurator, /* no configuration here */
.speed_switcher= NULL, /* no speed switcher */
.mode_switcher = NULL, /* no mode switcher */
.rate_switcher = NULL, /* no sample-rate switcher */
@@ -686,17 +686,20 @@ static int tnt_packet_sniff(struct gps_device_t *session)
return BAD_PACKET;
}
-static void tnt_probe_subtype(struct gps_device_t *session, unsigned int seq UNUSED)
+static void tnt_configurator(struct gps_device_t *session,
+ event_t event, unsigned int seq)
{
- // Send codes to start the flow of data
- //tnt_send(session->gpsdata.gps_fd, "@BA?"); // Query current rate
- //tnt_send(session->gpsdata.gps_fd, "@BA=8"); // Start HTM packet at 1Hz
- /*
- * Sending this twice seems to make it more reliable!!
- * I think it gets the input on the unit synced up.
- */
- (void)tnt_send(session->gpsdata.gps_fd, "@BA=15"); // Start HTM packet at 1200 per minute
- (void)tnt_send(session->gpsdata.gps_fd, "@BA=15"); // Start HTM packet at 1200 per minute
+ if (event == event_probe_subtype && seq == 0) {
+ // Send codes to start the flow of data
+ //tnt_send(session->gpsdata.gps_fd, "@BA?"); // Query current rate
+ //tnt_send(session->gpsdata.gps_fd, "@BA=8"); // Start HTM packet at 1Hz
+ /*
+ * Sending this twice seems to make it more reliable!!
+ * I think it gets the input on the unit synced up.
+ */
+ (void)tnt_send(session->gpsdata.gps_fd, "@BA=15"); // Start HTM packet at 1200 per minute
+ (void)tnt_send(session->gpsdata.gps_fd, "@BA=15"); // Start HTM packet at 1200 per minute
+ }
}
static bool tnt_probe(struct gps_device_t *session)
@@ -745,7 +748,6 @@ static const struct gps_type_t trueNorth = {
.channels = 0, /* not an actual GPS at all */
.probe_wakeup = NULL, /* this will become a real method */
.probe_detect = tnt_probe, /* probe by sending ID query */
- .probe_subtype = tnt_probe_subtype,/* probe for True North Digital Compass */
.get_packet = generic_get, /* how to get a packet */
.parse_packet = nmea_parse_input, /* how to interpret a packet */
.rtcm_writer = NULL, /* Don't send */
@@ -753,7 +755,7 @@ static const struct gps_type_t trueNorth = {
.control_send = nmea_write, /* how to send control strings */
#endif /* ALLOW_CONTROLSEND */
#ifdef ALLOW_RECONFIGURE
- .configurator = NULL, /* no setting changes */
+ .configurator = tnt_configurator, /* no setting changes */
.speed_switcher = NULL, /* no speed switcher */
.mode_switcher = NULL, /* no mode switcher */
.rate_switcher = NULL, /* no wrapup */
@@ -818,7 +820,6 @@ static const struct gps_type_t oceanServer = {
.channels = 0, /* not an actual GPS at all */
.probe_wakeup = NULL,
.probe_detect = NULL,
- .probe_subtype = NULL,
.get_packet = generic_get, /* how to get a packet */
.parse_packet = nmea_parse_input, /* how to interpret a packet */
.rtcm_writer = NULL, /* Don't send */
@@ -861,7 +862,6 @@ static const struct gps_type_t rtcm104v2 = {
.channels = 0, /* not used */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
.probe_detect = NULL, /* no probe */
- .probe_subtype = NULL, /* no subtypes */
.get_packet = generic_get, /* how to get a packet */
.parse_packet = rtcm104v2_analyze, /* */
.rtcm_writer = NULL, /* don't send RTCM data, */
@@ -904,7 +904,6 @@ static const struct gps_type_t rtcm104v3 = {
.channels = 0, /* not used */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
.probe_detect = NULL, /* no probe */
- .probe_subtype = NULL, /* no subtypes */
.get_packet = generic_get, /* how to get a packet */
.parse_packet = rtcm104v3_analyze, /* */
.rtcm_writer = NULL, /* don't send RTCM data, */
@@ -944,7 +943,6 @@ static const struct gps_type_t garmintxt = {
.channels = 0, /* not used */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
.probe_detect = NULL, /* no probe */
- .probe_subtype = NULL, /* no subtypes */
.get_packet = generic_get, /* how to get a packet */
.parse_packet = garmintxt_parse_input, /* */
.rtcm_writer = NULL, /* don't send RTCM data, */
@@ -1000,7 +998,8 @@ gps_mask_t processMKT3301(int c UNUSED, char *field[], struct gps_device_t *sess
}
#ifdef ALLOW_RECONFIGURE
-static void mkt3301_configure(struct gps_device_t *session, unsigned int seq)
+static void mkt3301_configure(struct gps_device_t *session,
+ event_t event, unsigned int seq)
{
/*
0 NMEA_SEN_GLL, GPGLL interval - Geographic Position - Latitude longitude
@@ -1021,7 +1020,7 @@ static void mkt3301_configure(struct gps_device_t *session, unsigned int seq)
"$PMTK314,1,1,1,1,1,5,1,1,0,0,0,0,0,0,0,0,0,1,0"
*/
- if(seq == 0) {
+ if(event == event_configure && seq == 0) {
(void)nmea_send(session,"$PMTK320,0"); /* power save off */
(void)nmea_send(session,"$PMTK300,1000,0,0,0.0,0.0"); /* Fix interval */
(void)nmea_send(session,"$PMTK314,0,1,0,1,1,5,1,1,0,0,0,0,0,0,0,0,0,1,0");
@@ -1038,7 +1037,6 @@ const struct gps_type_t mkt3301 = {
.channels = 12, /* not used by this driver */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
.probe_detect = NULL, /* no probe */
- .probe_subtype = NULL, /* to be sent unconditionally */
.get_packet = generic_get, /* how to get a packet */
.parse_packet = nmea_parse_input, /* how to interpret a packet */
.rtcm_writer = pass_rtcm, /* write RTCM data straight */
@@ -1089,8 +1087,6 @@ static const struct gps_type_t aivdm = {
.probe_detect = NULL,
/* Wakeup to be done before each baud hunt */
.probe_wakeup = NULL,
- /* Initialize the device and get subtype */
- .probe_subtype = NULL,
/* Packet getter (using default routine) */
.get_packet = generic_get,
/* Parse message packets */
diff --git a/gpsd.h-tail b/gpsd.h-tail
index 70a4ca38..4d57cb9e 100644
--- a/gpsd.h-tail
+++ b/gpsd.h-tail
@@ -193,6 +193,7 @@ struct gps_device_t;
#define MODE_BINARY 1
typedef enum {ANY, GPS, RTCM2, RTCM3, AIS} gnss_type;
+typedef enum {event_configure, event_probe_subtype} event_t;
struct gps_type_t {
/* GPS method table, describes how to talk to a particular GPS type */
@@ -202,7 +203,6 @@ struct gps_type_t {
int channels;
/*@null@*/bool (*probe_detect)(struct gps_device_t *session);
/*@null@*/void (*probe_wakeup)(struct gps_device_t *session);
- /*@null@*/void (*probe_subtype)(struct gps_device_t *session, unsigned int seq);
/*@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, char *rtcmbuf, size_t rtcmbytes);
@@ -210,7 +210,8 @@ struct gps_type_t {
/*@null@*/ssize_t (*control_send)(struct gps_device_t *session, char *buf, size_t buflen);
#endif /* ALLOW_CONTROLSEND */
#ifdef ALLOW_RECONFIGURE
- /*@null@*/void (*configurator)(struct gps_device_t *session, unsigned int seq);
+ /*@null@*/void (*configurator)(struct gps_device_t *session,
+ event_t event, unsigned int seq);
/*@null@*/bool (*speed_switcher)(struct gps_device_t *session,
speed_t speed, char parity, int stopbits);
/*@null@*/void (*mode_switcher)(struct gps_device_t *session, int mode);
diff --git a/gpsmon.c b/gpsmon.c
index 738d09e3..5d92ea8d 100644
--- a/gpsmon.c
+++ b/gpsmon.c
@@ -842,7 +842,7 @@ int main (int argc, char **argv)
} else if (matchcount == 1) {
assert(forcetype != NULL);
if (switch_type(forcetype))
- (int)gpsd_switch_driver(&session, forcetype->type_name);
+ (void)gpsd_switch_driver(&session, forcetype->type_name);
} else {
monitor_complain("Multiple driver type names match '%s'.", arg);
}
diff --git a/libgpsd_core.c b/libgpsd_core.c
index 717835bd..a0e7638d 100644
--- a/libgpsd_core.c
+++ b/libgpsd_core.c
@@ -38,7 +38,7 @@ int gpsd_switch_driver(struct gps_device_t *session, char* type_name)
gpsd_report(LOG_PROG, "Reconfiguring for %s...\n", session->device_type->type_name);
if (session->enable_reconfigure
&& session->device_type->configurator != NULL)
- session->device_type->configurator(session, 0);
+ session->device_type->configurator(session, event_configure, 0);
#endif /* ALLOW_RECONFIGURE */
return 0;
}
@@ -50,13 +50,15 @@ int gpsd_switch_driver(struct gps_device_t *session, char* type_name)
gpsd_assert_sync(session);
/*@i@*/session->device_type = *dp;
session->gpsdata.dev.mincycle = session->device_type->min_cycle;
- if (!session->context->readonly && session->device_type->probe_subtype != NULL)
- session->device_type->probe_subtype(session, session->packet.counter = 0);
+ if (!session->context->readonly && session->device_type->configurator != NULL)
+ session->device_type->configurator(session,
+ event_probe_subtype,
+ session->packet.counter = 0);
#ifdef ALLOW_RECONFIGURE
if (session->enable_reconfigure
&& session->device_type->configurator != NULL) {
gpsd_report(LOG_PROG, "configuring for %s...\n", session->device_type->type_name);
- session->device_type->configurator(session, 0);
+ session->device_type->configurator(session, event_configure, 0);
}
#endif /* ALLOW_RECONFIGURE */
return 1;
@@ -300,12 +302,14 @@ int gpsd_activate(struct gps_device_t *session, bool reconfigurable)
memset(&session->driver, '\0', sizeof(session->driver));
/* if we know the device type, probe for subtype and configure it */
if (session->device_type != NULL) {
- if (!session->context->readonly && session->device_type->probe_subtype !=NULL)
- session->device_type->probe_subtype(session, session->packet.counter = 0);
+ if (!session->context->readonly && session->device_type->configurator !=NULL)
+ session->device_type->configurator(session,
+ event_probe_subtype,
+ session->packet.counter = 0);
#ifdef ALLOW_RECONFIGURE
if (reconfigurable) {
if (session->device_type->configurator != NULL)
- session->device_type->configurator(session, session->packet.counter);
+ session->device_type->configurator(session, event_configure, session->packet.counter);
}
#endif /* ALLOW_RECONFIGURE */
}
@@ -707,8 +711,10 @@ gps_mask_t gpsd_poll(struct gps_device_t *session)
if (session->device_type) {
newlen = session->device_type->get_packet(session);
session->gpsdata.d_xmit_time = timestamp();
- if (session->packet.outbuflen>0 && !session->context->readonly && session->device_type->probe_subtype!=NULL)
- session->device_type->probe_subtype(session, ++session->packet.counter);
+ if (session->packet.outbuflen>0 && !session->context->readonly && session->device_type->configurator!=NULL)
+ session->device_type->configurator(session,
+ event_probe_subtype,
+ ++session->packet.counter);
} else {
const struct gps_type_t **dp;
diff --git a/www/writing-a-driver.xml b/www/writing-a-driver.xml
index d8aeefea..bbeef663 100644
--- a/www/writing-a-driver.xml
+++ b/www/writing-a-driver.xml
@@ -17,6 +17,14 @@
<revhistory>
<revision>
<revnumber>1.8</revnumber>
+ <date>12 Sep 2009</date>
+ <authorinitials>er</authorinitials>
+ <revremark>
+ Updated by esr; cinfigurator and probe_subtype have merged.
+ </revremark>
+ </revision>
+ <revision>
+ <revnumber>1.8</revnumber>
<date>9 Aug 2009</date>
<authorinitials>er</authorinitials>
<revremark>
@@ -597,24 +605,54 @@ document I discuss my work to implement this function.</para>
that wakes up the device when the main auto-baud hunt loop in
the daemon offers a new speed to probe at.</para>
-<para><structfield>.probe_subtype</structfield> points to a block of
-code that will be executed whenever the device-driver type is switched
-(with second argument 0) or whenever a full packet is received (with
-second argument being the sequence number of the packet). It is
-normally used to send probe strings that are expected to elicit a
-later response that will reveal the subtype of the driver. If this
-function fetches driver subtype information immediately, it should
-store information about the software version in member
-<quote><filename>subtype</filename></quote> of the driver data
-structure <userinput>struct gps_device_t *session</userinput>.</para>
-
-<para><structfield>.configurator</structfield> points to a block of code
-that should set up the device to deliver the correct set of sentences
-to supply the parser with the data needed by
-<filename>gpsd</filename>. Like the
-<structfield>.probe_subtype</structfield> method, a second sequence
-number argument allows you to intersperse your configuration sends
-with early packet receipts.</para>
+<para><structfield>.configurator</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. It also gets a scond
+argument which may be a packet sequence number. The configurator hook
+is called in the following circumstances:</para>
+
+<itemizedlist>
+<listitem><para>
+Whenever a call to gpsd_switch_driver() sets a
+device's driver to a different type, with event type
+'event_probe_subtype' and sequence number zero.
+</para></listitem>
+
+<listitem><para>
+Whenever gpsd_switch_driver() is called, with event
+type 'configurator' and sequence number zero, <emphasis>even if no driver
+change occurs</emphasis>. (Thus, when rhe driver type changes, the
+configurator hook is called twice with two different event types. _
+</para></listitem>
+
+<listitem><para>
+When a device is reactivated &mdash; that is, reopened after being
+been cloesed because no clients were listening to it. If the
+device's type is known, the configurator is called with the
+event argument set to 'event_probe_subtype'. Then, if the second
+argument has specified that the device is to be configured, it is
+called again with the even type 'event_configure'. The packet sequence
+number is set to zero and passed to both these calls.
+</para></listitem>
+
+<listitem><para>
+Whenever a full packet is received, with event type 'event_probe_subtype'
+and the second argument being the sequence number of the packet since
+the last driver switch (1 or greater).
+</para></listitem>
+</itemizedlist>
+
+<para>The 'event_probe_subtype' event is normally used to send probe
+strings that are expected to elicit a later response that will reveal
+the subtype of the driver. If this function fetches driver subtype
+information immediately, it should store information about the
+software version in member <quote><filename>subtype</filename></quote>
+of the driver data structure <userinput>struct gps_device_t
+*session</userinput>.</para>
+
+<para>The 'event_configure' event should set up the device to deliver
+the correct set of sentences to supply the parser with the data needed
+by <filename>gpsd</filename>.</para>
<para><structfield>.get_packet</structfield> points to a block of code
that actually gets the packets from the serial stream. You will