diff options
-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 |