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 <dirk@hohndel.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Dirk Hohndel 2018-09-04 14:41:03 -07:00 committed by Linus Torvalds
parent ac25976258
commit e02037bf84
3 changed files with 45 additions and 19 deletions

View File

@ -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;
}

View File

@ -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.

View File

@ -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;
}