diff options
author | Eric S. Raymond <esr@thyrsus.com> | 2009-09-13 03:30:05 +0000 |
---|---|---|
committer | Eric S. Raymond <esr@thyrsus.com> | 2009-09-13 03:30:05 +0000 |
commit | 00cd07ffcaa670709bc492e01d5c97be0262580b (patch) | |
tree | 4f21deae21586a533b279d272d74af3a0899b5e1 | |
parent | bff151b7897e75612f871d44087c6f90cf412b52 (diff) | |
download | gpsd-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.c | 8 | ||||
-rw-r--r-- | driver_garmin.c | 12 | ||||
-rw-r--r-- | driver_italk.c | 12 | ||||
-rw-r--r-- | driver_navcom.c | 8 | ||||
-rw-r--r-- | driver_oncore.c | 21 | ||||
-rw-r--r-- | driver_proto.c | 45 | ||||
-rw-r--r-- | driver_sirf.c | 6 | ||||
-rw-r--r-- | driver_superstar2.c | 56 | ||||
-rw-r--r-- | driver_tsip.c | 72 | ||||
-rw-r--r-- | driver_ubx.c | 83 | ||||
-rw-r--r-- | driver_zodiac.c | 1 | ||||
-rw-r--r-- | drivers.c | 336 | ||||
-rw-r--r-- | gpsd.h-tail | 5 | ||||
-rw-r--r-- | gpsmon.c | 2 | ||||
-rw-r--r-- | libgpsd_core.c | 24 | ||||
-rw-r--r-- | www/writing-a-driver.xml | 74 |
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 */ @@ -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); @@ -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 — 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 |