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.
This commit is contained in:
Jef Driesen 2023-06-22 20:35:47 +02:00
parent ee147afceb
commit 13705f2b2d
3 changed files with 43 additions and 57 deletions

View File

@ -36,6 +36,9 @@
#define ESC_END 0xDC #define ESC_END 0xDC
#define ESC_ESC 0xDD #define ESC_ESC 0xDD
#define RDBI_REQUEST 0x22
#define RDBI_RESPONSE 0x62
dc_status_t dc_status_t
shearwater_common_setup (shearwater_common_device_t *device, dc_context_t *context, dc_iostream_t *iostream) 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 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_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. // Transfer the request.
unsigned int n = 0; unsigned int n = 0;
unsigned char request[] = {0x22, unsigned char request[] = {
RDBI_REQUEST,
(id >> 8) & 0xFF, (id >> 8) & 0xFF,
(id ) & 0xFF}; (id ) & 0xFF};
unsigned char response[SZ_PACKET]; unsigned char response[SZ_PACKET];
rc = shearwater_common_transfer (device, request, sizeof (request), response, sizeof (response), &n); status = shearwater_common_transfer (device, request, sizeof (request), response, sizeof (response), &n);
if (rc != DC_STATUS_SUCCESS) { if (status != DC_STATUS_SUCCESS) {
return rc; return status;
} }
// Verify the response. // 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."); ERROR (abstract->context, "Unexpected response packet.");
return DC_STATUS_PROTOCOL; return DC_STATUS_PROTOCOL;
} }
// Append the packet to the output buffer. unsigned int length = n - 3;
if (!dc_buffer_append (buffer, response + 3, n - 3)) {
ERROR (abstract->context, "Insufficient buffer space available."); if (length != size) {
return DC_STATUS_NOMEMORY; 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 unsigned int

View File

@ -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); 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 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 unsigned int
shearwater_common_get_model (shearwater_common_device_t *device, unsigned int hardware); shearwater_common_get_model (shearwater_common_device_t *device, unsigned int hardware);

View File

@ -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; shearwater_petrel_device_t *device = (shearwater_petrel_device_t *) abstract;
dc_status_t rc = DC_STATUS_SUCCESS; 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. // Enable progress notifications.
unsigned int current = 0, maximum = 0; unsigned int current = 0, maximum = 0;
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER; dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
// Read the serial number. // 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) { if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to read the serial number."); ERROR (abstract->context, "Failed to read the serial number.");
dc_buffer_free (buffer);
dc_buffer_free (manifests);
return rc; return rc;
} }
// Convert to a number. // Convert to a number.
unsigned char serial[4] = {0}; unsigned char serial[4] = {0};
if (array_convert_hex2bin (dc_buffer_get_data (buffer), dc_buffer_get_size (buffer), if (array_convert_hex2bin (rsp_serial, sizeof(rsp_serial), serial, sizeof (serial)) != 0 ) {
serial, sizeof (serial)) != 0 ) {
ERROR (abstract->context, "Failed to convert the serial number."); ERROR (abstract->context, "Failed to convert the serial number.");
dc_buffer_free (buffer);
dc_buffer_free (manifests);
return DC_STATUS_DATAFORMAT; return DC_STATUS_DATAFORMAT;
} }
// Read the firmware version. // 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) { if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to read the firmware version."); ERROR (abstract->context, "Failed to read the firmware version.");
dc_buffer_free (buffer);
dc_buffer_free (manifests);
return rc; return rc;
} }
// Convert to a number. // 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. // 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) { if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to read the hardware type."); ERROR (abstract->context, "Failed to read the hardware type.");
dc_buffer_free (buffer);
dc_buffer_free (manifests);
return rc; return rc;
} }
// Convert and map to the model number. // 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); unsigned int model = shearwater_common_get_model (&device->base, hardware);
// Emit a device info event. // 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); device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);
// Read the logbook type // 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) { if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to read the logbook type."); ERROR (abstract->context, "Failed to read the logbook type.");
dc_buffer_free (buffer);
dc_buffer_free (manifests);
return rc; return rc;
} }
if (dc_buffer_get_size (buffer) != 9) { unsigned int base_addr = array_uint32_be (rsp_logupload + 1);
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);
switch (base_addr) { switch (base_addr) {
case 0xDD000000: // Predator - we shouldn't get here, we could give up or we can try 0xC0000000 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) 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; break;
default: // unknown format default: // unknown format
ERROR (abstract->context, "Unknown logbook format %08x", base_addr); 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 (buffer);
dc_buffer_free (manifests); dc_buffer_free (manifests);
return DC_STATUS_DATAFORMAT; return DC_STATUS_NOMEMORY;
} }
// Read the manifest pages // Read the manifest pages