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: