summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--dive.h18
-rw-r--r--libdivecomputer.c62
-rw-r--r--libdivecomputer.h1
-rw-r--r--parse-xml.c15
-rw-r--r--save-xml.c10
-rw-r--r--uemis.c11
7 files changed, 105 insertions, 14 deletions
diff --git a/Makefile b/Makefile
index ee74d4b98..a20d32061 100644
--- a/Makefile
+++ b/Makefile
@@ -125,7 +125,7 @@ ifneq ($(strip $(LIBXSLT)),)
endif
endif
-LIBS = $(LIBXML2) $(LIBXSLT) $(LIBGTK) $(LIBGCONF2) $(LIBDIVECOMPUTER) $(EXTRALIBS) $(LIBZIP) -lpthread -lm
+LIBS = $(LIBXML2) $(LIBXSLT) $(LIBGTK) $(LIBGCONF2) $(LIBDIVECOMPUTER) $(EXTRALIBS) $(LIBZIP) -lpthread -lm -lssl -lcrypto
MSGLANGS=$(notdir $(wildcard po/*po))
MSGOBJS=$(addprefix share/locale/,$(MSGLANGS:.po=.UTF-8/LC_MESSAGES/subsurface.mo))
diff --git a/dive.h b/dive.h
index 2e7841b45..44023b705 100644
--- a/dive.h
+++ b/dive.h
@@ -2,11 +2,13 @@
#define DIVE_H
#include <stdlib.h>
+#include <stdint.h>
#include <time.h>
#include <glib.h>
#include <glib/gstdio.h>
#include <libxml/tree.h>
+#include <openssl/sha.h>
/*
* Some silly typedefs to make our units very explicit.
@@ -239,9 +241,23 @@ struct event {
char name[];
};
+/*
+ * NOTE! The deviceid and diveid are model-specific *hashes* of
+ * whatever device identification that model may have. Different
+ * dive computers will have different identifying data, it could
+ * be a firmware number or a serial ID (in either string or in
+ * numeric format), and we do not care.
+ *
+ * The only thing we care about is that subsurface will hash
+ * that information the same way. So then you can check the ID
+ * of a dive computer by comparing the hashes for equality.
+ *
+ * A deviceid or diveid of zero is assumed to be "no ID".
+ */
struct divecomputer {
timestamp_t when;
- const char *vendor, *product;
+ const char *model;
+ uint32_t deviceid, diveid;
int samples, alloc_samples;
struct sample *sample;
struct event *events;
diff --git a/libdivecomputer.c b/libdivecomputer.c
index 82b1ba3cd..3325c68ff 100644
--- a/libdivecomputer.c
+++ b/libdivecomputer.c
@@ -186,9 +186,7 @@ static inline int match_dc(struct divecomputer *a, struct divecomputer *b)
{
if (a->when != b->when)
return 0;
- if (a->vendor && b->vendor && strcasecmp(a->vendor, b->vendor))
- return 0;
- if (a->product && b->product && strcasecmp(a->product, b->product))
+ if (a->model && b->model && strcasecmp(a->model, b->model))
return 0;
return 1;
}
@@ -226,6 +224,39 @@ static inline int year(int year)
return year;
}
+/*
+ * Like g_strdup_printf(), but without the stupid g_malloc/g_free confusion.
+ * And we limit the string to some arbitrary size.
+ */
+static char *str_printf(const char *fmt, ...)
+{
+ va_list args;
+ char buf[80];
+
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf)-1, fmt, args);
+ va_end(args);
+ buf[sizeof(buf)-1] = 0;
+ return strdup(buf);
+}
+
+/*
+ * The dive ID for libdivecomputer dives is the first word of the
+ * SHA1 of the fingerprint, if it exists.
+ *
+ * NOTE! This is byte-order dependent, and I don't care.
+ */
+static uint32_t calculate_diveid(const unsigned char *fingerprint, unsigned int fsize)
+{
+ uint32_t csum[5];
+
+ if (!fingerprint || !fsize)
+ return 0;
+
+ SHA1(fingerprint, fsize, (unsigned char *)csum);
+ return csum[0];
+}
+
static int dive_cb(const unsigned char *data, unsigned int size,
const unsigned char *fingerprint, unsigned int fsize,
void *userdata)
@@ -258,8 +289,9 @@ static int dive_cb(const unsigned char *data, unsigned int size,
dc_parser_destroy(parser);
return rc;
}
- dive->dc.vendor = strdup(devdata->vendor);
- dive->dc.product = strdup(devdata->product);
+ dive->dc.model = str_printf("%s %s", devdata->vendor, devdata->product);
+ dive->dc.deviceid = devdata->deviceid;
+ dive->dc.diveid = calculate_diveid(fingerprint, fsize);
tm.tm_year = dt.year;
tm.tm_mon = dt.month-1;
@@ -345,6 +377,25 @@ static dc_status_t import_device_data(dc_device_t *device, device_data_t *device
return dc_device_foreach(device, dive_cb, devicedata);
}
+/*
+ * The device ID for libdivecomputer devices is the first 32-bit word
+ * of the SHA1 hash of the model/firmware/serial numbers.
+ *
+ * NOTE! This is byte-order-dependent. And I can't find it in myself to
+ * care.
+ */
+static uint32_t calculate_sha1(unsigned int model, unsigned int firmware, unsigned int serial)
+{
+ SHA_CTX ctx;
+ uint32_t csum[5];
+
+ SHA1_Init(&ctx);
+ SHA1_Update(&ctx, &model, sizeof(model));
+ SHA1_Update(&ctx, &firmware, sizeof(firmware));
+ SHA1_Update(&ctx, &serial, sizeof(serial));
+ SHA1_Final((unsigned char *)csum, &ctx);
+ return csum[0];
+}
static void event_cb(dc_device_t *device, dc_event_type_t event, const void *data, void *userdata)
{
@@ -367,6 +418,7 @@ static void event_cb(dc_device_t *device, dc_event_type_t event, const void *dat
devinfo->model, devinfo->model,
devinfo->firmware, devinfo->firmware,
devinfo->serial, devinfo->serial);
+ devdata->deviceid = calculate_sha1(devinfo->model, devinfo->firmware, devinfo->serial);
break;
case DC_EVENT_CLOCK:
dev_info(devdata, _("Event: systime=%"PRId64", devtime=%u\n"),
diff --git a/libdivecomputer.h b/libdivecomputer.h
index 2121c27bc..81eb78abd 100644
--- a/libdivecomputer.h
+++ b/libdivecomputer.h
@@ -13,6 +13,7 @@
typedef struct device_data_t {
dc_descriptor_t *descriptor;
const char *vendor, *product, *devname;
+ unsigned int deviceid, diveid;
dc_device_t *device;
dc_context_t *context;
progressbar_t progress;
diff --git a/parse-xml.c b/parse-xml.c
index 98e7fc9e4..5f1dfed82 100644
--- a/parse-xml.c
+++ b/parse-xml.c
@@ -523,6 +523,13 @@ static void get_index(char *buffer, void *_i)
free(buffer);
}
+static void hex_value(char *buffer, void *_i)
+{
+ uint32_t *i = _i;
+ *i = strtol(buffer, NULL, 16);
+ free(buffer);
+}
+
static void get_tripflag(char *buffer, void *_tf)
{
tripflag_t *tf = _tf;
@@ -715,9 +722,11 @@ static void try_to_fill_dc(struct divecomputer *dc, const char *name, char *buf)
return;
if (MATCH(".time", divetime, &dc->when))
return;
- if (MATCH(".vendor", utf8_string, &dc->vendor))
+ if (MATCH(".model", utf8_string, &dc->model))
+ return;
+ if (MATCH(".deviceid", hex_value, &dc->deviceid))
return;
- if (MATCH(".product", utf8_string, &dc->product))
+ if (MATCH(".diveid", hex_value, &dc->diveid))
return;
nonmatch("divecomputer", name, buf);
@@ -1333,7 +1342,7 @@ static void divecomputer_start(void)
dc = dc->next;
/* Did we already fill that in? */
- if (dc->samples || dc->vendor || dc->product || dc->when) {
+ if (dc->samples || dc->model || dc->when) {
struct divecomputer *newdc = calloc(1, sizeof(*newdc));
if (newdc) {
dc->next = newdc;
diff --git a/save-xml.c b/save-xml.c
index af4356840..58faf6aeb 100644
--- a/save-xml.c
+++ b/save-xml.c
@@ -351,10 +351,12 @@ static void save_dc(FILE *f, struct dive *dive, struct divecomputer *dc)
int i;
fprintf(f, " <divecomputer");
- if (dc->vendor)
- show_utf8(f, dc->vendor, " vendor='", "'", 1);
- if (dc->product)
- show_utf8(f, dc->product, " product='", "'", 1);
+ if (dc->model)
+ show_utf8(f, dc->model, " model='", "'", 1);
+ if (dc->deviceid)
+ fprintf(f, " deviceid='%08x'", dc->deviceid);
+ if (dc->diveid)
+ fprintf(f, " diveid='%08x'", dc->diveid);
if (dc->when && dc->when != dive->when)
show_date(f, dc->when);
fprintf(f, ">\n");
diff --git a/uemis.c b/uemis.c
index dd98012a4..88099beb3 100644
--- a/uemis.c
+++ b/uemis.c
@@ -199,6 +199,17 @@ void uemis_parse_divelog_binary(char *base64, void *datap) {
else
dive->salinity = 10000; /* grams per 10l fresh water */
+ dc->model = strdup("Uemis Zurich");
+
+ /*
+ * FIXME:
+ * - make the deive ID the first word of the SHA1 sum of the deviceid string
+ * - do we want to have a dive ID? Without one, we'll just use the dive date,
+ * which is likely fine.
+ */
+ dc->deviceid = 0;
+ dc->diveid = 0;
+
/* dive template in use:
0 = air
1 = nitrox (B)