diff options
Diffstat (limited to 'ostctools.c')
-rw-r--r-- | ostctools.c | 156 |
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); +} |