summaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--file.c6
-rw-r--r--file.h1
-rw-r--r--ostctools.c156
-rw-r--r--qt-ui/mainwindow.cpp1
-rw-r--r--subsurface.pro3
5 files changed, 166 insertions, 1 deletions
diff --git a/file.c b/file.c
index 5be16a2a0..b0bc37aa9 100644
--- a/file.c
+++ b/file.c
@@ -460,6 +460,12 @@ int parse_file(const char *filename)
return 0;
}
+ /* OSTCtools */
+ if (fmt && (!strcasecmp(fmt + 1, "DIVE"))) {
+ ostctools_import(filename, &dive_table);
+ return 0;
+ }
+
ret = parse_file_buffer(filename, &mem);
free(mem.buffer);
return ret;
diff --git a/file.h b/file.h
index b1fb6941d..baeb8e1b9 100644
--- a/file.h
+++ b/file.h
@@ -9,6 +9,7 @@ struct memblock {
extern int try_to_open_cochran(const char *filename, struct memblock *mem);
extern int try_to_open_liquivision(const char *filename, struct memblock *mem);
extern void datatrak_import(const char *file, struct dive_table *table);
+extern void ostctools_import(const char *file, struct dive_table *table);
#ifdef __cplusplus
extern "C" {
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);
+}
diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp
index 76cfc8550..19c2e212d 100644
--- a/qt-ui/mainwindow.cpp
+++ b/qt-ui/mainwindow.cpp
@@ -1463,6 +1463,7 @@ void MainWindow::on_actionImportDiveLog_triggered()
"XML files (*.xml *.XML);;"
"APD log viewer (*.apd *.APD);;"
"Datatrak/WLog Files (*.log *.LOG);;"
+ "OSTCtools Files (*.dive *.DIVE);;"
"All files (*)"));
if (fileNames.isEmpty())
diff --git a/subsurface.pro b/subsurface.pro
index cedc92622..bec7d6590 100644
--- a/subsurface.pro
+++ b/subsurface.pro
@@ -213,7 +213,8 @@ SOURCES = \
qt-ui/diveshareexportdialog.cpp \
qt-ui/filtermodels.cpp \
qt-ui/undocommands.cpp \
- qt-ui/notificationwidget.cpp
+ qt-ui/notificationwidget.cpp \
+ ostctools.c
android: SOURCES += android.cpp
else: win32: SOURCES += windows.c