From bc2ba57302ad2ffcbc36b511180c3bb11236c0e5 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 28 Aug 2018 16:18:06 -0700 Subject: [PATCH] garmin: teach the parser about invalid values and more dates The invalid values skip the parser callback function entirely. Of course, since it's not really doing anything right now, that's mostly costmetic. Extend the FIT type declarations to also have the invalid values. Also, add a few timestamp entries, and print them out to show the timestamps in a human-legible format. Signed-off-by: Linus Torvalds --- src/garmin_parser.c | 58 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/src/garmin_parser.c b/src/garmin_parser.c index 22def7c..22421af 100644 --- a/src/garmin_parser.c +++ b/src/garmin_parser.c @@ -109,9 +109,24 @@ garmin_parser_create (dc_parser_t **out, dc_context_t *context) return DC_STATUS_SUCCESS; } -typedef unsigned char ENUM; -typedef unsigned short UINT16; -typedef unsigned int UINT32; +#define DECLARE_FIT_TYPE(name, ctype, inval) \ + typedef ctype name; \ + static const name name##_INVAL = inval + +DECLARE_FIT_TYPE(ENUM, unsigned char, 0xff); +DECLARE_FIT_TYPE(UINT8, unsigned char, 0xff); +DECLARE_FIT_TYPE(UINT16, unsigned short, 0xffff); +DECLARE_FIT_TYPE(UINT32, unsigned int, 0xffffffff); +DECLARE_FIT_TYPE(UINT64, unsigned long long, 0xffffffffffffffffull); + +DECLARE_FIT_TYPE(UINT8Z, unsigned char, 0); +DECLARE_FIT_TYPE(UINT16Z, unsigned short, 0); +DECLARE_FIT_TYPE(UINT32Z, unsigned int, 0); + +DECLARE_FIT_TYPE(SINT8, signed char, 0x7f); +DECLARE_FIT_TYPE(SINT16, signed short, 0x7fff); +DECLARE_FIT_TYPE(SINT32, signed int, 0x7fffffff); +DECLARE_FIT_TYPE(SINT64, signed long long, 0x7fffffffffffffffll); /* * Garmin FIT events are described by tuples of "global mesg ID" and @@ -133,6 +148,7 @@ struct field_desc { static int parse_##name##_##type(struct garmin_parser_t *g, const unsigned char *p) \ { \ type val = *(type *)p; \ + if (val == type##_INVAL) return 0; \ fprintf(stderr, "%s: %llx\n", #name, (long long)val); \ return parse_##name(g, *(type *)p); \ } \ @@ -140,7 +156,19 @@ struct field_desc { static int parse_##name(struct garmin_parser_t *garmin, type data) // All msg formats can have a timestamp -DECLARE_FIELD(ANY, timestamp, UINT32) { return 0; } +// Garmin timestamps are in seconds since 00:00 Dec 31 1989 UTC +// Convert to "standard epoch time" by adding 631065600. +DECLARE_FIELD(ANY, timestamp, UINT32) +{ + dc_ticks_t time = 631065600 + (dc_ticks_t) data; + dc_datetime_t date; + + dc_datetime_gmtime(&date, time); + fprintf(stderr, "%04d-%02d-%02d %2d:%02d:%02d\n", + date.year, date.month, date.day, + date.hour, date.minute, date.second); + return 0; +} DECLARE_FIELD(ANY, message_index, UINT16) { return 0; } DECLARE_FIELD(ANY, part_index, UINT32) { return 0; } @@ -149,13 +177,18 @@ DECLARE_FIELD(FILE, file_type, ENUM) { return 0; } DECLARE_FIELD(FILE, manufacturer, UINT16) { return 0; } DECLARE_FIELD(FILE, product, UINT16) { return 0; } DECLARE_FIELD(FILE, serial, UINT32) { return 0; } -DECLARE_FIELD(FILE, creation_time, UINT32) { return 0; } +DECLARE_FIELD(FILE, creation_time, UINT32) { return parse_ANY_timestamp(garmin, data); } +DECLARE_FIELD(FILE, number, UINT16) { return 0; } +DECLARE_FIELD(FILE, other_time, UINT32) { return parse_ANY_timestamp(garmin, data); } // SESSION msg -DECLARE_FIELD(SESSION, start_time, UINT32) { return 0; } +DECLARE_FIELD(SESSION, start_time, UINT32) { return parse_ANY_timestamp(garmin, data); } + +// LAP msg +DECLARE_FIELD(LAP, start_time, UINT32) { return parse_ANY_timestamp(garmin, data); } // RECORD msg -DECLARE_FIELD(RECORD, start_time, UINT32) { return 0; } +DECLARE_FIELD(RECORD, start_time, UINT32) { return parse_ANY_timestamp(garmin, data); } struct msg_desc { @@ -170,13 +203,15 @@ struct msg_desc { static const struct msg_desc name##_msg_desc DECLARE_MESG(FILE) = { - .maxfield = 5, + .maxfield = 8, .field = { SET_FIELD(FILE, 0, file_type, ENUM), SET_FIELD(FILE, 1, manufacturer, UINT16), SET_FIELD(FILE, 2, product, UINT16), SET_FIELD(FILE, 3, serial, UINT32), SET_FIELD(FILE, 4, creation_time, UINT32), + SET_FIELD(FILE, 5, number, UINT16), + SET_FIELD(FILE, 7, other_time, UINT32), } }; @@ -192,7 +227,12 @@ DECLARE_MESG(SESSION) = { } }; -DECLARE_MESG(LAP) = { }; +DECLARE_MESG(LAP) = { + .maxfield = 3, + .field = { + SET_FIELD(LAP, 2, start_time, UINT32), + } +}; DECLARE_MESG(RECORD) = { .maxfield = 3,