Stupid Mac.

From 86068ba435a01ed2963d0ee2bd449b1c0fd60a75 Mon Sep 17 00:00:00 2001
From: Dirk Hohndel <[email protected]>
Date: Mon, 3 Sep 2018 14:32:58 -0700
Subject: [PATCH] Garmin: ignore FIT files that aren't dives

Dives are identified by a sub_sport range of 53-57 in the SPORT message.

This means that we need to parse the files before we actually offer them to the
application, which means we parse them three times all together, but I don't
see a way around that. Thankfully parsing a memory buffer is reasonably fast.

Signed-off-by: Dirk Hohndel <[email protected]>
---
 src/garmin.c        | 12 ++++++++++++
 src/garmin.h        |  5 +++++
 src/garmin_parser.c | 22 +++++++++++++++++++++-
 3 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/src/garmin.c b/src/garmin.c
index 4a731e1..0d9d71f 100644
--- a/src/garmin.c
+++ b/src/garmin.c
@@ -194,6 +194,7 @@ garmin_device_foreach (dc_device_t *abstract, 
dc_dive_callback_t callback, void
 {
        dc_status_t status = DC_STATUS_SUCCESS;
        garmin_device_t *device = (garmin_device_t *) abstract;
+       dc_parser_t *parser;
        char pathname[PATH_MAX];
        size_t pathlen;
        struct file_list files = { 0, 0, NULL };
@@ -268,6 +269,11 @@ garmin_device_foreach (dc_device_t *abstract, 
dc_dive_callback_t callback, void
                free(files.array);
                return DC_STATUS_NOMEMORY;
        }
+       if ((rc = garmin_parser_create(&parser, abstract->context) != 
DC_STATUS_SUCCESS)) {
+               ERROR (abstract->context, "Failed to create parser for dive 
verification.");
+               free(files.array);
+               return rc;
+       }
 
        for (int i = 0; i < files.nr; i++) {
                const char *name = files.array[i].name;
@@ -290,6 +296,11 @@ garmin_device_foreach (dc_device_t *abstract, 
dc_dive_callback_t callback, void
                data = dc_buffer_get_data(file);
                size = dc_buffer_get_size(file);
 
+               if (!garmin_parser_is_dive(parser, data, size)) {
+                       DEBUG (abstract->context, "decided %s isn't a dive.", 
name);
+                       continue;
+               }
+
                if (callback && !callback(data, size, name, FIT_NAME_SIZE, 
userdata))
                        break;
 
@@ -298,5 +309,6 @@ garmin_device_foreach (dc_device_t *abstract, 
dc_dive_callback_t callback, void
        }
 
        free(files.array);
+       dc_parser_destroy(parser);
        return status;
 }
diff --git a/src/garmin.h b/src/garmin.h
index 50f9f6e..4eec22a 100644
--- a/src/garmin.h
+++ b/src/garmin.h
@@ -37,6 +37,11 @@ garmin_device_open (dc_device_t **device, dc_context_t 
*context, dc_iostream_t *
 dc_status_t
 garmin_parser_create (dc_parser_t **parser, dc_context_t *context);
 
+// we need to be able to call into the parser to check if the
+// files that we find are actual dives
+short
+garmin_parser_is_dive (dc_parser_t *abstract, const unsigned char *data, 
unsigned int size);
+
 // The dive names are of the form "2018-08-20-10-23-30.fit"
 // With the terminating zero, that's 24 bytes.
 //
diff --git a/src/garmin_parser.c b/src/garmin_parser.c
index 7e35e32..0f561c8 100644
--- a/src/garmin_parser.c
+++ b/src/garmin_parser.c
@@ -90,6 +90,7 @@ typedef struct garmin_parser_t {
        // Field cache
        struct {
                unsigned int initialized;
+               unsigned int sub_sport;
                unsigned int protocol;
                unsigned int profile;
                unsigned int time;
@@ -488,6 +489,9 @@ DECLARE_FIELD(RECORD, n2_load, UINT16) { }          // 
percent
 DECLARE_FIELD(DEVICE_SETTINGS, utc_offset, UINT32) { garmin->cache.utc_offset 
= (SINT32) data; }       // wrong type in FIT
 DECLARE_FIELD(DEVICE_SETTINGS, time_offset, UINT32) { 
garmin->cache.time_offset = (SINT32) data; }     // wrong type in FIT
 
+// SPORT
+DECLARE_FIELD(SPORT, sub_sport, ENUM) { garmin->cache.sub_sport = (ENUM) data; 
}
+
 // DIVE_GAS - uses msg index
 DECLARE_FIELD(DIVE_GAS, helium, UINT8)
 {
@@ -574,7 +578,13 @@ DECLARE_MESG(DEVICE_SETTINGS) = {
 };
 DECLARE_MESG(USER_PROFILE) = { };
 DECLARE_MESG(ZONES_TARGET) = { };
-DECLARE_MESG(SPORT) = { };
+
+DECLARE_MESG(SPORT) = {
+       .maxfield = 2,
+       .field = {
+               SET_FIELD(SPORT, 1, sub_sport, ENUM),   // 53 - 57 are dive 
activities
+       }
+};
 
 DECLARE_MESG(SESSION) = {
        .maxfield = 40,
@@ -1014,6 +1024,16 @@ static void add_gps_string(garmin_parser_t *garmin, 
const char *desc, struct pos
        }
 }
 
+short
+garmin_parser_is_dive (dc_parser_t *abstract, const unsigned char *data, 
unsigned int size)
+{
+       // set up the parser and extract data
+       dc_parser_set_data(abstract, data, size);
+       garmin_parser_t *garmin = (garmin_parser_t *) abstract;
+
+       return garmin->cache.sub_sport >= 53 && garmin->cache.sub_sport <= 57;
+}
+
 static dc_status_t
 garmin_parser_set_data (dc_parser_t *abstract, const unsigned char *data, 
unsigned int size)
 {
-- 
2.15.2 (Apple Git-101.1)


_______________________________________________
subsurface mailing list
[email protected]
http://lists.subsurface-divelog.org/cgi-bin/mailman/listinfo/subsurface

Reply via email to