From ee147afcebb8cb3ff643df52ed65ed36a61a1fa2 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 22 Jun 2023 20:18:26 +0200 Subject: [PATCH 1/5] Move the model number mapping to a function --- src/shearwater_common.c | 61 +++++++++++++++++++++++++++++++++++++++++ src/shearwater_common.h | 3 ++ src/shearwater_petrel.c | 54 +----------------------------------- 3 files changed, 65 insertions(+), 53 deletions(-) diff --git a/src/shearwater_common.c b/src/shearwater_common.c index a7f67f6..2dfb34a 100644 --- a/src/shearwater_common.c +++ b/src/shearwater_common.c @@ -548,3 +548,64 @@ shearwater_common_identifier (shearwater_common_device_t *device, dc_buffer_t *b return rc; } + +unsigned int +shearwater_common_get_model (shearwater_common_device_t *device, unsigned int hardware) +{ + unsigned int model = 0; + + switch (hardware) { + case 0x0101: + case 0x0202: + model = PREDATOR; + break; + case 0x0404: + case 0x0909: + model = PETREL; + break; + case 0x0505: + case 0x0808: + case 0x0838: + case 0x08A5: + case 0x0B0B: + case 0x7828: + case 0x7B2C: + case 0x8838: + model = PETREL2; + break; + case 0xB407: + model = PETREL3; + break; + case 0x0606: + case 0x0A0A: + model = NERD; + break; + case 0x0E0D: + case 0x7E2D: + model = NERD2; + break; + case 0x0707: + model = PERDIX; + break; + case 0x0C0D: + case 0x7C2D: + case 0x8D6C: + model = PERDIXAI; + break; + case 0xC407: + model = PERDIX2; + break; + case 0x0F0F: + case 0x1F0A: + case 0x1F0F: + model = TERIC; + break; + case 0x1512: + model = PEREGRINE; + break; + default: + WARNING (device->base.context, "Unknown hardware type 0x%04x.", hardware); + } + + return model; +} diff --git a/src/shearwater_common.h b/src/shearwater_common.h index b1f8c3b..dd6b180 100644 --- a/src/shearwater_common.h +++ b/src/shearwater_common.h @@ -67,6 +67,9 @@ shearwater_common_download (shearwater_common_device_t *device, dc_buffer_t *buf dc_status_t shearwater_common_identifier (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int id); +unsigned int +shearwater_common_get_model (shearwater_common_device_t *device, unsigned int hardware); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/shearwater_petrel.c b/src/shearwater_petrel.c index c047cca..1e32c17 100644 --- a/src/shearwater_petrel.c +++ b/src/shearwater_petrel.c @@ -210,59 +210,7 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call // Convert and map to the model number. unsigned int hardware = array_uint_be (dc_buffer_get_data (buffer), dc_buffer_get_size (buffer)); - unsigned int model = 0; - switch (hardware) { - case 0x0101: - case 0x0202: - model = PREDATOR; - break; - case 0x0404: - case 0x0909: - model = PETREL; - break; - case 0x0505: - case 0x0808: - case 0x0838: - case 0x08A5: - case 0x0B0B: - case 0x7828: - case 0x7B2C: - case 0x8838: - model = PETREL2; - break; - case 0xB407: - model = PETREL3; - break; - case 0x0606: - case 0x0A0A: - model = NERD; - break; - case 0x0E0D: - case 0x7E2D: - model = NERD2; - break; - case 0x0707: - model = PERDIX; - break; - case 0x0C0D: - case 0x7C2D: - case 0x8D6C: - model = PERDIXAI; - break; - case 0xC407: - model = PERDIX2; - break; - case 0x0F0F: - case 0x1F0A: - case 0x1F0F: - model = TERIC; - break; - case 0x1512: - model = PEREGRINE; - break; - default: - WARNING (abstract->context, "Unknown hardware type %04x.", hardware); - } + unsigned int model = shearwater_common_get_model (&device->base, hardware); // Emit a device info event. dc_event_devinfo_t devinfo; From 13705f2b2d62b8e0e126c85ba6d8f6bff5ac6aa2 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 22 Jun 2023 20:35:47 +0200 Subject: [PATCH 2/5] Use a static buffer for the RDBI function The RDBI (Read Data by Identifier) responses always have a fixed length. Using a resizable buffer for the API only makes the memory management more complex than necessary. Also add some symbolic constants to improve readability. --- src/shearwater_common.c | 39 ++++++++++++++------------- src/shearwater_common.h | 2 +- src/shearwater_petrel.c | 59 +++++++++++++++-------------------------- 3 files changed, 43 insertions(+), 57 deletions(-) diff --git a/src/shearwater_common.c b/src/shearwater_common.c index 2dfb34a..c184bb3 100644 --- a/src/shearwater_common.c +++ b/src/shearwater_common.c @@ -36,6 +36,9 @@ #define ESC_END 0xDC #define ESC_ESC 0xDD +#define RDBI_REQUEST 0x22 +#define RDBI_RESPONSE 0x62 + dc_status_t shearwater_common_setup (shearwater_common_device_t *device, dc_context_t *context, dc_iostream_t *iostream) { @@ -512,41 +515,41 @@ shearwater_common_download (shearwater_common_device_t *device, dc_buffer_t *buf dc_status_t -shearwater_common_identifier (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int id) +shearwater_common_rdbi (shearwater_common_device_t *device, unsigned int id, unsigned char data[], unsigned int size) { + dc_status_t status = DC_STATUS_SUCCESS; dc_device_t *abstract = (dc_device_t *) device; - dc_status_t rc = DC_STATUS_SUCCESS; - - // Erase the buffer. - if (!dc_buffer_clear (buffer)) { - ERROR (abstract->context, "Insufficient buffer space available."); - return DC_STATUS_NOMEMORY; - } // Transfer the request. unsigned int n = 0; - unsigned char request[] = {0x22, + unsigned char request[] = { + RDBI_REQUEST, (id >> 8) & 0xFF, (id ) & 0xFF}; unsigned char response[SZ_PACKET]; - rc = shearwater_common_transfer (device, request, sizeof (request), response, sizeof (response), &n); - if (rc != DC_STATUS_SUCCESS) { - return rc; + status = shearwater_common_transfer (device, request, sizeof (request), response, sizeof (response), &n); + if (status != DC_STATUS_SUCCESS) { + return status; } // Verify the response. - if (n < 3 || response[0] != 0x62 || response[1] != request[1] || response[2] != request[2]) { + if (n < 3 || response[0] != RDBI_RESPONSE || response[1] != request[1] || response[2] != request[2]) { ERROR (abstract->context, "Unexpected response packet."); return DC_STATUS_PROTOCOL; } - // Append the packet to the output buffer. - if (!dc_buffer_append (buffer, response + 3, n - 3)) { - ERROR (abstract->context, "Insufficient buffer space available."); - return DC_STATUS_NOMEMORY; + unsigned int length = n - 3; + + if (length != size) { + ERROR (abstract->context, "Unexpected packet size (%u bytes).", length); + return DC_STATUS_PROTOCOL; } - return rc; + if (length) { + memcpy (data, response + 3, length); + } + + return status; } unsigned int diff --git a/src/shearwater_common.h b/src/shearwater_common.h index dd6b180..8f8e356 100644 --- a/src/shearwater_common.h +++ b/src/shearwater_common.h @@ -65,7 +65,7 @@ dc_status_t shearwater_common_download (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int address, unsigned int size, unsigned int compression, dc_event_progress_t *progress); dc_status_t -shearwater_common_identifier (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int id); +shearwater_common_rdbi (shearwater_common_device_t *device, unsigned int id, unsigned char data[], unsigned int size); unsigned int shearwater_common_get_model (shearwater_common_device_t *device, unsigned int hardware); diff --git a/src/shearwater_petrel.c b/src/shearwater_petrel.c index 1e32c17..0d91c03 100644 --- a/src/shearwater_petrel.c +++ b/src/shearwater_petrel.c @@ -152,64 +152,47 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call shearwater_petrel_device_t *device = (shearwater_petrel_device_t *) abstract; dc_status_t rc = DC_STATUS_SUCCESS; - // Allocate memory buffers for the manifests. - dc_buffer_t *buffer = dc_buffer_new (MANIFEST_SIZE); - dc_buffer_t *manifests = dc_buffer_new (MANIFEST_SIZE); - if (buffer == NULL || manifests == NULL) { - ERROR (abstract->context, "Insufficient buffer space available."); - dc_buffer_free (buffer); - dc_buffer_free (manifests); - return DC_STATUS_NOMEMORY; - } - // Enable progress notifications. unsigned int current = 0, maximum = 0; dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER; device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); // Read the serial number. - rc = shearwater_common_identifier (&device->base, buffer, ID_SERIAL); + unsigned char rsp_serial[8] = {0}; + rc = shearwater_common_rdbi (&device->base, ID_SERIAL, rsp_serial, sizeof(rsp_serial)); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to read the serial number."); - dc_buffer_free (buffer); - dc_buffer_free (manifests); return rc; } // Convert to a number. unsigned char serial[4] = {0}; - if (array_convert_hex2bin (dc_buffer_get_data (buffer), dc_buffer_get_size (buffer), - serial, sizeof (serial)) != 0 ) { + if (array_convert_hex2bin (rsp_serial, sizeof(rsp_serial), serial, sizeof (serial)) != 0 ) { ERROR (abstract->context, "Failed to convert the serial number."); - dc_buffer_free (buffer); - dc_buffer_free (manifests); return DC_STATUS_DATAFORMAT; - } // Read the firmware version. - rc = shearwater_common_identifier (&device->base, buffer, ID_FIRMWARE); + unsigned char rsp_firmware[11] = {0}; + rc = shearwater_common_rdbi (&device->base, ID_FIRMWARE, rsp_firmware, sizeof(rsp_firmware)); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to read the firmware version."); - dc_buffer_free (buffer); - dc_buffer_free (manifests); return rc; } // Convert to a number. - unsigned int firmware = str2num (dc_buffer_get_data (buffer), dc_buffer_get_size (buffer), 1); + unsigned int firmware = str2num (rsp_firmware, sizeof(rsp_firmware), 1); // Read the hardware type. - rc = shearwater_common_identifier (&device->base, buffer, ID_HARDWARE); + unsigned char rsp_hardware[2] = {0}; + rc = shearwater_common_rdbi (&device->base, ID_HARDWARE, rsp_hardware, sizeof(rsp_hardware)); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to read the hardware type."); - dc_buffer_free (buffer); - dc_buffer_free (manifests); return rc; } // Convert and map to the model number. - unsigned int hardware = array_uint_be (dc_buffer_get_data (buffer), dc_buffer_get_size (buffer)); + unsigned int hardware = array_uint16_be (rsp_hardware); unsigned int model = shearwater_common_get_model (&device->base, hardware); // Emit a device info event. @@ -220,22 +203,14 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo); // Read the logbook type - rc = shearwater_common_identifier (&device->base, buffer, ID_LOGUPLOAD); + unsigned char rsp_logupload[9] = {0}; + rc = shearwater_common_rdbi (&device->base, ID_LOGUPLOAD, rsp_logupload, sizeof(rsp_logupload)); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to read the logbook type."); - dc_buffer_free (buffer); - dc_buffer_free (manifests); return rc; } - if (dc_buffer_get_size (buffer) != 9) { - ERROR (abstract->context, "Unexpected packet size (" DC_PRINTF_SIZE " bytes).", dc_buffer_get_size(buffer)); - dc_buffer_free (buffer); - dc_buffer_free (manifests); - return DC_STATUS_DATAFORMAT; - } - - unsigned int base_addr = array_uint32_be (dc_buffer_get_data (buffer) + 1); + unsigned int base_addr = array_uint32_be (rsp_logupload + 1); switch (base_addr) { case 0xDD000000: // Predator - we shouldn't get here, we could give up or we can try 0xC0000000 case 0xC0000000: // Predator-Like Format (what we used to call the Petrel format) @@ -248,9 +223,17 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call break; default: // unknown format ERROR (abstract->context, "Unknown logbook format %08x", base_addr); + return DC_STATUS_DATAFORMAT; + } + + // Allocate memory buffers for the manifests. + dc_buffer_t *buffer = dc_buffer_new (MANIFEST_SIZE); + dc_buffer_t *manifests = dc_buffer_new (MANIFEST_SIZE); + if (buffer == NULL || manifests == NULL) { + ERROR (abstract->context, "Insufficient buffer space available."); dc_buffer_free (buffer); dc_buffer_free (manifests); - return DC_STATUS_DATAFORMAT; + return DC_STATUS_NOMEMORY; } // Read the manifest pages From d4402aa29606866476f982c6667f3deba94b9593 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 22 Jun 2023 20:42:12 +0200 Subject: [PATCH 3/5] Add support for the WDBI function The RDBI (Read Data by Identifier) has a WDBI (Write Data by Identifier) counterpart, which supports changing settings on the dive computer. --- src/shearwater_common.c | 37 +++++++++++++++++++++++++++++++++++++ src/shearwater_common.h | 3 +++ 2 files changed, 40 insertions(+) diff --git a/src/shearwater_common.c b/src/shearwater_common.c index c184bb3..7a47f58 100644 --- a/src/shearwater_common.c +++ b/src/shearwater_common.c @@ -39,6 +39,9 @@ #define RDBI_REQUEST 0x22 #define RDBI_RESPONSE 0x62 +#define WDBI_REQUEST 0x2E +#define WDBI_RESPONSE 0x6E + dc_status_t shearwater_common_setup (shearwater_common_device_t *device, dc_context_t *context, dc_iostream_t *iostream) { @@ -552,6 +555,40 @@ shearwater_common_rdbi (shearwater_common_device_t *device, unsigned int id, uns return status; } +dc_status_t +shearwater_common_wdbi (shearwater_common_device_t *device, unsigned int id, const unsigned char data[], unsigned int size) +{ + dc_status_t status = DC_STATUS_SUCCESS; + dc_device_t *abstract = (dc_device_t *) device; + + if (size + 3 > SZ_PACKET) { + return DC_STATUS_INVALIDARGS; + } + + // Transfer the request. + unsigned int n = 0; + unsigned char request[SZ_PACKET] = { + WDBI_REQUEST, + (id >> 8) & 0xFF, + (id ) & 0xFF}; + if (size) { + memcpy (request + 3, data, size); + } + unsigned char response[SZ_PACKET]; + status = shearwater_common_transfer (device, request, size + 3, response, sizeof (response), &n); + if (status != DC_STATUS_SUCCESS) { + return status; + } + + // Verify the response. + if (n < 3 || response[0] != WDBI_RESPONSE || response[1] != request[1] || response[2] != request[2]) { + ERROR (abstract->context, "Unexpected response packet."); + return DC_STATUS_PROTOCOL; + } + + return status; +} + unsigned int shearwater_common_get_model (shearwater_common_device_t *device, unsigned int hardware) { diff --git a/src/shearwater_common.h b/src/shearwater_common.h index 8f8e356..1c25b75 100644 --- a/src/shearwater_common.h +++ b/src/shearwater_common.h @@ -67,6 +67,9 @@ shearwater_common_download (shearwater_common_device_t *device, dc_buffer_t *buf dc_status_t shearwater_common_rdbi (shearwater_common_device_t *device, unsigned int id, unsigned char data[], unsigned int size); +dc_status_t +shearwater_common_wdbi (shearwater_common_device_t *device, unsigned int id, const unsigned char data[], unsigned int size); + unsigned int shearwater_common_get_model (shearwater_common_device_t *device, unsigned int hardware); From c16530b8ab34f73e5506a1be25c3e521c819f7ed Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 22 Jun 2023 21:16:08 +0200 Subject: [PATCH 4/5] Detect negative response packets When the dive computer receives an RDBI or WDBI command it doesn't support, it sends a 3 byte NAK packet containing an error code. Detect these NAK packets and use it to return a more appropriate error. --- src/shearwater_common.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/shearwater_common.c b/src/shearwater_common.c index 7a47f58..1e2a65b 100644 --- a/src/shearwater_common.c +++ b/src/shearwater_common.c @@ -42,6 +42,8 @@ #define WDBI_REQUEST 0x2E #define WDBI_RESPONSE 0x6E +#define NAK 0x7F + dc_status_t shearwater_common_setup (shearwater_common_device_t *device, dc_context_t *context, dc_iostream_t *iostream) { @@ -537,6 +539,10 @@ shearwater_common_rdbi (shearwater_common_device_t *device, unsigned int id, uns // Verify the response. if (n < 3 || response[0] != RDBI_RESPONSE || response[1] != request[1] || response[2] != request[2]) { + if (n == 3 && response[0] == NAK && response[1] == RDBI_REQUEST) { + ERROR (abstract->context, "Received NAK packet with error code 0x%02x.", response[2]); + return DC_STATUS_UNSUPPORTED; + } ERROR (abstract->context, "Unexpected response packet."); return DC_STATUS_PROTOCOL; } @@ -582,6 +588,10 @@ shearwater_common_wdbi (shearwater_common_device_t *device, unsigned int id, con // Verify the response. if (n < 3 || response[0] != WDBI_RESPONSE || response[1] != request[1] || response[2] != request[2]) { + if (n == 3 && response[0] == NAK && response[1] == WDBI_REQUEST) { + ERROR (abstract->context, "Received NAK packet with error code 0x%02x.", response[2]); + return DC_STATUS_UNSUPPORTED; + } ERROR (abstract->context, "Unexpected response packet."); return DC_STATUS_PROTOCOL; } From 25bd1f98536f16e71c32e91d7c879957d07063c0 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 22 Jun 2023 21:23:28 +0200 Subject: [PATCH 5/5] Add support for time synchronization Add time synchronisation for the Shearwater dive computers. All models support setting the local time. Only the Teric has basic support for time zones, and can set UTC time with a timezone offset. Co-authored-by: Michael Keller --- src/shearwater_common.c | 85 +++++++++++++++++++++++++++++++++++++++ src/shearwater_common.h | 11 +++++ src/shearwater_petrel.c | 28 ++++++++++++- src/shearwater_predator.c | 9 ++++- 4 files changed, 131 insertions(+), 2 deletions(-) diff --git a/src/shearwater_common.c b/src/shearwater_common.c index 1e2a65b..ca3f237 100644 --- a/src/shearwater_common.c +++ b/src/shearwater_common.c @@ -599,6 +599,91 @@ shearwater_common_wdbi (shearwater_common_device_t *device, unsigned int id, con return status; } +dc_status_t +shearwater_common_timesync_local (shearwater_common_device_t *device, const dc_datetime_t *datetime) +{ + dc_status_t status = DC_STATUS_SUCCESS; + dc_device_t *abstract = (dc_device_t *) device; + + // Convert to local time. + dc_datetime_t local = *datetime; + local.timezone = DC_TIMEZONE_NONE; + + dc_ticks_t ticks = dc_datetime_mktime (&local); + if (ticks == -1) { + ERROR (abstract->context, "Invalid date/time value specified."); + return DC_STATUS_INVALIDARGS; + } + + const unsigned char timestamp[] = { + (ticks >> 24) & 0xFF, + (ticks >> 16) & 0xFF, + (ticks >> 8) & 0xFF, + (ticks ) & 0xFF, + }; + + status = shearwater_common_wdbi (device, ID_TIME_LOCAL, timestamp, sizeof(timestamp)); + if (status != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to write the dive computer local time."); + return status; + } + + return status; +} + +dc_status_t +shearwater_common_timesync_utc (shearwater_common_device_t *device, const dc_datetime_t *datetime) +{ + dc_status_t status = DC_STATUS_SUCCESS; + dc_device_t *abstract = (dc_device_t *) device; + + // Convert to UTC time. + dc_ticks_t ticks = dc_datetime_mktime (datetime); + if (ticks == -1) { + ERROR (abstract->context, "Invalid date/time value specified."); + return DC_STATUS_INVALIDARGS; + } + + const unsigned char timestamp[] = { + (ticks >> 24) & 0xFF, + (ticks >> 16) & 0xFF, + (ticks >> 8) & 0xFF, + (ticks ) & 0xFF, + }; + + status = shearwater_common_wdbi (device, ID_TIME_UTC, timestamp, sizeof(timestamp)); + if (status != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to write the dive computer UTC time."); + return status; + } + + int timezone = datetime->timezone / 60; + const unsigned char offset[] = { + (timezone >> 24) & 0xFF, + (timezone >> 16) & 0xFF, + (timezone >> 8) & 0xFF, + (timezone ) & 0xFF, + }; + + status = shearwater_common_wdbi (device, ID_TIME_OFFSET, offset, sizeof (offset)); + if (status != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to write the dive computer timezone offset."); + return status; + } + + // We don't have a way to determine the daylight savings time setting, + // but the required offset is already factored into the timezone offset. + const unsigned char dst[] = {0, 0, 0, 0}; + + status = shearwater_common_wdbi (device, ID_TIME_DST, dst, sizeof (dst)); + if (status != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to write the dive computer DST setting."); + return status; + } + + return status; +} + unsigned int shearwater_common_get_model (shearwater_common_device_t *device, unsigned int hardware) { diff --git a/src/shearwater_common.h b/src/shearwater_common.h index 1c25b75..4c7f186 100644 --- a/src/shearwater_common.h +++ b/src/shearwater_common.h @@ -35,6 +35,11 @@ extern "C" { #define ID_LOGUPLOAD 0x8021 #define ID_HARDWARE 0x8050 +#define ID_TIME_LOCAL 0x9030 +#define ID_TIME_UTC 0x9031 +#define ID_TIME_OFFSET 0x9032 +#define ID_TIME_DST 0x9033 + #define PREDATOR 2 #define PETREL 3 #define PETREL2 PETREL @@ -70,6 +75,12 @@ shearwater_common_rdbi (shearwater_common_device_t *device, unsigned int id, uns dc_status_t shearwater_common_wdbi (shearwater_common_device_t *device, unsigned int id, const unsigned char data[], unsigned int size); +dc_status_t +shearwater_common_timesync_local (shearwater_common_device_t *device, const dc_datetime_t *datetime); + +dc_status_t +shearwater_common_timesync_utc (shearwater_common_device_t *device, const dc_datetime_t *datetime); + unsigned int shearwater_common_get_model (shearwater_common_device_t *device, unsigned int hardware); diff --git a/src/shearwater_petrel.c b/src/shearwater_petrel.c index 0d91c03..7ec18ff 100644 --- a/src/shearwater_petrel.c +++ b/src/shearwater_petrel.c @@ -46,6 +46,7 @@ typedef struct shearwater_petrel_device_t { static dc_status_t shearwater_petrel_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size); static dc_status_t shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata); +static dc_status_t shearwater_petrel_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime); static dc_status_t shearwater_petrel_device_close (dc_device_t *abstract); static const dc_device_vtable_t shearwater_petrel_device_vtable = { @@ -56,7 +57,7 @@ static const dc_device_vtable_t shearwater_petrel_device_vtable = { NULL, /* write */ NULL, /* dump */ shearwater_petrel_device_foreach, /* foreach */ - NULL, /* timesync */ + shearwater_petrel_device_timesync, shearwater_petrel_device_close /* close */ }; @@ -350,3 +351,28 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call return rc; } + +static dc_status_t +shearwater_petrel_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime) +{ + dc_status_t status = DC_STATUS_SUCCESS; + shearwater_common_device_t *device = (shearwater_common_device_t *) abstract; + + // Read the hardware type. + unsigned char rsp_hardware[2] = {0}; + status = shearwater_common_rdbi (device, ID_HARDWARE, rsp_hardware, sizeof(rsp_hardware)); + if (status != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to read the hardware type."); + return status; + } + + // Convert and map to the model number. + unsigned int hardware = array_uint16_be (rsp_hardware); + unsigned int model = shearwater_common_get_model (device, hardware); + + if (model == TERIC) { + return shearwater_common_timesync_utc (device, datetime); + } else { + return shearwater_common_timesync_local (device, datetime); + } +} diff --git a/src/shearwater_predator.c b/src/shearwater_predator.c index d4c97b4..fffd511 100644 --- a/src/shearwater_predator.c +++ b/src/shearwater_predator.c @@ -44,6 +44,7 @@ typedef struct shearwater_predator_device_t { static dc_status_t shearwater_predator_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size); static dc_status_t shearwater_predator_device_dump (dc_device_t *abstract, dc_buffer_t *buffer); static dc_status_t shearwater_predator_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata); +static dc_status_t shearwater_predator_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime); static const dc_device_vtable_t shearwater_predator_device_vtable = { sizeof(shearwater_predator_device_t), @@ -53,7 +54,7 @@ static const dc_device_vtable_t shearwater_predator_device_vtable = { NULL, /* write */ shearwater_predator_device_dump, /* dump */ shearwater_predator_device_foreach, /* foreach */ - NULL, /* timesync */ + shearwater_predator_device_timesync, NULL /* close */ }; @@ -357,3 +358,9 @@ shearwater_predator_extract_dives (dc_device_t *abstract, const unsigned char da return shearwater_predator_extract_predator (abstract, data, size, callback, userdata); } } + +static dc_status_t +shearwater_predator_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime) +{ + return shearwater_common_timesync_local ((shearwater_common_device_t *) abstract, datetime); +}