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 <dirk@hohndel.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
41303bbc70
commit
ac25976258
12
src/garmin.c
12
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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
int
|
||||
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.
|
||||
//
|
||||
|
||||
@ -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,
|
||||
@ -1079,6 +1089,16 @@ static void add_gps_string(garmin_parser_t *garmin, const char *desc, struct pos
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
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)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user