Merge branch 'master' of git://github.com/libdivecomputer/libdivecomputer into Subsurface-DS9

Merge with Jef's upstream libdivecomputer updates:

 - support new Ratio iX3M 2021 model IDs

 - support Mares Horizon, and fix the Mares Genius layout

 - add support for Shearwood Sage

 - various warning fixes, other minor details

* 'master' of git://github.com/libdivecomputer/libdivecomputer: (23 commits)
  Wait before sending the firmware data
  Add support for the new iX3M 2021 models
  Avoid generating the SIGPIPE signal
  Use an unsigned value to represent the undefined state
  Use an unsigned integer for the number of dives
  Use the cross-platform socket file descriptor type
  Limit the size to INT_MAX
  Define DC_TIMEZONE_NONE as a signed integer
  Use an unsigned integer for the length
  Fix -Wsign-compare compiler warnings
  Fix -Wshadow compiler warnings
  Fix -Wcast-qual compiler warning
  Fix -Wswitch compiler warning
  Remove unused variables
  Implement the rbt sample
  Use some more descriptive variable names
  Verify the oxygen and helium percentage
  Add support for the Mares Horizon
  Swap the object major and minor version
  Fix the Mares Genius memory layout
  ...
This commit is contained in:
Linus Torvalds 2021-01-23 11:00:50 -08:00
commit 38ebb81536
26 changed files with 242 additions and 132 deletions

View File

@ -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];

View File

@ -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) {

View File

@ -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;

View File

@ -22,11 +22,13 @@
#ifndef DC_DATETIME_H
#define DC_DATETIME_H
#include <limits.h>
#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;

View File

@ -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

View File

@ -27,6 +27,7 @@
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <limits.h>
#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;

View File

@ -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

View File

@ -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) {

View File

@ -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.");

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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.");

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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++];

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}