diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c index 0d4dafe..5e68fe7 100644 --- a/src/oceanic_atom2.c +++ b/src/oceanic_atom2.c @@ -78,6 +78,7 @@ static const unsigned char oceanic_vt41_version[] = "OCEAVT41 \0\0 1024"; static const unsigned char oceanic_geo2_version[] = "OCEGEO20 \0\0 512K"; static const unsigned char oceanic_oc1a_version[] = "OCWATCH R\0\0 1024"; static const unsigned char oceanic_oc1b_version[] = "OC1WATCH \0\0 1024"; +static const unsigned char oceanic_ocs_version[] = "OCSWATCH \0\0 1024"; static const unsigned char oceanic_veo1_version[] = "OCEVEO10 \0\0 8K"; static const unsigned char oceanic_veo2_version[] = "OCEVEO20 \0\0 512K"; static const unsigned char oceanic_veo3_version[] = "OCEVEO30 \0\0 512K"; @@ -372,6 +373,7 @@ oceanic_atom2_device_open (dc_device_t **out, dc_context_t *context, const char // Override the base class values. if (oceanic_common_match (oceanic_oc1a_version, device->version, sizeof (device->version)) || oceanic_common_match (oceanic_oc1b_version, device->version, sizeof (device->version)) || + oceanic_common_match (oceanic_ocs_version, device->version, sizeof (device->version)) || oceanic_common_match (oceanic_atom3_version, device->version, sizeof (device->version)) || oceanic_common_match (oceanic_atom31_version, device->version, sizeof (device->version)) || oceanic_common_match (oceanic_vt4_version, device->version, sizeof (device->version)) || diff --git a/src/oceanic_atom2_parser.c b/src/oceanic_atom2_parser.c index 6e188dc..c0576ca 100644 --- a/src/oceanic_atom2_parser.c +++ b/src/oceanic_atom2_parser.c @@ -47,6 +47,7 @@ #define VT4 0x4447 #define OC1B 0x4449 #define ATOM3 0x444C +#define OCS 0x4450 #define VT41 0x4452 #define ATOM31 0x4456 @@ -166,6 +167,7 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim switch (parser->model) { case OC1A: case OC1B: + case OCS: case VT4: case VT41: case ATOM3: @@ -178,6 +180,7 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim break; case VT3: case VEO20: + case VEO30: case GEO20: datetime->year = ((p[3] & 0xE0) >> 1) + (p[4] & 0x0F) + 2000; datetime->month = (p[4] & 0xF0) >> 4; @@ -267,7 +270,8 @@ oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns unsigned int footersize = 2 * PAGESIZE / 2; if (parser->model == DATAMASK || parser->model == COMPUMASK || parser->model == GEO || parser->model == GEO20 || - parser->model == VEO20 || parser->model == VEO30) { + parser->model == VEO20 || parser->model == VEO30 || + parser->model == OCS) { headersize -= PAGESIZE; } else if (parser->model == VT4 || parser->model == VT41) { headersize += PAGESIZE; @@ -360,7 +364,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ unsigned int footersize = 2 * PAGESIZE / 2; if (parser->model == DATAMASK || parser->model == COMPUMASK || parser->model == GEO || parser->model == GEO20 || - parser->model == VEO20 || parser->model == VEO30) { + parser->model == VEO20 || parser->model == VEO30 || + parser->model == OCS) { headersize -= PAGESIZE; } else if (parser->model == VT4 || parser->model == VT41) { headersize += PAGESIZE; @@ -403,7 +408,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ samplesize = 2; unsigned int have_temperature = 1, have_pressure = 1; - if (parser->model == VEO30) { + if (parser->model == VEO30 || parser->model == OCS) { have_pressure = 0; } else if (parser->model == F10) { have_temperature = 0; @@ -507,6 +512,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ parser->model == VEO30 || parser->model == OC1A || parser->model == OC1B) { temperature = data[offset + 3]; + } else if (parser->model == OCS) { + temperature = data[offset + 1]; } else if (parser->model == VT4 || parser->model == VT41 || parser->model == ATOM3 || parser->model == ATOM31) { temperature = ((data[offset + 7] & 0xF0) >> 4) | ((data[offset + 7] & 0x0C) << 2) | ((data[offset + 5] & 0x0C) << 4); } else { diff --git a/src/suunto_d9_parser.c b/src/suunto_d9_parser.c index fbbe2c7..120bb4d 100644 --- a/src/suunto_d9_parser.c +++ b/src/suunto_d9_parser.c @@ -43,6 +43,12 @@ #define D6i 0x1A #define D9tx 0x1B +#define AIR 0 +#define NITROX 1 +#define GAUGE 2 +#define FREEDIVE 3 +#define MIXED 4 + typedef struct suunto_d9_parser_t suunto_d9_parser_t; struct suunto_d9_parser_t { @@ -186,6 +192,14 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne if (size < config) return DC_STATUS_DATAFORMAT; + // Gas model + unsigned int gasmodel_offset = 0x1D - SKIP; + if (parser->model == HELO2) + gasmodel_offset += 6; + if (parser->model == D4i || parser->model == D6i || parser->model == D9tx) + gasmodel_offset = 0x1D; + unsigned int gasmodel = data[gasmodel_offset]; + dc_gasmix_t *gasmix = (dc_gasmix_t *) value; if (value) { @@ -204,7 +218,9 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne *((double *) value) = array_uint16_le (data + 0x0D - SKIP) / 100.0; break; case DC_FIELD_GASMIX_COUNT: - if (parser->model == HELO2) { + if (gasmodel == AIR) { + *((unsigned int *) value) = 1; + } else if (parser->model == HELO2) { *((unsigned int *) value) = 8; } else if (parser->model == D9tx) { *((unsigned int *) value) = 8; @@ -217,10 +233,16 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne } break; case DC_FIELD_GASMIX: - if (parser->model == HELO2) { + if (gasmodel == AIR) { + gasmix->helium = 0.0; + gasmix->oxygen = 0.21; + } else if (parser->model == HELO2) { gasmix->helium = data[0x58 - SKIP + 6 * flags + 2] / 100.0; gasmix->oxygen = data[0x58 - SKIP + 6 * flags + 1] / 100.0; - } else if (parser->model == D4i || parser->model == D6i || parser->model == D9tx) { + } else if (parser->model == D9tx) { + gasmix->helium = data[0x87 + 6 * flags + 2] / 100.0; + gasmix->oxygen = data[0x87 + 6 * flags + 1] / 100.0; + } else if (parser->model == D4i || parser->model == D6i) { gasmix->helium = data[0x5F + 6 * flags + 2] / 100.0; gasmix->oxygen = data[0x5F + 6 * flags + 1] / 100.0; } else { diff --git a/src/suunto_vyper.c b/src/suunto_vyper.c index a9b899f..12956e3 100644 --- a/src/suunto_vyper.c +++ b/src/suunto_vyper.c @@ -440,6 +440,8 @@ suunto_vyper_read_dive (dc_device_t *abstract, dc_buffer_t *buffer, int init, dc // Update and emit a progress event. if (progress) { progress->current += len; + if (progress->current > progress->maximum) + progress->current = progress->maximum; device_event_emit (abstract, DC_EVENT_PROGRESS, progress); } @@ -557,10 +559,17 @@ suunto_vyper_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, return DC_STATUS_NOMEMORY; unsigned int ndives = 0; + unsigned int remaining = layout->rb_profile_end - layout->rb_profile_begin; while ((rc = suunto_vyper_read_dive (abstract, buffer, (ndives == 0), &progress)) == DC_STATUS_SUCCESS) { unsigned char *data = dc_buffer_get_data (buffer); unsigned int size = dc_buffer_get_size (buffer); + if (size > remaining) { + ERROR (abstract->context, "Unexpected number of bytes received."); + dc_buffer_free (buffer); + return DC_STATUS_DATAFORMAT; + } + if (size == 0) { dc_buffer_free (buffer); return DC_STATUS_SUCCESS; @@ -576,6 +585,7 @@ suunto_vyper_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, return DC_STATUS_SUCCESS; } + remaining -= size; ndives++; } diff --git a/src/uwatec_smart_parser.c b/src/uwatec_smart_parser.c index 4db45a3..035f508 100644 --- a/src/uwatec_smart_parser.c +++ b/src/uwatec_smart_parser.c @@ -38,6 +38,7 @@ #define ALADINTEC2G 0x13 #define SMARTCOM 0x14 #define SMARTTEC 0x18 +#define GALILEOTRIMIX 0x19 #define SMARTZ 0x1C typedef struct uwatec_smart_parser_t uwatec_smart_parser_t; @@ -208,6 +209,7 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi unsigned int size = abstract->size; unsigned int header = 0; + unsigned int trimix = 0; const uwatec_smart_header_info_t *table = NULL; // Load the correct table. @@ -217,7 +219,12 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi table = &uwatec_smart_pro_header; break; case GALILEO: + case GALILEOTRIMIX: header = 152; + if (data[43] & 0x80) { + header = 0xB1; + trimix = 1; + } table = &uwatec_galileo_sol_header; break; case ALADINTEC: @@ -258,7 +265,10 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi *((double *) value) = array_uint16_le (data + table->maxdepth) / 100.0; break; case DC_FIELD_GASMIX_COUNT: - *((unsigned int *) value) = table->ngases; + if (trimix) + *((unsigned int *) value) = 0; + else + *((unsigned int *) value) = table->ngases; break; case DC_FIELD_GASMIX: gasmix->helium = 0.0; @@ -341,6 +351,8 @@ typedef enum { BEARING, ALARMS, TIME, + UNKNOWN1, + UNKNOWN2, } uwatec_smart_sample_t; typedef struct uwatec_smart_sample_info_t { @@ -430,6 +442,8 @@ uwatec_smart_sample_info_t uwatec_galileo_sol_table [] = { {HEARTRATE, 1, 0, 8, 0, 1}, // 1111 0111 dddddddd {BEARING, 1, 0, 8, 0, 2}, // 1111 1000 dddddddd dddddddd {ALARMS, 1, 2, 8, 0, 1}, // 1111 1001 dddddddd + {UNKNOWN1, 1, 0, 8, 0, 0}, // 1111 1010 (8 bytes) + {UNKNOWN2, 1, 0, 8, 0, 1}, // 1111 1011 dddddddd (n-1 bytes) }; static dc_status_t @@ -446,6 +460,7 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t const uwatec_smart_sample_info_t *table = NULL; unsigned int entries = 0; unsigned int header = 0; + unsigned int trimix = 0; // Load the correct table. switch (parser->model) { @@ -455,7 +470,12 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t entries = NELEMENTS (uwatec_smart_pro_table); break; case GALILEO: + case GALILEOTRIMIX: header = 152; + if (data[43] & 0x80) { + header = 0xB1; + trimix = 1; + } table = uwatec_galileo_sol_table; entries = NELEMENTS (uwatec_galileo_sol_table); break; @@ -516,7 +536,7 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t // Process the type bits in the bitstream. unsigned int id = 0; - if (parser->model == GALILEO) { + if (parser->model == GALILEO || parser->model == GALILEOTRIMIX) { // Uwatec Galileo id = uwatec_galileo_identify (data[offset]); } else { @@ -589,8 +609,13 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t break; case PRESSURE: if (table[id].absolute) { - tank = table[id].index; - pressure = value / 4.0; + if (trimix) { + tank = (value & 0xF000) >> 24; + pressure = (value & 0x0FFF) / 4.0; + } else { + tank = table[id].index; + pressure = value / 4.0; + } have_pressure = 1; } else { pressure += svalue / 4.0; @@ -628,6 +653,20 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t case TIME: complete = value; break; + case UNKNOWN1: + if (offset + 8 > size) { + ERROR (abstract->context, "Incomplete sample data."); + return DC_STATUS_DATAFORMAT; + } + offset += 8; + break; + case UNKNOWN2: + if (value < 1 || offset + value - 1 > size) { + ERROR (abstract->context, "Incomplete sample data."); + return DC_STATUS_DATAFORMAT; + } + offset += value - 1; + break; default: WARNING (abstract->context, "Unknown sample type."); break;