diff --git a/examples/dctool.c b/examples/dctool.c index ddcd596..3104bc4 100644 --- a/examples/dctool.c +++ b/examples/dctool.c @@ -240,7 +240,8 @@ main (int argc, char *argv[]) } // Translate the help option into a command. - char *argv_help[] = {(char *) "help", NULL, NULL}; + char helpcmd[] = "help"; + char *argv_help[] = {helpcmd, NULL, NULL}; if (help || argv[0] == NULL) { if (argv[0]) { argv_help[1] = argv[0]; diff --git a/examples/dctool_parse.c b/examples/dctool_parse.c index 6ea8550..6b7da08 100644 --- a/examples/dctool_parse.c +++ b/examples/dctool_parse.c @@ -152,7 +152,7 @@ dctool_parse_run (int argc, char *argv[], dc_context_t *context, dc_descriptor_t goto cleanup; } - for (unsigned int i = 0; i < argc; ++i) { + for (int i = 0; i < argc; ++i) { // Read the input file. buffer = dctool_file_read (argv[i]); if (buffer == NULL) { diff --git a/examples/output_raw.c b/examples/output_raw.c index 951531e..9e71780 100644 --- a/examples/output_raw.c +++ b/examples/output_raw.c @@ -80,7 +80,7 @@ mktemplate_datetime (char *buffer, size_t size, dc_parser_t *parser) n = snprintf (buffer, size, "%04i%02i%02iT%02i%02i%02i", datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute, datetime.second); - if (n < 0 || n >= size) + if (n < 0 || (size_t) n >= size) return -1; return n; @@ -92,7 +92,7 @@ mktemplate_number (char *buffer, size_t size, unsigned int number) int n = 0; n = snprintf (buffer, size, "%04u", number); - if (n < 0 || n >= size) + if (n < 0 || (size_t) n >= size) return -1; return n; diff --git a/include/libdivecomputer/datetime.h b/include/libdivecomputer/datetime.h index 768883d..e5b876f 100644 --- a/include/libdivecomputer/datetime.h +++ b/include/libdivecomputer/datetime.h @@ -22,11 +22,13 @@ #ifndef DC_DATETIME_H #define DC_DATETIME_H +#include + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -#define DC_TIMEZONE_NONE 0x80000000 +#define DC_TIMEZONE_NONE INT_MIN #if defined (_WIN32) && !defined (__GNUC__) typedef __int64 dc_ticks_t; diff --git a/src/cochran_commander.c b/src/cochran_commander.c index 63a00ba..e3677e9 100644 --- a/src/cochran_commander.c +++ b/src/cochran_commander.c @@ -41,6 +41,8 @@ #define COCHRAN_MODEL_EMC_16 4 #define COCHRAN_MODEL_EMC_20 5 +#define UNDEFINED 0xFFFFFFFF + typedef enum cochran_endian_t { ENDIAN_LE, ENDIAN_BE, @@ -57,8 +59,8 @@ typedef struct cochran_data_t { unsigned char *logbook; unsigned short int dive_count; - int fp_dive_num; - int invalid_profile_dive_num; + unsigned int fp_dive_num; + unsigned int invalid_profile_dive_num; unsigned int logbook_size; } cochran_data_t; @@ -621,18 +623,17 @@ cochran_commander_find_fingerprint(cochran_commander_device_t *device, cochran_d // We track profile ringbuffer usage to determine which dives have profile data int profile_capacity_remaining = device->layout->rb_profile_end - device->layout->rb_profile_begin; - int dive_count = -1; - data->fp_dive_num = -1; + unsigned int dive_count = 0; + data->fp_dive_num = UNDEFINED; // Start at end of log if (data->dive_count < device->layout->rb_logbook_entry_count) dive_count = data->dive_count; else dive_count = device->layout->rb_logbook_entry_count; - dive_count--; unsigned int sample_read_size = 0; - data->invalid_profile_dive_num = -1; + data->invalid_profile_dive_num = UNDEFINED; // Remove the pre-dive events that occur after the last dive unsigned int rb_head_ptr = 0; @@ -676,7 +677,7 @@ cochran_commander_find_fingerprint(cochran_commander_device_t *device, cochran_d // Loop through dives to find FP, Accumulate profile data size, // and find the last dive with invalid profile - for (unsigned int i = 0; i <= dive_count; ++i) { + for (unsigned int i = 0; i < dive_count; ++i) { unsigned int idx = (device->layout->rb_logbook_entry_count + head_dive - (i + 1)) % device->layout->rb_logbook_entry_count; unsigned char *log_entry = data->logbook + idx * device->layout->rb_logbook_entry_size; @@ -953,7 +954,7 @@ cochran_commander_device_foreach (dc_device_t *abstract, dc_dive_callback_t call } // Change tail to dive following the fingerprint dive. - if (data.fp_dive_num > -1) + if (data.fp_dive_num != UNDEFINED) tail_dive = (data.fp_dive_num + 1) % layout->rb_logbook_entry_count; // Number of dives to read diff --git a/src/context.c b/src/context.c index 9800eee..17f7245 100644 --- a/src/context.c +++ b/src/context.c @@ -27,6 +27,7 @@ #include #include #include +#include #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN @@ -77,7 +78,7 @@ l_vsnprintf (char *str, size_t size, const char *format, va_list ap) * enough. */ n = vsnprintf (str, size, format, ap); - if (n >= size) + if (n >= 0 && (size_t) n >= size) n = -1; #endif @@ -104,7 +105,7 @@ l_hexdump (char *str, size_t size, const unsigned char data[], size_t n) '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; - if (size == 0) + if (size == 0 || size > INT_MAX) return -1; /* The maximum number of bytes. */ @@ -126,11 +127,11 @@ l_hexdump (char *str, size_t size, const unsigned char data[], size_t n) /* Null terminate the hex string. */ str[length * 2] = 0; - return (n > maxlength ? -1 : length * 2); + return (n > maxlength ? -1 : (int) (length * 2)); } static void -logfunc (dc_context_t *context, dc_loglevel_t loglevel, const char *file, unsigned int line, const char *function, const char *msg, void *userdata) +loghandler (dc_context_t *context, dc_loglevel_t loglevel, const char *file, unsigned int line, const char *function, const char *msg, void *userdata) { const char *loglevels[] = {"NONE", "ERROR", "WARNING", "INFO", "DEBUG", "ALL"}; @@ -166,7 +167,7 @@ dc_context_new (dc_context_t **out) #ifdef ENABLE_LOGGING context->loglevel = DC_LOGLEVEL_WARNING; - context->logfunc = logfunc; + context->logfunc = loghandler; #else context->loglevel = DC_LOGLEVEL_NONE; context->logfunc = NULL; diff --git a/src/descriptor.c b/src/descriptor.c index 0b99ccb..52a3832 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -258,6 +258,7 @@ static const dc_descriptor_t g_descriptors[] = { {"Aqualung", "i450T", DC_FAMILY_OCEANIC_ATOM2, 0x4641, DC_TRANSPORT_SERIAL, NULL}, {"Aqualung", "i550", DC_FAMILY_OCEANIC_ATOM2, 0x4642, DC_TRANSPORT_SERIAL, NULL}, {"Aqualung", "i200", DC_FAMILY_OCEANIC_ATOM2, 0x4646, DC_TRANSPORT_SERIAL, NULL}, + {"Sherwood", "Sage", DC_FAMILY_OCEANIC_ATOM2, 0x4647, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_oceanic}, {"Aqualung", "i300C", DC_FAMILY_OCEANIC_ATOM2, 0x4648, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_oceanic}, {"Aqualung", "i200C", DC_FAMILY_OCEANIC_ATOM2, 0x4649, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_oceanic}, {"Aqualung", "i100", DC_FAMILY_OCEANIC_ATOM2, 0x464E, DC_TRANSPORT_SERIAL, NULL}, @@ -298,6 +299,7 @@ static const dc_descriptor_t g_descriptors[] = { {"Mares", "Quad Air", DC_FAMILY_MARES_ICONHD , 0x23, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_mares}, {"Mares", "Smart Air", DC_FAMILY_MARES_ICONHD , 0x24, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_mares}, {"Mares", "Quad", DC_FAMILY_MARES_ICONHD , 0x29, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_mares}, + {"Mares", "Horizon", DC_FAMILY_MARES_ICONHD , 0x2C, DC_TRANSPORT_SERIAL, NULL}, /* Heinrichs Weikamp */ {"Heinrichs Weikamp", "OSTC", DC_FAMILY_HW_OSTC, 0, DC_TRANSPORT_SERIAL, NULL}, {"Heinrichs Weikamp", "OSTC Mk2", DC_FAMILY_HW_OSTC, 1, DC_TRANSPORT_SERIAL, NULL}, @@ -387,6 +389,18 @@ static const dc_descriptor_t g_descriptors[] = { {"Ratio", "iDive Color Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x54, DC_TRANSPORT_SERIAL, NULL}, {"Ratio", "iDive Color Tech+",DC_FAMILY_DIVESYSTEM_IDIVE, 0x55, DC_TRANSPORT_SERIAL, NULL}, {"Ratio", "iDive Color Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x56, DC_TRANSPORT_SERIAL, NULL}, + {"Ratio", "iX3M 2021 GPS Fancy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x60, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH, dc_filter_divesystem}, + {"Ratio", "iX3M 2021 GPS Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x61, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH, dc_filter_divesystem}, + {"Ratio", "iX3M 2021 GPS Pro ", DC_FAMILY_DIVESYSTEM_IDIVE, 0x62, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH, dc_filter_divesystem}, + {"Ratio", "iX3M 2021 GPS Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x63, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH, dc_filter_divesystem}, + {"Ratio", "iX3M 2021 GPS Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x64, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH, dc_filter_divesystem}, + {"Ratio", "iX3M 2021 GPS Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x65, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH, dc_filter_divesystem}, + {"Ratio", "iX3M 2021 Pro Fancy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x70, DC_TRANSPORT_SERIAL, NULL}, + {"Ratio", "iX3M 2021 Pro Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x71, DC_TRANSPORT_SERIAL, NULL}, + {"Ratio", "iX3M 2021 Pro Pro", DC_FAMILY_DIVESYSTEM_IDIVE, 0x72, DC_TRANSPORT_SERIAL, NULL}, + {"Ratio", "iX3M 2021 Pro Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x73, DC_TRANSPORT_SERIAL, NULL}, + {"Ratio", "iX3M 2021 Pro Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x74, DC_TRANSPORT_SERIAL, NULL}, + {"Ratio", "iX3M 2021 Pro Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x75, DC_TRANSPORT_SERIAL, NULL}, {"Seac", "Jack", DC_FAMILY_DIVESYSTEM_IDIVE, 0x1000, DC_TRANSPORT_SERIAL, NULL}, {"Seac", "Guru", DC_FAMILY_DIVESYSTEM_IDIVE, 0x1002, DC_TRANSPORT_SERIAL, NULL}, /* Cochran Commander */ @@ -643,6 +657,7 @@ static int dc_filter_divesystem (dc_transport_t transport, const void *userdata, { static const char * const bluetooth[] = { "DS", + "IX5M", }; if (transport == DC_TRANSPORT_BLUETOOTH) { @@ -656,6 +671,7 @@ static int dc_filter_oceanic (dc_transport_t transport, const void *userdata, vo { static const unsigned int model[] = { 0x4552, // Oceanic Pro Plus X + 0x4647, // Sherwood Sage 0x4648, // Aqualung i300C 0x4649, // Aqualung i200C 0x4651, // Aqualung i770R diff --git a/src/divesystem_idive.c b/src/divesystem_idive.c index 0659d06..b544ecb 100644 --- a/src/divesystem_idive.c +++ b/src/divesystem_idive.c @@ -903,6 +903,9 @@ divesystem_idive_device_fwupdate (dc_device_t *abstract, const char *filename) goto error_free; } + // Wait before sending the firmware data. + dc_iostream_sleep (device->iostream, 100); + // Upload the firmware. unsigned int offset = 0; while (offset + 2 <= size) { diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c index c669ea2..3ed6bc7 100644 --- a/src/hw_ostc3.c +++ b/src/hw_ostc3.c @@ -1024,7 +1024,7 @@ hw_ostc3_firmware_readline (FILE *fp, dc_context_t *context, unsigned int addr, unsigned char ascii[39]; unsigned char faddr_byte[3]; unsigned int faddr = 0; - int n = 0; + size_t n = 0; if (size > 16) { ERROR (context, "Invalid arguments."); diff --git a/src/hw_ostc_parser.c b/src/hw_ostc_parser.c index 83746e3..a975699 100644 --- a/src/hw_ostc_parser.c +++ b/src/hw_ostc_parser.c @@ -428,7 +428,6 @@ hw_ostc_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime) { hw_ostc_parser_t *parser = (hw_ostc_parser_t *) abstract; const unsigned char *data = abstract->data; - unsigned int size = abstract->size; // Cache the header data. dc_status_t rc = hw_ostc_parser_cache (parser); @@ -491,7 +490,6 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned { hw_ostc_parser_t *parser = (hw_ostc_parser_t *) abstract; const unsigned char *data = abstract->data; - unsigned int size = abstract->size; // Cache the header data. dc_status_t rc = hw_ostc_parser_cache (parser); diff --git a/src/irda.c b/src/irda.c index 448c57c..2cc58ab 100644 --- a/src/irda.c +++ b/src/irda.c @@ -155,7 +155,7 @@ dc_irda_iterator_new (dc_iterator_t **out, dc_context_t *context, dc_descriptor_ } // Open the socket. - int fd = socket (AF_IRDA, SOCK_STREAM, 0); + s_socket_t fd = socket (AF_IRDA, SOCK_STREAM, 0); if (fd == S_INVALID) { s_errcode_t errcode = S_ERRNO; SYSERROR (context, errcode); diff --git a/src/mares_iconhd.c b/src/mares_iconhd.c index 4e3bb87..7ef528e 100644 --- a/src/mares_iconhd.c +++ b/src/mares_iconhd.c @@ -49,6 +49,7 @@ #define QUADAIR 0x23 #define SMARTAIR 0x24 #define QUAD 0x29 +#define HORIZON 0x2C #define MAXRETRIES 4 @@ -129,6 +130,12 @@ static const mares_iconhd_layout_t mares_iconhdnet_layout = { 0x100000, /* rb_profile_end */ }; +static const mares_iconhd_layout_t mares_genius_layout = { + 0x1000000, /* memsize */ + 0x0100000, /* rb_profile_begin */ + 0x1000000, /* rb_profile_end */ +}; + static const mares_iconhd_layout_t mares_matrix_layout = { 0x40000, /* memsize */ 0x0A000, /* rb_profile_begin */ @@ -157,6 +164,7 @@ mares_iconhd_get_model (mares_iconhd_device_t *device) {"Quad Air", QUADAIR}, {"Smart Air", SMARTAIR}, {"Quad", QUAD}, + {"Horizon", HORIZON}, }; // Check the product name in the version packet against the list @@ -573,8 +581,9 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_ device->packetsize = 256; break; case GENIUS: - device->layout = &mares_iconhdnet_layout; - device->packetsize = 256; + case HORIZON: + device->layout = &mares_genius_layout; + device->packetsize = 4096; device->fingerprint_size = 4; break; case ICONHDNET: @@ -985,7 +994,7 @@ mares_iconhd_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, devinfo.serial = array_uint32_le (serial); device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo); - if (device->model == GENIUS) { + if (device->model == GENIUS || device->model == HORIZON) { return mares_iconhd_device_foreach_object (abstract, callback, userdata); } else { return mares_iconhd_device_foreach_raw (abstract, callback, userdata); diff --git a/src/mares_iconhd_parser.c b/src/mares_iconhd_parser.c index 5d35bea..5d26d13 100644 --- a/src/mares_iconhd_parser.c +++ b/src/mares_iconhd_parser.c @@ -38,6 +38,7 @@ #define GENIUS 0x1C #define QUADAIR 0x23 #define SMARTAIR 0x24 +#define HORIZON 0x2C #define NGASMIXES_ICONHD 3 #define NGASMIXES_GENIUS 5 @@ -58,6 +59,8 @@ #define GENIUS_TRIMIX 3 #define GENIUS_GAUGE 4 #define GENIUS_FREEDIVE 5 +#define GENIUS_SCR 6 +#define GENIUS_OC 7 // Record types and sizes #define DSTR_TYPE 0x44535452 // Dive start record @@ -66,6 +69,8 @@ #define TISS_SIZE 138 #define DPRS_TYPE 0x44505253 // Sample record #define DPRS_SIZE 34 +#define SDPT_TYPE 0x53445054 // SCR sample record +#define SDPT_SIZE 78 #define AIRS_TYPE 0x41495253 // Air integration record #define AIRS_SIZE 16 #define DEND_TYPE 0x44454E44 // Dive end record @@ -128,6 +133,7 @@ struct mares_iconhd_parser_t { unsigned int model; // Cached fields. unsigned int cached; + unsigned int logformat; unsigned int mode; unsigned int nsamples; unsigned int samplesize; @@ -331,6 +337,7 @@ mares_iconhd_cache (mares_iconhd_parser_t *parser) parser->base.size = length; // Cache the data for later use. + parser->logformat = 0; parser->mode = mode; parser->nsamples = nsamples; parser->samplesize = samplesize; @@ -358,30 +365,39 @@ mares_genius_cache (mares_iconhd_parser_t *parser) const unsigned char *data = parser->base.data; unsigned int size = parser->base.size; - if (size < 4) { + if (size < 20) { ERROR (abstract->context, "Buffer overflow detected!"); return DC_STATUS_DATAFORMAT; } // Check the header type and version. unsigned int type = array_uint16_le (data); - unsigned int major = data[2]; - unsigned int minor = data[3]; - if (type != 1 || major != 0 || minor != 0) { + unsigned int minor = data[2]; + unsigned int major = data[3]; + if (type != 1 || major != 0 || minor > 1) { ERROR (abstract->context, "Unsupported object type (%u) or version (%u.%u).", type, major, minor); return DC_STATUS_DATAFORMAT; } + // Get the data format. + unsigned int logformat = data[0x10]; + + // The Horizon header has 8 bytes extra at offset 0x18. + unsigned int extra = 0; + if (logformat == 1) { + extra = 8; + } + // Get the header size. - unsigned int headersize = 0xB8; + unsigned int headersize = 0xB8 + extra; if (headersize > size) { ERROR (abstract->context, "Buffer overflow detected!"); return DC_STATUS_DATAFORMAT; } // Get the number of samples in the profile data. - unsigned int nsamples = array_uint16_le (data + 0x20); + unsigned int nsamples = array_uint16_le (data + 0x20 + extra); // Get the dive settings. unsigned int settings = array_uint32_le (data + 0x0C); @@ -389,8 +405,11 @@ mares_genius_cache (mares_iconhd_parser_t *parser) // Get the dive mode. unsigned int mode = settings & 0xF; + // Get the sample size. + unsigned int samplesize = logformat == 1 ? SDPT_SIZE: DPRS_SIZE; + // Calculate the total number of bytes for this dive. - unsigned int nbytes = headersize + 4 + DSTR_SIZE + TISS_SIZE + nsamples * DPRS_SIZE + (nsamples / 4) * AIRS_SIZE + DEND_SIZE; + unsigned int nbytes = headersize + 4 + DSTR_SIZE + TISS_SIZE + nsamples * samplesize + (nsamples / 4) * AIRS_SIZE + DEND_SIZE; if (nbytes > size) { ERROR (abstract->context, "Buffer overflow detected!"); return DC_STATUS_DATAFORMAT; @@ -402,7 +421,7 @@ mares_genius_cache (mares_iconhd_parser_t *parser) mares_iconhd_gasmix_t gasmix[NGASMIXES_GENIUS] = {0}; mares_iconhd_tank_t tank[NTANKS_GENIUS] = {0}; for (unsigned int i = 0; i < NGASMIXES_GENIUS; i++) { - unsigned int offset = 0x54 + i * 20; + unsigned int offset = 0x54 + extra + i * 20; unsigned int gasmixparams = array_uint32_le(data + offset + 0); unsigned int beginpressure = array_uint16_le(data + offset + 4); unsigned int endpressure = array_uint16_le(data + offset + 6); @@ -441,9 +460,10 @@ mares_genius_cache (mares_iconhd_parser_t *parser) } // Cache the data for later use. + parser->logformat = logformat; parser->mode = mode; parser->nsamples = nsamples; - parser->samplesize = DPRS_SIZE; + parser->samplesize = samplesize; parser->headersize = headersize; parser->settings = settings; parser->interval = 5; @@ -468,7 +488,7 @@ mares_iconhd_parser_cache (mares_iconhd_parser_t *parser) return DC_STATUS_SUCCESS; } - if (parser->model == GENIUS) { + if (parser->model == GENIUS || parser->model == HORIZON) { return mares_genius_cache (parser); } else { return mares_iconhd_cache (parser); @@ -493,7 +513,8 @@ mares_iconhd_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i // Set the default values. parser->model = model; parser->cached = 0; - parser->mode = (model == GENIUS) ? GENIUS_AIR : ICONHD_AIR; + parser->logformat = 0; + parser->mode = (model == GENIUS || model == HORIZON) ? GENIUS_AIR : ICONHD_AIR; parser->nsamples = 0; parser->samplesize = 0; parser->headersize = 0; @@ -526,7 +547,8 @@ mares_iconhd_parser_set_data (dc_parser_t *abstract, const unsigned char *data, // Reset the cache. parser->cached = 0; - parser->mode = (parser->model == GENIUS) ? GENIUS_AIR : ICONHD_AIR; + parser->logformat = 0; + parser->mode = (parser->model == GENIUS || parser->model == HORIZON) ? GENIUS_AIR : ICONHD_AIR; parser->nsamples = 0; parser->samplesize = 0; parser->headersize = 0; @@ -562,7 +584,7 @@ mares_iconhd_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime // Pointer to the header data. const unsigned char *p = abstract->data; - if (parser->model != GENIUS) { + if (parser->model != GENIUS && parser->model != HORIZON) { p += abstract->size - parser->headersize; if (parser->model != SMART && parser->model != SMARTAPNEA && parser->model != SMARTAIR) { p += 4; @@ -570,7 +592,7 @@ mares_iconhd_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime } // Offset to the date/time field. - if (parser->model == GENIUS) { + if (parser->model == GENIUS || parser->model == HORIZON) { p += 0x08; } else if (parser->model == SMARTAPNEA) { p += 0x40; @@ -581,7 +603,7 @@ mares_iconhd_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime } if (datetime) { - if (parser->model == GENIUS) { + if (parser->model == GENIUS || parser->model == HORIZON) { unsigned int timestamp = array_uint32_le (p); datetime->hour = (timestamp ) & 0x1F; datetime->minute = (timestamp >> 5) & 0x3F; @@ -616,14 +638,21 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi // Pointer to the header data. const unsigned char *p = abstract->data; - if (parser->model != GENIUS) { + if (parser->model != GENIUS && parser->model != HORIZON) { p += abstract->size - parser->headersize; if (parser->model != SMART && parser->model != SMARTAPNEA && parser->model != SMARTAIR) { p += 4; } } - unsigned int metric = parser->model == GENIUS ? p[0x34] : parser->settings & 0x0100; + // The Horizon header has 8 bytes extra at offset 0x18. + unsigned int extra = 0; + if (parser->logformat == 1) { + extra = 8; + } + + unsigned int metric = (parser->model == GENIUS || parser->model == HORIZON) ? + p[0x34 + extra] : parser->settings & 0x0100; dc_gasmix_t *gasmix = (dc_gasmix_t *) value; dc_tank_t *tank = (dc_tank_t *) value; @@ -632,7 +661,7 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi if (value) { switch (type) { case DC_FIELD_DIVETIME: - if (parser->model == GENIUS) { + if (parser->model == GENIUS || parser->model == HORIZON) { *((unsigned int *) value) = parser->nsamples * parser->interval; } else if (parser->model == SMARTAPNEA) { *((unsigned int *) value) = array_uint16_le (p + 0x24); @@ -649,8 +678,8 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi } break; case DC_FIELD_MAXDEPTH: - if (parser->model == GENIUS) - *((double *) value) = array_uint16_le (p + 0x22) / 10.0; + if (parser->model == GENIUS || parser->model == HORIZON) + *((double *) value) = array_uint16_le (p + 0x22 + extra) / 10.0; else if (parser->model == SMARTAPNEA) *((double *) value) = array_uint16_le (p + 0x3A) / 10.0; else if (parser->mode == ICONHD_FREEDIVE) @@ -691,8 +720,8 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi } break; case DC_FIELD_ATMOSPHERIC: - if (parser->model == GENIUS) - *((double *) value) = array_uint16_le (p + 0x3E) / 1000.0; + if (parser->model == GENIUS || parser->model == HORIZON) + *((double *) value) = array_uint16_le (p + 0x3E + extra) / 1000.0; else if (parser->model == SMARTAPNEA) *((double *) value) = array_uint16_le (p + 0x38) / 1000.0; else if (parser->mode == ICONHD_FREEDIVE) @@ -701,7 +730,7 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi *((double *) value) = array_uint16_le (p + 0x22) / 8000.0; break; case DC_FIELD_SALINITY: - if (parser->model == GENIUS) { + if (parser->model == GENIUS || parser->model == HORIZON) { unsigned int salinity = (parser->settings >> 5) & 0x03; switch (salinity) { case WATER_FRESH: @@ -737,8 +766,8 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi } break; case DC_FIELD_TEMPERATURE_MINIMUM: - if (parser->model == GENIUS) - *((double *) value) = (signed short) array_uint16_le (p + 0x28) / 10.0; + if (parser->model == GENIUS || parser->model == HORIZON) + *((double *) value) = (signed short) array_uint16_le (p + 0x28 + extra) / 10.0; else if (parser->model == SMARTAPNEA) *((double *) value) = (signed short) array_uint16_le (p + 0x3E) / 10.0; else if (parser->mode == ICONHD_FREEDIVE) @@ -747,8 +776,8 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi *((double *) value) = (signed short) array_uint16_le (p + 0x42) / 10.0; break; case DC_FIELD_TEMPERATURE_MAXIMUM: - if (parser->model == GENIUS) - *((double *) value) = (signed short) array_uint16_le (p + 0x26) / 10.0; + if (parser->model == GENIUS || parser->model == HORIZON) + *((double *) value) = (signed short) array_uint16_le (p + 0x26 + extra) / 10.0; else if (parser->model == SMARTAPNEA) *((double *) value) = (signed short) array_uint16_le (p + 0x3C) / 10.0; else if (parser->mode == ICONHD_FREEDIVE) @@ -757,12 +786,13 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi *((double *) value) = (signed short) array_uint16_le (p + 0x44) / 10.0; break; case DC_FIELD_DIVEMODE: - if (parser->model == GENIUS) { + if (parser->model == GENIUS || parser->model == HORIZON) { switch (parser->mode) { case GENIUS_AIR: case GENIUS_NITROX_SINGLE: case GENIUS_NITROX_MULTI: case GENIUS_TRIMIX: + case GENIUS_OC: *((dc_divemode_t *) value) = DC_DIVEMODE_OC; break; case GENIUS_GAUGE: @@ -771,6 +801,9 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi case GENIUS_FREEDIVE: *((dc_divemode_t *) value) = DC_DIVEMODE_FREEDIVE; break; + case GENIUS_SCR: + *((dc_divemode_t *) value) = DC_DIVEMODE_SCR; + break; default: return DC_STATUS_DATAFORMAT; } @@ -823,19 +856,20 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t // Previous gas mix - initialize with impossible value unsigned int gasmix_previous = 0xFFFFFFFF; - unsigned int isairintegrated = (parser->model == ICONHDNET || parser->model == QUADAIR || parser->model == SMARTAIR || parser->model == GENIUS); + unsigned int isairintegrated = (parser->model == ICONHDNET || parser->model == QUADAIR || + parser->model == SMARTAIR || parser->model == GENIUS || parser->model == HORIZON); unsigned int offset = 4; unsigned int marker = 0; - if (parser->model == GENIUS) { + if (parser->model == GENIUS || parser->model == HORIZON) { // Skip the dive header. data += parser->headersize; // Check the profile type and version. unsigned int type = array_uint16_le (data); - unsigned int major = data[2]; - unsigned int minor = data[3]; - if (type != 0 || major != 2 || minor != 0) { + unsigned int minor = data[2]; + unsigned int major = data[3]; + if (type > 1 || major != 0 || minor != 2) { ERROR (abstract->context, "Unsupported object type (%u) or version (%u.%u).", type, major, minor); return DC_STATUS_DATAFORMAT; @@ -894,7 +928,7 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t offset += 2 * parser->samplerate; } - } else if (parser->model != GENIUS && parser->mode == ICONHD_FREEDIVE) { + } else if (parser->model != GENIUS && parser->model != HORIZON && parser->mode == ICONHD_FREEDIVE) { unsigned int maxdepth = array_uint16_le (data + offset + 0); unsigned int divetime = array_uint16_le (data + offset + 2); unsigned int surftime = array_uint16_le (data + offset + 4); @@ -921,18 +955,46 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t nsamples++; } else { unsigned int depth = 0, temperature = 0; - unsigned int gasmix = 0, misc = 0, alarms = 0; - if (parser->model == GENIUS) { - if (!mares_genius_isvalid (data + offset, DPRS_SIZE, DPRS_TYPE)) { - ERROR (abstract->context, "Invalid DPRS record."); - return DC_STATUS_DATAFORMAT; - } + unsigned int gasmix = 0, alarms = 0; + unsigned int decostop = 0, decodepth = 0, decotime = 0, tts = 0; + if (parser->model == GENIUS || parser->model == HORIZON) { + if (parser->logformat == 1) { + if (!mares_genius_isvalid (data + offset, SDPT_SIZE, SDPT_TYPE)) { + ERROR (abstract->context, "Invalid SDPT record."); + return DC_STATUS_DATAFORMAT; + } - depth = array_uint16_le (data + offset + marker + 0); - temperature = array_uint16_le (data + offset + marker + 4); - alarms = array_uint32_le (data + offset + marker + 0x0C); - misc = array_uint32_le (data + offset + marker + 0x14); - gasmix = (misc >> 6) & 0xF; + unsigned int misc = 0, deco = 0; + depth = array_uint16_le (data + offset + marker + 2); + temperature = array_uint16_le (data + offset + marker + 6); + alarms = array_uint32_le (data + offset + marker + 0x14); + misc = array_uint32_le (data + offset + marker + 0x18); + deco = array_uint32_le (data + offset + marker + 0x1C); + gasmix = (misc >> 6) & 0x0F; + decostop = (misc >> 10) & 0x01; + if (decostop) { + decodepth = (deco >> 3) & 0x7F; + decotime = (deco >> 10) & 0xFF; + tts = (deco >> 18) & 0x3FFF; + } else { + decotime = deco & 0xFF; + } + } else { + if (!mares_genius_isvalid (data + offset, DPRS_SIZE, DPRS_TYPE)) { + ERROR (abstract->context, "Invalid DPRS record."); + return DC_STATUS_DATAFORMAT; + } + + unsigned int misc = 0; + depth = array_uint16_le (data + offset + marker + 0); + temperature = array_uint16_le (data + offset + marker + 4); + decotime = array_uint16_le (data + offset + marker + 0x0A); + alarms = array_uint32_le (data + offset + marker + 0x0C); + misc = array_uint32_le (data + offset + marker + 0x14); + gasmix = (misc >> 6) & 0x0F; + decostop = (misc >> 18) & 0x01; + decodepth = (misc >> 19) & 0x7F; + } } else { depth = array_uint16_le (data + offset + 0); temperature = array_uint16_le (data + offset + 2) & 0x0FFF; @@ -965,10 +1027,8 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t } } - if (parser->model == GENIUS) { + if (parser->model == GENIUS || parser->model == HORIZON) { // Deco stop / NDL. - unsigned int decostop = (misc >> 18) & 0x01; - unsigned int decodepth = (misc >> 19) & 0x7F; if (decostop) { sample.deco.type = DC_DECO_DECOSTOP; sample.deco.depth = decodepth; @@ -976,7 +1036,7 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t sample.deco.type = DC_DECO_NDL; sample.deco.depth = 0.0; } - sample.deco.time = array_uint16_le (data + offset + marker + 0x0A) * 60; + sample.deco.time = decotime * 60; if (callback) callback (DC_SAMPLE_DECO, sample, userdata); // Alarms @@ -1013,7 +1073,8 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t // Some extra data. if (isairintegrated && (nsamples % 4) == 0) { - if (parser->model == GENIUS && !mares_genius_isvalid (data + offset, AIRS_SIZE, AIRS_TYPE)) { + if ((parser->model == GENIUS || parser->model == HORIZON) && + !mares_genius_isvalid (data + offset, AIRS_SIZE, AIRS_TYPE)) { ERROR (abstract->context, "Invalid AIRS record."); return DC_STATUS_DATAFORMAT; } @@ -1028,12 +1089,12 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t WARNING (abstract->context, "Invalid tank with non-zero pressure."); } - offset += (parser->model == GENIUS) ? AIRS_SIZE : 8; + offset += (parser->model == GENIUS || parser->model == HORIZON) ? AIRS_SIZE : 8; } } } - if (parser->model == GENIUS) { + if (parser->model == GENIUS || parser->model == HORIZON) { // Skip the DEND record. if (!mares_genius_isvalid (data + offset, DEND_SIZE, DEND_TYPE)) { ERROR (abstract->context, "Invalid DEND record."); diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c index 8c804b9..333b994 100644 --- a/src/oceanic_atom2.c +++ b/src/oceanic_atom2.c @@ -38,6 +38,7 @@ #define PROPLUSX 0x4552 #define VTX 0x4557 #define I750TC 0x455A +#define SAGE 0x4647 #define I770R 0x4651 #define GEO40 0x4653 @@ -491,6 +492,7 @@ static const oceanic_common_version_t versions[] = { {"AER300CS \0\0 2048", 0, &aeris_a300cs_layout}, {"OCEANVTX \0\0 2048", 0, &aeris_a300cs_layout}, {"AQUAI750 \0\0 2048", 0, &aeris_a300cs_layout}, + {"SWDRAGON \0\0 2048", 0, &aeris_a300cs_layout}, {"AQUAI450 \0\0 2048", 0, &aqualung_i450t_layout}, @@ -902,7 +904,7 @@ oceanic_atom2_device_open (dc_device_t **out, dc_context_t *context, dc_iostream } if (dc_iostream_get_transport (device->iostream) == DC_TRANSPORT_BLE && - model != PROPLUSX) { + model != PROPLUSX && model != SAGE ) { status = oceanic_atom2_ble_handshake(device); if (status != DC_STATUS_SUCCESS) { goto error_free; diff --git a/src/oceanic_atom2_parser.c b/src/oceanic_atom2_parser.c index f582110..0f58e4c 100644 --- a/src/oceanic_atom2_parser.c +++ b/src/oceanic_atom2_parser.c @@ -89,6 +89,7 @@ #define I450T 0x4641 #define I550 0x4642 #define I200 0x4646 +#define SAGE 0x4647 #define I300C 0x4648 #define I200C 0x4649 #define I100 0x464E @@ -191,7 +192,7 @@ oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, unsigned parser->footersize = 0; } else if (model == A300CS || model == VTX || model == I450T || model == I750TC || - model == I770R) { + model == I770R || model == SAGE) { parser->headersize = 5 * PAGESIZE; } else if (model == PROPLUSX) { parser->headersize = 3 * PAGESIZE; @@ -345,6 +346,7 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim case I750TC: case PROPLUSX: case I770R: + case SAGE: datetime->year = (p[10]) + 2000; datetime->month = (p[8]); datetime->day = (p[9]); @@ -466,7 +468,7 @@ oceanic_atom2_parser_cache (oceanic_atom2_parser_t *parser) he_offset = 0x48; ngasmixes = 6; } else if (parser->model == A300CS || parser->model == VTX || - parser->model == I750TC) { + parser->model == I750TC || parser->model == SAGE) { o2_offset = 0x2A; if (data[0x39] & 0x04) { ngasmixes = 1; @@ -530,9 +532,7 @@ oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns { dc_status_t status = DC_STATUS_SUCCESS; oceanic_atom2_parser_t *parser = (oceanic_atom2_parser_t *) abstract; - const unsigned char *data = abstract->data; - unsigned int size = abstract->size; // Cache the header data. status = oceanic_atom2_parser_cache (parser); @@ -689,7 +689,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ unsigned int idx = 0x17; if (parser->model == A300CS || parser->model == VTX || parser->model == I450T || parser->model == I750TC || - parser->model == PROPLUSX || parser->model == I770R) + parser->model == PROPLUSX || parser->model == I770R || + parser->model == SAGE) idx = 0x1f; switch (data[idx] & 0x03) { case 0: @@ -745,7 +746,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ parser->model == TX1 || parser->model == A300CS || parser->model == VTX || parser->model == I450T || parser->model == I750TC || parser->model == PROPLUSX || - parser->model == I770R || parser->model == I470TC) { + parser->model == I770R || parser->model == I470TC || + parser->model == SAGE) { samplesize = PAGESIZE; } @@ -830,7 +832,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ tank = 0; pressure = (((data[offset + 7] << 8) + data[offset + 6]) & 0x0FFF); } else if (parser->model == A300CS || parser->model == VTX || - parser->model == I750TC || parser->model == I770R) { + parser->model == I750TC || parser->model == I770R || + parser->model == SAGE) { // Tank pressure (1 psi) and number (one based index) tank = (data[offset + 1] & 0x03) - 1; pressure = ((data[offset + 7] << 8) + data[offset + 6]) & 0x0FFF; @@ -932,7 +935,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ temperature = ((data[offset + 7] & 0xF0) >> 4) | ((data[offset + 7] & 0x0C) << 2) | ((data[offset + 5] & 0x0C) << 4); } else if (parser->model == A300CS || parser->model == VTX || parser->model == I750TC || parser->model == PROPLUSX || - parser->model == I770R) { + parser->model == I770R|| parser->model == SAGE) { temperature = data[offset + 11]; } else { unsigned int sign; @@ -976,7 +979,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ pressure = (((data[offset + 0] & 0x03) << 8) + data[offset + 1]) * 5; else if (parser->model == TX1 || parser->model == A300CS || parser->model == VTX || parser->model == I750TC || - parser->model == PROPLUSX || parser->model == I770R) + parser->model == PROPLUSX || parser->model == I770R || + parser->model == SAGE) pressure = array_uint16_le (data + offset + 4); else pressure -= data[offset + 1]; @@ -1027,7 +1031,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ unsigned int have_deco = 0; unsigned int decostop = 0, decotime = 0; if (parser->model == A300CS || parser->model == VTX || - parser->model == I750TC || + parser->model == I750TC || parser->model == SAGE || parser->model == PROPLUSX || parser->model == I770R) { decostop = (data[offset + 15] & 0x70) >> 4; decotime = array_uint16_le(data + offset + 6) & 0x03FF; diff --git a/src/oceanic_common.c b/src/oceanic_common.c index 9a7c2e2..51c234f 100644 --- a/src/oceanic_common.c +++ b/src/oceanic_common.c @@ -415,7 +415,7 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr ERROR (abstract->context, "Invalid ringbuffer pointer detected (0x%06x 0x%06x).", rb_entry_first, rb_entry_last); status = DC_STATUS_DATAFORMAT; - break; + continue; } // Calculate the end pointer and the number of bytes. @@ -504,9 +504,8 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr { ERROR (abstract->context, "Invalid ringbuffer pointer detected (0x%06x 0x%06x).", rb_entry_first, rb_entry_last); - dc_rbstream_free (rbstream); - free (profiles); - return DC_STATUS_DATAFORMAT; + status = DC_STATUS_DATAFORMAT; + continue; } // Calculate the end pointer and the number of bytes. @@ -533,9 +532,8 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr rc = dc_rbstream_read (rbstream, progress, profiles + offset, rb_entry_size + gap); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to read the dive."); - dc_rbstream_free (rbstream); - free (profiles); - return rc; + status = rc; + break; } remaining -= rb_entry_size + gap; @@ -570,7 +568,7 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr dc_rbstream_free (rbstream); free (profiles); - return DC_STATUS_SUCCESS; + return status; } diff --git a/src/oceanic_vtpro.c b/src/oceanic_vtpro.c index 22d61fd..74b94ec 100644 --- a/src/oceanic_vtpro.c +++ b/src/oceanic_vtpro.c @@ -592,8 +592,8 @@ oceanic_vtpro_device_version (dc_device_t *abstract, unsigned char data[], unsig return rc; // Verify the checksum of the answer. - unsigned char crc = answer[PAGESIZE / 2]; - unsigned char ccrc = checksum_add_uint4 (answer, PAGESIZE / 2, 0x00); + crc = answer[PAGESIZE / 2]; + ccrc = checksum_add_uint4 (answer, PAGESIZE / 2, 0x00); if (crc != ccrc) { ERROR (abstract->context, "Unexpected answer checksum."); return DC_STATUS_PROTOCOL; diff --git a/src/reefnet_sensuspro_parser.c b/src/reefnet_sensuspro_parser.c index fe62668..7e68a72 100644 --- a/src/reefnet_sensuspro_parser.c +++ b/src/reefnet_sensuspro_parser.c @@ -163,8 +163,8 @@ reefnet_sensuspro_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, while (offset + sizeof (footer) <= size && memcmp (data + offset, footer, sizeof (footer)) != 0) { - unsigned int value = array_uint16_le (data + offset); - unsigned int depth = (value & 0x01FF); + unsigned int raw = array_uint16_le (data + offset); + unsigned int depth = (raw & 0x01FF); if (depth > maxdepth) maxdepth = depth; diff --git a/src/socket.c b/src/socket.c index e9412ab..84d58a4 100644 --- a/src/socket.c +++ b/src/socket.c @@ -24,6 +24,10 @@ #include "common-private.h" #include "context-private.h" +#ifndef MSG_NOSIGNAL +#define MSG_NOSIGNAL 0 +#endif + dc_status_t dc_socket_syserror (s_errcode_t errcode) { @@ -106,8 +110,22 @@ dc_socket_open (dc_iostream_t *abstract, int family, int type, int protocol) goto error; } +#ifdef SO_NOSIGPIPE + int optval = 1; + if (setsockopt(device->fd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)) != 0) { + s_errcode_t errcode = S_ERRNO; + SYSERROR (abstract->context, errcode); + status = dc_socket_syserror(errcode); + goto error_close; + } +#endif + return DC_STATUS_SUCCESS; +#ifdef SO_NOSIGPIPE +error_close: + S_CLOSE (device->fd); +#endif error: dc_socket_exit (abstract->context); return status; @@ -304,7 +322,7 @@ dc_socket_write (dc_iostream_t *abstract, const void *data, size_t size, size_t break; // Timeout. } - s_ssize_t n = send (socket->fd, (const char *) data + nbytes, size - nbytes, 0); + s_ssize_t n = send (socket->fd, (const char *) data + nbytes, size - nbytes, MSG_NOSIGNAL); if (n < 0) { s_errcode_t errcode = S_ERRNO; if (errcode == S_EINTR || errcode == S_EAGAIN) diff --git a/src/suunto_d9.c b/src/suunto_d9.c index ab6eee1..8b8320e 100644 --- a/src/suunto_d9.c +++ b/src/suunto_d9.c @@ -261,7 +261,8 @@ suunto_d9_device_packet (dc_device_t *abstract, const unsigned char command[], u } // Verify the size of the package. - if (array_uint16_be (answer + 1) + 4 != asize) { + unsigned int len = array_uint16_be (answer + 1); + if (len + 4 != asize) { ERROR (abstract->context, "Unexpected answer size."); return DC_STATUS_PROTOCOL; } diff --git a/src/suunto_d9_parser.c b/src/suunto_d9_parser.c index e3561d2..933f7bf 100644 --- a/src/suunto_d9_parser.c +++ b/src/suunto_d9_parser.c @@ -352,9 +352,7 @@ static dc_status_t suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value) { suunto_d9_parser_t *parser = (suunto_d9_parser_t*) abstract; - const unsigned char *data = abstract->data; - unsigned int size = abstract->size; // Cache the gas mix data. dc_status_t rc = suunto_d9_parser_cache (parser); @@ -571,7 +569,7 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca if ((nsamples + 1) == marker) { while (offset < size) { unsigned int event = data[offset++]; - unsigned int seconds, type, unknown, heading; + unsigned int seconds, type, state, number, heading; unsigned int current, next; unsigned int he, o2, ppo2, idx; unsigned int length; @@ -600,7 +598,7 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca ERROR (abstract->context, "Buffer overflow detected!"); return DC_STATUS_DATAFORMAT; } - unknown = data[offset + 0]; + state = data[offset + 0]; seconds = data[offset + 1]; sample.event.type = SAMPLE_EVENT_SURFACE; sample.event.time = seconds; @@ -719,7 +717,7 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca ERROR (abstract->context, "Buffer overflow detected!"); return DC_STATUS_DATAFORMAT; } - unknown = data[offset + 0]; + number = data[offset + 0]; seconds = data[offset + 1]; heading = array_uint16_le (data + offset + 2); if (heading == 0xFFFF) { @@ -775,7 +773,7 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca if ((type & 0x80) == 0) { idx += parser->nccr; } - if (idx >= parser->ngasmixes) { + if (idx >= parser->ngasmixes || o2 != parser->oxygen[idx] || he != parser->helium[idx]) { ERROR (abstract->context, "Invalid gas mix."); return DC_STATUS_DATAFORMAT; } diff --git a/src/suunto_eonsteel_parser.c b/src/suunto_eonsteel_parser.c index 6633514..326ee5d 100644 --- a/src/suunto_eonsteel_parser.c +++ b/src/suunto_eonsteel_parser.c @@ -78,7 +78,7 @@ typedef struct suunto_eonsteel_parser_t { struct dc_field_cache cache; } suunto_eonsteel_parser_t; -typedef int (*eon_data_cb_t)(unsigned short type, const struct type_desc *desc, const unsigned char *data, int len, void *user); +typedef int (*eon_data_cb_t)(unsigned short type, const struct type_desc *desc, const unsigned char *data, unsigned int len, void *user); static const struct { const char *name; @@ -115,7 +115,6 @@ static const struct { static enum eon_sample lookup_descriptor_type(suunto_eonsteel_parser_t *eon, struct type_desc *desc) { - int i; const char *name = desc->desc; // Not a sample type? Skip it @@ -138,7 +137,7 @@ static enum eon_sample lookup_descriptor_type(suunto_eonsteel_parser_t *eon, str name += 8; // .. and look it up in the table of sample type strings - for (i = 0; i < C_ARRAY_SIZE(type_translation); i++) { + for (size_t i = 0; i < C_ARRAY_SIZE(type_translation); i++) { if (!strcmp(name, type_translation[i].name)) return type_translation[i].type; } @@ -147,8 +146,7 @@ static enum eon_sample lookup_descriptor_type(suunto_eonsteel_parser_t *eon, str static const char *desc_type_name(enum eon_sample type) { - int i; - for (i = 0; i < C_ARRAY_SIZE(type_translation); i++) { + for (size_t i = 0; i < C_ARRAY_SIZE(type_translation); i++) { if (type == type_translation[i].type) return type_translation[i].name; } @@ -334,10 +332,10 @@ static int record_type(suunto_eonsteel_parser_t *eon, unsigned short type, const return 0; } -static int traverse_entry(suunto_eonsteel_parser_t *eon, const unsigned char *p, int len, eon_data_cb_t callback, void *user) +static int traverse_entry(suunto_eonsteel_parser_t *eon, const unsigned char *p, int size, eon_data_cb_t callback, void *user) { - const unsigned char *name, *data, *end, *last, *one_past_end = p + len; - int textlen, type; + const unsigned char *name, *data, *end, *last, *one_past_end = p + size; + int textlen, id; int rc; // First two bytes: zero and text length @@ -356,7 +354,7 @@ static int traverse_entry(suunto_eonsteel_parser_t *eon, const unsigned char *p, // Two bytes of 'type' followed by the name/descriptor, followed by the data data = name + textlen; - type = array_uint16_le(name); + id = array_uint16_le(name); name += 2; if (*name != '<') { @@ -364,7 +362,7 @@ static int traverse_entry(suunto_eonsteel_parser_t *eon, const unsigned char *p, return -1; } - record_type(eon, type, (const char *) name, textlen-3); + record_type(eon, id, (const char *) name, textlen-3); end = data; last = data; @@ -529,7 +527,8 @@ static void sample_gastime(struct sample_data *info, short gastime) if (gastime < 0) return; - // Hmm. We have no good way to report airtime remaining + sample.rbt = gastime / 60; + if (info->callback) info->callback (DC_SAMPLE_RBT, sample, info->userdata); } /* @@ -784,7 +783,7 @@ static void sample_setpoint_automatic(struct sample_data *info, unsigned char va DEBUG(info->eon->base.context, "sample_setpoint_automatic(%u)", value); } -static int handle_sample_type(const struct type_desc *desc, struct sample_data *info, enum eon_sample type, const unsigned char *data) +static unsigned int handle_sample_type(const struct type_desc *desc, struct sample_data *info, enum eon_sample type, const unsigned char *data) { switch (type) { case ES_dtime: @@ -892,7 +891,7 @@ static int handle_sample_type(const struct type_desc *desc, struct sample_data * } } -static int traverse_samples(unsigned short type, const struct type_desc *desc, const unsigned char *data, int len, void *user) +static int traverse_samples(unsigned short type, const struct type_desc *desc, const unsigned char *data, unsigned int len, void *user) { struct sample_data *info = (struct sample_data *) user; suunto_eonsteel_parser_t *eon = info->eon; @@ -902,8 +901,7 @@ static int traverse_samples(unsigned short type, const struct type_desc *desc, c ERROR(eon->base.context, "Got %d bytes of data for '%s' that wants %d bytes", len, desc->desc, desc->size); for (i = 0; i < EON_MAX_GROUP; i++) { - enum eon_sample type = desc->type[i]; - int bytes = handle_sample_type(desc, info, type, data); + unsigned int bytes = handle_sample_type(desc, info, desc->type[i], data); if (!bytes) break; @@ -1392,7 +1390,7 @@ static int traverse_sample_fields(suunto_eonsteel_parser_t *eon, const struct ty return 0; } -static int traverse_fields(unsigned short type, const struct type_desc *desc, const unsigned char *data, int len, void *user) +static int traverse_fields(unsigned short type, const struct type_desc *desc, const unsigned char *data, unsigned int len, void *user) { suunto_eonsteel_parser_t *eon = (suunto_eonsteel_parser_t *) user; diff --git a/src/suunto_solution_parser.c b/src/suunto_solution_parser.c index 9b2ac9d..34aab7d 100644 --- a/src/suunto_solution_parser.c +++ b/src/suunto_solution_parser.c @@ -110,10 +110,10 @@ suunto_solution_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, u unsigned int depth = 0, maxdepth = 0; unsigned int offset = 3; while (offset < size && data[offset] != 0x80) { - unsigned char value = data[offset++]; - if (value < 0x7e || value > 0x82) { - depth += (signed char) value; - if (value == 0x7D || value == 0x83) { + unsigned char raw = data[offset++]; + if (raw < 0x7e || raw > 0x82) { + depth += (signed char) raw; + if (raw == 0x7D || raw == 0x83) { if (offset + 1 > size) return DC_STATUS_DATAFORMAT; depth += (signed char) data[offset++]; diff --git a/src/suunto_vyper2.c b/src/suunto_vyper2.c index 02f38ed..7a9f7ce 100644 --- a/src/suunto_vyper2.c +++ b/src/suunto_vyper2.c @@ -252,7 +252,8 @@ suunto_vyper2_device_packet (dc_device_t *abstract, const unsigned char command[ } // Verify the size of the package. - if (array_uint16_be (answer + 1) + 4 != asize) { + unsigned int len = array_uint16_be (answer + 1); + if (len + 4 != asize) { ERROR (abstract->context, "Unexpected answer size."); return DC_STATUS_PROTOCOL; } diff --git a/src/suunto_vyper_parser.c b/src/suunto_vyper_parser.c index 80f7d54..369ad5c 100644 --- a/src/suunto_vyper_parser.c +++ b/src/suunto_vyper_parser.c @@ -234,9 +234,7 @@ static dc_status_t suunto_vyper_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value) { suunto_vyper_parser_t *parser = (suunto_vyper_parser_t *) abstract; - const unsigned char *data = abstract->data; - unsigned int size = abstract->size; dc_gasmix_t *gas = (dc_gasmix_t *) value; dc_tank_t *tank = (dc_tank_t *) value; diff --git a/src/usbhid.c b/src/usbhid.c index 9231e64..b3805ca 100644 --- a/src/usbhid.c +++ b/src/usbhid.c @@ -777,7 +777,7 @@ dc_usbhid_write (dc_iostream_t *abstract, const void *data, size_t size, size_t out: #ifdef _WIN32 - if (nbytes > size) { + if ((size_t) nbytes > size) { WARNING (abstract->context, "Number of bytes exceeds the buffer size (" DC_PRINTF_SIZE " > " DC_PRINTF_SIZE ")!", nbytes, size); nbytes = size; }