From c39dda89bcd3074e59013549e75656ec501a546b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 27 Oct 2014 17:19:48 -0700 Subject: [PATCH] Suunto EON Steel: populate various string data The EON Steel saves the dive computer firmware versions etc per dive, which is really nice for upgrades: old dives done with older firmware still show the firmware at the time of the dive. That, in turn, is nice because we can use it for a reliable dive ID - dive time with serial number etc. This uses the new DC_FIELD_STRING model to feed the hw/sw information to the application, since we need the parser to access it. It also returns battery state and deco model information. Signed-off-by: Linus Torvalds Signed-off-by: Dirk Hohndel --- src/suunto_eonsteel_parser.c | 49 +++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/suunto_eonsteel_parser.c b/src/suunto_eonsteel_parser.c index 10577b2..f8322a4 100644 --- a/src/suunto_eonsteel_parser.c +++ b/src/suunto_eonsteel_parser.c @@ -68,6 +68,7 @@ struct type_desc { #define MAXTYPE 512 #define MAXGASES 16 +#define MAXSTRINGS 16 typedef struct suunto_eonsteel_parser_t { dc_parser_t base; @@ -82,6 +83,7 @@ typedef struct suunto_eonsteel_parser_t { dc_gasmix_t gasmix[MAXGASES]; dc_salinity_t salinity; double surface_pressure; + dc_field_string_t strings[MAXSTRINGS]; } cache; } suunto_eonsteel_parser_t; @@ -868,6 +870,19 @@ suunto_eonsteel_parser_samples_foreach(dc_parser_t *abstract, dc_sample_callback return DC_STATUS_SUCCESS; } +static dc_status_t get_string_field(suunto_eonsteel_parser_t *eon, unsigned idx, dc_field_string_t *value) +{ + if (idx < MAXSTRINGS) { + dc_field_string_t *res = eon->cache.strings+idx; + if (res->desc && res->value) { + *value = *res; + return DC_STATUS_SUCCESS; + } + + } + return DC_STATUS_UNSUPPORTED; +} + // Ugly define thing makes the code much easier to read // I'd love to use __typeof__, but that's a gcc'ism #define field_value(p, set) \ @@ -905,6 +920,8 @@ suunto_eonsteel_parser_get_field(dc_parser_t *parser, dc_field_type_t type, unsi case DC_FIELD_ATMOSPHERIC: field_value(value, eon->cache.surface_pressure); break; + case DC_FIELD_STRING: + return get_string_field(eon, flags, (dc_field_string_t *)value); default: return DC_STATUS_UNSUPPORTED; } @@ -980,6 +997,22 @@ static int add_gas_he(suunto_eonsteel_parser_t *eon, unsigned char he) return 0; } +static int add_string(suunto_eonsteel_parser_t *eon, const char *desc, const char *value) +{ + int i; + + eon->cache.initialized |= 1 << DC_FIELD_STRING; + for (i = 0; i < MAXSTRINGS; i++) { + dc_field_string_t *str = eon->cache.strings+i; + if (str->desc) + continue; + str->desc = desc; + str->value = strdup(value); + break; + } + return 0; +} + static float get_le32_float(const unsigned char *src) { union { @@ -1003,7 +1036,16 @@ static int traverse_device_fields(suunto_eonsteel_parser_t *eon, const struct ty const unsigned char *data, int len) { const char *name = desc->desc + strlen("sml.DeviceLog.Device."); - + if (!strcmp(name, "SerialNumber")) + return add_string(eon, "Serial", data); + if (!strcmp(name, "Info.HW")) + return add_string(eon, "HW Version", data); + if (!strcmp(name, "Info.SW")) + return add_string(eon, "FW Version", data); + if (!strcmp(name, "Info.BatteryAtStart")) + return add_string(eon, "Battery at start", data); + if (!strcmp(name, "Info.BatteryAtEnd")) + return add_string(eon, "Battery at end", data); return 0; } @@ -1070,6 +1112,9 @@ static int traverse_diving_fields(suunto_eonsteel_parser_t *eon, const struct ty return 0; } + if (!strcmp(name, "Algorithm")) + return add_string(eon, "Deco algorithm", data); + return 0; } @@ -1096,6 +1141,8 @@ static int traverse_header_fields(suunto_eonsteel_parser_t *eon, const struct ty eon->cache.maxdepth = d; return 0; } + if (!strcmp(name, "DateTime")) + return add_string(eon, "Dive ID", data); return 0; }