diff --git a/examples/universal.c b/examples/universal.c index 54d8ebd..332b0bf 100644 --- a/examples/universal.c +++ b/examples/universal.c @@ -335,7 +335,7 @@ doparse (FILE *fp, device_data_t *devdata, const unsigned char data[], unsigned rc = mares_nemo_parser_create (&parser, devdata->devinfo.model); break; case DEVICE_TYPE_MARES_ICONHD: - rc = mares_iconhd_parser_create (&parser); + rc = mares_iconhd_parser_create (&parser, devdata->devinfo.model); break; case DEVICE_TYPE_HW_OSTC: rc = hw_ostc_parser_create (&parser); diff --git a/src/mares_iconhd.c b/src/mares_iconhd.c index a2f986b..6e40c87 100644 --- a/src/mares_iconhd.c +++ b/src/mares_iconhd.c @@ -33,11 +33,12 @@ rc == -1 ? DEVICE_STATUS_IO : DEVICE_STATUS_TIMEOUT \ ) +#define ICONHD 0x14 +#define ICONHDNET 0x15 + #define ACK 0xAA #define EOF 0xEA -#define HEADER 0x5C - #define RB_PROFILE_BEGIN 0xA000 #define RB_PROFILE_END MARES_ICONHD_MEMORY_SIZE @@ -339,7 +340,7 @@ mares_iconhd_device_foreach (device_t *abstract, dive_callback_t callback, void // Emit a device info event. unsigned char *data = dc_buffer_get_data (buffer); device_devinfo_t devinfo; - devinfo.model = 0; + devinfo.model = data[0]; devinfo.firmware = 0; devinfo.serial = array_uint16_le (data + 12); device_event_emit (abstract, DEVICE_EVENT_DEVINFO, &devinfo); @@ -364,6 +365,14 @@ mares_iconhd_extract_dives (device_t *abstract, const unsigned char data[], unsi if (size < MARES_ICONHD_MEMORY_SIZE) return DEVICE_STATUS_ERROR; + // Get the model code. + unsigned int model = data[0]; + + // Get the corresponding dive header size. + unsigned int header = 0x5C; + if (model == ICONHDNET) + header = 0x80; + // Get the end of the profile ring buffer. unsigned int eop = 0; const unsigned int config[] = {0x2001, 0x3001}; @@ -388,9 +397,9 @@ mares_iconhd_extract_dives (device_t *abstract, const unsigned char data[], unsi memcpy (buffer + RB_PROFILE_END - eop, data + RB_PROFILE_BEGIN, eop - RB_PROFILE_BEGIN); unsigned int offset = RB_PROFILE_END - RB_PROFILE_BEGIN; - while (offset >= HEADER + 4) { + while (offset >= header + 4) { // Get the number of samples in the profile data. - unsigned int nsamples = array_uint16_le (buffer + offset - HEADER + 2); + unsigned int nsamples = array_uint16_le (buffer + offset - header + 2); if (nsamples == 0xFFFF) break; @@ -398,7 +407,11 @@ mares_iconhd_extract_dives (device_t *abstract, const unsigned char data[], unsi // If the buffer does not contain that much bytes, we reached the // end of the ringbuffer. The current dive is incomplete (partially // overwritten with newer data), and processing should stop. - unsigned int nbytes = 4 + nsamples * 8 + HEADER; + unsigned int nbytes = 4 + header; + if (model == ICONHDNET) + nbytes += nsamples * 12 + (nsamples / 4) * 8; + else + nbytes += nsamples * 8; if (offset < nbytes) break; @@ -417,7 +430,7 @@ mares_iconhd_extract_dives (device_t *abstract, const unsigned char data[], unsi return DEVICE_STATUS_ERROR; } - unsigned char *fp = buffer + offset + length - HEADER + 6; + unsigned char *fp = buffer + offset + length - header + 6; if (device && memcmp (fp, device->fingerprint, sizeof (device->fingerprint)) == 0) { free (buffer); return DEVICE_STATUS_SUCCESS; diff --git a/src/mares_iconhd.h b/src/mares_iconhd.h index 41b8780..32e15c3 100644 --- a/src/mares_iconhd.h +++ b/src/mares_iconhd.h @@ -38,7 +38,7 @@ device_status_t mares_iconhd_extract_dives (device_t *abstract, const unsigned char data[], unsigned int size, dive_callback_t callback, void *userdata); parser_status_t -mares_iconhd_parser_create (parser_t **parser); +mares_iconhd_parser_create (parser_t **parser, unsigned int model); #ifdef __cplusplus } diff --git a/src/mares_iconhd_parser.c b/src/mares_iconhd_parser.c index 20b8770..49840b2 100644 --- a/src/mares_iconhd_parser.c +++ b/src/mares_iconhd_parser.c @@ -26,12 +26,14 @@ #include "utils.h" #include "array.h" -#define HEADER 0x5C +#define ICONHD 0x14 +#define ICONHDNET 0x15 typedef struct mares_iconhd_parser_t mares_iconhd_parser_t; struct mares_iconhd_parser_t { parser_t base; + unsigned int model; }; static parser_status_t mares_iconhd_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size); @@ -61,7 +63,7 @@ parser_is_mares_iconhd (parser_t *abstract) parser_status_t -mares_iconhd_parser_create (parser_t **out) +mares_iconhd_parser_create (parser_t **out, unsigned int model) { if (out == NULL) return PARSER_STATUS_ERROR; @@ -76,6 +78,9 @@ mares_iconhd_parser_create (parser_t **out) // Initialize the base class. parser_init (&parser->base, &mares_iconhd_parser_backend); + // Set the default values. + parser->model = model; + *out = (parser_t*) parser; return PARSER_STATUS_SUCCESS; @@ -105,15 +110,22 @@ mares_iconhd_parser_set_data (parser_t *abstract, const unsigned char *data, uns static parser_status_t mares_iconhd_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime) { + mares_iconhd_parser_t *parser = (mares_iconhd_parser_t *) abstract; + + unsigned int header = 0x5C; + if (parser->model == ICONHDNET) { + header = 0x80; + } + if (abstract->size < 4) return PARSER_STATUS_ERROR; unsigned int length = array_uint32_le (abstract->data); - if (abstract->size < length || length < HEADER + 4) + if (abstract->size < length || length < header + 4) return PARSER_STATUS_ERROR; - const unsigned char *p = abstract->data + length - HEADER + 6; + const unsigned char *p = abstract->data + length - header + 6; if (datetime) { datetime->hour = array_uint16_le (p + 0); @@ -131,15 +143,22 @@ mares_iconhd_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime) static parser_status_t mares_iconhd_parser_get_field (parser_t *abstract, parser_field_type_t type, unsigned int flags, void *value) { + mares_iconhd_parser_t *parser = (mares_iconhd_parser_t *) abstract; + + unsigned int header = 0x5C; + if (parser->model == ICONHDNET) { + header = 0x80; + } + if (abstract->size < 4) return PARSER_STATUS_ERROR; unsigned int length = array_uint32_le (abstract->data); - if (abstract->size < length || length < HEADER + 4) + if (abstract->size < length || length < header + 4) return PARSER_STATUS_ERROR; - const unsigned char *p = abstract->data + length - HEADER; + const unsigned char *p = abstract->data + length - header; gasmix_t *gasmix = (gasmix_t *) value; @@ -171,22 +190,32 @@ mares_iconhd_parser_get_field (parser_t *abstract, parser_field_type_t type, uns static parser_status_t mares_iconhd_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) { + mares_iconhd_parser_t *parser = (mares_iconhd_parser_t *) abstract; + + unsigned int header = 0x5C; + unsigned int samplesize = 8; + if (parser->model == ICONHDNET) { + header = 0x80; + samplesize = 12; + } + if (abstract->size < 4) return PARSER_STATUS_ERROR; unsigned int length = array_uint32_le (abstract->data); - if (abstract->size < length || length < HEADER + 4) + if (abstract->size < length || length < header + 4) return PARSER_STATUS_ERROR; const unsigned char *data = abstract->data; - unsigned int size = length - HEADER; + unsigned int size = length - header; unsigned int time = 0; unsigned int interval = 5; unsigned int offset = 4; - while (offset + 8 <= size) { + unsigned int nsamples = 0; + while (offset + samplesize <= size) { parser_sample_value_t sample = {0}; // Time (seconds). @@ -204,7 +233,15 @@ mares_iconhd_parser_samples_foreach (parser_t *abstract, sample_callback_t callb sample.temperature = temperature / 10.0; if (callback) callback (SAMPLE_TYPE_TEMPERATURE, sample, userdata); - offset += 8; + offset += samplesize; + nsamples++; + + // Some extra data. + if (parser->model == ICONHDNET && (nsamples % 4) == 0) { + if (offset + 8 > size) + return PARSER_STATUS_ERROR; + offset += 8; + } } return PARSER_STATUS_SUCCESS;