static dc_status_t shearwater_petrel_device_close (dc_device_t *abstract) { dc_status_t status = DC_STATUS_SUCCESS; shearwater_common_device_t *device = (shearwater_common_device_t *) abstract; dc_status_t rc = DC_STATUS_SUCCESS; // Shutdown the device. unsigned char request[] = {0x2E, 0x90, 0x20, 0x00}; rc = shearwater_common_transfer (device, request, sizeof (request), NULL, 0, NULL); if (rc != DC_STATUS_SUCCESS) { dc_status_set_error(&status, rc); } // Close the device. rc = shearwater_common_close (device); if (rc != DC_STATUS_SUCCESS) { dc_status_set_error(&status, rc); } return status; }
dc_status_t shearwater_common_identifier (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int id) { 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, (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; } // Verify the response. if (n < 3 || response[0] != 0x62 || 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; } return rc; }
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_device_t *abstract = (dc_device_t *) device; dc_status_t rc = DC_STATUS_SUCCESS; unsigned int n = 0; unsigned char req_init[] = { 0x35, (compression ? 0x10 : 0x00), 0x34, (address >> 24) & 0xFF, (address >> 16) & 0xFF, (address >> 8) & 0xFF, (address ) & 0xFF, (size >> 16) & 0xFF, (size >> 8) & 0xFF, (size ) & 0xFF}; unsigned char req_block[] = {0x36, 0x00}; unsigned char req_quit[] = {0x37}; unsigned char response[SZ_PACKET]; // Erase the current contents of the buffer. if (!dc_buffer_clear (buffer)) { ERROR (abstract->context, "Insufficient buffer space available."); return DC_STATUS_NOMEMORY; } // Enable progress notifications. dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER; progress.maximum = 3 + size + 1; device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); // Transfer the init request. rc = shearwater_common_transfer (device, req_init, sizeof (req_init), response, 3, &n); if (rc != DC_STATUS_SUCCESS) { return rc; } // Verify the init response. if (n != 3 || response[0] != 0x75 || response[1] != 0x10 || response[2] > SZ_PACKET) { ERROR (abstract->context, "Unexpected response packet."); return DC_STATUS_PROTOCOL; } // Update and emit a progress event. progress.current += 3; device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); unsigned int done = 0; unsigned char block = 1; unsigned int nbytes = 0; while (nbytes < size && !done) { // Transfer the block request. req_block[1] = block; rc = shearwater_common_transfer (device, req_block, sizeof (req_block), response, sizeof (response), &n); if (rc != DC_STATUS_SUCCESS) { return rc; } // Verify the block header. if (n < 2 || response[0] != 0x76 || response[1] != block) { ERROR (abstract->context, "Unexpected response packet."); return DC_STATUS_PROTOCOL; } // Verify the block length. unsigned int length = n - 2; if (nbytes + length > size) { ERROR (abstract->context, "Unexpected packet size."); return DC_STATUS_PROTOCOL; } // Update and emit a progress event. progress.current += length; device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); if (compression) { if (shearwater_common_decompress_lre (response + 2, length, buffer, &done) != 0) { ERROR (abstract->context, "Decompression error (LRE phase)."); return DC_STATUS_PROTOCOL; } } else { if (!dc_buffer_append (buffer, response + 2, length)) { ERROR (abstract->context, "Insufficient buffer space available."); return DC_STATUS_PROTOCOL; } } nbytes += length; block++; } if (compression) { if (shearwater_common_decompress_xor (dc_buffer_get_data (buffer), dc_buffer_get_size (buffer)) != 0) { ERROR (abstract->context, "Decompression error (XOR phase)."); return DC_STATUS_PROTOCOL; } } // Transfer the quit request. rc = shearwater_common_transfer (device, req_quit, sizeof (req_quit), response, 2, &n); if (rc != DC_STATUS_SUCCESS) { return rc; } // Verify the quit response. if (n != 2 || response[0] != 0x77 || response[1] != 0x00) { ERROR (abstract->context, "Unexpected response packet."); return DC_STATUS_PROTOCOL; } // Update and emit a progress event. progress.current += 1; device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); return DC_STATUS_SUCCESS; }