From a8116a0aec730e80c3b7aa3c27dbeb151f2ce2d4 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 2 Feb 2010 15:04:46 +0000 Subject: [PATCH] Add datetime support to the parsers. --- src/libdivecomputer.symbols | 1 + src/mares_nemo_parser.c | 28 ++++++++++++++++++++ src/oceanic_atom2.h | 2 +- src/oceanic_atom2_parser.c | 45 +++++++++++++++++++++++++++++++- src/oceanic_veo250_parser.c | 22 ++++++++++++++++ src/oceanic_vtpro_parser.c | 28 ++++++++++++++++++++ src/parser-private.h | 6 +++-- src/parser.c | 13 +++++++++ src/parser.h | 5 ++++ src/reefnet_sensus.h | 2 +- src/reefnet_sensus_parser.c | 29 +++++++++++++++++++- src/reefnet_sensuspro.h | 2 +- src/reefnet_sensuspro_parser.c | 28 +++++++++++++++++++- src/reefnet_sensusultra.h | 2 +- src/reefnet_sensusultra_parser.c | 28 +++++++++++++++++++- src/suunto_d9_parser.c | 23 ++++++++++++++++ src/suunto_eon.h | 2 +- src/suunto_eon_parser.c | 40 +++++++++++++++++++++++++++- src/suunto_solution_parser.c | 1 + src/suunto_vyper_parser.c | 23 ++++++++++++++++ src/uwatec_memomouse.h | 2 +- src/uwatec_memomouse_parser.c | 29 +++++++++++++++++++- src/uwatec_smart.h | 2 +- src/uwatec_smart_parser.c | 28 +++++++++++++++++++- 24 files changed, 375 insertions(+), 16 deletions(-) diff --git a/src/libdivecomputer.symbols b/src/libdivecomputer.symbols index 450c1b9..cc13e01 100644 --- a/src/libdivecomputer.symbols +++ b/src/libdivecomputer.symbols @@ -15,6 +15,7 @@ dc_datetime_gmtime parser_get_type parser_set_data +parser_get_datetime parser_samples_foreach parser_destroy diff --git a/src/mares_nemo_parser.c b/src/mares_nemo_parser.c index 772b083..1bd6339 100644 --- a/src/mares_nemo_parser.c +++ b/src/mares_nemo_parser.c @@ -35,12 +35,14 @@ struct mares_nemo_parser_t { }; static parser_status_t mares_nemo_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size); +static parser_status_t mares_nemo_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime); static parser_status_t mares_nemo_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); static parser_status_t mares_nemo_parser_destroy (parser_t *abstract); static const parser_backend_t mares_nemo_parser_backend = { PARSER_TYPE_MARES_NEMO, mares_nemo_parser_set_data, /* set_data */ + mares_nemo_parser_get_datetime, /* datetime */ mares_nemo_parser_samples_foreach, /* samples_foreach */ mares_nemo_parser_destroy /* destroy */ }; @@ -101,6 +103,32 @@ mares_nemo_parser_set_data (parser_t *abstract, const unsigned char *data, unsig } +static parser_status_t +mares_nemo_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime) +{ + if (abstract->size < 2) + return PARSER_STATUS_ERROR; + + unsigned int length = array_uint16_le (abstract->data); + + if (length < 8 || length > abstract->size) + return PARSER_STATUS_ERROR; + + const unsigned char *p = abstract->data + length - 8; + + if (datetime) { + datetime->year = p[0] + 2000; + datetime->month = p[1]; + datetime->day = p[2]; + datetime->hour = p[3]; + datetime->minute = p[4]; + datetime->second = 0; + } + + return PARSER_STATUS_SUCCESS; +} + + static parser_status_t mares_nemo_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) { diff --git a/src/oceanic_atom2.h b/src/oceanic_atom2.h index 7dc359d..52c182e 100644 --- a/src/oceanic_atom2.h +++ b/src/oceanic_atom2.h @@ -36,7 +36,7 @@ device_status_t oceanic_atom2_device_keepalive (device_t *device); parser_status_t -oceanic_atom2_parser_create (parser_t **parser); +oceanic_atom2_parser_create (parser_t **parser, unsigned int model); #ifdef __cplusplus } diff --git a/src/oceanic_atom2_parser.c b/src/oceanic_atom2_parser.c index ab5e76c..1e0536e 100644 --- a/src/oceanic_atom2_parser.c +++ b/src/oceanic_atom2_parser.c @@ -33,15 +33,18 @@ typedef struct oceanic_atom2_parser_t oceanic_atom2_parser_t; struct oceanic_atom2_parser_t { parser_t base; + unsigned int model; }; static parser_status_t oceanic_atom2_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size); +static parser_status_t oceanic_atom2_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime); static parser_status_t oceanic_atom2_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); static parser_status_t oceanic_atom2_parser_destroy (parser_t *abstract); static const parser_backend_t oceanic_atom2_parser_backend = { PARSER_TYPE_OCEANIC_ATOM2, oceanic_atom2_parser_set_data, /* set_data */ + oceanic_atom2_parser_get_datetime, /* datetime */ oceanic_atom2_parser_samples_foreach, /* samples_foreach */ oceanic_atom2_parser_destroy /* destroy */ }; @@ -58,7 +61,7 @@ parser_is_oceanic_atom2 (parser_t *abstract) parser_status_t -oceanic_atom2_parser_create (parser_t **out) +oceanic_atom2_parser_create (parser_t **out, unsigned int model) { if (out == NULL) return PARSER_STATUS_ERROR; @@ -73,6 +76,9 @@ oceanic_atom2_parser_create (parser_t **out) // Initialize the base class. parser_init (&parser->base, &oceanic_atom2_parser_backend); + // Set the default values. + parser->model = model; + *out = (parser_t*) parser; return PARSER_STATUS_SUCCESS; @@ -102,6 +108,43 @@ oceanic_atom2_parser_set_data (parser_t *abstract, const unsigned char *data, un } +static parser_status_t +oceanic_atom2_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime) +{ + oceanic_atom2_parser_t *parser = (oceanic_atom2_parser_t *) abstract; + + if (abstract->size < 8) + return PARSER_STATUS_ERROR; + + const unsigned char *p = abstract->data; + + if (datetime) { + if (parser->model == 0x4258) { + // VT3 + datetime->year = ((p[3] & 0xE0) >> 1) + (p[4] & 0x0F) + 2000; + datetime->month = (p[4] & 0xF0) >> 4; + datetime->day = p[3] & 0x1F; + datetime->hour = bcd2dec (p[1] & 0x7F); + } else { + // Atom 2 + datetime->year = bcd2dec (((p[3] & 0xC0) >> 2) + (p[4] & 0x0F)) + 2000; + datetime->month = (p[4] & 0xF0) >> 4; + datetime->day = bcd2dec (p[3] & 0x3F); + datetime->hour = bcd2dec (p[1] & 0x1F); + } + datetime->minute = bcd2dec (p[0]); + datetime->second = 0; + + // Convert to a 24-hour clock. + datetime->hour %= 12; + if (p[1] & 0x80) + datetime->hour += 12; + } + + return PARSER_STATUS_SUCCESS; +} + + static parser_status_t oceanic_atom2_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) { diff --git a/src/oceanic_veo250_parser.c b/src/oceanic_veo250_parser.c index d870116..5954566 100644 --- a/src/oceanic_veo250_parser.c +++ b/src/oceanic_veo250_parser.c @@ -36,12 +36,14 @@ struct oceanic_veo250_parser_t { }; static parser_status_t oceanic_veo250_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size); +static parser_status_t oceanic_veo250_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime); static parser_status_t oceanic_veo250_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); static parser_status_t oceanic_veo250_parser_destroy (parser_t *abstract); static const parser_backend_t oceanic_veo250_parser_backend = { PARSER_TYPE_OCEANIC_VEO250, oceanic_veo250_parser_set_data, /* set_data */ + oceanic_veo250_parser_get_datetime, /* datetime */ oceanic_veo250_parser_samples_foreach, /* samples_foreach */ oceanic_veo250_parser_destroy /* destroy */ }; @@ -102,6 +104,26 @@ oceanic_veo250_parser_set_data (parser_t *abstract, const unsigned char *data, u } +static parser_status_t +oceanic_veo250_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime) +{ + if (abstract->size < 8) + return PARSER_STATUS_ERROR; + + const unsigned char *p = abstract->data; + + if (datetime) { + datetime->year = ((p[5] & 0xF0) >> 4) + ((p[1] & 0xE0) >> 1) + 2003; + datetime->month = ((p[7] & 0xF0) >> 4); + datetime->day = p[1] & 0x1F; + datetime->hour = p[3]; + datetime->minute = p[2]; + datetime->second = 0; + } + + return PARSER_STATUS_SUCCESS; +} + static parser_status_t oceanic_veo250_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) { diff --git a/src/oceanic_vtpro_parser.c b/src/oceanic_vtpro_parser.c index 88d8246..df686fb 100644 --- a/src/oceanic_vtpro_parser.c +++ b/src/oceanic_vtpro_parser.c @@ -36,12 +36,14 @@ struct oceanic_vtpro_parser_t { }; static parser_status_t oceanic_vtpro_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size); +static parser_status_t oceanic_vtpro_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime); static parser_status_t oceanic_vtpro_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); static parser_status_t oceanic_vtpro_parser_destroy (parser_t *abstract); static const parser_backend_t oceanic_vtpro_parser_backend = { PARSER_TYPE_OCEANIC_VTPRO, oceanic_vtpro_parser_set_data, /* set_data */ + oceanic_vtpro_parser_get_datetime, /* datetime */ oceanic_vtpro_parser_samples_foreach, /* samples_foreach */ oceanic_vtpro_parser_destroy /* destroy */ }; @@ -102,6 +104,32 @@ oceanic_vtpro_parser_set_data (parser_t *abstract, const unsigned char *data, un } +static parser_status_t +oceanic_vtpro_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime) +{ + if (abstract->size < 8) + return PARSER_STATUS_ERROR; + + const unsigned char *p = abstract->data; + + if (datetime) { + datetime->year = bcd2dec (p[4] & 0x0F) + 2000; + datetime->month = (p[4] & 0xF0) >> 4; + datetime->day = bcd2dec (p[3]); + datetime->hour = bcd2dec (p[1] & 0x7F); + datetime->minute = bcd2dec (p[0]); + datetime->second = 0; + + // Convert to a 24-hour clock. + datetime->hour %= 12; + if (p[1] & 0x80) + datetime->hour += 12; + } + + return PARSER_STATUS_SUCCESS; +} + + static parser_status_t oceanic_vtpro_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) { diff --git a/src/parser-private.h b/src/parser-private.h index 4156434..6eea8b4 100644 --- a/src/parser-private.h +++ b/src/parser-private.h @@ -22,12 +22,12 @@ #ifndef PARSER_PRIVATE_H #define PARSER_PRIVATE_H +#include "parser.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -#include "parser.h" - struct parser_t; struct parser_backend_t; @@ -44,6 +44,8 @@ struct parser_backend_t { parser_status_t (*set_data) (parser_t *parser, const unsigned char *data, unsigned int size); + parser_status_t (*datetime) (parser_t *parser, dc_datetime_t *datetime); + parser_status_t (*samples_foreach) (parser_t *parser, sample_callback_t callback, void *userdata); parser_status_t (*destroy) (parser_t *parser); diff --git a/src/parser.c b/src/parser.c index b9162f2..8304b7a 100644 --- a/src/parser.c +++ b/src/parser.c @@ -59,6 +59,19 @@ parser_set_data (parser_t *parser, const unsigned char *data, unsigned int size) } +parser_status_t +parser_get_datetime (parser_t *parser, dc_datetime_t *datetime) +{ + if (parser == NULL) + return PARSER_STATUS_UNSUPPORTED; + + if (parser->backend->datetime == NULL) + return PARSER_STATUS_UNSUPPORTED; + + return parser->backend->datetime (parser, datetime); +} + + parser_status_t parser_samples_foreach (parser_t *parser, sample_callback_t callback, void *userdata) { diff --git a/src/parser.h b/src/parser.h index 3be1356..c2a18ca 100644 --- a/src/parser.h +++ b/src/parser.h @@ -22,6 +22,8 @@ #ifndef PARSER_H #define PARSER_H +#include "datetime.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -140,6 +142,9 @@ parser_get_type (parser_t *device); parser_status_t parser_set_data (parser_t *parser, const unsigned char *data, unsigned int size); +parser_status_t +parser_get_datetime (parser_t *parser, dc_datetime_t *datetime); + parser_status_t parser_samples_foreach (parser_t *parser, sample_callback_t callback, void *userdata); diff --git a/src/reefnet_sensus.h b/src/reefnet_sensus.h index 2d9f781..b2c131c 100644 --- a/src/reefnet_sensus.h +++ b/src/reefnet_sensus.h @@ -45,7 +45,7 @@ device_status_t reefnet_sensus_extract_dives (device_t *device, const unsigned char data[], unsigned int size, dive_callback_t callback, void *userdata); parser_status_t -reefnet_sensus_parser_create (parser_t **parser); +reefnet_sensus_parser_create (parser_t **parser, unsigned int devtime, dc_ticks_t systime); parser_status_t reefnet_sensus_parser_set_calibration (parser_t *parser, double atmospheric, double hydrostatic); diff --git a/src/reefnet_sensus_parser.c b/src/reefnet_sensus_parser.c index d649970..768f79d 100644 --- a/src/reefnet_sensus_parser.c +++ b/src/reefnet_sensus_parser.c @@ -26,6 +26,7 @@ #include "parser-private.h" #include "units.h" #include "utils.h" +#include "array.h" #define SAMPLE_DEPTH_ADJUST 13 @@ -36,15 +37,20 @@ struct reefnet_sensus_parser_t { // Depth calibration. double atmospheric; double hydrostatic; + // Clock synchronization. + unsigned int devtime; + dc_ticks_t systime; }; static parser_status_t reefnet_sensus_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size); +static parser_status_t reefnet_sensus_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime); static parser_status_t reefnet_sensus_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); static parser_status_t reefnet_sensus_parser_destroy (parser_t *abstract); static const parser_backend_t reefnet_sensus_parser_backend = { PARSER_TYPE_REEFNET_SENSUS, reefnet_sensus_parser_set_data, /* set_data */ + reefnet_sensus_parser_get_datetime, /* datetime */ reefnet_sensus_parser_samples_foreach, /* samples_foreach */ reefnet_sensus_parser_destroy /* destroy */ }; @@ -61,7 +67,7 @@ parser_is_reefnet_sensus (parser_t *abstract) parser_status_t -reefnet_sensus_parser_create (parser_t **out) +reefnet_sensus_parser_create (parser_t **out, unsigned int devtime, dc_ticks_t systime) { if (out == NULL) return PARSER_STATUS_ERROR; @@ -79,6 +85,8 @@ reefnet_sensus_parser_create (parser_t **out) // Set the default values. parser->atmospheric = ATM; parser->hydrostatic = 1025.0 * GRAVITY; + parser->devtime = devtime; + parser->systime = systime; *out = (parser_t*) parser; @@ -124,6 +132,25 @@ reefnet_sensus_parser_set_calibration (parser_t *abstract, double atmospheric, d } +static parser_status_t +reefnet_sensus_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime) +{ + reefnet_sensus_parser_t *parser = (reefnet_sensus_parser_t *) abstract; + + if (abstract->size < 2 + 4) + return PARSER_STATUS_ERROR; + + unsigned int timestamp = array_uint32_le (abstract->data + 2); + + dc_ticks_t ticks = parser->systime - (parser->devtime - timestamp); + + if (!dc_datetime_localtime (datetime, ticks)) + return PARSER_STATUS_ERROR; + + return PARSER_STATUS_SUCCESS; +} + + static parser_status_t reefnet_sensus_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) { diff --git a/src/reefnet_sensuspro.h b/src/reefnet_sensuspro.h index 247e4d9..a8deabe 100644 --- a/src/reefnet_sensuspro.h +++ b/src/reefnet_sensuspro.h @@ -48,7 +48,7 @@ device_status_t reefnet_sensuspro_extract_dives (device_t *device, const unsigned char data[], unsigned int size, dive_callback_t callback, void *userdata); parser_status_t -reefnet_sensuspro_parser_create (parser_t **parser); +reefnet_sensuspro_parser_create (parser_t **parser, unsigned int devtime, dc_ticks_t systime); parser_status_t reefnet_sensuspro_parser_set_calibration (parser_t *parser, double atmospheric, double hydrostatic); diff --git a/src/reefnet_sensuspro_parser.c b/src/reefnet_sensuspro_parser.c index acd8a07..0d9a57e 100644 --- a/src/reefnet_sensuspro_parser.c +++ b/src/reefnet_sensuspro_parser.c @@ -36,15 +36,20 @@ struct reefnet_sensuspro_parser_t { // Depth calibration. double atmospheric; double hydrostatic; + // Clock synchronization. + unsigned int devtime; + dc_ticks_t systime; }; static parser_status_t reefnet_sensuspro_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size); +static parser_status_t reefnet_sensuspro_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime); static parser_status_t reefnet_sensuspro_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); static parser_status_t reefnet_sensuspro_parser_destroy (parser_t *abstract); static const parser_backend_t reefnet_sensuspro_parser_backend = { PARSER_TYPE_REEFNET_SENSUSPRO, reefnet_sensuspro_parser_set_data, /* set_data */ + reefnet_sensuspro_parser_get_datetime, /* datetime */ reefnet_sensuspro_parser_samples_foreach, /* samples_foreach */ reefnet_sensuspro_parser_destroy /* destroy */ }; @@ -61,7 +66,7 @@ parser_is_reefnet_sensuspro (parser_t *abstract) parser_status_t -reefnet_sensuspro_parser_create (parser_t **out) +reefnet_sensuspro_parser_create (parser_t **out, unsigned int devtime, dc_ticks_t systime) { if (out == NULL) return PARSER_STATUS_ERROR; @@ -79,6 +84,8 @@ reefnet_sensuspro_parser_create (parser_t **out) // Set the default values. parser->atmospheric = ATM; parser->hydrostatic = 1025.0 * GRAVITY; + parser->devtime = devtime; + parser->systime = systime; *out = (parser_t*) parser; @@ -124,6 +131,25 @@ reefnet_sensuspro_parser_set_calibration (parser_t *abstract, double atmospheric } +static parser_status_t +reefnet_sensuspro_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime) +{ + reefnet_sensuspro_parser_t *parser = (reefnet_sensuspro_parser_t *) abstract; + + if (abstract->size < 6 + 4) + return PARSER_STATUS_ERROR; + + unsigned int timestamp = array_uint32_le (abstract->data + 6); + + dc_ticks_t ticks = parser->systime - (parser->devtime - timestamp); + + if (!dc_datetime_localtime (datetime, ticks)) + return PARSER_STATUS_ERROR; + + return PARSER_STATUS_SUCCESS; +} + + static parser_status_t reefnet_sensuspro_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) { diff --git a/src/reefnet_sensusultra.h b/src/reefnet_sensusultra.h index 4879237..68d0ca8 100644 --- a/src/reefnet_sensusultra.h +++ b/src/reefnet_sensusultra.h @@ -71,7 +71,7 @@ device_status_t reefnet_sensusultra_extract_dives (device_t *device, const unsigned char data[], unsigned int size, dive_callback_t callback, void *userdata); parser_status_t -reefnet_sensusultra_parser_create (parser_t **parser); +reefnet_sensusultra_parser_create (parser_t **parser, unsigned int devtime, dc_ticks_t systime); parser_status_t reefnet_sensusultra_parser_set_calibration (parser_t *parser, double atmospheric, double hydrostatic); diff --git a/src/reefnet_sensusultra_parser.c b/src/reefnet_sensusultra_parser.c index 2dcb74f..e65ad76 100644 --- a/src/reefnet_sensusultra_parser.c +++ b/src/reefnet_sensusultra_parser.c @@ -36,15 +36,20 @@ struct reefnet_sensusultra_parser_t { // Depth calibration. double atmospheric; double hydrostatic; + // Clock synchronization. + unsigned int devtime; + dc_ticks_t systime; }; static parser_status_t reefnet_sensusultra_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size); +static parser_status_t reefnet_sensusultra_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime); static parser_status_t reefnet_sensusultra_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); static parser_status_t reefnet_sensusultra_parser_destroy (parser_t *abstract); static const parser_backend_t reefnet_sensusultra_parser_backend = { PARSER_TYPE_REEFNET_SENSUSULTRA, reefnet_sensusultra_parser_set_data, /* set_data */ + reefnet_sensusultra_parser_get_datetime, /* datetime */ reefnet_sensusultra_parser_samples_foreach, /* samples_foreach */ reefnet_sensusultra_parser_destroy /* destroy */ }; @@ -61,7 +66,7 @@ parser_is_reefnet_sensusultra (parser_t *abstract) parser_status_t -reefnet_sensusultra_parser_create (parser_t **out) +reefnet_sensusultra_parser_create (parser_t **out, unsigned int devtime, dc_ticks_t systime) { if (out == NULL) return PARSER_STATUS_ERROR; @@ -79,6 +84,8 @@ reefnet_sensusultra_parser_create (parser_t **out) // Set the default values. parser->atmospheric = ATM; parser->hydrostatic = 1025.0 * GRAVITY; + parser->devtime = devtime; + parser->systime = systime; *out = (parser_t*) parser; @@ -124,6 +131,25 @@ reefnet_sensusultra_parser_set_calibration (parser_t *abstract, double atmospher } +static parser_status_t +reefnet_sensusultra_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime) +{ + reefnet_sensusultra_parser_t *parser = (reefnet_sensusultra_parser_t *) abstract; + + if (abstract->size < 4 + 4) + return PARSER_STATUS_ERROR; + + unsigned int timestamp = array_uint32_le (abstract->data + 4); + + dc_ticks_t ticks = parser->systime - (parser->devtime - timestamp); + + if (!dc_datetime_localtime (datetime, ticks)) + return PARSER_STATUS_ERROR; + + return PARSER_STATUS_SUCCESS; +} + + static parser_status_t reefnet_sensusultra_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) { diff --git a/src/suunto_d9_parser.c b/src/suunto_d9_parser.c index 7729ec6..9918cdf 100644 --- a/src/suunto_d9_parser.c +++ b/src/suunto_d9_parser.c @@ -38,12 +38,14 @@ struct suunto_d9_parser_t { }; static parser_status_t suunto_d9_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size); +static parser_status_t suunto_d9_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime); static parser_status_t suunto_d9_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); static parser_status_t suunto_d9_parser_destroy (parser_t *abstract); static const parser_backend_t suunto_d9_parser_backend = { PARSER_TYPE_SUUNTO_D9, suunto_d9_parser_set_data, /* set_data */ + suunto_d9_parser_get_datetime, /* datetime */ suunto_d9_parser_samples_foreach, /* samples_foreach */ suunto_d9_parser_destroy /* destroy */ }; @@ -107,6 +109,27 @@ suunto_d9_parser_set_data (parser_t *abstract, const unsigned char *data, unsign } +static parser_status_t +suunto_d9_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime) +{ + if (abstract->size < 0x15 - 4 + 7) + return PARSER_STATUS_ERROR; + + const unsigned char *p = abstract->data + 0x15 - 4; + + if (datetime) { + datetime->hour = p[0]; + datetime->minute = p[1]; + datetime->second = p[2]; + datetime->year = p[3] + (p[4] << 8); + datetime->month = p[5]; + datetime->day = p[6]; + } + + return PARSER_STATUS_SUCCESS; +} + + static parser_status_t suunto_d9_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) { diff --git a/src/suunto_eon.h b/src/suunto_eon.h index 3e1519b..0f2c63a 100644 --- a/src/suunto_eon.h +++ b/src/suunto_eon.h @@ -44,7 +44,7 @@ device_status_t suunto_eon_extract_dives (device_t *device, const unsigned char data[], unsigned int size, dive_callback_t callback, void *userdata); parser_status_t -suunto_eon_parser_create (parser_t **parser); +suunto_eon_parser_create (parser_t **parser, int spyder); #ifdef __cplusplus } diff --git a/src/suunto_eon_parser.c b/src/suunto_eon_parser.c index dc3a6a3..bde2a93 100644 --- a/src/suunto_eon_parser.c +++ b/src/suunto_eon_parser.c @@ -26,20 +26,24 @@ #include "parser-private.h" #include "units.h" #include "utils.h" +#include "array.h" typedef struct suunto_eon_parser_t suunto_eon_parser_t; struct suunto_eon_parser_t { parser_t base; + int spyder; }; static parser_status_t suunto_eon_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size); +static parser_status_t suunto_eon_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime); static parser_status_t suunto_eon_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); static parser_status_t suunto_eon_parser_destroy (parser_t *abstract); static const parser_backend_t suunto_eon_parser_backend = { PARSER_TYPE_SUUNTO_EON, suunto_eon_parser_set_data, /* set_data */ + suunto_eon_parser_get_datetime, /* datetime */ suunto_eon_parser_samples_foreach, /* samples_foreach */ suunto_eon_parser_destroy /* destroy */ }; @@ -56,7 +60,7 @@ parser_is_suunto_eon (parser_t *abstract) parser_status_t -suunto_eon_parser_create (parser_t **out) +suunto_eon_parser_create (parser_t **out, int spyder) { if (out == NULL) return PARSER_STATUS_ERROR; @@ -71,6 +75,9 @@ suunto_eon_parser_create (parser_t **out) // Initialize the base class. parser_init (&parser->base, &suunto_eon_parser_backend); + // Set the default values. + parser->spyder = spyder; + *out = (parser_t*) parser; return PARSER_STATUS_SUCCESS; @@ -100,6 +107,37 @@ suunto_eon_parser_set_data (parser_t *abstract, const unsigned char *data, unsig } +static parser_status_t +suunto_eon_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime) +{ + suunto_eon_parser_t *parser = (suunto_eon_parser_t *) abstract; + + if (abstract->size < 6 + 5) + return DEVICE_STATUS_ERROR; + + const unsigned char *p = abstract->data + 6; + + if (datetime) { + if (parser->spyder) { + datetime->year = p[0] + (p[0] < 90 ? 2000 : 1900); + datetime->month = p[1]; + datetime->day = p[2]; + datetime->hour = p[3]; + datetime->minute = p[4]; + } else { + datetime->year = bcd2dec (p[0]) + (bcd2dec (p[0]) < 85 ? 2000 : 1900); + datetime->month = bcd2dec (p[1]); + datetime->day = bcd2dec (p[2]); + datetime->hour = bcd2dec (p[3]); + datetime->minute = bcd2dec (p[4]); + } + datetime->second = 0; + } + + return PARSER_STATUS_SUCCESS; +} + + static parser_status_t suunto_eon_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) { diff --git a/src/suunto_solution_parser.c b/src/suunto_solution_parser.c index 1029fd0..28353a9 100644 --- a/src/suunto_solution_parser.c +++ b/src/suunto_solution_parser.c @@ -40,6 +40,7 @@ static parser_status_t suunto_solution_parser_destroy (parser_t *abstract); static const parser_backend_t suunto_solution_parser_backend = { PARSER_TYPE_SUUNTO_SOLUTION, suunto_solution_parser_set_data, /* set_data */ + NULL, /* datetime */ suunto_solution_parser_samples_foreach, /* samples_foreach */ suunto_solution_parser_destroy /* destroy */ }; diff --git a/src/suunto_vyper_parser.c b/src/suunto_vyper_parser.c index 56a356b..3d3a638 100644 --- a/src/suunto_vyper_parser.c +++ b/src/suunto_vyper_parser.c @@ -34,12 +34,14 @@ struct suunto_vyper_parser_t { }; static parser_status_t suunto_vyper_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size); +static parser_status_t suunto_vyper_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime); static parser_status_t suunto_vyper_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); static parser_status_t suunto_vyper_parser_destroy (parser_t *abstract); static const parser_backend_t suunto_vyper_parser_backend = { PARSER_TYPE_SUUNTO_VYPER, suunto_vyper_parser_set_data, /* set_data */ + suunto_vyper_parser_get_datetime, /* datetime */ suunto_vyper_parser_samples_foreach, /* samples_foreach */ suunto_vyper_parser_destroy /* destroy */ }; @@ -100,6 +102,27 @@ suunto_vyper_parser_set_data (parser_t *abstract, const unsigned char *data, uns } +static parser_status_t +suunto_vyper_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime) +{ + if (abstract->size < 9 + 5) + return DEVICE_STATUS_ERROR; + + const unsigned char *p = abstract->data + 9; + + if (datetime) { + datetime->year = p[0] + (p[0] < 90 ? 2000 : 1900); + datetime->month = p[1]; + datetime->day = p[2]; + datetime->hour = p[3]; + datetime->minute = p[4]; + datetime->second = 0; + } + + return PARSER_STATUS_SUCCESS; +} + + static parser_status_t suunto_vyper_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) { diff --git a/src/uwatec_memomouse.h b/src/uwatec_memomouse.h index a758182..a6c9b64 100644 --- a/src/uwatec_memomouse.h +++ b/src/uwatec_memomouse.h @@ -39,7 +39,7 @@ device_status_t uwatec_memomouse_extract_dives (device_t *device, const unsigned char data[], unsigned int size, dive_callback_t callback, void *userdata); parser_status_t -uwatec_memomouse_parser_create (parser_t **parser); +uwatec_memomouse_parser_create (parser_t **parser, unsigned int devtime, dc_ticks_t systime); #ifdef __cplusplus } diff --git a/src/uwatec_memomouse_parser.c b/src/uwatec_memomouse_parser.c index 8a55d4b..6df999d 100644 --- a/src/uwatec_memomouse_parser.c +++ b/src/uwatec_memomouse_parser.c @@ -31,15 +31,19 @@ typedef struct uwatec_memomouse_parser_t uwatec_memomouse_parser_t; struct uwatec_memomouse_parser_t { parser_t base; + unsigned int devtime; + dc_ticks_t systime; }; static parser_status_t uwatec_memomouse_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size); +static parser_status_t uwatec_memomouse_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime); static parser_status_t uwatec_memomouse_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); static parser_status_t uwatec_memomouse_parser_destroy (parser_t *abstract); static const parser_backend_t uwatec_memomouse_parser_backend = { PARSER_TYPE_UWATEC_MEMOMOUSE, uwatec_memomouse_parser_set_data, /* set_data */ + uwatec_memomouse_parser_get_datetime, /* datetime */ uwatec_memomouse_parser_samples_foreach, /* samples_foreach */ uwatec_memomouse_parser_destroy /* destroy */ }; @@ -56,7 +60,7 @@ parser_is_uwatec_memomouse (parser_t *abstract) parser_status_t -uwatec_memomouse_parser_create (parser_t **out) +uwatec_memomouse_parser_create (parser_t **out, unsigned int devtime, dc_ticks_t systime) { if (out == NULL) return PARSER_STATUS_ERROR; @@ -71,6 +75,10 @@ uwatec_memomouse_parser_create (parser_t **out) // Initialize the base class. parser_init (&parser->base, &uwatec_memomouse_parser_backend); + // Set the default values. + parser->devtime = devtime; + parser->systime = systime; + *out = (parser_t*) parser; return PARSER_STATUS_SUCCESS; @@ -100,6 +108,25 @@ uwatec_memomouse_parser_set_data (parser_t *abstract, const unsigned char *data, } +static parser_status_t +uwatec_memomouse_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime) +{ + uwatec_memomouse_parser_t *parser = (uwatec_memomouse_parser_t *) abstract; + + if (abstract->size < 11 + 4) + return PARSER_STATUS_ERROR; + + unsigned int timestamp = array_uint32_le (abstract->data + 11); + + dc_ticks_t ticks = parser->systime - (parser->devtime - timestamp) / 2; + + if (!dc_datetime_localtime (datetime, ticks)) + return PARSER_STATUS_ERROR; + + return PARSER_STATUS_SUCCESS; +} + + static parser_status_t uwatec_memomouse_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) { diff --git a/src/uwatec_smart.h b/src/uwatec_smart.h index 66e5718..fa3045e 100644 --- a/src/uwatec_smart.h +++ b/src/uwatec_smart.h @@ -41,7 +41,7 @@ device_status_t uwatec_smart_extract_dives (device_t *device, const unsigned char data[], unsigned int size, dive_callback_t callback, void *userdata); parser_status_t -uwatec_smart_parser_create (parser_t **parser, unsigned int model); +uwatec_smart_parser_create (parser_t **parser, unsigned int model, unsigned int devtime, dc_ticks_t systime); #ifdef __cplusplus } diff --git a/src/uwatec_smart_parser.c b/src/uwatec_smart_parser.c index 963c4ba..299241c 100644 --- a/src/uwatec_smart_parser.c +++ b/src/uwatec_smart_parser.c @@ -27,6 +27,7 @@ #include "parser-private.h" #include "units.h" #include "utils.h" +#include "array.h" #define NBITS 8 #define NELEMENTS(x) ( sizeof(x) / sizeof((x)[0]) ) @@ -36,15 +37,19 @@ typedef struct uwatec_smart_parser_t uwatec_smart_parser_t; struct uwatec_smart_parser_t { parser_t base; unsigned int model; + unsigned int devtime; + dc_ticks_t systime; }; static parser_status_t uwatec_smart_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size); +static parser_status_t uwatec_smart_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime); static parser_status_t uwatec_smart_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); static parser_status_t uwatec_smart_parser_destroy (parser_t *abstract); static const parser_backend_t uwatec_smart_parser_backend = { PARSER_TYPE_UWATEC_SMART, uwatec_smart_parser_set_data, /* set_data */ + uwatec_smart_parser_get_datetime, /* datetime */ uwatec_smart_parser_samples_foreach, /* samples_foreach */ uwatec_smart_parser_destroy /* destroy */ }; @@ -61,7 +66,7 @@ parser_is_uwatec_smart (parser_t *abstract) parser_status_t -uwatec_smart_parser_create (parser_t **out, unsigned int model) +uwatec_smart_parser_create (parser_t **out, unsigned int model, unsigned int devtime, dc_ticks_t systime) { if (out == NULL) return PARSER_STATUS_ERROR; @@ -78,6 +83,8 @@ uwatec_smart_parser_create (parser_t **out, unsigned int model) // Set the default values. parser->model = model; + parser->devtime = devtime; + parser->systime = systime; *out = (parser_t*) parser; @@ -108,6 +115,25 @@ uwatec_smart_parser_set_data (parser_t *abstract, const unsigned char *data, uns } +static parser_status_t +uwatec_smart_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime) +{ + uwatec_smart_parser_t *parser = (uwatec_smart_parser_t *) abstract; + + if (abstract->size < 8 + 4) + return PARSER_STATUS_ERROR; + + unsigned int timestamp = array_uint32_le (abstract->data + 8); + + dc_ticks_t ticks = parser->systime - (parser->devtime - timestamp) / 2; + + if (!dc_datetime_localtime (datetime, ticks)) + return PARSER_STATUS_ERROR; + + return PARSER_STATUS_SUCCESS; +} + + static unsigned int uwatec_smart_identify (const unsigned char data[], unsigned int size) {