diff --git a/msvc/libdivecomputer.vcproj b/msvc/libdivecomputer.vcproj
index c194f9f..242276a 100644
--- a/msvc/libdivecomputer.vcproj
+++ b/msvc/libdivecomputer.vcproj
@@ -692,6 +692,10 @@
RelativePath="..\include\libdivecomputer\parser.h"
>
+
+
diff --git a/src/Makefile.am b/src/Makefile.am
index 1856483..1545bc7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -63,6 +63,7 @@ libdivecomputer_la_SOURCES = \
diverite_nitekq.h diverite_nitekq.c diverite_nitekq_parser.c \
citizen_aqualand.h citizen_aqualand.c citizen_aqualand_parser.c \
divesystem_idive.h divesystem_idive.c divesystem_idive_parser.c \
+ platform.h \
ringbuffer.h ringbuffer.c \
rbstream.h rbstream.c \
checksum.h checksum.c \
diff --git a/src/cochran_commander.c b/src/cochran_commander.c
index b515909..688c019 100644
--- a/src/cochran_commander.c
+++ b/src/cochran_commander.c
@@ -199,8 +199,8 @@ static const cochran_device_layout_t cochran_emc14_device_layout = {
COCHRAN_MODEL_EMC_14, // model
32, // address_bits
ENDIAN_LE, // endian
- 806400, // baudrate
- 65536, // rbstream_size
+ 850000, // baudrate
+ 32768, // rbstream_size
0x0D2, // cf_dive_count
0x13E, // cf_last_log
0x142, // cf_last_interdive
@@ -224,8 +224,8 @@ static const cochran_device_layout_t cochran_emc16_device_layout = {
COCHRAN_MODEL_EMC_16, // model
32, // address_bits
ENDIAN_LE, // endian
- 806400, // baudrate
- 65536, // rbstream_size
+ 850000, // baudrate
+ 32768, // rbstream_size
0x0D2, // cf_dive_count
0x13E, // cf_last_log
0x142, // cf_last_interdive
@@ -249,8 +249,8 @@ static const cochran_device_layout_t cochran_emc20_device_layout = {
COCHRAN_MODEL_EMC_20, // model
32, // address_bits
ENDIAN_LE, // endian
- 806400, // baudrate
- 65536, // rbstream_size
+ 850000, // baudrate
+ 32768, // rbstream_size
0x0D2, // cf_dive_count
0x13E, // cf_last_log
0x142, // cf_last_interdive
@@ -372,7 +372,7 @@ cochran_commander_packet (cochran_commander_device_t *device, dc_event_progress_
// Give the DC time to process the command.
dc_serial_sleep(device->port, 45);
- // Rates are odd, like 806400 for the EMC, 115200 for commander
+ // Rates are odd, like 850400 for the EMC, 115200 for commander
status = dc_serial_configure(device->port, device->layout->baudrate, 8, DC_PARITY_NONE, DC_STOPBITS_TWO, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to set the high baud rate.");
@@ -523,7 +523,7 @@ cochran_commander_read (cochran_commander_device_t *device, dc_event_progress_t
return DC_STATUS_UNSUPPORTED;
}
- dc_serial_sleep(device->port, 800);
+ dc_serial_sleep(device->port, 550);
// set back to 9600 baud
rc = cochran_commander_serial_setup(device);
@@ -539,6 +539,37 @@ cochran_commander_read (cochran_commander_device_t *device, dc_event_progress_t
}
+static dc_status_t
+cochran_commander_read_retry (cochran_commander_device_t *device, dc_event_progress_t *progress, unsigned int address, unsigned char data[], unsigned int size)
+{
+ // Save the state of the progress events.
+ unsigned int saved = 0;
+ if (progress) {
+ saved = progress->current;
+ }
+
+ unsigned int nretries = 0;
+ dc_status_t rc = DC_STATUS_SUCCESS;
+ while ((rc = cochran_commander_read (device, progress, address, data, size)) != DC_STATUS_SUCCESS) {
+ // Automatically discard a corrupted packet,
+ // and request a new one.
+ if (rc != DC_STATUS_PROTOCOL && rc != DC_STATUS_TIMEOUT)
+ return rc;
+
+ // Abort if the maximum number of retries is reached.
+ if (nretries++ >= MAXRETRIES)
+ return rc;
+
+ // Restore the state of the progress events.
+ if (progress) {
+ progress->current = saved;
+ }
+ }
+
+ return rc;
+}
+
+
/*
* For corrupt dives the end-of-samples pointer is 0xFFFFFFFF
* search for a reasonable size, e.g. using next dive start sample
@@ -798,7 +829,7 @@ cochran_commander_device_read (dc_device_t *abstract, unsigned int address, unsi
{
cochran_commander_device_t *device = (cochran_commander_device_t *) abstract;
- return cochran_commander_read(device, NULL, address, data, size);
+ return cochran_commander_read_retry(device, NULL, address, data, size);
}
@@ -842,7 +873,7 @@ cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
return rc;
// Read the sample data, logbook and sample data are contiguous
- rc = cochran_commander_read (device, &progress, device->layout->rb_logbook_begin, dc_buffer_get_data(buffer), size);
+ rc = cochran_commander_read_retry (device, &progress, device->layout->rb_logbook_begin, dc_buffer_get_data(buffer), size);
if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to read the sample data.");
return rc;
@@ -919,7 +950,7 @@ cochran_commander_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
}
// Request log book
- rc = cochran_commander_read(device, &progress, layout->rb_logbook_begin, data.logbook, data.logbook_size);
+ rc = cochran_commander_read_retry(device, &progress, layout->rb_logbook_begin, data.logbook, data.logbook_size);
if (rc != DC_STATUS_SUCCESS) {
status = rc;
goto error;
diff --git a/src/descriptor.c b/src/descriptor.c
index e849883..a1fa965 100644
--- a/src/descriptor.c
+++ b/src/descriptor.c
@@ -96,6 +96,7 @@ static const dc_descriptor_t g_descriptors[] = {
{"Suunto", "DX", DC_FAMILY_SUUNTO_D9, 0x1C}, // FTDI
{"Suunto", "Vyper Novo", DC_FAMILY_SUUNTO_D9, 0x1D}, // FTDI
{"Suunto", "Zoop Novo", DC_FAMILY_SUUNTO_D9, 0x1E}, // FTDI
+ {"Suunto", "D4f", DC_FAMILY_SUUNTO_D9, 0x20}, // FTDI
/* Suunto EON Steel */
#ifdef USBHID
{"Suunto", "EON Steel", DC_FAMILY_SUUNTO_EONSTEEL, 0}, // BLE
@@ -294,7 +295,7 @@ static const dc_descriptor_t g_descriptors[] = {
{"Dive Rite", "NiTek Q", DC_FAMILY_DIVERITE_NITEKQ, 0},
/* Citizen Hyper Aqualand */
{"Citizen", "Hyper Aqualand", DC_FAMILY_CITIZEN_AQUALAND, 0},
- /* DiveSystem iDive */
+ /* DiveSystem/Ratio iDive */
{"DiveSystem", "Orca", DC_FAMILY_DIVESYSTEM_IDIVE, 0x02},
{"DiveSystem", "iDive Pro", DC_FAMILY_DIVESYSTEM_IDIVE, 0x03},
{"DiveSystem", "iDive DAN", DC_FAMILY_DIVESYSTEM_IDIVE, 0x04},
@@ -305,17 +306,17 @@ static const dc_descriptor_t g_descriptors[] = {
{"DiveSystem", "iDive Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x09},
{"DiveSystem", "iDive X3M", DC_FAMILY_DIVESYSTEM_IDIVE, 0x0A},
{"DiveSystem", "iDive Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x0B},
- {"DiveSystem", "iX3M Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x22},
- {"DiveSystem", "iX3M Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x23},
- {"DiveSystem", "iX3M Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x24},
- {"DiveSystem", "iX3M Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x25},
- {"DiveSystem", "iX3M Pro Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x32},
- {"DiveSystem", "iX3M Pro Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x34},
- {"DiveSystem", "iX3M Pro Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x35},
- {"DiveSystem", "iDive2 Free", DC_FAMILY_DIVESYSTEM_IDIVE, 0x40},
- {"DiveSystem", "iDive2 Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x42},
- {"DiveSystem", "iDive2 Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x44},
- {"DiveSystem", "iDive2 Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x45},
+ {"Ratio", "iX3M Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x22},
+ {"Ratio", "iX3M Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x23},
+ {"Ratio", "iX3M Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x24},
+ {"Ratio", "iX3M Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x25},
+ {"Ratio", "iX3M Pro Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x32},
+ {"Ratio", "iX3M Pro Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x34},
+ {"Ratio", "iX3M Pro Tech+",DC_FAMILY_DIVESYSTEM_IDIVE, 0x35},
+ {"Ratio", "iDive Free", DC_FAMILY_DIVESYSTEM_IDIVE, 0x40},
+ {"Ratio", "iDive Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x42},
+ {"Ratio", "iDive Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x44},
+ {"Ratio", "iDive Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x45},
/* Cochran Commander */
{"Cochran", "Commander TM", DC_FAMILY_COCHRAN_COMMANDER, 0}, // FTDI
{"Cochran", "Commander I", DC_FAMILY_COCHRAN_COMMANDER, 1}, // FTDI
diff --git a/src/divesystem_idive_parser.c b/src/divesystem_idive_parser.c
index f37d142..ca5c2b1 100644
--- a/src/divesystem_idive_parser.c
+++ b/src/divesystem_idive_parser.c
@@ -64,6 +64,8 @@ struct divesystem_idive_parser_t {
unsigned int ngasmixes;
unsigned int oxygen[NGASMIXES];
unsigned int helium[NGASMIXES];
+ unsigned int beginpressure;
+ unsigned int endpressure;
};
static dc_status_t divesystem_idive_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
@@ -113,6 +115,8 @@ divesystem_idive_parser_create (dc_parser_t **out, dc_context_t *context, unsign
parser->oxygen[i] = 0;
parser->helium[i] = 0;
}
+ parser->beginpressure = 0;
+ parser->endpressure = 0;
*out = (dc_parser_t*) parser;
@@ -135,6 +139,8 @@ divesystem_idive_parser_set_data (dc_parser_t *abstract, const unsigned char *da
parser->oxygen[i] = 0;
parser->helium[i] = 0;
}
+ parser->beginpressure = 0;
+ parser->endpressure = 0;
return DC_STATUS_SUCCESS;
}
@@ -173,6 +179,7 @@ divesystem_idive_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
}
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
+ dc_tank_t *tank = (dc_tank_t *) value;
dc_salinity_t *water = (dc_salinity_t *) value;
if (value) {
@@ -191,6 +198,19 @@ divesystem_idive_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
gasmix->oxygen = parser->oxygen[flags] / 100.0;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
break;
+ case DC_FIELD_TANK_COUNT:
+ if (parser->beginpressure == 0 && parser->endpressure == 0)
+ return DC_STATUS_UNSUPPORTED;
+ *((unsigned int *) value) = 1;
+ break;
+ case DC_FIELD_TANK:
+ tank->type = DC_TANKVOLUME_NONE;
+ tank->volume = 0.0;
+ tank->workpressure = 0.0;
+ tank->beginpressure = parser->beginpressure;
+ tank->endpressure = parser->endpressure;
+ tank->gasmix = DC_GASMIX_UNKNOWN;
+ break;
case DC_FIELD_ATMOSPHERIC:
if (parser->model >= IX3M_EASY) {
*((double *) value) = array_uint16_le (data + 11) / 10000.0;
@@ -249,6 +269,8 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
unsigned int he_previous = 0xFFFFFFFF;
unsigned int mode_previous = INVALID;
unsigned int divemode = INVALID;
+ unsigned int beginpressure = 0;
+ unsigned int endpressure = 0;
unsigned int nsamples = array_uint16_le (data + 1);
unsigned int samplesize = SZ_SAMPLE_IDIVE;
@@ -363,10 +385,26 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
sample.cns = cns / 100.0;
if (callback) callback (DC_SAMPLE_CNS, sample, userdata);
+ // Tank Pressure
+ if (samplesize == SZ_SAMPLE_IX3M_APOS4) {
+ unsigned int pressure = data[offset + 49];
+ if (beginpressure == 0 && pressure != 0) {
+ beginpressure = pressure;
+ }
+ if (beginpressure) {
+ sample.pressure.tank = 0;
+ sample.pressure.value = pressure;
+ if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
+ endpressure = pressure;
+ }
+ }
+
offset += samplesize;
}
// Cache the data for later use.
+ parser->beginpressure = beginpressure;
+ parser->endpressure = endpressure;
for (unsigned int i = 0; i < ngasmixes; ++i) {
parser->helium[i] = helium[i];
parser->oxygen[i] = oxygen[i];
diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c
index a1a5efd..7ce7fd5 100644
--- a/src/hw_ostc3.c
+++ b/src/hw_ostc3.c
@@ -30,10 +30,7 @@
#include "serial.h"
#include "array.h"
#include "aes.h"
-
-#ifdef _MSC_VER
-#define snprintf _snprintf
-#endif
+#include "platform.h"
#define ISINSTANCE(device) dc_device_isinstance((device), &hw_ostc3_device_vtable)
diff --git a/src/irda.c b/src/irda.c
index 0f20970..d085ec0 100644
--- a/src/irda.c
+++ b/src/irda.c
@@ -53,6 +53,7 @@
#include "common-private.h"
#include "context-private.h"
#include "array.h"
+#include "platform.h"
#ifdef _WIN32
typedef int s_ssize_t;
@@ -82,10 +83,6 @@ typedef int s_errcode_t;
#define S_CLOSE close
#endif
-#ifdef _MSC_VER
-#define snprintf _snprintf
-#endif
-
struct dc_irda_t {
dc_context_t *context;
#ifdef _WIN32
diff --git a/src/oceanic_veo250_parser.c b/src/oceanic_veo250_parser.c
index a3acf57..fc7c6ed 100644
--- a/src/oceanic_veo250_parser.c
+++ b/src/oceanic_veo250_parser.c
@@ -34,6 +34,7 @@
#define REACTPRO 0x4247
#define VEO200 0x424B
#define VEO250 0x424C
+#define INSIGHT 0x425A
#define REACTPROWHITE 0x4354
typedef struct oceanic_veo250_parser_t oceanic_veo250_parser_t;
@@ -248,7 +249,8 @@ oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
// Temperature (°F)
unsigned int temperature;
- if (parser->model == REACTPRO || parser->model == REACTPROWHITE) {
+ if (parser->model == REACTPRO || parser->model == REACTPROWHITE ||
+ parser->model == INSIGHT) {
temperature = data[offset + 6];
} else {
temperature = data[offset + 7];
@@ -256,6 +258,31 @@ oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
+ // NDL / Deco
+ unsigned int have_deco = 0;
+ unsigned int decostop = 0, decotime = 0;
+ if (parser->model == REACTPRO || parser->model == REACTPROWHITE ||
+ parser->model == INSIGHT) {
+ decostop = (data[offset + 7] & 0xF0) >> 4;
+ decotime = ((data[offset + 3] & 0xC0) << 2) | data[offset + 4];
+ have_deco = 1;
+ } else {
+ decostop = (data[offset + 5] & 0xF0) >> 4;
+ decotime = array_uint16_le(data + offset + 4) & 0x0FFF;
+ have_deco = 1;
+ }
+ if (have_deco) {
+ if (decostop) {
+ sample.deco.type = DC_DECO_DECOSTOP;
+ sample.deco.depth = decostop * 10 * FEET;
+ } else {
+ sample.deco.type = DC_DECO_NDL;
+ sample.deco.depth = 0.0;
+ }
+ sample.deco.time = decotime * 60;
+ if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
+ }
+
offset += PAGESIZE / 2;
}
diff --git a/src/platform.h b/src/platform.h
new file mode 100644
index 0000000..877e320
--- /dev/null
+++ b/src/platform.h
@@ -0,0 +1,50 @@
+/*
+ * libdivecomputer
+ *
+ * Copyright (C) 2017 Jef Driesen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#ifndef DC_PLATFORM_H
+#define DC_PLATFORM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifdef _WIN32
+#define DC_PRINTF_SIZE "%Iu"
+#else
+#define DC_PRINTF_SIZE "%zu"
+#endif
+
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#define strcasecmp _stricmp
+#if _MSC_VER < 1800
+// The rint() function is only available in MSVC 2013 and later
+// versions. Our replacement macro isn't entirely correct, because the
+// rounding rules for halfway cases are slightly different (away from
+// zero vs to even). But for our use-case, that's not a problem.
+#define rint(x) ((x) >= 0.0 ? floor((x) + 0.5): ceil((x) - 0.5))
+#endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* DC_PLATFORM_H */
diff --git a/src/scubapro_g2.c b/src/scubapro_g2.c
index 319bf1f..6351b69 100644
--- a/src/scubapro_g2.c
+++ b/src/scubapro_g2.c
@@ -26,11 +26,15 @@
#include "scubapro_g2.h"
#include "context-private.h"
#include "device-private.h"
-#include "array.h"
#include "usbhid.h"
+#include "array.h"
+#include "platform.h"
#define ISINSTANCE(device) dc_device_isinstance((device), &scubapro_g2_device_vtable)
+#define RX_PACKET_SIZE 64
+#define TX_PACKET_SIZE 32
+
typedef struct scubapro_g2_device_t {
dc_device_t base;
unsigned int timestamp;
@@ -58,23 +62,22 @@ static const dc_device_vtable_t scubapro_g2_device_vtable = {
static dc_status_t
scubapro_g2_extract_dives (dc_device_t *device, const unsigned char data[], unsigned int size, dc_dive_callback_t callback, void *userdata);
-#define PACKET_SIZE 64
static int receive_data(scubapro_g2_device_t *g2, unsigned char *buffer, int size, dc_event_progress_t *progress)
{
dc_custom_io_t *io = _dc_context_custom_io(g2->base.context);
while (size) {
- unsigned char buf[PACKET_SIZE] = { 0 };
+ unsigned char buf[RX_PACKET_SIZE] = { 0 };
size_t transferred = 0;
dc_status_t rc;
int len;
- rc = io->packet_read(io, buf, PACKET_SIZE, &transferred);
+ rc = io->packet_read(io, buf, sizeof(buf), &transferred);
if (rc != DC_STATUS_SUCCESS) {
ERROR(g2->base.context, "read interrupt transfer failed");
return -1;
}
- if (io->packet_size == PACKET_SIZE && transferred != PACKET_SIZE) {
- ERROR(g2->base.context, "incomplete read interrupt transfer (got %zu, expected %d)", transferred, PACKET_SIZE);
+ if (transferred < 1) {
+ ERROR(g2->base.context, "incomplete read interrupt transfer (got empty packet)");
return -1;
}
len = buf[0];
@@ -82,7 +85,7 @@ static int receive_data(scubapro_g2_device_t *g2, unsigned char *buffer, int siz
ERROR(g2->base.context, "small packet read (got %zu, expected at least %d)", transferred, len + 1);
return -1;
}
- if (len >= PACKET_SIZE) {
+ if (len >= sizeof(buf)) {
ERROR(g2->base.context, "read interrupt transfer returns impossible packet size (%d)", len);
return -1;
}
@@ -108,11 +111,11 @@ static dc_status_t
scubapro_g2_transfer(scubapro_g2_device_t *g2, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize)
{
dc_custom_io_t *io = _dc_context_custom_io(g2->base.context);
- unsigned char buf[PACKET_SIZE];
+ unsigned char buf[TX_PACKET_SIZE] = { 0 };
dc_status_t status = DC_STATUS_SUCCESS;
size_t transferred = 0;
- if (csize > PACKET_SIZE-2) {
+ if (csize > sizeof(buf)-2) {
ERROR(g2->base.context, "command too big (%d)", csize);
return DC_STATUS_INVALIDARGS;
}
@@ -128,7 +131,7 @@ scubapro_g2_transfer(scubapro_g2_device_t *g2, const unsigned char command[], un
// No report type byte
status = io->packet_write(io, buf+1, csize+1, &transferred);
} else {
- status = io->packet_write(io, buf, csize+2, &transferred);
+ status = io->packet_write(io, buf, sizeof(buf), &transferred);
}
if (status != DC_STATUS_SUCCESS) {
diff --git a/src/suunto_d9.c b/src/suunto_d9.c
index 56f8c40..6f5b81c 100644
--- a/src/suunto_d9.c
+++ b/src/suunto_d9.c
@@ -40,6 +40,7 @@
#define DX 0x1C
#define VYPERNOVO 0x1D
#define ZOOPNOVO 0x1E
+#define D4F 0x20
typedef struct suunto_d9_device_t {
suunto_common2_device_t base;
@@ -101,7 +102,8 @@ suunto_d9_device_autodetect (suunto_d9_device_t *device, unsigned int model)
// Use the model number as a hint to speedup the detection.
unsigned int hint = 0;
if (model == D4i || model == D6i || model == D9tx ||
- model == DX || model == VYPERNOVO || model == ZOOPNOVO)
+ model == DX || model == VYPERNOVO || model == ZOOPNOVO ||
+ model == D4F)
hint = 1;
for (unsigned int i = 0; i < C_ARRAY_SIZE(baudrates); ++i) {
@@ -191,7 +193,8 @@ suunto_d9_device_open (dc_device_t **out, dc_context_t *context, const char *nam
// Override the base class values.
model = device->base.version[0];
if (model == D4i || model == D6i || model == D9tx ||
- model == VYPERNOVO || model == ZOOPNOVO)
+ model == VYPERNOVO || model == ZOOPNOVO ||
+ model == D4F)
device->base.layout = &suunto_d9tx_layout;
else if (model == DX)
device->base.layout = &suunto_dx_layout;
diff --git a/src/suunto_d9_parser.c b/src/suunto_d9_parser.c
index 5404997..e8908c5 100644
--- a/src/suunto_d9_parser.c
+++ b/src/suunto_d9_parser.c
@@ -47,6 +47,7 @@
#define DX 0x1C
#define VYPERNOVO 0x1D
#define ZOOPNOVO 0x1E
+#define D4F 0x20
#define ID_D6I_V1_MIX2 0x1871C062
#define ID_D6I_V1_MIX3 0x1871C063
@@ -140,7 +141,8 @@ suunto_d9_parser_cache (suunto_d9_parser_t *parser)
gasmode_offset = 0x1F;
gasmix_offset = 0x54;
gasmix_count = 8;
- } else if (parser->model == D4i || parser->model == ZOOPNOVO) {
+ } else if (parser->model == D4i || parser->model == ZOOPNOVO ||
+ parser->model == D4F) {
gasmode_offset = 0x1D;
if (id == ID_D4I_V2)
gasmix_offset = 0x67;
@@ -177,7 +179,7 @@ suunto_d9_parser_cache (suunto_d9_parser_t *parser)
} else if (parser->model == HELO2 || parser->model == D4i ||
parser->model == D6i || parser->model == D9tx ||
parser->model == DX || parser->model == ZOOPNOVO ||
- parser->model == VYPERNOVO) {
+ parser->model == VYPERNOVO || parser->model == D4F) {
config = gasmix_offset + gasmix_count * 6;
}
if (config + 1 > size)
@@ -198,7 +200,7 @@ suunto_d9_parser_cache (suunto_d9_parser_t *parser)
if (parser->model == HELO2 || parser->model == D4i ||
parser->model == D6i || parser->model == D9tx ||
parser->model == DX || parser->model == ZOOPNOVO ||
- parser->model == VYPERNOVO) {
+ parser->model == VYPERNOVO || parser->model == D4F) {
parser->oxygen[i] = data[gasmix_offset + 6 * i + 1];
parser->helium[i] = data[gasmix_offset + 6 * i + 2];
} else {
@@ -216,7 +218,7 @@ suunto_d9_parser_cache (suunto_d9_parser_t *parser)
parser->gasmix = data[0x26];
} else if (parser->model == D4i || parser->model == D6i ||
parser->model == D9tx || parser->model == ZOOPNOVO ||
- parser->model == VYPERNOVO) {
+ parser->model == VYPERNOVO || parser->model == D4F) {
if (id == ID_D4I_V2 || id == ID_D6I_V2) {
parser->gasmix = data[0x2D];
} else {
@@ -294,7 +296,7 @@ suunto_d9_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
offset = 0x17;
else if (parser->model == D4i || parser->model == D6i ||
parser->model == D9tx || parser->model == ZOOPNOVO ||
- parser->model == VYPERNOVO)
+ parser->model == VYPERNOVO || parser->model == D4F)
offset = 0x13;
if (abstract->size < offset + 7)
@@ -305,7 +307,8 @@ suunto_d9_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
if (datetime) {
if (parser->model == D4i || parser->model == D6i ||
parser->model == D9tx || parser->model == DX ||
- parser->model == ZOOPNOVO || parser->model == VYPERNOVO) {
+ parser->model == ZOOPNOVO || parser->model == VYPERNOVO ||
+ parser->model == D4F) {
datetime->year = p[0] + (p[1] << 8);
datetime->month = p[2];
datetime->day = p[3];
@@ -353,7 +356,8 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne
*((unsigned int *) value) = array_uint16_le (data + 0x0B);
else if (parser->model == D4i || parser->model == D6i ||
parser->model == D9tx || parser->model == DX ||
- parser->model == ZOOPNOVO || parser->model == VYPERNOVO)
+ parser->model == ZOOPNOVO || parser->model == VYPERNOVO ||
+ parser->model == D4F)
*((unsigned int *) value) = array_uint16_le (data + 0x0D);
else if (parser->model == HELO2)
*((unsigned int *) value) = array_uint16_le (data + 0x0D) * 60;
@@ -475,7 +479,8 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca
unsigned int interval_sample_offset = 0x18;
if (parser->model == HELO2 || parser->model == D4i ||
parser->model == D6i || parser->model == D9tx ||
- parser->model == ZOOPNOVO || parser->model == VYPERNOVO)
+ parser->model == ZOOPNOVO || parser->model == VYPERNOVO ||
+ parser->model == D4F)
interval_sample_offset = 0x1E;
else if (parser->model == DX)
interval_sample_offset = 0x22;
diff --git a/src/suunto_eonsteel.c b/src/suunto_eonsteel.c
index f4e028c..11e1e28 100644
--- a/src/suunto_eonsteel.c
+++ b/src/suunto_eonsteel.c
@@ -29,10 +29,7 @@
#include "device-private.h"
#include "array.h"
#include "usbhid.h"
-
-#ifdef _MSC_VER
-#define snprintf _snprintf
-#endif
+#include "platform.h"
typedef struct suunto_eonsteel_device_t {
dc_device_t base;
@@ -146,7 +143,7 @@ static int receive_usbhid_packet(dc_custom_io_t *io, suunto_eonsteel_device_t *e
return -1;
}
if (transferred != PACKET_SIZE) {
- ERROR(eon->base.context, "incomplete read interrupt transfer (got %zu, expected %d)", transferred, PACKET_SIZE);
+ ERROR(eon->base.context, "incomplete read interrupt transfer (got " DC_PRINTF_SIZE ", expected %d)", transferred, PACKET_SIZE);
return -1;
}
if (buf[0] != 0x3f) {
diff --git a/src/suunto_eonsteel_parser.c b/src/suunto_eonsteel_parser.c
index f385bc9..30dd9a4 100644
--- a/src/suunto_eonsteel_parser.c
+++ b/src/suunto_eonsteel_parser.c
@@ -36,17 +36,7 @@
#include "context-private.h"
#include "parser-private.h"
#include "array.h"
-
-#ifdef _MSC_VER
-#define strcasecmp _stricmp
-#if _MSC_VER < 1800
-// The rint() function is only available in MSVC 2013 and later
-// versions. Our replacement macro isn't entirely correct, because the
-// rounding rules for halfway cases are slightly different (away from
-// zero vs to even). But for our use-case, that's not a problem.
-#define rint(x) ((x) >= 0.0 ? floor((x) + 0.5): ceil((x) - 0.5))
-#endif
-#endif
+#include "platform.h"
#define C_ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
diff --git a/src/usbhid.c b/src/usbhid.c
index c604cf4..5cbad2b 100644
--- a/src/usbhid.c
+++ b/src/usbhid.c
@@ -45,6 +45,7 @@
#include "usbhid.h"
#include "common-private.h"
#include "context-private.h"
+#include "platform.h"
struct dc_usbhid_t {
/* Library context. */
@@ -507,15 +508,16 @@ dc_usbhid_write (dc_usbhid_t *usbhid, const void *data, size_t size, size_t *act
nbytes = 0;
goto out;
}
-
-#ifdef _WIN32
- if (nbytes > size) {
- nbytes = size;
- }
-#endif
#endif
out:
+#ifdef _WIN32
+ if (nbytes > size) {
+ WARNING (usbhid->context, "Number of bytes exceeds the buffer size (" DC_PRINTF_SIZE " > " DC_PRINTF_SIZE ")!", nbytes, size);
+ nbytes = size;
+ }
+#endif
+
HEXDUMP (usbhid->context, DC_LOGLEVEL_INFO, "Write", (unsigned char *) data, nbytes);
out_invalidargs: