From e02037bf8436dc8b159509efeaa5bfe052d05b60 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Tue, 4 Sep 2018 14:41:03 -0700 Subject: [PATCH] garmin: extract the devinfo from the first FIT file we parse A typical FIT file contains several DEVICE_INFO messages. We need to identify the one(s) for the creator (i.e. the actual device, not a sub-component). Note, Garmin identifies the Descent Mk1 as product 2859. I think we should use this as the model number (instead of currently using 0. Also, the vendor event is not to send the vendor name of the device, but in order to send vendor specific events :-) Signed-off-by: Dirk Hohndel Signed-off-by: Linus Torvalds --- src/garmin.c | 27 +++++++++++---------------- src/garmin.h | 2 +- src/garmin_parser.c | 35 +++++++++++++++++++++++++++++++++-- 3 files changed, 45 insertions(+), 19 deletions(-) diff --git a/src/garmin.c b/src/garmin.c index 0d9d71f..32a5936 100644 --- a/src/garmin.c +++ b/src/garmin.c @@ -248,21 +248,6 @@ garmin_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void progress.current = 0; device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); -#if 0 - // Emit a device info event. - dc_event_devinfo_t devinfo; - devinfo.model = 0; - devinfo.firmware = 0; - devinfo.serial = 0; - device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo); - - // Emit a vendor event. - dc_event_vendor_t vendor; - vendor.data = "Garmin"; - vendor.size = 6; - device_event_emit (abstract, DC_EVENT_VENDOR, &vendor); -#endif - file = dc_buffer_new (16384); if (file == NULL) { ERROR (abstract->context, "Insufficient buffer space available."); @@ -275,10 +260,13 @@ garmin_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void return rc; } + dc_event_devinfo_t devinfo; + dc_event_devinfo_t *devinfo_p = &devinfo; for (int i = 0; i < files.nr; i++) { const char *name = files.array[i].name; const unsigned char *data; unsigned int size; + short is_dive = 0; if (device_is_cancelled(abstract)) { status = DC_STATUS_CANCELLED; @@ -296,7 +284,14 @@ 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)) { + is_dive = garmin_parser_is_dive(parser, data, size, devinfo_p); + if (devinfo_p) { + // first time we came through here, let's emit the + // devinfo and vendor events + device_event_emit (abstract, DC_EVENT_DEVINFO, devinfo_p); + devinfo_p = NULL; + } + if (!is_dive) { DEBUG (abstract->context, "decided %s isn't a dive.", name); continue; } diff --git a/src/garmin.h b/src/garmin.h index fd1f504..bd09ed4 100644 --- a/src/garmin.h +++ b/src/garmin.h @@ -40,7 +40,7 @@ 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); +garmin_parser_is_dive (dc_parser_t *abstract, const unsigned char *data, unsigned int size, dc_event_devinfo_t *devinfo_p); // 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 d965e76..51ba677 100644 --- a/src/garmin_parser.c +++ b/src/garmin_parser.c @@ -91,6 +91,9 @@ typedef struct garmin_parser_t { struct { unsigned int initialized; unsigned int sub_sport; + unsigned int serial_nr; + unsigned int product; + unsigned int firmware; unsigned int protocol; unsigned int profile; unsigned int time; @@ -489,6 +492,21 @@ 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 +// DEVICE_INFO +// We just pick the first data we see +DECLARE_FIELD(DEVICE_INFO, product, UINT16) +{ + if (!garmin->cache.product) garmin->cache.product = data; +} +DECLARE_FIELD(DEVICE_INFO, serial_nr, UINT32Z) +{ + if (!garmin->cache.serial_nr) garmin->cache.serial_nr = data; +} +DECLARE_FIELD(DEVICE_INFO, firmware, UINT16) +{ + if (!garmin->cache.firmware) garmin->cache.firmware = data; +} + // SPORT DECLARE_FIELD(SPORT, sub_sport, ENUM) { garmin->cache.sub_sport = (ENUM) data; } @@ -673,7 +691,15 @@ DECLARE_MESG(EVENT) = { } }; -DECLARE_MESG(DEVICE_INFO) = { }; +DECLARE_MESG(DEVICE_INFO) = { + .maxfield = 6, + .field = { + SET_FIELD(DEVICE_INFO, 3, serial_nr, UINT32Z), + SET_FIELD(DEVICE_INFO, 4, product, UINT16), + SET_FIELD(DEVICE_INFO, 5, firmware, UINT16), + } +}; + DECLARE_MESG(ACTIVITY) = { }; DECLARE_MESG(FILE_CREATOR) = { }; DECLARE_MESG(DIVE_SETTINGS) = { }; @@ -1090,12 +1116,17 @@ 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) +garmin_parser_is_dive (dc_parser_t *abstract, const unsigned char *data, unsigned int size, dc_event_devinfo_t *devinfo_p) { // set up the parser and extract data dc_parser_set_data(abstract, data, size); garmin_parser_t *garmin = (garmin_parser_t *) abstract; + if (devinfo_p) { + devinfo_p->firmware = garmin->cache.firmware; + devinfo_p->serial = garmin->cache.serial_nr; + devinfo_p->model = garmin->cache.product; + } return garmin->cache.sub_sport >= 53 && garmin->cache.sub_sport <= 57; }