From 59b17858f4f75f7a4d9aca5274890ed74596196c Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 23 Apr 2013 20:17:33 +0200 Subject: [PATCH] Append the final block to each dive. There are two good reasons for this change. First of all, it makes the Predator data format more consistent with the Petrel data format, which also has the final block appended to each dive. But even more important is that we might actually need the information stored in the final block someday. The final block contains important information about the device, such as the firmware and logbook version. Right now this information is simply lost after the download. But if the data format ever changes to support some new feature, we'll likely need that information to autodetect the correct format. Unfortunately this also changes the dive format in a non-backwards compatible way. However, to minimize the inconvenience, the legacy format (without the extra final block) remains supported in the parser. --- src/shearwater_predator.c | 26 ++++++++++++++++++++++---- src/shearwater_predator_parser.c | 4 ++-- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/shearwater_predator.c b/src/shearwater_predator.c index f0b1e99..e8a44ac 100644 --- a/src/shearwater_predator.c +++ b/src/shearwater_predator.c @@ -238,7 +238,7 @@ shearwater_predator_extract_predator (dc_device_t *abstract, const unsigned char } // Allocate memory for the profiles. - unsigned char *buffer = (unsigned char *) malloc (RB_PROFILE_END - RB_PROFILE_BEGIN); + unsigned char *buffer = (unsigned char *) malloc (RB_PROFILE_END - RB_PROFILE_BEGIN + SZ_BLOCK); if (buffer == NULL) { return DC_STATUS_NOMEMORY; } @@ -258,11 +258,15 @@ shearwater_predator_extract_predator (dc_device_t *abstract, const unsigned char if (array_isequal (buffer + offset, SZ_BLOCK, 0xFF)) { break; } else if (buffer[offset + 0] == 0xFF && buffer[offset + 1] == 0xFF && have_footer) { + // Append the final block. + unsigned int length = footer + SZ_BLOCK - offset; + memcpy (buffer + offset + length, data + SZ_MEMORY - SZ_BLOCK, SZ_BLOCK); + // Check the fingerprint data. if (device && memcmp (buffer + offset + 12, device->fingerprint, sizeof (device->fingerprint)) == 0) break; - if (callback && !callback (buffer + offset, footer + SZ_BLOCK - offset, buffer + offset + 12, sizeof (device->fingerprint), userdata)) + if (callback && !callback (buffer + offset, length + SZ_BLOCK, buffer + offset + 12, sizeof (device->fingerprint), userdata)) break; have_footer = 0; @@ -284,6 +288,12 @@ shearwater_predator_extract_petrel (dc_device_t *abstract, const unsigned char d shearwater_predator_device_t *device = (shearwater_predator_device_t*) abstract; dc_context_t *context = (abstract ? abstract->context : NULL); + // Allocate memory for the profiles. + unsigned char *buffer = (unsigned char *) malloc (RB_PROFILE_END - RB_PROFILE_BEGIN + SZ_BLOCK); + if (buffer == NULL) { + return DC_STATUS_NOMEMORY; + } + // Search the ringbuffer to locate matching header and footer // markers. Because the Petrel does reorder the internal ringbuffer // before sending the data, the most recent dive is always the first @@ -305,14 +315,20 @@ shearwater_predator_extract_petrel (dc_device_t *abstract, const unsigned char d // The dive number in the header and footer should be identical. if (memcmp (data + header + 2, data + offset + 2, 2) != 0) { ERROR (context, "Unexpected dive number."); + free (buffer); return DC_STATUS_DATAFORMAT; } + // Append the final block. + unsigned int length = offset + SZ_BLOCK - header; + memcpy (buffer, data + header, length); + memcpy (buffer + length, data + SZ_MEMORY - SZ_BLOCK, SZ_BLOCK); + // Check the fingerprint data. - if (device && memcmp (data + header + 12, device->fingerprint, sizeof (device->fingerprint)) == 0) + if (device && memcmp (buffer + 12, device->fingerprint, sizeof (device->fingerprint)) == 0) break; - if (callback && !callback (data + header, offset + SZ_BLOCK - header, data + header + 12, sizeof (device->fingerprint), userdata)) + if (callback && !callback (buffer, length + SZ_BLOCK, buffer + 12, sizeof (device->fingerprint), userdata)) break; // Reset the header marker. @@ -322,6 +338,8 @@ shearwater_predator_extract_petrel (dc_device_t *abstract, const unsigned char d offset += SZ_BLOCK; } + free (buffer); + return DC_STATUS_SUCCESS; } diff --git a/src/shearwater_predator_parser.c b/src/shearwater_predator_parser.c index 88a4ec8..8bd65f2 100644 --- a/src/shearwater_predator_parser.c +++ b/src/shearwater_predator_parser.c @@ -160,7 +160,7 @@ shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t typ // Get the offset to the footer record. unsigned int footer = size - SZ_BLOCK; - if (parser->petrel) { + if (parser->petrel || array_uint16_be (data + footer) == 0xFFFD) { if (size < 3 * SZ_BLOCK) return DC_STATUS_DATAFORMAT; @@ -226,7 +226,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal // Get the offset to the footer record. unsigned int footer = size - SZ_BLOCK; - if (parser->petrel) { + if (parser->petrel || array_uint16_be (data + footer) == 0xFFFD) { if (size < 3 * SZ_BLOCK) return DC_STATUS_DATAFORMAT;