diff options
author | Salvador Cuñat <salvador.cunat@gmail.com> | 2015-04-04 01:07:59 +0200 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2015-04-04 10:33:49 -0700 |
commit | 3ca4e14d5c4f758ac3754619fea78bd6d7070177 (patch) | |
tree | 98a324891a43998764bfcbe9fa4d9f7388760b6d | |
parent | ed6ae14a9f6f608cb8ca72e8982806ea03c43571 (diff) | |
download | subsurface-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.c | 6 | ||||
-rw-r--r-- | file.h | 1 | ||||
-rw-r--r-- | ostctools.c | 156 | ||||
-rw-r--r-- | qt-ui/mainwindow.cpp | 1 | ||||
-rw-r--r-- | subsurface.pro | 3 |
5 files changed, 166 insertions, 1 deletions
@@ -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; @@ -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 |