summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2009-08-10 04:47:03 +0000
committerEric S. Raymond <esr@thyrsus.com>2009-08-10 04:47:03 +0000
commitf002dd431b2506ff7a1cd77545d9bc76edf59bc1 (patch)
treed8dc3b57425d1a5dd6b696f3cefa2760b7de6c1d
parentf17f90e2b520cd11a9aebcef0e6edaeaf12efe16 (diff)
downloadgpsd-f002dd431b2506ff7a1cd77545d9bc76edf59bc1.tar.gz
Abolish device classes.
That way of doing things coped poorly if, for example, NMEA and AIVDM packets were reported over the same wire. Instead, have ach device track the packet types it has actually seen and dispatch on that.
-rw-r--r--driver_evermore.c1
-rw-r--r--driver_garmin.c3
-rw-r--r--driver_italk.c2
-rw-r--r--driver_navcom.c1
-rw-r--r--driver_oncore.c2
-rw-r--r--driver_proto.c2
-rw-r--r--driver_sirf.c1
-rw-r--r--driver_superstar2.c2
-rw-r--r--driver_tsip.c1
-rw-r--r--driver_ubx.c1
-rw-r--r--driver_zodiac.c1
-rw-r--r--drivers.c16
-rw-r--r--gps_json.c2
-rw-r--r--gpsd.c75
-rw-r--r--gpsd.h-tail30
-rw-r--r--gpsd.xml15
-rw-r--r--libgpsd_core.c14
-rw-r--r--www/writing-a-driver.xml16
18 files changed, 98 insertions, 87 deletions
diff --git a/driver_evermore.c b/driver_evermore.c
index 9801dba3..60a8e11d 100644
--- a/driver_evermore.c
+++ b/driver_evermore.c
@@ -515,7 +515,6 @@ const struct gps_type_t evermore_binary =
{
.type_name = "EverMore binary", /* full name of type */
.packet_type = EVERMORE_PACKET, /* lexer packet type */
- .device_class = GPS, /* it's a GPS */
.trigger = "$PEMT,", /* recognize the type */
.channels = EVERMORE_CHANNELS, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
diff --git a/driver_garmin.c b/driver_garmin.c
index 8bfddc2e..008326ec 100644
--- a/driver_garmin.c
+++ b/driver_garmin.c
@@ -1202,7 +1202,6 @@ const struct gps_type_t garmin_usb_binary_old =
{
.type_name = "Garmin USB binary", /* full name of type */
.packet_type = GARMIN_PACKET; /* associated lexer packet type */
- .device_class = GPS, /* it's a GPS */
.trigger = NULL, /* no trigger, it has a probe */
.channels = GARMIN_CHANNELS, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
@@ -1230,7 +1229,6 @@ const struct gps_type_t garmin_usb_binary =
{
.type_name = "Garmin USB binary", /* full name of type */
.packet_type = GARMIN_PACKET, /* associated lexer packet type */
- .device_class = GPS, /* it's a GPS */
.trigger = NULL, /* no trigger, it has a probe */
.channels = GARMIN_CHANNELS, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
@@ -1257,7 +1255,6 @@ const struct gps_type_t garmin_ser_binary =
{
.type_name = "Garmin Serial binary", /* full name of type */
.packet_type = GARMIN_PACKET, /* associated lexer packet type */
- .device_class = GPS, /* it's a GPS */
.trigger = NULL, /* no trigger, it has a probe */
.channels = GARMIN_CHANNELS, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
diff --git a/driver_italk.c b/driver_italk.c
index 59ad4507..3f8de031 100644
--- a/driver_italk.c
+++ b/driver_italk.c
@@ -409,7 +409,6 @@ const struct gps_type_t italk_binary =
{
.type_name = "iTalk binary", /* full name of type */
.packet_type = ITALK_PACKET, /* associated lexer packet type */
- .device_class = GPS, /* it's a GPS */
.trigger = NULL, /* recognize the type */
.channels = 12, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
@@ -536,7 +535,6 @@ static void itrax_wrap(struct gps_device_t *session)
const static struct gps_type_t itrax = {
.type_name = "iTrax", /* full name of type */
.packet_type = NMEA_PACKET; /* associated lexer packet type */
- .device_class = GPS, /* it's a GPS */
.trigger = "$PFST,OK", /* tells us to switch to Itrax */
.channels = 12, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
diff --git a/driver_navcom.c b/driver_navcom.c
index 8398e003..02832fdf 100644
--- a/driver_navcom.c
+++ b/driver_navcom.c
@@ -1252,7 +1252,6 @@ const struct gps_type_t navcom_binary =
{
.type_name = "Navcom binary", /* full name of type */
.packet_type = NAVCOM_PACKET, /* lexer packet type */
- .device_class = GPS, /* it's a GPS */
.trigger = "\x02\x99\x66", /* packet leader */
.channels = NAVCOM_CHANNELS, /* 12 L1 + 12 L2 + 2 Inmarsat L-Band */
.probe_wakeup = navcom_ping, /* wakeup to be done before hunt */
diff --git a/driver_oncore.c b/driver_oncore.c
index 3beb2a00..4ee3cbc5 100644
--- a/driver_oncore.c
+++ b/driver_oncore.c
@@ -470,8 +470,6 @@ const struct gps_type_t oncore_binary = {
.type_name = "oncore binary",
/* associated lexer packet type */
.packet_type = ONCORE_PACKET,
- /* device class - what kind of data it hands back */
- .device_class = GPS, /* it's a GPS */
/* Response string that identifies device (not active) */
.trigger = NULL,
/* Number of satellite channels supported by the device */
diff --git a/driver_proto.c b/driver_proto.c
index 0a5a5ed7..63c0da73 100644
--- a/driver_proto.c
+++ b/driver_proto.c
@@ -403,8 +403,6 @@ const struct gps_type_t _proto__binary = {
.type_name = "_proto_ binary",
/* Associated lexer packet type */
.packet_type = _PROTO__PACKET,
- /* Device class - what kind of data we hand back */
- .device_class = GPS,
/* Response string that identifies device (not active) */
.trigger = NULL,
/* Number of satellite channels supported by the device */
diff --git a/driver_sirf.c b/driver_sirf.c
index df824faf..72e847cb 100644
--- a/driver_sirf.c
+++ b/driver_sirf.c
@@ -988,7 +988,6 @@ const struct gps_type_t sirf_binary =
{
.type_name = "SiRF binary", /* full name of type */
.packet_type = SIRF_PACKET, /* associated lexer packet type */
- .device_class = GPS, /* it's a GPS */
.trigger = NULL, /* no trigger */
.channels = SIRF_CHANNELS, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
diff --git a/driver_superstar2.c b/driver_superstar2.c
index d0309d25..45e13e09 100644
--- a/driver_superstar2.c
+++ b/driver_superstar2.c
@@ -603,8 +603,6 @@ const struct gps_type_t superstar2_binary = {
.type_name = "SuperStarII binary",
/* Associated lexer packet type */
.packet_type = SUPERSTAR2_PACKET,
- /* Device class - what kind of data it hands back */
- .device_class = GPS,
/* Response string that identifies device (not active) */
.trigger = NULL,
/* Number of satellite channels supported by the device */
diff --git a/driver_tsip.c b/driver_tsip.c
index 55030e2e..76d959c1 100644
--- a/driver_tsip.c
+++ b/driver_tsip.c
@@ -844,7 +844,6 @@ const struct gps_type_t tsip_binary =
{
.type_name = "Trimble TSIP", /* full name of type */
.packet_type = TSIP_PACKET, /* associated lexer packet type */
- .device_class = GPS, /* it's a GPS */
.trigger = NULL, /* no trigger */
.channels = TSIP_CHANNELS, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
diff --git a/driver_ubx.c b/driver_ubx.c
index db8c3bc7..9f2ce882 100644
--- a/driver_ubx.c
+++ b/driver_ubx.c
@@ -715,7 +715,6 @@ static bool ubx_rate(struct gps_device_t *session, double cycletime)
const struct gps_type_t ubx_binary = {
.type_name = "uBlox UBX binary", /* Full name of type */
.packet_type = UBX_PACKET, /* associated lexer packet type */
- .device_class = GPS, /* it's a GPS */
.trigger = NULL, /* Response string that identifies device (not active) */
.channels = 50, /* Number of satellite channels supported by the device */
.probe_detect = NULL, /* Startup-time device detector */
diff --git a/driver_zodiac.c b/driver_zodiac.c
index d91ffbec..b4b07848 100644
--- a/driver_zodiac.c
+++ b/driver_zodiac.c
@@ -472,7 +472,6 @@ static bool zodiac_speed_switch(struct gps_device_t *session,
const struct gps_type_t zodiac_binary =
{
.type_name = "Zodiac binary", /* full name of type */
- .device_class = GPS, /* it's a GPS */
.packet_type = ZODIAC_PACKET, /* associated lexer packet type */
.trigger = NULL, /* no trigger */
.channels = 12, /* consumer-grade GPS */
diff --git a/drivers.c b/drivers.c
index 4f920318..16a90f33 100644
--- a/drivers.c
+++ b/drivers.c
@@ -214,7 +214,6 @@ static void nmea_probe_subtype(struct gps_device_t *session, unsigned int seq)
const struct gps_type_t nmea = {
.type_name = "Generic NMEA", /* full name of type */
.packet_type = NMEA_PACKET, /* associated lexer packet type */
- .device_class = GPS, /* it's a GPS */
.trigger = NULL, /* it's the default */
.channels = 12, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
@@ -304,7 +303,6 @@ static void garmin_nmea_configurator(struct gps_device_t *session, unsigned int
const struct gps_type_t garmin = {
.type_name = "Garmin Serial", /* full name of type */
.packet_type = GARMIN_PACKET, /* associated lexer packet type */
- .device_class = GPS, /* it's a GPS */
.trigger = "$PGRMC,", /* Garmin private */
.channels = 12, /* not used by this driver */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
@@ -367,7 +365,6 @@ static void ashtech_ping(struct gps_device_t *session)
const struct gps_type_t ashtech = {
.type_name = "Ashtech", /* full name of type */
.packet_type = NMEA_PACKET, /* associated lexer packet type */
- .device_class = GPS, /* it's a GPS */
.trigger = "$PASHR,RID,", /* Ashtech receivers respond thus */
.channels = 24, /* not used, GG24 has 24 channels */
.probe_wakeup = ashtech_ping, /* wakeup to be done before hunt */
@@ -414,7 +411,6 @@ static void fv18_configure(struct gps_device_t *session, unsigned int seq)
const struct gps_type_t fv18 = {
.type_name = "San Jose Navigation FV18", /* full name of type */
.packet_type = NMEA_PACKET, /* associated lexer packet type */
- .device_class = GPS, /* it's a GPS */
.trigger = "$PFEC,GPint,", /* FV18s should echo the probe */
.channels = 12, /* not used by this driver */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
@@ -464,7 +460,6 @@ static void gpsclock_probe_subtype(struct gps_device_t *session, unsigned int se
const struct gps_type_t gpsclock = {
.type_name = "Furuno Electric GH-79L4", /* full name of type */
.packet_type = NMEA_PACKET, /* associated lexer packet type */
- .device_class = GPS, /* it's a GPS */
.trigger = "$PFEC,GPssd", /* GPSclock should return this */
.channels = 12, /* not used by this driver */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
@@ -522,7 +517,6 @@ static void tripmate_configurator(struct gps_device_t *session, unsigned int seq
static const struct gps_type_t tripmate = {
.type_name = "Delorme TripMate", /* full name of type */
.packet_type = NMEA_PACKET, /* lexer packet type */
- .device_class = GPS, /* it's a GPS */
.trigger ="ASTRAL", /* tells us to switch */
.channels = 12, /* consumer-grade GPS */
.probe_wakeup = NULL, /* no wakeup before hunt */
@@ -570,7 +564,6 @@ static void earthmate_probe_subtype(struct gps_device_t *session, unsigned int s
static const struct gps_type_t earthmate = {
.type_name = "Delorme EarthMate (pre-2003, Zodiac chipset)",
.packet_type = NMEA_PACKET, /* associated lexer packet type */
- .device_class = GPS, /* it's a GPS */
.trigger = "EARTHA", /* Earthmate trigger string */
.channels = 12, /* not used by NMEA parser */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
@@ -746,7 +739,6 @@ static bool tnt_probe(struct gps_device_t *session)
static const struct gps_type_t trueNorth = {
.type_name = "True North", /* full name of type */
.packet_type = NMEA_PACKET, /* associated lexer packet type */
- .device_class = GPS, /* it's a GPS */
.trigger = " TNT1500",
.channels = 0, /* not an actual GPS at all */
.probe_wakeup = NULL, /* this will become a real method */
@@ -820,7 +812,6 @@ static void oceanserver_configure(struct gps_device_t *session, unsigned int seq
static const struct gps_type_t oceanServer = {
.type_name = "OceanServer Digital Compass OS5000", /* full name of type */
.packet_type = NMEA_PACKET, /* associated lexer packet type */
- .device_class = GPS, /* it's a GPS */
.trigger = "$C,",
.channels = 0, /* not an actual GPS at all */
.probe_wakeup = NULL,
@@ -864,7 +855,6 @@ static gps_mask_t rtcm104v2_analyze(struct gps_device_t *session)
static const struct gps_type_t rtcm104v2 = {
.type_name = "RTCM104V2", /* full name of type */
.packet_type = RTCM2_PACKET, /* associated lexer packet type */
- .device_class = RTCM2, /* it's an RTCM source */
.trigger = NULL, /* no recognition string */
.channels = 0, /* not used */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
@@ -908,7 +898,6 @@ static gps_mask_t rtcm104v3_analyze(struct gps_device_t *session)
static const struct gps_type_t rtcm104v3 = {
.type_name = "RTCM104V3", /* full name of type */
.packet_type = RTCM3_PACKET, /* associated lexer packet type */
- .device_class = RTCM3, /* it's an RTCM source */
.trigger = NULL, /* no recognition string */
.channels = 0, /* not used */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
@@ -1043,7 +1032,6 @@ static void mkt3301_configure(struct gps_device_t *session, unsigned int seq)
const struct gps_type_t mkt3301 = {
.type_name = "MKT-3301", /* full name of type */
.packet_type = NMEA_PACKET, /* associated lexer packet type */
- .device_class = GPS, /* it's a GPS */
.trigger = "$PMTK705,", /* MKT-3301s send firmware release name and version */
.channels = 12, /* not used by this driver */
.probe_wakeup = NULL, /* no wakeup to be done before hunt */
@@ -1073,7 +1061,7 @@ gps_mask_t aivdm_analyze(struct gps_device_t *);
gps_mask_t aivdm_analyze(struct gps_device_t *session)
{
- if (aivdm_decode((char *)session->packet.outbuffer, session->packet.outbuflen, &session->driver.aivdm))
+ if (aivdm_decode((char *)session->packet.outbuffer, session->packet.outbuflen, &session->aivdm))
return ONLINE_SET | AIS_SET;
else
return ONLINE_SET;
@@ -1084,8 +1072,6 @@ static const struct gps_type_t aivdm = {
.type_name = "AIVDM",
/* Associated lexer packet type */
.packet_type = AIVDM_PACKET,
- /* Device class, what kind of ata it returns */
- .device_class = AIS,
/* Response string that identifies device (not active) */
.trigger = NULL,
/* Number of satellite channels supported by the device */
diff --git a/gps_json.c b/gps_json.c
index b7773c73..59b1042e 100644
--- a/gps_json.c
+++ b/gps_json.c
@@ -239,7 +239,7 @@ int json_sky_read(const char *buf, struct gps_data_t *gpsdata)
/*
* To add new device types to be eligible for watching, bump
- * NWATCHTYPES add a matching pair of lines to the watchmap
+ * NWATCHTYPES and add a matching pair of lines to the watchmap
* initializer and the watch_attrs initializer.
*/
const struct watchmap_t watchmap[NWATCHTYPES] = {
diff --git a/gpsd.c b/gpsd.c
index 588d5976..f466f72a 100644
--- a/gpsd.c
+++ b/gpsd.c
@@ -108,8 +108,19 @@
/*
* Manifest names for the gnss_type enum - must be kept synced with it.
+ * Also, masks so we can tell what packet types correspond to each class.
*/
-const char *gnss_type_names[] = {"ANY", "GPS", "RTCM2", "RTCM3", "AIS"};
+struct classmap_t {
+ char *name;
+ int mask;
+};
+static struct classmap_t classmap[] = {
+ {"ANY", 0},
+ {"GPS", GPS_TYPEMASK},
+ {"RTCM2", PACKET_TYPEMASK(RTCM2_PACKET)},
+ {"RTCM3", PACKET_TYPEMASK(RTCM3_PACKET)},
+ {"AIS", PACKET_TYPEMASK(AIVDM_PACKET)},
+};
static fd_set all_fds;
static int maxfd;
@@ -694,17 +705,19 @@ static bool allocation_filter(struct gps_device_t *device, gnss_type type)
}
gpsd_report(LOG_PROG,
- "user requires %d=%s, device %d=%s emits packet type %d\n",
- type, gnss_type_names[type],
+ "user requires %d=%s, device %d=%s emits packet type %d, observed mask is 0x%0x, checking against 0x%0x\n",
+ type, classmap[type].name,
(int)(device - devices), device->gpsdata.gps_device,
- device->packet.type);
+ device->packet.type,
+ device->observed,
+ classmap[type].mask);
/* we might have type constraints */
if (type == ANY)
return true;
else if (device->device_type == NULL)
return false;
else
- return device->device_type->device_class == type;
+ return (device->observed & classmap[type].mask) != 0;
}
/*@ -branchstate -usedef -globstate @*/
@@ -725,7 +738,7 @@ static struct channel_t *assign_channel(struct subscriber_t *user,
gpsd_report(LOG_PROG, "client(%d): reusing channel %d (type %s)\n",
sub_index(user),
(int)(chp-channels),
- gnss_type_names[type]);
+ classmap[type].name);
channel = chp;
}
/* if we didn't find one, allocate a new channel */
@@ -736,14 +749,14 @@ static struct channel_t *assign_channel(struct subscriber_t *user,
gpsd_report(LOG_PROG, "client(%d): attaching channel %d (type %s)\n",
sub_index(user),
(int)(chp-channels),
- gnss_type_names[type]);
+ classmap[type].name);
break;
}
}
if (channel == NULL) {
gpsd_report(LOG_ERROR, "client(%d): channel allocation for type %s failed.\n",
sub_index(user),
- gnss_type_names[type]);
+ classmap[type].name);
return NULL;
}
@@ -862,11 +875,11 @@ static void deassign_channel(struct subscriber_t *user, gnss_type type)
for (chp = channels; chp < channels + NITEMS(channels); chp++)
if (chp->subscriber == user
&& chp->device
- && chp->device->device_type->device_class == type) {
+ && (chp->device->observed & classmap[type].mask) != 0) {
gpsd_report(LOG_PROG, "client(%d): detaching channel %d (type %s)\n",
sub_index(user),
(int)(chp-channels),
- gnss_type_names[type]);
+ classmap[type].name);
/*@i1@*/chp->device = NULL;
chp->conf.buffer_policy = casoc;
chp->conf.scaled = false;
@@ -1614,26 +1627,42 @@ static int handle_gpsd_request(struct subscriber_t *sub, char *buf, int buflen)
"{\"class\"=\"DEVICES\",\"devices\":[", sizeof(reply));
for (i = 0; i < MAXDEVICES; i++) {
if (allocated_device(&devices[i]) && strlen(reply)+strlen(devices[i].gpsdata.gps_device)+3 < sizeof(reply)-1) {
+ struct classmap_t *cmp;
(void)strlcat(reply, "{\"class\":\"DEVICE\",\"name\":\"", sizeof(reply));
(void)strlcat(reply, devices[i].gpsdata.gps_device, sizeof(reply));
- (void)strlcat(reply, "\",\"type\":\"", sizeof(reply));
- (void)strlcat(reply,
- gpsd_type(devices[i].device_type),
- sizeof(reply));
- (void)strlcat(reply, "\",\"driver\":\"", sizeof(reply));
- (void)strlcat(reply,
- devices[i].device_type->type_name,
- sizeof(reply));
+ (void)strlcat(reply, "\",", sizeof(reply));
+ if (devices[i].observed != 0) {
+ (void)strlcat(reply, "\"type\":[", sizeof(reply));
+ for (cmp = classmap; cmp < classmap+NITEMS(classmap); cmp++)
+ if ((devices[i].observed & cmp->mask) != 0) {
+ (void)strlcat(reply, "\"", sizeof(reply));
+ (void)strlcat(reply, cmp->name, sizeof(reply));
+ (void)strlcat(reply, "\",", sizeof(reply));
+ }
+ if (reply[strlen(reply)-1] == ',')
+ reply[strlen(reply)-1] = '\0';
+ (void)strlcat(reply, "],", sizeof(reply));
+ }
+ if (devices[i].device_type != NULL) {
+ (void)strlcat(reply, "\"driver\":\"", sizeof(reply));
+ (void)strlcat(reply,
+ devices[i].device_type->type_name,
+ sizeof(reply));
+ (void)strlcat(reply, "\",", sizeof(reply));
+ }
if (devices[i].subtype[0] != '\0') {
(void)strlcat(reply, "\",\"subtype\":\"", sizeof(reply));
(void)strlcat(reply,
devices[i].subtype,
sizeof(reply));
}
- (void)strlcat(reply, "\"},", sizeof(reply));
+ if (reply[strlen(reply)-1] == ',')
+ reply[strlen(reply)-1] = '\0';
+ (void)strlcat(reply, "},", sizeof(reply));
}
}
- reply[strlen(reply)-1] = '\0';
+ if (reply[strlen(reply)-1] == ',')
+ reply[strlen(reply)-1] = '\0';
(void)strlcat(reply, "]}", sizeof(reply));
} else if (strncmp(buf, "?WATCH", 6) == 0) {
if (buf[6] == '=') {
@@ -1697,7 +1726,7 @@ static int handle_gpsd_request(struct subscriber_t *sub, char *buf, int buflen)
continue;
} else if (pathp != NULL && chp->device && strcmp(chp->device->gpsdata.gps_device, pathp)!=0) {
continue;
- } else if (conf.buffer_policy != -1 && chp->device->device_type->device_class != GPS) {
+ } else if (conf.buffer_policy != -1 && (chp->device->observed & GPS_TYPEMASK)==0) {
(void)strlcpy(reply,
"{\"class\":ERROR\",\"message\":\"Attempt to apply buffer policy to a non-GPS device.\"}\r\n",
sizeof(reply));
@@ -2281,7 +2310,7 @@ int main(int argc, char *argv[])
(void)handle_oldstyle(sub, cmds, (int)strlen(cmds));
#ifdef AIVDM_ENABLE
if ((changed & AIS_SET) != 0) {
- aivdm_dump(&channel->device->driver.aivdm.decoded,
+ aivdm_dump(&channel->device->aivdm.decoded,
channel->conf.scaled, false, buf2, sizeof(buf2));
(void)strlcat(buf2, "\r\n", sizeof(buf2));
(void)throttled_write(sub, buf2, strlen(buf2));
@@ -2308,7 +2337,7 @@ int main(int argc, char *argv[])
}
#ifdef AIVDM_ENABLE
if ((sub->watcher & WATCH_AIS)!=0 && (changed & AIS_SET)!=0) {
- aivdm_dump(&channel->device->driver.aivdm.decoded,
+ aivdm_dump(&channel->device->aivdm.decoded,
false, true, buf2, sizeof(buf2));
(void)strlcat(buf2, "\r\n", sizeof(buf2));
(void)throttled_write(sub, buf2, strlen(buf2));
diff --git a/gpsd.h-tail b/gpsd.h-tail
index fa575b11..b59ae33c 100644
--- a/gpsd.h-tail
+++ b/gpsd.h-tail
@@ -59,6 +59,19 @@ struct gps_packet_t {
#define AIVDM_PACKET 14
#define ONCORE_PACKET 15
#define TEXTUAL_PACKET_TYPE(n) ((n)==NMEA_PACKET||(n)==GARMINTXT_PACKET||(n)==COMMENT_PACKET||(n)==AIVDM_PACKET)
+#define PACKET_TYPEMASK(n) (1 << (n))
+#define GPS_TYPEMASK (PACKET_TYPEMASK(NMEA_PACKET) | \
+ PACKET_TYPEMASK(SIRF_PACKET) | \
+ PACKET_TYPEMASK(ZODIAC_PACKET) | \
+ PACKET_TYPEMASK(TSIP_PACKET) | \
+ PACKET_TYPEMASK(EVERMORE_PACKET) | \
+ PACKET_TYPEMASK(ITALK_PACKET) | \
+ PACKET_TYPEMASK(GARMIN_PACKET) | \
+ PACKET_TYPEMASK(NAVCOM_PACKET) | \
+ PACKET_TYPEMASK(UBX_PACKET) | \
+ PACKET_TYPEMASK(GARMINTXT_PACKET) | \
+ PACKET_TYPEMASK(SUPERSTAR2_PACKET) | \
+ PACKET_TYPEMASK(ONCORE_PACKET))
unsigned int state;
size_t length;
unsigned char inbuffer[MAX_PACKET_LENGTH*2+1];
@@ -190,7 +203,6 @@ struct gps_type_t {
/* GPS method table, describes how to talk to a particular GPS type */
/*@observer@*/char *type_name;
int packet_type;
- gnss_type device_class;
/*@observer@*//*@null@*/char *trigger;
int channels;
/*@null@*/bool (*probe_detect)(struct gps_device_t *session);
@@ -237,10 +249,11 @@ struct gps_device_t {
int shmTimeP;
# endif /* PPS_ENABLE */
#endif /* NTPSHM_ENABLE */
- double mag_var; /* Magnetic variation in degrees */
+ double mag_var; /* magnetic variation in degrees */
bool back_to_nmea; /* back to NMEA on revert? */
char msgbuf[MAX_PACKET_LENGTH*2+1]; /* command message buffer for sends */
size_t msgbuflen;
+ int observed; /* which packet type`s have we seen? */
/*
* The rest of this structure is driver-specific private storage.
* Because the Garmin driver uses a long buffer, you can have
@@ -260,9 +273,6 @@ struct gps_device_t {
#endif /* GPSCLOCK_ENABLE */
} nmea;
#endif /* NMEA_ENABLE */
-#ifdef AIVDM_ENABLE
- struct aivdm_context_t aivdm;
-#endif /* AIVDM_ENABLE */
#ifdef BINARY_ENABLE
#ifdef SIRF_ENABLE
struct {
@@ -363,6 +373,15 @@ struct gps_device_t {
} isgps;
#endif /* BINARY_ENABLE */
} driver;
+ /*
+ * Auxiliary structures for parsing data that can be interleaved with
+ * GPS sentences. Can't be in the driver union or it will get stepped on.
+ * So far the only case of this is AIS reports, which in marine navigation
+ * systems may come over the same wire with GPS NMEA sentences.
+ */
+#ifdef AIVDM_ENABLE
+ struct aivdm_context_t aivdm;
+#endif /* AIVDM_ENABLE */
};
/* logging levels */
@@ -442,7 +461,6 @@ extern int hex2bin(char *);
extern ssize_t hex_escapes(/*@out@*/char *cooked, const char *raw);
extern void ntpd_link_activate(struct gps_device_t *session);
extern char /*@observer@*/ *gpsd_id(/*@in@*/struct gps_device_t *);
-extern const char /*@observer@*/ *gpsd_type(/*@in@*/const struct gps_type_t *);
extern void gpsd_position_fix_dump(struct gps_device_t *, /*@out@*/char[], size_t);
extern void gpsd_error_model(struct gps_device_t *, struct gps_fix_t *, struct gps_fix_t *);
extern void gpsd_clear_data(struct gps_device_t *);
diff --git a/gpsd.xml b/gpsd.xml
index ef60fd40..34e636a4 100644
--- a/gpsd.xml
+++ b/gpsd.xml
@@ -900,15 +900,20 @@ following elements:</para>
</row>
<row>
<entry>type</entry>
- <entry>Yes</entry>
- <entry>string</entry>
- <entry>type (GPS, RTCM2, RTCM3, AIS)</entry>
+ <entry>No</entry>
+ <entry>list of strings</entry>
+ <entry>List of packet types seen (GPS, RTCM2, RTCM3,
+ AIS). Won't be reported if empty, e.g. before
+ <application>gpsd</application> has seen identifiable packets
+ from the device.</entry>
</row>
<row>
<entry>driver</entry>
- <entry>Yes</entry>
+ <entry>No</entry>
<entry>string</entry>
- <entry>GPSD's name for the device driver type.</entry>
+ <entry>GPSD's name for the device driver type. Won't be reported before
+ <application>gpsd</application> has seen identifiable packets
+ from the device.</entry>
</row>
<row>
<entry>driver</entry>
diff --git a/libgpsd_core.c b/libgpsd_core.c
index 8e13a01a..40a30b5d 100644
--- a/libgpsd_core.c
+++ b/libgpsd_core.c
@@ -73,6 +73,7 @@ void gpsd_init(struct gps_device_t *session, struct gps_context_t *context, char
(void)strlcpy(session->gpsdata.gps_device, device, PATH_MAX);
/*@ -mustfreeonly @*/
session->device_type = NULL; /* start by hunting packets */
+ session->observed = 0;
session->rtcmtime = 0;
/*@ -temptrans @*/
session->context = context;
@@ -342,18 +343,6 @@ char /*@observer@*/ *gpsd_id(/*@in@*/struct gps_device_t *session)
return(buf);
}
-const char *gpsd_type(const struct gps_type_t *dev)
-{
- switch(dev->device_class) {
- case ANY: return "UNKNOWN";
- case GPS: return "GPS";
- case RTCM2: return "RTCM2";
- case RTCM3: return "RTCM3";
- case AIS: return "AIS";
- }
- return "INTERNAL_ERROR";
-}
-
#if defined(BINARY_ENABLE) || defined(RTCM104V2_ENABLE) || defined(NTRIP_ENABLE)
/*
* Support for generic binary drivers. These functions dump NMEA for passing
@@ -716,6 +705,7 @@ gps_mask_t gpsd_poll(struct gps_device_t *session)
session->gpsdata.gps_device,
session->packet.type);
if (session->packet.type > COMMENT_PACKET) {
+ session->observed |= PACKET_TYPEMASK(session->packet.type);
for (dp = gpsd_drivers; *dp; dp++)
if (session->packet.type == (*dp)->packet_type) {
(void)gpsd_switch_driver(session, (*dp)->type_name);
diff --git a/www/writing-a-driver.xml b/www/writing-a-driver.xml
index db7e8b2c..d8aeefea 100644
--- a/www/writing-a-driver.xml
+++ b/www/writing-a-driver.xml
@@ -16,6 +16,14 @@
<revhistory>
<revision>
+ <revnumber>1.8</revnumber>
+ <date>9 Aug 2009</date>
+ <authorinitials>er</authorinitials>
+ <revremark>
+ Updated by esr; the device_class experiment failed.
+ </revremark>
+ </revision>
+ <revision>
<revnumber>1.7</revnumber>
<date>24 Jul 2009</date>
<authorinitials>er</authorinitials>
@@ -563,14 +571,6 @@ packet sniffer and <emphasis>must be unique to each
driver</emphasis>. It is used internally to dispatch to the correct
driver when it collects a complete packet.</para>
-<!-- added by ESR, 2009 -->
-<para><structfield>.device_class</structfield> What type of data this
-driver hands back. This value need <emphasis>not</emphasis> be unique
-to each driver. Usually it will be the enumerated value GPS; other
-passible values are RTCM2, RTCM3, and AIS. This field is directly used
-to implement the 'G' command (old format) and the '?DEVICES' command
-(new format).</para>
-
<para><structfield>.trigger</structfield> is the unique string that,
when seen, will confirm your device is present. This will be detected
in <quote><filename>drivers.c</filename></quote> and will probably