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