static dc_status_t shearwater_predator_device_dump (dc_device_t *abstract, dc_buffer_t *buffer) { shearwater_common_device_t *device = (shearwater_common_device_t *) abstract; // Erase the current contents of the buffer. if (!dc_buffer_clear (buffer) || !dc_buffer_reserve (buffer, SZ_MEMORY)) { ERROR (abstract->context, "Insufficient buffer space available."); return DC_STATUS_NOMEMORY; } return shearwater_common_download (device, buffer, 0xDD000000, SZ_MEMORY, 0); }
static dc_status_t shearwater_predator_device_dump (dc_device_t *abstract, dc_buffer_t *buffer) { shearwater_common_device_t *device = (shearwater_common_device_t *) abstract; // Erase the current contents of the buffer. if (!dc_buffer_clear (buffer) || !dc_buffer_reserve (buffer, SZ_MEMORY)) { ERROR (abstract->context, "Insufficient buffer space available."); return DC_STATUS_NOMEMORY; } // Enable progress notifications. dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER; progress.current = 0; progress.maximum = NSTEPS; return shearwater_common_download (device, buffer, 0xDD000000, SZ_MEMORY, 0, &progress); }
static dc_status_t shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata) { 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); 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 ) { 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); 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); // Read the hardware type. rc = shearwater_common_identifier (&device->base, buffer, ID_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 model = 0; switch (hardware) { case 0x0808: // Petrel 2 case 0x0909: // Petrel 1 case 0x0B0B: // Petrel 1 (newer hardware) model = PETREL; break; case 0x0A0A: // Nerd 1 case 0x0E0D: // Nerd 2 model = NERD; break; case 0x0707: model = PERDIX; break; case 0x0C0D: model = PERDIXAI; break; default: WARNING (abstract->context, "Unknown hardware type %04x.", hardware); } // Emit a device info event. dc_event_devinfo_t devinfo; devinfo.model = model; devinfo.firmware = firmware; devinfo.serial = array_uint32_be (serial); device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo); while (1) { // Update the progress state. // Assume the worst case scenario of a full manifest, and adjust the // value with the actual number of dives after the manifest has been // processed. maximum += 1 + RECORD_COUNT; // Download a manifest. progress.current = NSTEPS * current; progress.maximum = NSTEPS * maximum; rc = shearwater_common_download (&device->base, buffer, MANIFEST_ADDR, MANIFEST_SIZE, 0, &progress); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to download the manifest."); dc_buffer_free (buffer); dc_buffer_free (manifests); return rc; } // Cache the buffer pointer and size. unsigned char *data = dc_buffer_get_data (buffer); unsigned int size = dc_buffer_get_size (buffer); // Process the records in the manifest. unsigned int count = 0; unsigned int offset = 0; while (offset < size) { // Check for a valid dive header. unsigned int header = array_uint16_be (data + offset); if (header != 0xA5C4) break; // Check the fingerprint data. if (memcmp (data + offset + 4, device->fingerprint, sizeof (device->fingerprint)) == 0) break; offset += RECORD_SIZE; count++; } // Update the progress state. current += 1; maximum -= RECORD_COUNT - count; // Append the manifest records to the main buffer. if (!dc_buffer_append (manifests, data, count * RECORD_SIZE)) { ERROR (abstract->context, "Insufficient buffer space available."); dc_buffer_free (buffer); dc_buffer_free (manifests); return DC_STATUS_NOMEMORY; } // Stop downloading manifest if there are no more records. if (count != RECORD_COUNT) break; } // Update and emit a progress event. progress.current = NSTEPS * current; progress.maximum = NSTEPS * maximum; device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); // Cache the buffer pointer and size. unsigned char *data = dc_buffer_get_data (manifests); unsigned int size = dc_buffer_get_size (manifests); unsigned int offset = 0; while (offset < size) { // Get the address of the dive. unsigned int address = array_uint32_be (data + offset + 20); // Download the dive. progress.current = NSTEPS * current; progress.maximum = NSTEPS * maximum; rc = shearwater_common_download (&device->base, buffer, DIVE_ADDR + address, DIVE_SIZE, 1, &progress); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to download the dive."); dc_buffer_free (buffer); dc_buffer_free (manifests); return rc; } // Update the progress state. current += 1; unsigned char *buf = dc_buffer_get_data (buffer); unsigned int len = dc_buffer_get_size (buffer); if (callback && !callback (buf, len, buf + 12, sizeof (device->fingerprint), userdata)) break; offset += RECORD_SIZE; } // Update and emit a progress event. progress.current = NSTEPS * current; progress.maximum = NSTEPS * maximum; device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); dc_buffer_free (manifests); dc_buffer_free (buffer); return rc; }
static dc_status_t shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata) { 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; } while (1) { // Download a manifest. rc = shearwater_common_download (&device->base, buffer, MANIFEST_ADDR, MANIFEST_SIZE, 0); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to download the manifest."); dc_buffer_free (buffer); dc_buffer_free (manifests); return rc; } // Cache the buffer pointer and size. unsigned char *data = dc_buffer_get_data (buffer); unsigned int size = dc_buffer_get_size (buffer); // Process the records in the manifest. unsigned int count = 0; unsigned int offset = 0; while (offset < size) { // Check for a valid dive header. unsigned int header = array_uint16_be (data + offset); if (header != 0xA5C4) break; // Check the fingerprint data. if (memcmp (data + offset + 4, device->fingerprint, sizeof (device->fingerprint)) == 0) break; offset += RECORD_SIZE; count++; } // Append the manifest records to the main buffer. if (!dc_buffer_append (manifests, data, count * RECORD_SIZE)) { ERROR (abstract->context, "Insufficient buffer space available."); dc_buffer_free (buffer); dc_buffer_free (manifests); return DC_STATUS_NOMEMORY; } // Stop downloading manifest if there are no more records. if (count != RECORD_COUNT) break; } // Cache the buffer pointer and size. unsigned char *data = dc_buffer_get_data (manifests); unsigned int size = dc_buffer_get_size (manifests); unsigned int offset = 0; while (offset < size) { // Get the address of the dive. unsigned int address = array_uint32_be (data + offset + 20); // Download the dive. rc = shearwater_common_download (&device->base, buffer, DIVE_ADDR + address, DIVE_SIZE, 1); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to download the dive."); dc_buffer_free (buffer); dc_buffer_free (manifests); return rc; } unsigned char *buf = dc_buffer_get_data (buffer); unsigned int len = dc_buffer_get_size (buffer); if (callback && !callback (buf, len, buf + 12, sizeof (device->fingerprint), userdata)) break; offset += RECORD_SIZE; } dc_buffer_free (manifests); dc_buffer_free (buffer); return rc; }