static dc_status_t shearwater_predator_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata) { dc_buffer_t *buffer = dc_buffer_new (SZ_MEMORY); if (buffer == NULL) return DC_STATUS_NOMEMORY; dc_status_t rc = shearwater_predator_device_dump (abstract, buffer); if (rc != DC_STATUS_SUCCESS) { dc_buffer_free (buffer); return rc; } // Emit a device info event. unsigned char *data = dc_buffer_get_data (buffer); dc_event_devinfo_t devinfo; devinfo.model = data[0x2000D]; devinfo.firmware = bcd2dec (data[0x2000A]); devinfo.serial = array_uint32_be (data + 0x20002); device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo); rc = shearwater_predator_extract_dives (abstract, data, SZ_MEMORY, callback, userdata); dc_buffer_free (buffer); return rc; }
static device_status_t suunto_eon_device_foreach (device_t *abstract, dive_callback_t callback, void *userdata) { dc_buffer_t *buffer = dc_buffer_new (SUUNTO_EON_MEMORY_SIZE); if (buffer == NULL) return DEVICE_STATUS_MEMORY; device_status_t rc = suunto_eon_device_dump (abstract, buffer); if (rc != DEVICE_STATUS_SUCCESS) { dc_buffer_free (buffer); return rc; } // Emit a device info event. unsigned char *data = dc_buffer_get_data (buffer); device_devinfo_t devinfo; devinfo.model = 0; devinfo.firmware = 0; devinfo.serial = array_uint24_be (data + 244); device_event_emit (abstract, DEVICE_EVENT_DEVINFO, &devinfo); rc = suunto_eon_extract_dives (abstract, dc_buffer_get_data (buffer), dc_buffer_get_size (buffer), callback, userdata); dc_buffer_free (buffer); return rc; }
static dc_status_t hw_ostc_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata) { dc_buffer_t *buffer = dc_buffer_new (0); if (buffer == NULL) return DC_STATUS_NOMEMORY; dc_status_t rc = hw_ostc_device_dump (abstract, buffer); if (rc != DC_STATUS_SUCCESS) { dc_buffer_free (buffer); return rc; } // Emit a device info event. unsigned char *data = dc_buffer_get_data (buffer); dc_event_devinfo_t devinfo; devinfo.firmware = array_uint16_be (data + 264); devinfo.serial = array_uint16_le (data + 6); if (devinfo.serial > 7000) devinfo.model = 3; // OSTC 2C else if (devinfo.serial > 2048) devinfo.model = 2; // OSTC 2N else if (devinfo.serial > 300) devinfo.model = 1; // OSTC Mk2 else devinfo.model = 0; // OSTC device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo); rc = hw_ostc_extract_dives (abstract, dc_buffer_get_data (buffer), dc_buffer_get_size (buffer), callback, userdata); dc_buffer_free (buffer); return rc; }
dc_status_t test_dump_memory (const char* name, const char* filename) { dc_context_t *context = NULL; dc_device_t *device = NULL; dc_context_new (&context); dc_context_set_loglevel (context, DC_LOGLEVEL_ALL); dc_context_set_logfunc (context, logfunc, NULL); message ("oceanic_atom2_device_open\n"); dc_status_t rc = oceanic_atom2_device_open (&device, context, name); if (rc != DC_STATUS_SUCCESS) { WARNING ("Error opening serial port."); dc_context_free (context); return rc; } dc_buffer_t *buffer = dc_buffer_new (0); message ("dc_device_dump\n"); rc = dc_device_dump (device, buffer); if (rc != DC_STATUS_SUCCESS) { WARNING ("Cannot read memory."); dc_buffer_free (buffer); dc_device_close (device); dc_context_free (context); return rc; } message ("Dumping data\n"); FILE* fp = fopen (filename, "wb"); if (fp != NULL) { fwrite (dc_buffer_get_data (buffer), sizeof (unsigned char), dc_buffer_get_size (buffer), fp); fclose (fp); } dc_buffer_free (buffer); message ("dc_device_foreach\n"); rc = dc_device_foreach (device, NULL, NULL); if (rc != DC_STATUS_SUCCESS) { WARNING ("Cannot read dives."); dc_device_close (device); dc_context_free (context); return rc; } message ("dc_device_close\n"); rc = dc_device_close (device); if (rc != DC_STATUS_SUCCESS) { WARNING ("Cannot close device."); dc_context_free (context); return rc; } dc_context_free (context); return DC_STATUS_SUCCESS; }
device_status_t test_dump_memory (const char* filename) { device_t *device = NULL; message ("uwatec_smart_device_open\n"); device_status_t rc = uwatec_smart_device_open (&device); if (rc != DEVICE_STATUS_SUCCESS) { WARNING ("Cannot open device."); return rc; } message ("device_version\n"); unsigned char version[UWATEC_SMART_VERSION_SIZE] = {0}; rc = device_version (device, version, sizeof (version)); if (rc != DEVICE_STATUS_SUCCESS) { WARNING ("Cannot identify computer."); device_close (device); return rc; } dc_buffer_t *buffer = dc_buffer_new (0); message ("device_dump\n"); rc = device_dump (device, buffer); if (rc != DEVICE_STATUS_SUCCESS) { WARNING ("Cannot read memory."); dc_buffer_free (buffer); device_close (device); return rc; } message ("Dumping data\n"); FILE* fp = fopen (filename, "wb"); if (fp != NULL) { fwrite (dc_buffer_get_data (buffer), sizeof (unsigned char), dc_buffer_get_size (buffer), fp); fclose (fp); } dc_buffer_free (buffer); message ("device_close\n"); rc = device_close (device); if (rc != DEVICE_STATUS_SUCCESS) { WARNING ("Cannot close device."); return rc; } return DEVICE_STATUS_SUCCESS; }
device_status_t test_dump_memory (const char* name, const char* filename) { device_t *device = NULL; message ("reefnet_sensuspro_device_open\n"); device_status_t rc = reefnet_sensuspro_device_open (&device, name); if (rc != DEVICE_STATUS_SUCCESS) { WARNING ("Error opening serial port."); return rc; } time_t now = time (NULL); char datetime[21] = {0}; strftime (datetime, sizeof (datetime), "%Y-%m-%dT%H:%M:%SZ", gmtime (&now)); message ("time=%lu (%s)\n", (unsigned long)now, datetime); dc_buffer_t *buffer = dc_buffer_new (0); message ("device_dump\n"); rc = device_dump (device, buffer); if (rc != DEVICE_STATUS_SUCCESS) { WARNING ("Cannot read memory."); dc_buffer_free (buffer); device_close (device); return rc; } message ("Dumping data\n"); FILE* fp = fopen (filename, "wb"); if (fp != NULL) { fwrite (dc_buffer_get_data (buffer), sizeof (unsigned char), dc_buffer_get_size (buffer), fp); fclose (fp); } dc_buffer_free (buffer); message ("device_close\n"); rc = device_close (device); if (rc != DEVICE_STATUS_SUCCESS) { WARNING ("Cannot close device."); return rc; } return DEVICE_STATUS_SUCCESS; }
int dump_dives(program_options_t *options) { dc_family_t backend = DC_FAMILY_NULL; dc_loglevel_t loglevel = DC_LOGLEVEL_WARNING; const char *logfile = "output.log"; const char *name = NULL; const char *fingerprint = NULL; unsigned int model = 0; if (options->backend != NULL) { backend = lookup_type(options->backend); } signal (SIGINT, sighandler); message_set_logfile(logfile); dc_context_t *context = NULL; /* create a new context */ dc_status_t rc = dc_context_new(&context); if (rc != DC_STATUS_SUCCESS) { message_set_logfile(NULL); return EXIT_FAILURE; } dc_context_set_loglevel(context, loglevel); dc_context_set_logfunc(context, logfunc, NULL); dc_descriptor_t *descriptor = NULL; rc = search(&descriptor, name, backend, model); if (rc != DC_STATUS_SUCCESS) { message_set_logfile(NULL); return EXIT_FAILURE; } /* fail if no device descriptor found */ if (descriptor == NULL) { WARNING("No matching device found"); /* FIXME: bail out to usage information */ message_set_logfile(NULL); return EXIT_FAILURE; } dc_buffer_t *fp = fpconvert(fingerprint); rc = dowork(context, descriptor, options, fp); dc_buffer_free(fp); /* FIXME: why aren't calls to errmsg working? */ // message("Result: %s\n", errmsg(rc)); dc_descriptor_free(descriptor); dc_context_free(context); message_set_logfile(NULL); return rc != DC_STATUS_SUCCESS ? EXIT_FAILURE : EXIT_SUCCESS; }
static dc_status_t uwatec_meridian_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata) { dc_buffer_t *buffer = dc_buffer_new (0); if (buffer == NULL) return DC_STATUS_NOMEMORY; dc_status_t rc = uwatec_meridian_device_dump (abstract, buffer); if (rc != DC_STATUS_SUCCESS) { dc_buffer_free (buffer); return rc; } rc = uwatec_meridian_extract_dives (abstract, dc_buffer_get_data (buffer), dc_buffer_get_size (buffer), callback, userdata); dc_buffer_free (buffer); return rc; }
device_status_t test_dump_memory (const char* name, const char* filename) { device_t *device = NULL; message ("suunto_solution_device_open\n"); int rc = suunto_solution_device_open (&device, name); if (rc != DEVICE_STATUS_SUCCESS) { WARNING ("Error opening serial port."); return rc; } dc_buffer_t *buffer = dc_buffer_new (0); message ("device_dump\n"); rc = device_dump (device, buffer); if (rc != DEVICE_STATUS_SUCCESS) { WARNING ("Cannot read memory."); dc_buffer_free (buffer); device_close (device); return rc; } message ("Dumping data\n"); FILE* fp = fopen (filename, "wb"); if (fp != NULL) { fwrite (dc_buffer_get_data (buffer), sizeof (unsigned char), dc_buffer_get_size (buffer), fp); fclose (fp); } dc_buffer_free (buffer); message ("device_close\n"); rc = device_close (device); if (rc != DEVICE_STATUS_SUCCESS) { WARNING ("Cannot close device."); return rc; } return DEVICE_STATUS_SUCCESS; }
static void event_cb (dc_device_t *device, dc_event_type_t event, const void *data, void *userdata) { const dc_event_devinfo_t *devinfo = (const dc_event_devinfo_t *) data; event_data_t *eventdata = (event_data_t *) userdata; // Forward to the default event handler. dctool_event_cb (device, event, data, userdata); switch (event) { case DC_EVENT_DEVINFO: // Load the fingerprint from the cache. If there is no // fingerprint present in the cache, a NULL buffer is returned, // and the registered fingerprint will be cleared. if (eventdata->cachedir) { char filename[1024] = {0}; dc_family_t family = DC_FAMILY_NULL; dc_buffer_t *fingerprint = NULL; // Generate the fingerprint filename. family = dc_device_get_type (device); snprintf (filename, sizeof (filename), "%s/%s-%08X.bin", eventdata->cachedir, dctool_family_name (family), devinfo->serial); // Read the fingerprint file. fingerprint = dctool_file_read (filename); // Register the fingerprint data. dc_device_set_fingerprint (device, dc_buffer_get_data (fingerprint), dc_buffer_get_size (fingerprint)); // Free the buffer again. dc_buffer_free (fingerprint); } // Keep a copy of the event data. It will be used for generating // the fingerprint filename again after a (successful) download. eventdata->devinfo = *devinfo; break; default: break; } }
static dc_status_t dowork(dc_context_t *context, dc_descriptor_t *descriptor, program_options_t *options, dc_buffer_t *fingerprint) { dc_status_t rc = DC_STATUS_SUCCESS; /* initialize the device data */ device_data_t devdata = {{0}}; /* open the device */ message("Opening the device (%s, %s, %s.\n", dc_descriptor_get_vendor(descriptor), dc_descriptor_get_product(descriptor), options->devname ? options->devname : "null"); dc_device_t *device = NULL; rc = dc_device_open(&device, context, descriptor, options->devname); if (rc != DC_STATUS_SUCCESS) { WARNING("Error opening device."); return rc; } /* register the event handler */ message("Registering the event handler.\n"); int events = DC_EVENT_WAITING | DC_EVENT_PROGRESS | DC_EVENT_DEVINFO | DC_EVENT_CLOCK; rc = dc_device_set_events(device, events, event_cb, &devdata); if (rc != DC_STATUS_SUCCESS) { WARNING("Error registering the event handler."); dc_device_close(device); return rc; } /* register the cancellation handler */ message("Registering the cancellation handler.\n"); rc = dc_device_set_cancel(device, cancel_cb, NULL); if (rc != DC_STATUS_SUCCESS) { WARNING("Error registering the cancellation handler."); dc_device_close(device); return rc; } /* register the fingerprint data */ if (fingerprint) { message("Registering the fingerprint data.\n"); rc = dc_device_set_fingerprint(device, dc_buffer_get_data(fingerprint), dc_buffer_get_size(fingerprint)); if (rc != DC_STATUS_SUCCESS) { WARNING("Error registerting the fingerprint data"); dc_device_close(device); return rc; } } /* dump the memory if requested */ if (options->dumpMemory) { WARNING("Memory dump not enabled."); } /* dump the dives if requested */ if (options->dumpDives) { /* initialize the dive data */ dive_data_t divedata = {0}; dif_dive_collection_t *dc = dif_dive_collection_alloc(); divedata.device = device; divedata.fingerprint = NULL; divedata.number = 0; divedata.dc = dc; /* download the dives */ message("Downloading the dives.\n"); rc = dc_device_foreach(device, dive_cb, &divedata); if (rc != DC_STATUS_SUCCESS) { WARNING("Error downloading the dives."); dc_buffer_free(divedata.fingerprint); dc_device_close (device); return rc; } xml_options_t *xmlOptions = dif_xml_options_alloc(); xmlOptions->filename = options->xmlfile; xmlOptions->useInvalidElements = options->useInvalidElements; if (options->truncateDives) { divedata.dc = dif_alg_dc_truncate_dives(divedata.dc); } if (options->initialPressureFix) { divedata.dc = dif_alg_dc_initial_pressure_fix(divedata.dc); } dif_save_dive_collection_uddf_options(divedata.dc, xmlOptions); /* free the fingerprint buffer */ dc_buffer_free(divedata.fingerprint); dif_dive_collection_free(divedata.dc); dif_xml_options_free(xmlOptions); } /* close the device */ message("Closing the device.\n"); rc = dc_device_close(device); if (rc != DC_STATUS_SUCCESS) { WARNING("Error closing the device."); return rc; } return DC_STATUS_SUCCESS; }
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; }
static int dctool_download_run (int argc, char *argv[], dc_context_t *context, dc_descriptor_t *descriptor) { int exitcode = EXIT_SUCCESS; dc_status_t status = DC_STATUS_SUCCESS; dc_buffer_t *fingerprint = NULL; dctool_output_t *output = NULL; dctool_units_t units = DCTOOL_UNITS_METRIC; // Default option values. unsigned int help = 0; const char *fphex = NULL; const char *filename = NULL; const char *cachedir = NULL; const char *format = "xml"; // Parse the command-line options. int opt = 0; const char *optstring = "ho:p:c:f:u:"; #ifdef HAVE_GETOPT_LONG struct option options[] = { {"help", no_argument, 0, 'h'}, {"output", required_argument, 0, 'o'}, {"fingerprint", required_argument, 0, 'p'}, {"cache", required_argument, 0, 'c'}, {"format", required_argument, 0, 'f'}, {"units", required_argument, 0, 'u'}, {0, 0, 0, 0 } }; while ((opt = getopt_long (argc, argv, optstring, options, NULL)) != -1) { #else while ((opt = getopt (argc, argv, optstring)) != -1) { #endif switch (opt) { case 'h': help = 1; break; case 'o': filename = optarg; break; case 'p': fphex = optarg; break; case 'c': cachedir = optarg; break; case 'f': format = optarg; break; case 'u': if (strcmp (optarg, "metric") == 0) units = DCTOOL_UNITS_METRIC; if (strcmp (optarg, "imperial") == 0) units = DCTOOL_UNITS_IMPERIAL; break; default: return EXIT_FAILURE; } } argc -= optind; argv += optind; // Show help message. if (help) { dctool_command_showhelp (&dctool_download); return EXIT_SUCCESS; } // Convert the fingerprint to binary. fingerprint = dctool_convert_hex2bin (fphex); // Create the output. if (strcasecmp(format, "raw") == 0) { output = dctool_raw_output_new (filename); } else if (strcasecmp(format, "xml") == 0) { output = dctool_xml_output_new (filename, units); } else { message ("Unknown output format: %s\n", format); exitcode = EXIT_FAILURE; goto cleanup; } if (output == NULL) { message ("Failed to create the output.\n"); exitcode = EXIT_FAILURE; goto cleanup; } // Download the dives. status = download (context, descriptor, argv[0], cachedir, fingerprint, output); if (status != DC_STATUS_SUCCESS) { message ("ERROR: %s\n", dctool_errmsg (status)); exitcode = EXIT_FAILURE; goto cleanup; } cleanup: dctool_output_free (output); dc_buffer_free (fingerprint); return exitcode; } const dctool_command_t dctool_download = { dctool_download_run, DCTOOL_CONFIG_DESCRIPTOR, "download", "Download the dives", "Usage:\n" " dctool download [options] <devname>\n" "\n" "Options:\n" #ifdef HAVE_GETOPT_LONG " -h, --help Show help message\n" " -o, --output <filename> Output filename\n" " -p, --fingerprint <data> Fingerprint data (hexadecimal)\n" " -c, --cache <directory> Cache directory\n" " -f, --format <format> Output format\n" " -u, --units <units> Set units (metric or imperial)\n" #else " -h Show help message\n" " -o <filename> Output filename\n" " -p <fingerprint> Fingerprint data (hexadecimal)\n" " -c <directory> Cache directory\n" " -f <format> Output format\n" " -u <units> Set units (metric or imperial)\n" #endif "\n" "Supported output formats:\n" "\n" " XML (default)\n" "\n" " All dives are exported to a single xml file.\n" "\n" " RAW\n" "\n" " Each dive is exported to a raw (binary) file. To output multiple\n" " files, the filename is interpreted as a template and should\n" " contain one or more placeholders.\n" "\n" "Supported template placeholders:\n" "\n" " %f Fingerprint (hexadecimal format)\n" " %n Number (4 digits)\n" " %t Timestamp (basic ISO 8601 date/time format)\n" };
static dc_status_t download (dc_context_t *context, dc_descriptor_t *descriptor, const char *devname, const char *cachedir, dc_buffer_t *fingerprint, dctool_output_t *output) { dc_status_t rc = DC_STATUS_SUCCESS; dc_device_t *device = NULL; dc_buffer_t *ofingerprint = NULL; // Open the device. message ("Opening the device (%s %s, %s).\n", dc_descriptor_get_vendor (descriptor), dc_descriptor_get_product (descriptor), devname ? devname : "null"); rc = dc_device_open (&device, context, descriptor, devname); if (rc != DC_STATUS_SUCCESS) { ERROR ("Error opening the device."); goto cleanup; } // Initialize the event data. event_data_t eventdata = {0}; if (fingerprint) { eventdata.cachedir = NULL; } else { eventdata.cachedir = cachedir; } // Register the event handler. message ("Registering the event handler.\n"); int events = DC_EVENT_WAITING | DC_EVENT_PROGRESS | DC_EVENT_DEVINFO | DC_EVENT_CLOCK | DC_EVENT_VENDOR; rc = dc_device_set_events (device, events, event_cb, &eventdata); if (rc != DC_STATUS_SUCCESS) { ERROR ("Error registering the event handler."); goto cleanup; } // Register the cancellation handler. message ("Registering the cancellation handler.\n"); rc = dc_device_set_cancel (device, dctool_cancel_cb, NULL); if (rc != DC_STATUS_SUCCESS) { ERROR ("Error registering the cancellation handler."); goto cleanup; } // Register the fingerprint data. if (fingerprint) { message ("Registering the fingerprint data.\n"); rc = dc_device_set_fingerprint (device, dc_buffer_get_data (fingerprint), dc_buffer_get_size (fingerprint)); if (rc != DC_STATUS_SUCCESS) { ERROR ("Error registering the fingerprint data."); goto cleanup; } } // Initialize the dive data. dive_data_t divedata = {0}; divedata.device = device; divedata.fingerprint = &ofingerprint; divedata.number = 0; divedata.output = output; // Download the dives. message ("Downloading the dives.\n"); rc = dc_device_foreach (device, dive_cb, &divedata); if (rc != DC_STATUS_SUCCESS) { ERROR ("Error downloading the dives."); goto cleanup; } // Store the fingerprint data. if (cachedir && ofingerprint) { char filename[1024] = {0}; dc_family_t family = DC_FAMILY_NULL; // Generate the fingerprint filename. family = dc_device_get_type (device); snprintf (filename, sizeof (filename), "%s/%s-%08X.bin", cachedir, dctool_family_name (family), eventdata.devinfo.serial); // Write the fingerprint file. dctool_file_write (filename, ofingerprint); } cleanup: dc_buffer_free (ofingerprint); dc_device_close (device); return rc; }
static dc_status_t atomics_cobalt_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata) { atomics_cobalt_device_t *device = (atomics_cobalt_device_t *) abstract; // Enable progress notifications. dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER; progress.maximum = SZ_MEMORY + 2; device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); // Emit a vendor event. dc_event_vendor_t vendor; vendor.data = device->version; vendor.size = sizeof (device->version); device_event_emit (abstract, DC_EVENT_VENDOR, &vendor); // Emit a device info event. dc_event_devinfo_t devinfo; devinfo.model = array_uint16_le (device->version + 12); devinfo.firmware = (array_uint16_le (device->version + 8) << 16) + array_uint16_le (device->version + 10); devinfo.serial = 0; for (unsigned int i = 0; i < 8; ++i) { devinfo.serial *= 10; devinfo.serial += device->version[i] - '0'; } device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo); // Allocate a memory buffer. dc_buffer_t *buffer = dc_buffer_new (0); if (buffer == NULL) return DC_STATUS_NOMEMORY; unsigned int ndives = 0; dc_status_t rc = DC_STATUS_SUCCESS; while ((rc = atomics_cobalt_read_dive (abstract, buffer, (ndives == 0), &progress)) == DC_STATUS_SUCCESS) { unsigned char *data = dc_buffer_get_data (buffer); unsigned int size = dc_buffer_get_size (buffer); if (size == 0) { dc_buffer_free (buffer); return DC_STATUS_SUCCESS; } if (memcmp (data + FP_OFFSET, device->fingerprint, sizeof (device->fingerprint)) == 0) { dc_buffer_free (buffer); return DC_STATUS_SUCCESS; } if (callback && !callback (data, size, data + FP_OFFSET, sizeof (device->fingerprint), userdata)) { dc_buffer_free (buffer); return DC_STATUS_SUCCESS; } // Adjust the maximum value to take into account the two checksum bytes // for the next dive. Since we don't know the total number of dives in // advance, we can't calculate the total number of checksum bytes and // adjust the maximum on the fly. progress.maximum += 2; ndives++; } 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; } // 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; }
void Java_com_libdivecomputer_android_Buffer_delloc(JNIEnv* envPtr, jobject object_Buffer) { dc_buffer_t* bufferPtr = (dc_buffer_t*)getNativePtr(envPtr, object_Buffer); dc_buffer_free(bufferPtr); setNativePtr(envPtr, object_Buffer, NULL); }