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.
This commit is contained in:
Jef Driesen 2013-04-23 20:17:33 +02:00
parent 2e5faae9da
commit 59b17858f4
2 changed files with 24 additions and 6 deletions

View File

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

View File

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