summaryrefslogtreecommitdiffstats
path: root/ostctools.c
diff options
context:
space:
mode:
authorGravatar Salvador Cuñat <salvador.cunat@gmail.com>2015-04-04 01:07:59 +0200
committerGravatar Dirk Hohndel <dirk@hohndel.org>2015-04-04 10:33:49 -0700
commit3ca4e14d5c4f758ac3754619fea78bd6d7070177 (patch)
tree98a324891a43998764bfcbe9fa4d9f7388760b6d /ostctools.c
parented6ae14a9f6f608cb8ca72e8982806ea03c43571 (diff)
downloadsubsurface-3ca4e14d5c4f758ac3754619fea78bd6d7070177.tar.gz
OSTCTools-Add support to import .dive files
OSTCTools is a windows based software by Robert Angeymar which performs configuration upgrade, memory analysis and download tasks for H&W OSTC devices. Downloaded dives are stored in files (one archive each) with the raw binary data heavily padded at the begining of the file, and some other data not included in H&W dive header protocol as the device's serial number. The import function simply takes the raw data part of the file and lets libdivecomputer do the parseing. Then adds some additional info as OSTC reported dive number and serial device number. Please note that OSTCTools is *not* a real logging software, it simply gets the DC raw data, so there isn't any information about dive site, equipment and so. Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Diffstat (limited to 'ostctools.c')
-rw-r--r--ostctools.c156
1 files changed, 156 insertions, 0 deletions
diff --git a/ostctools.c b/ostctools.c
new file mode 100644
index 000000000..4fa0ba5e7
--- /dev/null
+++ b/ostctools.c
@@ -0,0 +1,156 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "dive.h"
+#include "gettext.h"
+#include "divelist.h"
+#include "libdivecomputer.h"
+
+/*
+ * Returns a dc_descriptor_t structure based on dc model's number and family.
+ */
+
+static dc_descriptor_t *ostc_get_data_descriptor(int data_model, dc_family_t data_fam)
+{
+ dc_descriptor_t *descriptor = NULL, *current = NULL;;
+ dc_iterator_t *iterator = NULL;
+ dc_status_t rc;
+
+ rc = dc_descriptor_iterator(&iterator);
+ if (rc != DC_STATUS_SUCCESS) {
+ fprintf(stderr,"Error creating the device descriptor iterator.\n");
+ return current;
+ }
+ while ((dc_iterator_next(iterator, &descriptor)) == DC_STATUS_SUCCESS) {
+ int desc_model = dc_descriptor_get_model(descriptor);
+ dc_family_t desc_fam = dc_descriptor_get_type(descriptor);
+ if (data_model == desc_model && data_fam == desc_fam) {
+ current = descriptor;
+ break;
+ }
+ dc_descriptor_free(descriptor);
+ }
+ dc_iterator_free(iterator);
+ return current;
+}
+
+/*
+ * Fills a device_data_t structure with known dc data and a descriptor.
+ */
+static void ostc_prepare_data(int data_model, dc_family_t dc_fam, device_data_t *dev_data)
+{
+ device_data_t *ldc_dat = calloc(1, sizeof(device_data_t));
+ dc_descriptor_t *data_descriptor;
+
+ *ldc_dat = *dev_data;
+ ldc_dat->device = NULL;
+ ldc_dat->context = NULL;
+
+ data_descriptor = ostc_get_data_descriptor(data_model, dc_fam);
+ if (data_descriptor) {
+ ldc_dat->descriptor = data_descriptor;
+ ldc_dat->vendor = copy_string(data_descriptor->vendor);
+ ldc_dat->model = copy_string(data_descriptor->product);
+ *dev_data = *ldc_dat;
+ }
+ free(ldc_dat);
+}
+
+/*
+ * OSTCTools stores the raw dive data in heavily padded files, one dive
+ * each file. So it's not necesary to iterate once and again on a parsing
+ * function. Actually there's only one kind of archive for every DC model.
+ */
+void ostctools_import(const char *file, struct dive_table *divetable)
+{
+ FILE *archive;
+ device_data_t *devdata = calloc(1, sizeof(device_data_t));
+ dc_family_t dc_fam;
+ unsigned char *buffer = calloc(65536, 1),
+ *tmp;
+ struct dive *ostcdive = alloc_dive();
+ dc_status_t rc = 0;
+ int model = 0, i = 0;
+ unsigned int serial;
+ struct extra_data *ptr;
+
+ // Open the archive
+ if ((archive = subsurface_fopen(file, "rb")) == NULL) {
+ report_error(translate("gettextFromC", "Error: couldn't open the file"));
+ return;
+ }
+
+ // Read dive number from the log
+ tmp = calloc(2,1);
+ fseek(archive, 258, 0);
+ fread(tmp, 1, 2, archive);
+ ostcdive->number = tmp[0] + (tmp[1] << 8);
+ free(tmp);
+
+ // Read device's serial number
+ tmp = calloc(2, 1);
+ fseek(archive, 265, 0);
+ fread(tmp, 1, 2, archive);
+ serial = tmp[0] + (tmp[1] << 8);
+ free(tmp);
+
+ // Read dive's raw data, header + profile
+ fseek(archive, 456, 0);
+ while (!feof(archive)) {
+ fread(buffer+i, 1, 1, archive);
+ if (buffer[i] == 0xFD && buffer[i-1] == 0xFD)
+ break;
+ i++;
+ }
+
+ // Try to determine the dc family based on the header type
+ switch (buffer[2]) {
+ case 0x20:
+ case 0x21:
+ dc_fam = DC_FAMILY_HW_OSTC;
+ break;
+ case 0x22:
+ dc_fam = DC_FAMILY_HW_FROG;
+ break;
+ case 0x23:
+ dc_fam = DC_FAMILY_HW_OSTC3;
+ break;
+ }
+
+ // Prepare data to pass to libdivecomputer. OSTC protocol doesn't include
+ // a model number so will use 0.
+ ostc_prepare_data(model, dc_fam, devdata);
+ tmp = calloc(strlen(devdata->vendor)+strlen(devdata->model)+28,1);
+ sprintf(tmp,"%s %s (Imported from OSTCTools)", devdata->vendor, devdata->model);
+ ostcdive->dc.model = copy_string(tmp);
+ free(tmp);
+
+ // Parse the dive data
+ rc = libdc_buffer_parser(ostcdive, devdata, buffer, i+1);
+ if (rc != DC_STATUS_SUCCESS)
+ report_error("Libdc returned error -%s- for dive %d", errmsg(rc), ostcdive->number);
+
+ // Serial number is not part of the header nor the profile, so libdc won't
+ // catch it. If Serial is part of the extra_data, and set to zero, remove
+ // it from the list and add again.
+ tmp = calloc(12,1);
+ sprintf(tmp, "%d", serial);
+ ostcdive->dc.serial = copy_string(tmp);
+ free(tmp);
+
+ ptr = ostcdive->dc.extra_data;
+ while (strcmp(ptr->key, "Serial"))
+ ptr = ptr->next;
+ if (!strcmp(ptr->value, "0")) {
+ add_extra_data(&ostcdive->dc, "Serial", ostcdive->dc.serial);
+ *ptr = *(ptr)->next;
+ }
+
+ free(devdata);
+ free(buffer);
+ record_dive_to_table(ostcdive, divetable);
+ mark_divelist_changed(true);
+ sort_table(divetable);
+ fclose(archive);
+}