summaryrefslogtreecommitdiff
path: root/src/gypsy-client.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gypsy-client.c')
-rw-r--r--src/gypsy-client.c294
1 files changed, 57 insertions, 237 deletions
diff --git a/src/gypsy-client.c b/src/gypsy-client.c
index 2312d7b..b9c32ea 100644
--- a/src/gypsy-client.c
+++ b/src/gypsy-client.c
@@ -61,10 +61,11 @@
#include "gypsy-client.h"
#include "gypsy-marshal-internal.h"
-#include "nmea.h"
-#include "nmea-parser.h"
+#include "gypsy-parser.h"
+#include "gypsy-garmin-parser.h"
+#include "gypsy-nmea-parser.h"
+
#include "garmin.h"
-#include "nmea-gen.h"
#define GYPSY_ERROR g_quark_from_static_string ("gypsy-error")
@@ -94,11 +95,7 @@ typedef struct _GypsyClientPrivate {
guint32 error_id, connect_id, input_id;
- char sentence[READ_BUFFER_SIZE + 1]; /* This is for building
- the NMEA sentence */
- int chars_in_buffer; /* How many characters are in the buffer */
-
- NMEAParseContext *ctxt;
+ GypsyParser *parser;
/* For serial devices */
speed_t baudrate;
@@ -200,11 +197,6 @@ static gboolean gypsy_client_get_time (GypsyClient *client,
#include "gypsy-client-glue.h"
-/* used for Garmin -> NMEA translation */
-D800_Pvt_Data_Type lastpvt;
-cpo_sat_data lastsatdata[SAT_MAX_COUNT];
-int satdata_valid = 0;
-
static void
shutdown_connection (GypsyClient *client)
{
@@ -242,7 +234,10 @@ shutdown_connection (GypsyClient *client)
priv->debug_log = NULL;
}
- priv->chars_in_buffer = 0;
+ if (priv->parser) {
+ g_object_unref (priv->parser);
+ priv->parser = NULL;
+ }
#ifdef ENABLE_N810
/* Turn off the N810's GPS device */
@@ -274,205 +269,33 @@ gps_channel_error (GIOChannel *channel,
}
static gboolean
-gps_channel_garmin_input (GIOChannel *channel,
- GIOCondition condition,
- gpointer userdata)
-{
- GypsyClientPrivate *priv;
- GIOStatus status;
- char *buf;
- gsize chars_left_in_buffer;
- gsize chars_read;
- GError *error = NULL;
-
- int pktlen;
- char nmeabuf[256];
-
- priv = GET_PRIVATE (userdata);
-
- /* set up for the next read */
- buf = priv->sentence + priv->chars_in_buffer;
- chars_left_in_buffer = READ_BUFFER_SIZE - priv->chars_in_buffer;
-
- status = g_io_channel_read_chars (priv->channel,
- buf,
- chars_left_in_buffer,
- &chars_read,
- &error);
-
- if (priv->debug_log) {
- g_io_channel_write_chars(priv->debug_log, buf, chars_read, NULL, NULL);
- }
-
- if (status == G_IO_STATUS_NORMAL) {
- /* update the count of how much we've read
- of the current packet */
- priv->chars_in_buffer += chars_read;
-
- /* get a pointer to our packet */
- G_Packet_t * pGpkt = (G_Packet_t*)priv->sentence;
-
- /* check that we have at least enough for the packet header
- and the packet data; we could conceivably have multiple
- packets in the buffer between reads */
-
- while ((priv->chars_in_buffer >= GARMIN_HEADER_SIZE) &&
- (priv->chars_in_buffer >= (pktlen = GARMIN_HEADER_SIZE + pGpkt->mDataSize))) {
- char *eos;
-
- /*g_debug("PacketId: %d pktlen = %d",
- pGpkt->mPacketId, pktlen);*/
-
- if (pGpkt->mPacketId == Pid_Pvt_Data) {
- memcpy(&lastpvt, pGpkt->mData, sizeof(lastpvt));
-
- /* A single Pvt_Data packet translates
- into 4 NMEA sentences. */
-
- if (nmea_gpgga(&lastpvt, satdata_valid ? lastsatdata : NULL, nmeabuf) == 0) {
- *(strchr (nmeabuf, '\r')) = '\0';
- g_debug ("NMEA sentence: %s", nmeabuf);
- if (nmea_parse_sentence (priv->ctxt, nmeabuf, NULL) == FALSE) {
- g_debug ("Invalid NMEA sentence: %s", nmeabuf);
- }
- }
-
- if (nmea_gprmc(&lastpvt, nmeabuf) == 0) {
- *(strchr (nmeabuf, '\r')) = '\0';
- g_debug ("NMEA sentence: %s", nmeabuf);
- if (nmea_parse_sentence (priv->ctxt, nmeabuf, NULL) == FALSE) {
- g_debug ("Invalid NMEA sentence: %s", nmeabuf);
- }
- }
-
- if (nmea_gpgll(&lastpvt, nmeabuf) == 0) {
- *(strchr (nmeabuf, '\r')) = '\0';
- g_debug ("NMEA sentence: %s", nmeabuf);
- if (nmea_parse_sentence (priv->ctxt, nmeabuf, NULL) == FALSE) {
- g_debug ("Invalid NMEA sentence: %s", nmeabuf);
- }
- }
-
- if (nmea_gpgsa(&lastpvt, satdata_valid ? lastsatdata : NULL, nmeabuf) == 0) {
- *(strchr (nmeabuf, '\r')) = '\0';
- g_debug ("NMEA sentence: %s", nmeabuf);
- if (nmea_parse_sentence (priv->ctxt, nmeabuf, NULL) == FALSE) {
- g_debug ("Invalid NMEA sentence: %s", nmeabuf);
- }
- }
- } else if (pGpkt->mPacketId == Pid_SatData_Record) {
- memcpy(lastsatdata, pGpkt->mData,
- sizeof(lastsatdata));
-
- satdata_valid = 1;
-
- if (nmea_gpgsv(lastsatdata, nmeabuf) == 0) {
- /*
- * The Garmin SatData record translates to multiple GPGSV sentences,
- * but the parser only handles one sentence per buffer so we have to
- * feed them in one at a time.
- */
-
- char *nmeabufptr = nmeabuf;
- int length;
-
- /* NMEA sentences end with <CR><LF>, so find the <CR> at the end of each sentence */
- while ((eos = strchr (nmeabufptr, '\r'))) {
- /* Accounf for <LF> */
- length = (eos - nmeabufptr) + 2;
- if (length > 1) {
- /* terminate the string at the <CR> */
- *eos = '\0';
-
- g_debug ("NMEA sentence: %s", nmeabufptr);
- if (nmea_parse_sentence (priv->ctxt, nmeabufptr, NULL) == FALSE)
- g_debug ("Invalid sentence: %s", nmeabufptr);
- }
-
- if (length > 0) {
- /* point to the next sentence in the buffer */
- nmeabufptr += length;
- }
- }
- }
- } else {
- g_debug ("Untranslated PacketId = %d", pGpkt->mPacketId);
- }
-
- /* now that we're done with this packet,
- move any remaining data up to the
- beginning of the buffer */
- memmove (priv->sentence, priv->sentence + pktlen,
- priv->chars_in_buffer - pktlen);
- priv->chars_in_buffer -= pktlen;
- }
- } else {
- g_warning ("Read error: %s", g_strerror (errno));
- g_set_error (&error, GYPSY_ERROR, errno, g_strerror (errno));
- }
-
- return TRUE;
-}
-
-static gboolean
gps_channel_input (GIOChannel *channel,
GIOCondition condition,
gpointer userdata)
{
GypsyClientPrivate *priv;
GIOStatus status;
- char *buf;
+ char buf[READ_BUFFER_SIZE];
gsize chars_left_in_buffer, chars_read;
GError *error = NULL;
priv = GET_PRIVATE (userdata);
- /* set up for the next read */
- buf = priv->sentence + priv->chars_in_buffer;
- chars_left_in_buffer = READ_BUFFER_SIZE - priv->chars_in_buffer;
-
+ chars_left_in_buffer = gypsy_parser_get_space_in_buffer (priv->parser);
status = g_io_channel_read_chars (priv->channel,
- buf,
+ buf,
chars_left_in_buffer,
&chars_read,
NULL);
if (priv->debug_log) {
- g_io_channel_write_chars (priv->debug_log, buf,
+ g_io_channel_write_chars (priv->debug_log, buf,
chars_read, NULL, NULL);
}
if (status == G_IO_STATUS_NORMAL) {
- char *eos = NULL;
- int length;
-
- priv->chars_in_buffer += chars_read;
-
- /* Append a \0 to treat as a string (so we don't run off the end of valid data);
- the \0 will be overwritten in the next call to g_io_channel_read_chars */
- *(priv->sentence + priv->chars_in_buffer) = '\0';
-
- /* NMEA sentences end with <CR><LF>, so find the <CR> at the end of each sentence */
- while ((eos = strchr (priv->sentence, '\r'))) {
- /* Account for <LF> */
- length = (eos - priv->sentence) + 2;
- if (length > 1) {
- /* terminate the string at the <CR> */
- *eos = '\0';
-
- g_debug ("NMEA sentence: %s", priv->sentence);
- if (nmea_parse_sentence (priv->ctxt, priv->sentence, NULL) == FALSE) {
- g_debug ("Invalid sentence: %s", priv->sentence);
- }
- }
-
- if (length > 0) {
- /* Remove the sentence from the builder and
- move the rest up including terminating 0 */
- memmove (priv->sentence, eos + 2, (priv->chars_in_buffer - length) + 1);
- priv->chars_in_buffer -= length;
- }
- }
+ gypsy_parser_received_data (priv->parser,
+ (guchar *)buf, chars_read, NULL);
} else {
g_warning ("Read error: %s", g_strerror (errno));
g_set_error (&error, GYPSY_ERROR, errno, g_strerror (errno));
@@ -481,9 +304,11 @@ gps_channel_input (GIOChannel *channel,
return TRUE;
}
-static int
-garmin_usb_device (GIOChannel *channel,
- char *devpath)
+/* Returns TRUE/FALSE to indicate success/error */
+static gboolean
+garmin_usb_device (GIOChannel *channel,
+ char *devpath,
+ gboolean *device_is_garmin)
{
GIOStatus status;
u_int32_t privcmd[GARMIN_PRIV_PKT_MAX_SIZE];
@@ -497,6 +322,7 @@ garmin_usb_device (GIOChannel *channel,
* FIXME: Use gudev to get the VID of the device, and check against Garmin?
*/
+ *device_is_garmin = FALSE;
if (! strcmp (devpath, "/dev/ttyUSB0")) {
/* query the device driver to see if it is Garmin */
@@ -512,9 +338,9 @@ garmin_usb_device (GIOChannel *channel,
NULL);
if (status != G_IO_STATUS_NORMAL) {
- g_warning ("GARMIN: Error writing \"Private Info Req\" packet:\n%s",
+ g_warning ("GARMIN: Error writing \"Private Info Req\" packet:\n%s",
g_strerror (errno));
- return -1;
+ return FALSE;
}
g_io_channel_flush (channel, NULL);
@@ -529,21 +355,22 @@ garmin_usb_device (GIOChannel *channel,
if (status != G_IO_STATUS_NORMAL) {
g_message ("GARMIN: Error reading \"Private Info Resp\" packet: %s", g_strerror (errno));
- return 0;
+ return TRUE;
}
if ((privcmd[0] == GARMIN_LAYERID_PRIVATE) &&
(privcmd[1] == GARMIN_PRIV_PKTID_INFO_RESP)) {
/* we're talking to the Garmin driver */
g_debug ("GARMIN: device type confirmed");
- return 1;
+ *device_is_garmin = TRUE;
+ return TRUE;
} else {
g_message ("GARMIN: \"Private Info Resp\" packet data not recognized");
- return 0;
+ return TRUE;
}
- } else {
- return 0;
}
+
+ return TRUE;
}
static gboolean
@@ -617,46 +444,42 @@ gps_channel_connect (GIOChannel *channel,
gpointer userdata)
{
GypsyClientPrivate *priv;
- int ret;
+ gboolean ret, device_is_garmin;
priv = GET_PRIVATE (userdata);
g_debug ("GPS channel can connect");
- ret = 0;
- if (priv->type == GYPSY_DEVICE_TYPE_SERIAL)
- ret = garmin_usb_device (channel, priv->device_path);
+ ret = FALSE;
+ device_is_garmin = FALSE;
+ if (priv->type == GYPSY_DEVICE_TYPE_SERIAL) {
+ ret = garmin_usb_device (channel, priv->device_path,
+ &device_is_garmin);
+ if (ret == FALSE) {
+ /* we got an error trying to figure it out */
+ g_warning ("Error determining device type for %s",
+ priv->device_path);
+ /* g_set_error () has already been called */
+ goto end;
+ }
+ }
- switch (ret) {
- case 1:
- /* the device *IS* a Garmin -- we must do translation to NMEA */
+ if (device_is_garmin) {
priv->type = GYPSY_DEVICE_TYPE_GARMIN;
+ priv->parser = gypsy_garmin_parser_new (GYPSY_CLIENT (userdata));
garmin_init (channel);
- priv->input_id = g_io_add_watch_full (priv->channel,
- G_PRIORITY_HIGH_IDLE,
- G_IO_IN | G_IO_PRI,
- gps_channel_garmin_input,
- userdata, NULL);
- break;
-
- case 0:
- /* the device is *NOT* a Garmin -- the data is NMEA */
- priv->input_id = g_io_add_watch_full (priv->channel,
- G_PRIORITY_HIGH_IDLE,
- G_IO_IN | G_IO_PRI,
- gps_channel_input,
- userdata, NULL);
- break;
-
- case -1:
- /* we got an error trying to figure it out */
- g_warning ("Error determining device type for %s",
- priv->device_path);
- /* g_set_error () has already been called */
- break;
+ } else {
+ priv->parser = gypsy_nmea_parser_new (GYPSY_CLIENT (userdata));
}
- g_signal_emit (G_OBJECT (userdata), signals[CONNECTION_CHANGED],
+ priv->input_id = g_io_add_watch_full (priv->channel,
+ G_PRIORITY_HIGH_IDLE,
+ G_IO_IN | G_IO_PRI,
+ gps_channel_input,
+ userdata, NULL);
+
+end:
+ g_signal_emit (G_OBJECT (userdata), signals[CONNECTION_CHANGED],
0, TRUE);
priv->connect_id = 0;
@@ -729,8 +552,6 @@ gypsy_client_start (GypsyClient *client,
priv = GET_PRIVATE (client);
- priv->chars_in_buffer = 0;
-
if (priv->fd != -1) {
g_debug ("Connection to %s already started", priv->device_path);
return TRUE;
@@ -837,7 +658,7 @@ gypsy_client_start (GypsyClient *client,
return FALSE;
}
- priv->error_id = g_io_add_watch_full (priv->channel,
+ priv->error_id = g_io_add_watch_full (priv->channel,
G_PRIORITY_HIGH_IDLE,
G_IO_ERR | G_IO_HUP,
gps_channel_error, client, NULL);
@@ -1056,7 +877,6 @@ finalize (GObject *object)
shutdown_connection ((GypsyClient *) object);
g_free (priv->device_path);
- g_free (priv->ctxt);
((GObjectClass *) gypsy_client_parent_class)->finalize (object);
}
@@ -1226,9 +1046,9 @@ gypsy_client_init (GypsyClient *client)
priv->fd = -1;
priv->type = GYPSY_DEVICE_TYPE_UNKNOWN;
priv->baudrate = B0;
- priv->ctxt = nmea_parse_context_new (client);
priv->timestamp = 0;
priv->last_alt_timestamp = 0;
+ priv->parser = NULL;
}
void