summaryrefslogtreecommitdiffstats
path: root/libdivecomputer.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdivecomputer.c')
-rw-r--r--libdivecomputer.c203
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);
+}