summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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