From 14fd0296d45d17eec4a6dc4cd4a03f0ba379f719 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 7 May 2021 21:22:36 +0200 Subject: [PATCH 01/17] Post release version bump to 0.8.0 --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index b02e7a6..ca39faf 100644 --- a/configure.ac +++ b/configure.ac @@ -1,8 +1,8 @@ # Versioning. m4_define([dc_version_major],[0]) -m4_define([dc_version_minor],[7]) +m4_define([dc_version_minor],[8]) m4_define([dc_version_micro],[0]) -m4_define([dc_version_suffix],[]) +m4_define([dc_version_suffix],[devel]) m4_define([dc_version],dc_version_major.dc_version_minor.dc_version_micro[]m4_ifset([dc_version_suffix],-[dc_version_suffix])) # Libtool versioning. From fba5676b78f14c7d6cb79b48f264e74fd12c1f28 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Mon, 24 May 2021 22:59:32 +0200 Subject: [PATCH 02/17] Fix the hwOS Sport firmware upgrade Support for the S_BLOCK_WRITE2 command is only available since the hwOS Tech firmware v3.09 and the hwOS Sport firmware v10.64. In commit 9e92381be48866f3f13a11e98d59962575bb5ad3 it was enabled for all firmware versions newer than v3.09, causing the firmware upgrade to fail for older hwOS Sport firmware versions. Reported-by: Anton Lundin --- src/hw_ostc3.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c index 3ed6bc7..119af09 100644 --- a/src/hw_ostc3.c +++ b/src/hw_ostc3.c @@ -33,6 +33,10 @@ #define ISINSTANCE(device) dc_device_isinstance((device), &hw_ostc3_device_vtable) +#define OSTC3FW(major,minor) ( \ + (((major) & 0xFF) << 8) | \ + ((minor) & 0xFF)) + #define SZ_DISPLAY 16 #define SZ_CUSTOMTEXT 60 #define SZ_VERSION (SZ_CUSTOMTEXT + 4) @@ -1282,10 +1286,13 @@ hw_ostc3_firmware_block_write2 (hw_ostc3_device_t *device, unsigned int address, static dc_status_t hw_ostc3_firmware_block_write (hw_ostc3_device_t *device, unsigned int address, const unsigned char data[], unsigned int size) { - if (device->firmware >= 0x0309) { - return hw_ostc3_firmware_block_write2 (device, address, data, size); - } else { + // Support for the S_BLOCK_WRITE2 command is only available since the + // hwOS Tech firmware v3.09 and the hwOS Sport firmware v10.64. + if ((device->firmware < OSTC3FW(3,9)) || + (device->firmware >= OSTC3FW(10,0) && device->firmware < OSTC3FW(10,64))) { return hw_ostc3_firmware_block_write1 (device, address, data, size); + } else { + return hw_ostc3_firmware_block_write2 (device, address, data, size); } } From 0bc7b195e531e4e214d9ed586a703385a8cf7eef Mon Sep 17 00:00:00 2001 From: Vincent Hagen Date: Sun, 30 May 2021 14:00:34 +0200 Subject: [PATCH 03/17] Add library dependencies in windows build Include libusb and hidapi when building for windows these are also added to the artifact --- .github/workflows/build.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8fa7569..8610ffc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -81,8 +81,37 @@ jobs: - uses: actions/checkout@v2 - name: Install dependencies run: sudo apt-get install gcc-mingw-w64 binutils-mingw-w64 mingw-w64-tools + - name: Install libusb + env: + LIBUSB_VERSION: 1.0.24 + run: | + wget -c https://github.com/libusb/libusb/archive/refs/tags/v${LIBUSB_VERSION}.tar.gz + tar xzf v${LIBUSB_VERSION}.tar.gz + pushd libusb-${LIBUSB_VERSION} + autoreconf --install --force + ./configure --host=${{ matrix.arch }}-w64-mingw32 --prefix=/usr + make + make install DESTDIR=$PWD/../artifacts + popd + - name: Install hidapi + env: + HIDAPI_VERSION: 0.10.1 + run: | + wget -c https://github.com/libusb/hidapi/archive/refs/tags/hidapi-${HIDAPI_VERSION}.tar.gz + tar xzf hidapi-${HIDAPI_VERSION}.tar.gz + pushd hidapi-hidapi-${HIDAPI_VERSION} + autoreconf --install --force + ./configure --host=${{ matrix.arch }}-w64-mingw32 --prefix=/usr + make + make install DESTDIR=$PWD/../artifacts + popd - run: autoreconf --install --force - run: ./configure --host=${{ matrix.arch }}-w64-mingw32 --prefix=/usr + env: + PKG_CONFIG_LIBDIR: ${{ github.workspace }}/artifacts/usr/lib/pkgconfig + PKG_CONFIG_SYSROOT_DIR: ${{ github.workspace }}/artifacts + PKG_CONFIG_ALLOW_SYSTEM_CFLAGS: 1 + PKG_CONFIG_ALLOW_SYSTEM_LIBS: 1 - run: make - run: make distcheck - name: Package artifacts From 449b65cf1b291e808dfb8dc2f378774438f8ab87 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 25 Jun 2021 17:15:43 +0200 Subject: [PATCH 04/17] Fix the depth decoding With just 12 bits, the depth values are limited to at most 40.95m. However for some deeper dives, this appears to be wrong. The next two higher bits, which were previously unknown, are also part of the depth. This increases the maximum depth to 163.83m. --- src/sporasub_sp2_parser.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sporasub_sp2_parser.c b/src/sporasub_sp2_parser.c index e036dd2..f2208a1 100644 --- a/src/sporasub_sp2_parser.c +++ b/src/sporasub_sp2_parser.c @@ -170,8 +170,7 @@ sporasub_sp2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t unsigned int value = array_uint32_le (data + offset); unsigned int heartrate = (value & 0xFF000000) >> 24; unsigned int temperature = (value & 0x00FFC000) >> 14; - unsigned int unknown = (value & 0x00003000) >> 12; - unsigned int depth = (value & 0x00000FFF) >> 0; + unsigned int depth = (value & 0x00003FFF) >> 0; // Time (seconds) time += interval; From 9106250a537cf85a1c960c854b91ab6851202b65 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 25 Jun 2021 17:17:12 +0200 Subject: [PATCH 05/17] Emit events when downloading a memory dump --- src/sporasub_sp2.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/sporasub_sp2.c b/src/sporasub_sp2.c index c0f6b49..4593f6d 100644 --- a/src/sporasub_sp2.c +++ b/src/sporasub_sp2.c @@ -342,22 +342,14 @@ sporasub_sp2_device_read (dc_device_t *abstract, unsigned int address, unsigned static dc_status_t sporasub_sp2_device_dump (dc_device_t *abstract, dc_buffer_t *buffer) { + sporasub_sp2_device_t *device = (sporasub_sp2_device_t *) abstract; + // Allocate the required amount of memory. if (!dc_buffer_resize (buffer, SZ_MEMORY)) { ERROR (abstract->context, "Insufficient buffer space available."); return DC_STATUS_NOMEMORY; } - return device_dump_read (abstract, dc_buffer_get_data (buffer), - dc_buffer_get_size (buffer), SZ_READ); -} - -static dc_status_t -sporasub_sp2_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata) -{ - dc_status_t status = DC_STATUS_SUCCESS; - sporasub_sp2_device_t *device = (sporasub_sp2_device_t *) abstract; - // Emit a device info event. dc_event_devinfo_t devinfo; devinfo.model = 0; @@ -371,6 +363,16 @@ sporasub_sp2_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, vendor.size = sizeof (device->version); device_event_emit (abstract, DC_EVENT_VENDOR, &vendor); + return device_dump_read (abstract, dc_buffer_get_data (buffer), + dc_buffer_get_size (buffer), SZ_READ); +} + +static dc_status_t +sporasub_sp2_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata) +{ + dc_status_t status = DC_STATUS_SUCCESS; + sporasub_sp2_device_t *device = (sporasub_sp2_device_t *) abstract; + dc_buffer_t *buffer = dc_buffer_new (SZ_MEMORY); if (buffer == NULL) { status = DC_STATUS_NOMEMORY; From 9307acbe4a226bcd108175f72fc8a6adf2e49dc6 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 18 May 2021 21:51:32 +0200 Subject: [PATCH 06/17] Migrate to Visual Studio 2013 (or newer) Starting with msvc 2013, the C compiler has much better C99 support. The previous workaround to compile everything as C++ code is no longer needed. Some additional changes: - Add a 64bit build - Enable _CRT_SECURE_NO_WARNINGS to silence warnings --- .gitignore | 5 +- Makefile.am | 3 +- msvc/libdivecomputer.vcproj | 959 --------------------------- msvc/libdivecomputer.vcxproj | 374 +++++++++++ msvc/libdivecomputer.vcxproj.filters | 17 + 5 files changed, 395 insertions(+), 963 deletions(-) delete mode 100644 msvc/libdivecomputer.vcproj create mode 100644 msvc/libdivecomputer.vcxproj create mode 100644 msvc/libdivecomputer.vcxproj.filters diff --git a/.gitignore b/.gitignore index 85901e8..4d369e6 100644 --- a/.gitignore +++ b/.gitignore @@ -47,11 +47,10 @@ Makefile.in /m4/ltsugar.m4 /m4/ltversion.m4 -/msvc/Debug/ -/msvc/Release/ +/msvc/x64/ +/msvc/x86/ /msvc/*.ncb /msvc/*.suo -/msvc/*.vcproj.*.user /src/libdivecomputer.exp /src/libdivecomputer.la diff --git a/Makefile.am b/Makefile.am index c3ae858..9ae4414 100644 --- a/Makefile.am +++ b/Makefile.am @@ -16,4 +16,5 @@ pkgconfig_DATA = libdivecomputer.pc EXTRA_DIST = \ libdivecomputer.pc.in \ - msvc/libdivecomputer.vcproj + msvc/libdivecomputer.vcxproj \ + msvc/libdivecomputer.vcxproj.filters diff --git a/msvc/libdivecomputer.vcproj b/msvc/libdivecomputer.vcproj deleted file mode 100644 index 3482457..0000000 --- a/msvc/libdivecomputer.vcproj +++ /dev/null @@ -1,959 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/msvc/libdivecomputer.vcxproj b/msvc/libdivecomputer.vcxproj new file mode 100644 index 0000000..2f99a43 --- /dev/null +++ b/msvc/libdivecomputer.vcxproj @@ -0,0 +1,374 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {CEA7215A-D6B5-4840-8086-3C854F371997} + libdivecomputer + Win32Proj + + + + DynamicLibrary + true + $(DefaultPlatformToolset) + Unicode + + + DynamicLibrary + true + $(DefaultPlatformToolset) + Unicode + + + DynamicLibrary + false + $(DefaultPlatformToolset) + Unicode + true + + + DynamicLibrary + false + $(DefaultPlatformToolset) + Unicode + true + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)$(PlatformTarget)\$(Configuration)\bin\ + $(PlatformTarget)\$(Configuration)\obj\ + + + true + $(SolutionDir)$(PlatformTarget)\$(Configuration)\bin\ + $(PlatformTarget)\$(Configuration)\obj\ + + + false + $(SolutionDir)$(PlatformTarget)\$(Configuration)\bin\ + $(PlatformTarget)\$(Configuration)\obj\ + + + false + $(SolutionDir)$(PlatformTarget)\$(Configuration)\bin\ + $(PlatformTarget)\$(Configuration)\obj\ + + + + Disabled + ..\include;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBDIVECOMPUTER_EXPORTS;ENABLE_LOGGING;HAVE_AF_IRDA_H;HAVE_WS2BTH_H;%(PreprocessorDefinitions) + + Level3 + true + + + ws2_32.lib;%(AdditionalDependencies) + $(OutDir)libdivecomputer.def + true + Windows + + + + + Disabled + ..\include;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBDIVECOMPUTER_EXPORTS;ENABLE_LOGGING;HAVE_AF_IRDA_H;HAVE_WS2BTH_H;%(PreprocessorDefinitions) + + + Level3 + true + + + ws2_32.lib;%(AdditionalDependencies) + $(OutDir)libdivecomputer.def + true + Windows + + + + + MaxSpeed + true + ..\include;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBDIVECOMPUTER_EXPORTS;ENABLE_LOGGING;HAVE_AF_IRDA_H;HAVE_WS2BTH_H;%(PreprocessorDefinitions) + true + + Level3 + true + + + ws2_32.lib;%(AdditionalDependencies) + $(OutDir)libdivecomputer.def + true + Windows + true + true + + + + + MaxSpeed + true + ..\include;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBDIVECOMPUTER_EXPORTS;ENABLE_LOGGING;HAVE_AF_IRDA_H;HAVE_WS2BTH_H;%(PreprocessorDefinitions) + true + + + Level3 + true + + + ws2_32.lib;%(AdditionalDependencies) + $(OutDir)libdivecomputer.def + true + Windows + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + echo EXPORTS > "$(OutDir)libdivecomputer.def" && type "%(FullPath)" >> "$(OutDir)libdivecomputer.def" + echo EXPORTS > "$(OutDir)libdivecomputer.def" && type "%(FullPath)" >> "$(OutDir)libdivecomputer.def" + $(OutDir)libdivecomputer.def;%(Outputs) + $(OutDir)libdivecomputer.def;%(Outputs) + echo EXPORTS > "$(OutDir)libdivecomputer.def" && type "%(FullPath)" >> "$(OutDir)libdivecomputer.def" + echo EXPORTS > "$(OutDir)libdivecomputer.def" && type "%(FullPath)" >> "$(OutDir)libdivecomputer.def" + $(OutDir)libdivecomputer.def;%(Outputs) + $(OutDir)libdivecomputer.def;%(Outputs) + + + + + + diff --git a/msvc/libdivecomputer.vcxproj.filters b/msvc/libdivecomputer.vcxproj.filters new file mode 100644 index 0000000..e5cb0c5 --- /dev/null +++ b/msvc/libdivecomputer.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + From c747dc71845b2b25a7af6e63e0fe85dbfc903a7d Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 18 May 2021 22:01:54 +0200 Subject: [PATCH 07/17] Add a CI job to build with Visual Studio The migration to Visual Studio 2013 allows to build the Visual Studio project in a Github Action. Because some of the source files (e.g. the resource script and version header) are normally auto-generated by the autotools build system, an msys environment is setup to run the configure script. When building from a distribution tarball, this extra step isn't necessary. --- .github/workflows/build.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8610ffc..161c2f3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -122,3 +122,33 @@ jobs: with: name: ${{ github.job }}-${{ matrix.arch }} path: ${{ github.job }}-${{ matrix.arch }}.tar.gz + + msvc: + + name: Visual Studio + + runs-on: windows-latest + + strategy: + fail-fast: false + matrix: + platform: [x86, x64] + + env: + CONFIGURATION: Release + + steps: + - uses: actions/checkout@v2 + - uses: msys2/setup-msys2@v2 + with: + install: autoconf automake libtool pkg-config make gcc + - run: | + autoreconf --install --force + ./configure --prefix=/usr + shell: msys2 {0} + - uses: microsoft/setup-msbuild@v1.0.2 + - run: msbuild -m -p:Platform=${{ matrix.platform }} -p:Configuration=${{ env.CONFIGURATION }} msvc/libdivecomputer.vcxproj + - uses: actions/upload-artifact@v2 + with: + name: ${{ github.job }}-${{ matrix.platform }} + path: msvc/${{ matrix.platform }}/${{ env.CONFIGURATION }}/bin From c8bd477c8479197e597164fd8a3fd67e1b67c45f Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 15 Jun 2021 21:24:12 +0200 Subject: [PATCH 08/17] Always use the stored atmospheric pressure The correct atmospheric pressure is measured and recorded by the dive computer. There is no need to replace the correct value with some other value. --- src/atomics_cobalt_parser.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/atomics_cobalt_parser.c b/src/atomics_cobalt_parser.c index 438eb39..f813f52 100644 --- a/src/atomics_cobalt_parser.c +++ b/src/atomics_cobalt_parser.c @@ -40,7 +40,6 @@ typedef struct atomics_cobalt_parser_t atomics_cobalt_parser_t; struct atomics_cobalt_parser_t { dc_parser_t base; // Depth calibration. - double atmospheric; double hydrostatic; }; @@ -76,7 +75,6 @@ atomics_cobalt_parser_create (dc_parser_t **out, dc_context_t *context) } // Set the default values. - parser->atmospheric = 0.0; parser->hydrostatic = 1025.0 * GRAVITY; *out = (dc_parser_t*) parser; @@ -100,7 +98,6 @@ atomics_cobalt_parser_set_calibration (dc_parser_t *abstract, double atmospheric if (!ISINSTANCE (abstract)) return DC_STATUS_INVALIDARGS; - parser->atmospheric = atmospheric; parser->hydrostatic = hydrostatic; return DC_STATUS_SUCCESS; @@ -142,11 +139,7 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un dc_gasmix_t *gasmix = (dc_gasmix_t *) value; dc_tank_t *tank = (dc_tank_t *) value; - double atmospheric = 0.0; - if (parser->atmospheric) - atmospheric = parser->atmospheric; - else - atmospheric = array_uint16_le (p + 0x26) * BAR / 1000.0; + unsigned int atmospheric = array_uint16_le (p + 0x26); unsigned int workpressure = 0; @@ -156,7 +149,7 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un *((unsigned int *) value) = array_uint16_le (p + 0x58) * 60; break; case DC_FIELD_MAXDEPTH: - *((double *) value) = (array_uint16_le (p + 0x56) * BAR / 1000.0 - atmospheric) / parser->hydrostatic; + *((double *) value) = (array_uint16_le (p + 0x56) - atmospheric) * (BAR / 1000.0) / parser->hydrostatic; break; case DC_FIELD_GASMIX_COUNT: case DC_FIELD_TANK_COUNT: @@ -239,11 +232,7 @@ atomics_cobalt_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback if (size < header + SZ_SEGMENT * nsegments) return DC_STATUS_DATAFORMAT; - double atmospheric = 0.0; - if (parser->atmospheric) - atmospheric = parser->atmospheric; - else - atmospheric = array_uint16_le (data + 0x26) * BAR / 1000.0; + unsigned int atmospheric = array_uint16_le (data + 0x26); // Previous gas mix - initialize with impossible value unsigned int gasmix_previous = 0xFFFFFFFF; @@ -274,7 +263,7 @@ atomics_cobalt_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback // Depth (1/1000 bar). unsigned int depth = array_uint16_le (data + offset + 0); - sample.depth = (depth * BAR / 1000.0 - atmospheric) / parser->hydrostatic; + sample.depth = (depth - atmospheric) * (BAR / 1000.0) / parser->hydrostatic; if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); // Pressure (1 psi). From 6645b3f5e40bf6e40fbc200eab59a5caa144a46a Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 15 Jun 2021 21:50:44 +0200 Subject: [PATCH 09/17] Implement the atmospheric pressure field --- src/atomics_cobalt_parser.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/atomics_cobalt_parser.c b/src/atomics_cobalt_parser.c index f813f52..282bbb8 100644 --- a/src/atomics_cobalt_parser.c +++ b/src/atomics_cobalt_parser.c @@ -201,6 +201,9 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un return DC_STATUS_DATAFORMAT; } break; + case DC_FIELD_ATMOSPHERIC: + *((double *) value) = atmospheric / 1000.0; + break; default: return DC_STATUS_UNSUPPORTED; } From da2446283aaf3be344ba772738333058a17eca0f Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 18 Jun 2021 20:36:31 +0200 Subject: [PATCH 10/17] Move the unit conversion to the last moment Processing the data in device units, and performing the unit conversion only at the very last moment, avoids the need for intermediate floating point math and thus possible rounding errors. In practice this is not really an important issue, except for some case where a negative zero value was returned. --- src/uwatec_smart_parser.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/uwatec_smart_parser.c b/src/uwatec_smart_parser.c index be74b1c..dd867e4 100644 --- a/src/uwatec_smart_parser.c +++ b/src/uwatec_smart_parser.c @@ -940,9 +940,9 @@ uwatec_smart_parse (uwatec_smart_parser_t *parser, dc_sample_callback_t callback unsigned int rbt = 99; unsigned int tank = 0; unsigned int gasmix = 0; - double depth = 0, depth_calibration = 0; - double temperature = 0; - double pressure = 0; + unsigned int depth = 0, depth_calibration = 0; + int temperature = 0; + unsigned int pressure = 0; unsigned int heartrate = 0; unsigned int bearing = 0; unsigned int bookmark = 0; @@ -1026,8 +1026,8 @@ uwatec_smart_parse (uwatec_smart_parser_t *parser, dc_sample_callback_t callback const uwatec_smart_event_info_t *events = NULL; switch (table[id].type) { case PRESSURE_DEPTH: - pressure += ((signed char) ((svalue >> NBITS) & 0xFF)) / 4.0; - depth += ((signed char) (svalue & 0xFF)) / 50.0; + pressure += (signed char) ((svalue >> NBITS) & 0xFF); + depth += (signed char) (svalue & 0xFF); complete = 1; break; case RBT: @@ -1040,37 +1040,37 @@ uwatec_smart_parse (uwatec_smart_parser_t *parser, dc_sample_callback_t callback break; case TEMPERATURE: if (table[id].absolute) { - temperature = svalue / 2.5; + temperature = svalue; have_temperature = 1; } else { - temperature += svalue / 2.5; + temperature += svalue; } break; case PRESSURE: if (table[id].absolute) { if (parser->trimix) { tank = (value & 0xF000) >> 12; - pressure = (value & 0x0FFF) / 4.0; + pressure = (value & 0x0FFF); } else { tank = table[id].index; - pressure = value / 4.0; + pressure = value; } have_pressure = 1; gasmix = tank; } else { - pressure += svalue / 4.0; + pressure += svalue; } break; case DEPTH: if (table[id].absolute) { - depth = value / 50.0; + depth = value; if (!calibrated) { calibrated = 1; depth_calibration = depth; } have_depth = 1; } else { - depth += svalue / 50.0; + depth += svalue; } complete = 1; break; @@ -1195,7 +1195,7 @@ uwatec_smart_parse (uwatec_smart_parser_t *parser, dc_sample_callback_t callback } if (have_temperature) { - sample.temperature = temperature; + sample.temperature = temperature / 2.5; if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata); } @@ -1216,7 +1216,7 @@ uwatec_smart_parse (uwatec_smart_parser_t *parser, dc_sample_callback_t callback idx = uwatec_smart_find_tank(parser, tank); if (idx < parser->ntanks) { sample.pressure.tank = idx; - sample.pressure.value = pressure; + sample.pressure.value = pressure / 4.0; if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata); } } @@ -1233,7 +1233,7 @@ uwatec_smart_parse (uwatec_smart_parser_t *parser, dc_sample_callback_t callback } if (have_depth) { - sample.depth = (depth - depth_calibration) / salinity; + sample.depth = (depth - depth_calibration) / 50.0 / salinity; if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); } From b186846a9e7fa5b542c451ca0917acce2f6a0e4b Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 18 Jun 2021 20:45:28 +0200 Subject: [PATCH 11/17] Fix negative depth values The difference between two unsigned integers can be negative. To avoid ending up with some very large positive values, an explicit cast to a signed integer is required. Depths are normally expected to be always positive, but near the surface the pressure will be very close to the atmospheric pressure. Therefore small negative values are not unusual. --- src/atomics_cobalt_parser.c | 4 ++-- src/mclean_extreme_parser.c | 4 ++-- src/shearwater_predator_parser.c | 2 +- src/uwatec_smart_parser.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/atomics_cobalt_parser.c b/src/atomics_cobalt_parser.c index 282bbb8..ace7b7a 100644 --- a/src/atomics_cobalt_parser.c +++ b/src/atomics_cobalt_parser.c @@ -149,7 +149,7 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un *((unsigned int *) value) = array_uint16_le (p + 0x58) * 60; break; case DC_FIELD_MAXDEPTH: - *((double *) value) = (array_uint16_le (p + 0x56) - atmospheric) * (BAR / 1000.0) / parser->hydrostatic; + *((double *) value) = (signed int)(array_uint16_le (p + 0x56) - atmospheric) * (BAR / 1000.0) / parser->hydrostatic; break; case DC_FIELD_GASMIX_COUNT: case DC_FIELD_TANK_COUNT: @@ -266,7 +266,7 @@ atomics_cobalt_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback // Depth (1/1000 bar). unsigned int depth = array_uint16_le (data + offset + 0); - sample.depth = (depth - atmospheric) * (BAR / 1000.0) / parser->hydrostatic; + sample.depth = (signed int)(depth - atmospheric) * (BAR / 1000.0) / parser->hydrostatic; if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); // Pressure (1 psi). diff --git a/src/mclean_extreme_parser.c b/src/mclean_extreme_parser.c index f053986..9b5c91c 100644 --- a/src/mclean_extreme_parser.c +++ b/src/mclean_extreme_parser.c @@ -177,10 +177,10 @@ mclean_extreme_parser_get_field(dc_parser_t *abstract, dc_field_type_t type, uns *((unsigned int *)value) = array_uint32_le(abstract->data + SZ_CFG + 0x000C) - array_uint32_le(abstract->data + SZ_CFG + 0x0000); break; case DC_FIELD_MAXDEPTH: - *((double *)value) = 0.01 * (array_uint16_le(abstract->data + SZ_CFG + 0x0016) - psurf) / density; + *((double *)value) = 0.01 * (signed int)(array_uint16_le(abstract->data + SZ_CFG + 0x0016) - psurf) / density; break; case DC_FIELD_AVGDEPTH: - *((double *)value) = 0.01 * (array_uint16_le(abstract->data + SZ_CFG + 0x0018) - psurf) / density; + *((double *)value) = 0.01 * (signed int)(array_uint16_le(abstract->data + SZ_CFG + 0x0018) - psurf) / density; break; case DC_FIELD_SALINITY: salinity->density = density * 1000.0; diff --git a/src/shearwater_predator_parser.c b/src/shearwater_predator_parser.c index 43eefa8..290001a 100644 --- a/src/shearwater_predator_parser.c +++ b/src/shearwater_predator_parser.c @@ -809,7 +809,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal // Depth (absolute pressure in millibar) unsigned int depth = array_uint16_be (data + idx + 1); - sample.depth = (depth - parser->atmospheric) * (BAR / 1000.0) / (parser->density * GRAVITY); + sample.depth = (signed int)(depth - parser->atmospheric) * (BAR / 1000.0) / (parser->density * GRAVITY); if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); // Temperature (1/10 °C). diff --git a/src/uwatec_smart_parser.c b/src/uwatec_smart_parser.c index dd867e4..c28e1d0 100644 --- a/src/uwatec_smart_parser.c +++ b/src/uwatec_smart_parser.c @@ -1233,7 +1233,7 @@ uwatec_smart_parse (uwatec_smart_parser_t *parser, dc_sample_callback_t callback } if (have_depth) { - sample.depth = (depth - depth_calibration) / 50.0 / salinity; + sample.depth = (signed int)(depth - depth_calibration) / 50.0 / salinity; if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); } From cffda88ae85b3a6107205dc9c148d121c3580175 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 18 Jun 2021 21:45:17 +0200 Subject: [PATCH 12/17] Use SI units internally Prefer SI units for internal constants (e.g. density) and calculations. This results in more consistent conversion formulas across the different backends. For the Uwatec backend, this changes makes it also much more visible that the unit for the depth is either 1 millibar (maximum depth) or 2 millibar (sample depth). --- src/mclean_extreme_parser.c | 18 ++++++++++-------- src/uwatec_smart_parser.c | 14 +++++++------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/mclean_extreme_parser.c b/src/mclean_extreme_parser.c index 9b5c91c..585c10c 100644 --- a/src/mclean_extreme_parser.c +++ b/src/mclean_extreme_parser.c @@ -22,6 +22,8 @@ #include #include +#include + #include "mclean_extreme.h" #include "context-private.h" #include "parser-private.h" @@ -152,19 +154,19 @@ mclean_extreme_parser_get_field(dc_parser_t *abstract, dc_field_type_t type, uns dc_gasmix_t *gasmix = (dc_gasmix_t *)value; dc_salinity_t *salinity = (dc_salinity_t *)value; - const unsigned int psurf = array_uint16_le(abstract->data + 0x001E); + const unsigned int atmospheric = array_uint16_le(abstract->data + 0x001E); const unsigned int density_index = abstract->data[0x0023]; double density = 0; switch (density_index) { case 0: - density = 1.000; + density = 1000.0; break; case 1: - density = 1.020; + density = 1020.0; break; case 2: - density = 1.030; + density = 1030.0; break; default: ERROR(abstract->context, "Corrupt density index in dive data"); @@ -177,17 +179,17 @@ mclean_extreme_parser_get_field(dc_parser_t *abstract, dc_field_type_t type, uns *((unsigned int *)value) = array_uint32_le(abstract->data + SZ_CFG + 0x000C) - array_uint32_le(abstract->data + SZ_CFG + 0x0000); break; case DC_FIELD_MAXDEPTH: - *((double *)value) = 0.01 * (signed int)(array_uint16_le(abstract->data + SZ_CFG + 0x0016) - psurf) / density; + *((double *)value) = (signed int)(array_uint16_le(abstract->data + SZ_CFG + 0x0016) - atmospheric) * (BAR / 1000.0) / (density * 10.0); break; case DC_FIELD_AVGDEPTH: - *((double *)value) = 0.01 * (signed int)(array_uint16_le(abstract->data + SZ_CFG + 0x0018) - psurf) / density; + *((double *)value) = (signed int)(array_uint16_le(abstract->data + SZ_CFG + 0x0018) - atmospheric) * (BAR / 1000.0) / (density * 10.0); break; case DC_FIELD_SALINITY: - salinity->density = density * 1000.0; + salinity->density = density; salinity->type = density_index == 0 ? DC_WATER_FRESH : DC_WATER_SALT; break; case DC_FIELD_ATMOSPHERIC: - *((double *)value) = 0.001 * array_uint16_le(abstract->data + 0x001E); + *((double *)value) = atmospheric / 1000.0; break; case DC_FIELD_TEMPERATURE_MINIMUM: *((double *)value) = (double)abstract->data[SZ_CFG + 0x0010]; diff --git a/src/uwatec_smart_parser.c b/src/uwatec_smart_parser.c index c28e1d0..3e4ed09 100644 --- a/src/uwatec_smart_parser.c +++ b/src/uwatec_smart_parser.c @@ -62,8 +62,8 @@ #define HEADER 1 #define PROFILE 2 -#define FRESH 1.000 -#define SALT 1.025 +#define FRESH 1000.0 +#define SALT 1025.0 #define FREEDIVE 0x00000080 #define GAUGE 0x00001000 @@ -789,7 +789,7 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi const uwatec_smart_header_info_t *table = parser->header; const unsigned char *data = abstract->data; - double salinity = (parser->watertype == DC_WATER_SALT ? SALT : FRESH); + double density = (parser->watertype == DC_WATER_SALT ? SALT : FRESH); dc_gasmix_t *gasmix = (dc_gasmix_t *) value; dc_tank_t *tank = (dc_tank_t *) value; @@ -801,7 +801,7 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi *((unsigned int *) value) = array_uint16_le (data + table->divetime) * 60; break; case DC_FIELD_MAXDEPTH: - *((double *) value) = array_uint16_le (data + table->maxdepth) / 100.0 / salinity; + *((double *) value) = array_uint16_le (data + table->maxdepth) * (BAR / 1000.0) / (density * 10.0); break; case DC_FIELD_GASMIX_COUNT: *((unsigned int *) value) = parser->ngasmixes; @@ -844,7 +844,7 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi if (table->settings == UNSUPPORTED) return DC_STATUS_UNSUPPORTED; water->type = parser->watertype; - water->density = salinity * 1000.0; + water->density = density; break; default: return DC_STATUS_UNSUPPORTED; @@ -950,7 +950,7 @@ uwatec_smart_parse (uwatec_smart_parser_t *parser, dc_sample_callback_t callback // Previous gas mix - initialize with impossible value unsigned int gasmix_previous = 0xFFFFFFFF; - double salinity = (parser->watertype == DC_WATER_SALT ? SALT : FRESH); + double density = (parser->watertype == DC_WATER_SALT ? SALT : FRESH); unsigned int interval = 4; if (parser->divemode == DC_DIVEMODE_FREEDIVE) { @@ -1233,7 +1233,7 @@ uwatec_smart_parse (uwatec_smart_parser_t *parser, dc_sample_callback_t callback } if (have_depth) { - sample.depth = (signed int)(depth - depth_calibration) / 50.0 / salinity; + sample.depth = (signed int)(depth - depth_calibration) * (2.0 * BAR / 1000.0) / (density * 10.0); if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); } From cfc9ddc380bdc5616893fc2af4e05204b5500ea2 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 18 Jun 2021 21:54:29 +0200 Subject: [PATCH 13/17] Use the correct standard gravity factor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For manual depth calculations by divers, the standard gravity is often approximated as 10.0 (e.g. 1 bar corresponds to 10 meter), but libdivecomputer prefers to use the exact value of 9.80665 m/s². For the McLean Extreme, it has been confirmed that the device also uses the correct standard gravity internally for the conversion of the sample depth. --- src/mclean_extreme_parser.c | 4 ++-- src/uwatec_smart_parser.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mclean_extreme_parser.c b/src/mclean_extreme_parser.c index 585c10c..5fef8aa 100644 --- a/src/mclean_extreme_parser.c +++ b/src/mclean_extreme_parser.c @@ -179,10 +179,10 @@ mclean_extreme_parser_get_field(dc_parser_t *abstract, dc_field_type_t type, uns *((unsigned int *)value) = array_uint32_le(abstract->data + SZ_CFG + 0x000C) - array_uint32_le(abstract->data + SZ_CFG + 0x0000); break; case DC_FIELD_MAXDEPTH: - *((double *)value) = (signed int)(array_uint16_le(abstract->data + SZ_CFG + 0x0016) - atmospheric) * (BAR / 1000.0) / (density * 10.0); + *((double *)value) = (signed int)(array_uint16_le(abstract->data + SZ_CFG + 0x0016) - atmospheric) * (BAR / 1000.0) / (density * GRAVITY); break; case DC_FIELD_AVGDEPTH: - *((double *)value) = (signed int)(array_uint16_le(abstract->data + SZ_CFG + 0x0018) - atmospheric) * (BAR / 1000.0) / (density * 10.0); + *((double *)value) = (signed int)(array_uint16_le(abstract->data + SZ_CFG + 0x0018) - atmospheric) * (BAR / 1000.0) / (density * GRAVITY); break; case DC_FIELD_SALINITY: salinity->density = density; diff --git a/src/uwatec_smart_parser.c b/src/uwatec_smart_parser.c index 3e4ed09..7a12a4e 100644 --- a/src/uwatec_smart_parser.c +++ b/src/uwatec_smart_parser.c @@ -801,7 +801,7 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi *((unsigned int *) value) = array_uint16_le (data + table->divetime) * 60; break; case DC_FIELD_MAXDEPTH: - *((double *) value) = array_uint16_le (data + table->maxdepth) * (BAR / 1000.0) / (density * 10.0); + *((double *) value) = array_uint16_le (data + table->maxdepth) * (BAR / 1000.0) / (density * GRAVITY); break; case DC_FIELD_GASMIX_COUNT: *((unsigned int *) value) = parser->ngasmixes; @@ -1233,7 +1233,7 @@ uwatec_smart_parse (uwatec_smart_parser_t *parser, dc_sample_callback_t callback } if (have_depth) { - sample.depth = (signed int)(depth - depth_calibration) * (2.0 * BAR / 1000.0) / (density * 10.0); + sample.depth = (signed int)(depth - depth_calibration) * (2.0 * BAR / 1000.0) / (density * GRAVITY); if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); } From 5cb527d53ca88ac692beb55288172fc1003975fa Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 1 Jul 2021 09:15:15 +0200 Subject: [PATCH 14/17] Add support for the new Mares Genius firmware The new Mares Genius firmware v01.02.00 has a header which is 10 bytes larger. This difference is indicated with a change in the major version from 0 to 1. --- src/mares_iconhd_parser.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/mares_iconhd_parser.c b/src/mares_iconhd_parser.c index 5d26d13..b518da6 100644 --- a/src/mares_iconhd_parser.c +++ b/src/mares_iconhd_parser.c @@ -374,7 +374,7 @@ mares_genius_cache (mares_iconhd_parser_t *parser) unsigned int type = array_uint16_le (data); unsigned int minor = data[2]; unsigned int major = data[3]; - if (type != 1 || major != 0 || minor > 1) { + if (type != 1 || major > 1 || minor > 1) { ERROR (abstract->context, "Unsupported object type (%u) or version (%u.%u).", type, major, minor); return DC_STATUS_DATAFORMAT; @@ -389,8 +389,14 @@ mares_genius_cache (mares_iconhd_parser_t *parser) extra = 8; } + // The Genius header (v1.x) has 10 bytes more at the end. + unsigned int more = 0; + if (major == 1) { + more = 16; + } + // Get the header size. - unsigned int headersize = 0xB8 + extra; + unsigned int headersize = 0xB8 + extra + more; if (headersize > size) { ERROR (abstract->context, "Buffer overflow detected!"); return DC_STATUS_DATAFORMAT; From 060c0b72151d40873169b9e724c2c4e96ff1f175 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Sun, 4 Jul 2021 11:25:22 +0200 Subject: [PATCH 15/17] Fix the sample rate parsing The byte at offset 0x1A appears to be some settings byte, containing not only the sample rate index, but also some other values in the higher bits. Except for the 4th bit, which contains the salinity setting, the meaning of those higher bits remains unknown. Since the sample rate is limited to only 4 possible values, 2 bits are sufficient for encoding the sample rate index. The 3th bit might contain some other setting, or be reserved for future sample rates. --- src/sporasub_sp2_parser.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sporasub_sp2_parser.c b/src/sporasub_sp2_parser.c index f2208a1..0479d59 100644 --- a/src/sporasub_sp2_parser.c +++ b/src/sporasub_sp2_parser.c @@ -151,9 +151,10 @@ sporasub_sp2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t return DC_STATUS_DATAFORMAT; unsigned int nsamples = array_uint16_le(data); + unsigned int settings = data[0x1A]; // Get the sample interval. - unsigned int interval_idx = data[0x1A]; + unsigned int interval_idx = settings & 0x03; const unsigned int intervals[] = {1, 2, 5, 10}; if (interval_idx >= C_ARRAY_SIZE(intervals)) { ERROR (abstract->context, "Invalid sample interval index %u", interval_idx); From 5bb6257acbc994db478ecbacb532142edb7b996f Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Sun, 4 Jul 2021 11:25:51 +0200 Subject: [PATCH 16/17] Implement the salinity field The 4th bit of the settings byte contains the salinity setting (salt or fresh water). --- src/sporasub_sp2_parser.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/sporasub_sp2_parser.c b/src/sporasub_sp2_parser.c index 0479d59..e041495 100644 --- a/src/sporasub_sp2_parser.c +++ b/src/sporasub_sp2_parser.c @@ -112,9 +112,13 @@ sporasub_sp2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi const unsigned char *data = abstract->data; unsigned int size = abstract->size; + dc_salinity_t *water = (dc_salinity_t *) value; + if (size < SZ_HEADER) return DC_STATUS_DATAFORMAT; + unsigned int settings = data[0x1A]; + if (value) { switch (type) { case DC_FIELD_DIVETIME: @@ -132,6 +136,10 @@ sporasub_sp2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi case DC_FIELD_TEMPERATURE_MAXIMUM: *((double *) value) = array_uint16_le (data + 0x16) / 10.0; break; + case DC_FIELD_SALINITY: + water->type = settings & 0x08 ? DC_WATER_FRESH : DC_WATER_SALT; + water->density = 0.0; + break; default: return DC_STATUS_UNSUPPORTED; } From 927362354d07df1b683e38d4158f3723ef89e391 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 13 Jul 2021 22:45:40 +0200 Subject: [PATCH 17/17] Some more fixes for the new Mares Genius firmware The changes in commit 5cb527d53ca88ac692beb55288172fc1003975fa to support the new Mares Genius firmware v01.02.00 were incomplete. For dives recorded prior to the firmware upgrade, only the header version changed from 0.0 to 1.1, while the profile version remained the same. But for dives recorded after the firmware upgrade, the profile version also changed from 0.2 to 1.0. The known header and profile object versions (indicated as type.major.minor) are now: Model | Firmware | Header | Profile ========|==========|========|========= Genius | 1.0.x | 1.0.0 | 0.0.2 Genius | 1.2.0 | 1.1.1 | 0.1.0 Horizon | 1.7.28 | 1.0.1 | 1.0.2 To simplify the object version check, all versions below a certain upper limit are now considered supported. --- src/mares_iconhd_parser.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/mares_iconhd_parser.c b/src/mares_iconhd_parser.c index b518da6..34d39c7 100644 --- a/src/mares_iconhd_parser.c +++ b/src/mares_iconhd_parser.c @@ -31,6 +31,10 @@ #define ISINSTANCE(parser) dc_parser_isinstance((parser), &mares_iconhd_parser_vtable) +#define OBJVERSION(major,minor) ( \ + (((major) & 0xFF) << 8) | \ + ((minor) & 0xFF)) + #define SMART 0x000010 #define SMARTAPNEA 0x010010 #define ICONHD 0x14 @@ -374,7 +378,7 @@ mares_genius_cache (mares_iconhd_parser_t *parser) unsigned int type = array_uint16_le (data); unsigned int minor = data[2]; unsigned int major = data[3]; - if (type != 1 || major > 1 || minor > 1) { + if (type != 1 || OBJVERSION(major,minor) > OBJVERSION(1,1)) { ERROR (abstract->context, "Unsupported object type (%u) or version (%u.%u).", type, major, minor); return DC_STATUS_DATAFORMAT; @@ -875,7 +879,9 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t unsigned int type = array_uint16_le (data); unsigned int minor = data[2]; unsigned int major = data[3]; - if (type > 1 || major != 0 || minor != 2) { + if (type > 1 || + (type == 0 && OBJVERSION(major,minor) > OBJVERSION(1,0)) || + (type == 1 && OBJVERSION(major,minor) > OBJVERSION(0,2))) { ERROR (abstract->context, "Unsupported object type (%u) or version (%u.%u).", type, major, minor); return DC_STATUS_DATAFORMAT;