diff options
Diffstat (limited to 'libdivecomputer.c')
-rw-r--r-- | libdivecomputer.c | 203 |
1 files changed, 161 insertions, 42 deletions
diff --git a/libdivecomputer.c b/libdivecomputer.c index 942b1ec14..f07023f88 100644 --- a/libdivecomputer.c +++ b/libdivecomputer.c @@ -9,6 +9,9 @@ #include "display.h" #include "libdivecomputer.h" +#include <libdivecomputer/uwatec.h> +#include <libdivecomputer/hw.h> + /* Christ. Libdivecomputer has the worst configuration system ever. */ #ifdef HW_FROG_H @@ -26,13 +29,46 @@ double progress_bar_fraction = 0.0; static int stoptime, stopdepth, ndl, po2, cns; static bool in_deco, first_temp_is_air; +/* + * Directly taken from libdivecomputer's examples/common.c to improve + * the error messages resulting from libdc's return codes + */ +const char *errmsg (dc_status_t rc) +{ + switch (rc) { + case DC_STATUS_SUCCESS: + return "Success"; + case DC_STATUS_UNSUPPORTED: + return "Unsupported operation"; + case DC_STATUS_INVALIDARGS: + return "Invalid arguments"; + case DC_STATUS_NOMEMORY: + return "Out of memory"; + case DC_STATUS_NODEVICE: + return "No device found"; + case DC_STATUS_NOACCESS: + return "Access denied"; + case DC_STATUS_IO: + return "Input/output error"; + case DC_STATUS_TIMEOUT: + return "Timeout"; + case DC_STATUS_PROTOCOL: + return "Protocol error"; + case DC_STATUS_DATAFORMAT: + return "Data format error"; + case DC_STATUS_CANCELLED: + return "Cancelled"; + default: + return "Unknown error"; + } +} + static dc_status_t create_parser(device_data_t *devdata, dc_parser_t **parser) { return dc_parser_new(parser, devdata->device); } -static int parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_parser_t *parser, int ngases, - const unsigned char *data) +static int parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_parser_t *parser, int ngases) { static bool shown_warning = false; int i, rc; @@ -107,7 +143,7 @@ static int parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_parser_t * dive computer, fill in the default tank information (if set) */ fill_default_cylinder(&dive->cylinder[i]); } - /* whatever happens, make sure there is a name for the cylidner */ + /* whatever happens, make sure there is a name for the cylinder */ if (same_string(dive->cylinder[i].type.description, "")) dive->cylinder[i].type.description = strdup(translate("gettextFromC", "unknown")); } @@ -400,45 +436,19 @@ static void parse_string_field(struct dive *dive, dc_field_string_t *str) } #endif -/* returns true if we want libdivecomputer's dc_device_foreach() to continue, - * false otherwise */ -static int dive_cb(const unsigned char *data, unsigned int size, - const unsigned char *fingerprint, unsigned int fsize, - void *userdata) +static dc_status_t libdc_header_parser(dc_parser_t *parser, struct device_data_t *devdata, struct dive *dive) { - int rc; - dc_parser_t *parser = NULL; - device_data_t *devdata = userdata; + dc_status_t rc = 0; dc_datetime_t dt = { 0 }; struct tm tm; - struct dive *dive = NULL; - - /* reset the deco / ndl data */ - ndl = stoptime = stopdepth = 0; - in_deco = false; - - rc = create_parser(devdata, &parser); - if (rc != DC_STATUS_SUCCESS) { - dev_info(devdata, translate("gettextFromC", "Unable to create parser for %s %s"), devdata->vendor, devdata->product); - return false; - } - - rc = dc_parser_set_data(parser, data, size); - if (rc != DC_STATUS_SUCCESS) { - dev_info(devdata, translate("gettextFromC", "Error registering the data")); - goto error_exit; - } - import_dive_number++; - dive = alloc_dive(); rc = dc_parser_get_datetime(parser, &dt); if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) { dev_info(devdata, translate("gettextFromC", "Error parsing the datetime")); - goto error_exit; + return rc; } - dive->dc.model = strdup(devdata->model); + dive->dc.deviceid = devdata->deviceid; - dive->dc.diveid = calculate_diveid(fingerprint, fsize); if (rc == DC_STATUS_SUCCESS) { tm.tm_year = dt.year; @@ -449,13 +459,14 @@ static int dive_cb(const unsigned char *data, unsigned int size, tm.tm_sec = dt.second; dive->when = dive->dc.when = utc_mktime(&tm); } + // Parse the divetime. dev_info(devdata, translate("gettextFromC", "Dive %d: %s"), import_dive_number, get_dive_date_c_string(dive->when)); unsigned int divetime = 0; rc = dc_parser_get_field(parser, DC_FIELD_DIVETIME, 0, &divetime); if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) { dev_info(devdata, translate("gettextFromC", "Error parsing the divetime")); - goto error_exit; + return rc; } if (rc == DC_STATUS_SUCCESS) dive->dc.duration.seconds = divetime; @@ -465,7 +476,7 @@ static int dive_cb(const unsigned char *data, unsigned int size, rc = dc_parser_get_field(parser, DC_FIELD_MAXDEPTH, 0, &maxdepth); if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) { dev_info(devdata, translate("gettextFromC", "Error parsing the maxdepth")); - goto error_exit; + return rc; } if (rc == DC_STATUS_SUCCESS) dive->dc.maxdepth.mm = rint(maxdepth * 1000); @@ -484,7 +495,7 @@ static int dive_cb(const unsigned char *data, unsigned int size, rc = dc_parser_get_field(parser, temp_fields[i], 0, &temperature); if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) { dev_info(devdata, translate("gettextFromC", "Error parsing temperature")); - goto error_exit; + return rc; } if (rc == DC_STATUS_SUCCESS) switch(i) { @@ -504,7 +515,7 @@ static int dive_cb(const unsigned char *data, unsigned int size, rc = dc_parser_get_field(parser, DC_FIELD_GASMIX_COUNT, 0, &ngases); if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) { dev_info(devdata, translate("gettextFromC", "Error parsing the gas mix count")); - goto error_exit; + return rc; } #if DC_VERSION_CHECK(0, 3, 0) @@ -516,7 +527,7 @@ static int dive_cb(const unsigned char *data, unsigned int size, rc = dc_parser_get_field(parser, DC_FIELD_SALINITY, 0, &salinity); if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) { dev_info(devdata, translate("gettextFromC", "Error obtaining water salinity")); - goto error_exit; + return rc; } if (rc == DC_STATUS_SUCCESS) dive->dc.salinity = rint(salinity.density * 10.0); @@ -525,7 +536,7 @@ static int dive_cb(const unsigned char *data, unsigned int size, rc = dc_parser_get_field(parser, DC_FIELD_ATMOSPHERIC, 0, &surface_pressure); if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) { dev_info(devdata, translate("gettextFromC", "Error obtaining surface pressure")); - goto error_exit; + return rc; } if (rc == DC_STATUS_SUCCESS) dive->dc.surface_pressure.mbar = rint(surface_pressure * 1000.0); @@ -550,7 +561,7 @@ static int dive_cb(const unsigned char *data, unsigned int size, rc = dc_parser_get_field(parser, DC_FIELD_DIVEMODE, 0, &divemode); if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) { dev_info(devdata, translate("gettextFromC", "Error obtaining divemode")); - goto error_exit; + return rc; } if (rc == DC_STATUS_SUCCESS) switch(divemode) { @@ -567,12 +578,57 @@ static int dive_cb(const unsigned char *data, unsigned int size, } #endif - rc = parse_gasmixes(devdata, dive, parser, ngases, data); - if (rc != DC_STATUS_SUCCESS) { + rc = parse_gasmixes(devdata, dive, parser, ngases); + if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) { dev_info(devdata, translate("gettextFromC", "Error parsing the gas mix")); + return rc; + } + + return DC_STATUS_SUCCESS; +} + +/* returns true if we want libdivecomputer's dc_device_foreach() to continue, + * false otherwise */ +static int dive_cb(const unsigned char *data, unsigned int size, + const unsigned char *fingerprint, unsigned int fsize, + void *userdata) +{ + int rc; + dc_parser_t *parser = NULL; + device_data_t *devdata = userdata; + dc_datetime_t dt = { 0 }; + struct tm tm; + struct dive *dive = NULL; + + /* reset the deco / ndl data */ + ndl = stoptime = stopdepth = 0; + in_deco = false; + + rc = create_parser(devdata, &parser); + if (rc != DC_STATUS_SUCCESS) { + dev_info(devdata, translate("gettextFromC", "Unable to create parser for %s %s"), devdata->vendor, devdata->product); + return false; + } + + rc = dc_parser_set_data(parser, data, size); + if (rc != DC_STATUS_SUCCESS) { + dev_info(devdata, translate("gettextFromC", "Error registering the data")); + goto error_exit; + } + + import_dive_number++; + dive = alloc_dive(); + + // Parse the dive's header data + rc = libdc_header_parser (parser, devdata, dive); + if (rc != DC_STATUS_SUCCESS) { + dev_info(devdata, translate("getextFromC", "Error parsing the header")); goto error_exit; } + dive->dc.model = strdup(devdata->model); + dive->dc.diveid = calculate_diveid(fingerprint, fsize); + // Initialize the sample data. rc = parse_samples(devdata, &dive->dc, parser); if (rc != DC_STATUS_SUCCESS) { @@ -876,3 +932,66 @@ const char *do_libdivecomputer_import(device_data_t *data) return err; } + +/* + * Parse data buffers instead of dc devices downloaded data. + * Intended to be used to parse profile data from binary files during import tasks. + * Actually included Uwatec families because of works on datatrak and smartrak logs + * and OSTC families for OSTCTools logs import. + * For others, simply include them in the switch (check parameters). + * Note that dc_descriptor_t in data *must* have been filled using dc_descriptor_iterator() + * calls. + */ +dc_status_t libdc_buffer_parser(struct dive *dive, device_data_t *data, unsigned char *buffer, int size) +{ + dc_status_t rc; + dc_parser_t *parser = NULL; + + switch (data->descriptor->type) { + case DC_FAMILY_UWATEC_ALADIN: + case DC_FAMILY_UWATEC_MEMOMOUSE: + rc = uwatec_memomouse_parser_create(&parser, data->context, 0, 0); + break; + case DC_FAMILY_UWATEC_SMART: + case DC_FAMILY_UWATEC_MERIDIAN: + rc = uwatec_smart_parser_create (&parser, data->context, data->descriptor->model, 0, 0); + break; + case DC_FAMILY_HW_OSTC: + rc = hw_ostc_parser_create (&parser, data->context, data->deviceid, 0); + break; + case DC_FAMILY_HW_FROG: + case DC_FAMILY_HW_OSTC3: + rc = hw_ostc_parser_create (&parser, data->context, data->deviceid, 1); + break; + default: + report_error("Device type not handled!"); + return DC_STATUS_UNSUPPORTED; + } + if (rc != DC_STATUS_SUCCESS) { + report_error("Error creating parser."); + dc_parser_destroy (parser); + return rc; + } + rc = dc_parser_set_data(parser, buffer, size); + if (rc != DC_STATUS_SUCCESS) { + report_error("Error registering the data."); + dc_parser_destroy (parser); + return rc; + } + // Do not parse Aladin/Memomouse headers as they are fakes + // Do not return on error, we can still parse the samples + if (data->descriptor->type != DC_FAMILY_UWATEC_ALADIN && data->descriptor->type != DC_FAMILY_UWATEC_MEMOMOUSE) { + rc = libdc_header_parser (parser, data, dive); + if (rc != DC_STATUS_SUCCESS) { + report_error("Error parsing the dive header data. Dive # %d\nStatus = %s", dive->number, errmsg(rc)); + } + } + rc = dc_parser_samples_foreach (parser, sample_cb, &dive->dc); + if (rc != DC_STATUS_SUCCESS) { + report_error("Error parsing the sample data. Dive # %d\nStatus = %s", dive->number, errmsg(rc)); + dc_parser_destroy (parser); + return rc; + } + dc_parser_destroy(parser); + return(DC_STATUS_SUCCESS); +} |