From 86068ba435a01ed2963d0ee2bd449b1c0fd60a75 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel 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 --- 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)