diff --git a/src/suunto_solution.c b/src/suunto_solution.c
index 9a8149e..792e102 100644
--- a/src/suunto_solution.c
+++ b/src/suunto_solution.c
@@ -20,6 +20,7 @@
  */
 
 #include <stdlib.h> // malloc, free
+#include <string.h> // memcpy
 
 #include <libdivecomputer/suunto_solution.h>
 #include <libdivecomputer/units.h>
@@ -39,9 +40,12 @@
 
 typedef struct suunto_solution_device_t {
 	dc_device_t base;
+	unsigned char fingerprint[16];
+	int hasfingerprint;
 	dc_serial_t *port;
 } suunto_solution_device_t;
 
+static dc_status_t suunto_solution_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size);
 static dc_status_t suunto_solution_device_dump (dc_device_t *abstract, dc_buffer_t *buffer);
 static dc_status_t suunto_solution_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata);
 static dc_status_t suunto_solution_device_close (dc_device_t *abstract);
@@ -49,7 +53,7 @@ static dc_status_t suunto_solution_device_close (dc_device_t *abstract);
 static const dc_device_vtable_t suunto_solution_device_vtable = {
 	sizeof(suunto_solution_device_t),
 	DC_FAMILY_SUUNTO_SOLUTION,
-	NULL, /* set_fingerprint */
+	suunto_solution_device_set_fingerprint, /* set_fingerprint */
 	NULL, /* read */
 	NULL, /* write */
 	suunto_solution_device_dump, /* dump */
@@ -58,6 +62,26 @@ static const dc_device_vtable_t suunto_solution_device_vtable = {
 };
 
 
+static dc_status_t
+suunto_solution_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size)
+{
+	suunto_solution_device_t *device = (suunto_solution_device_t*) abstract;
+
+	if (size && size != sizeof (device->fingerprint))
+		return DC_STATUS_INVALIDARGS;
+
+	if (size) {
+		memcpy (device->fingerprint, data, sizeof (device->fingerprint));
+		device->hasfingerprint = 1;
+	} else {
+		memset (device->fingerprint, 0, sizeof (device->fingerprint));
+		device->hasfingerprint = 0;
+	}
+
+	return DC_STATUS_SUCCESS;
+}
+
+
 dc_status_t
 suunto_solution_device_open (dc_device_t **out, dc_context_t *context, const char *name)
 {
@@ -74,6 +98,9 @@ suunto_solution_device_open (dc_device_t **out, dc_context_t *context, const cha
 		return DC_STATUS_NOMEMORY;
 	}
 
+	// Set that we don't have a fingerprint yet.
+	device->hasfingerprint = 0;
+
 	// Set the default values.
 	device->port = NULL;
 
@@ -280,10 +307,119 @@ suunto_solution_device_foreach (dc_device_t *abstract, dc_dive_callback_t callba
 	return rc;
 }
 
+/*
+ * Compute a 128-bit Murmur3 hash.
+ * Slightly de-tangled version of Peter Scott's implementation, which is
+ * in the public domain.
+ */
+static void
+suunto_solution_hash(const unsigned char data[], unsigned int len, void *out) 
+{
+	const uint64_t	 c1 = 0x87c37b91114253d5ULL,
+			 c2 = 0x4cf5ad432745937fULL;
+	size_t		 i, nb;
+	const uint64_t	*blocks;
+	const uint8_t	*tail;
+	uint64_t 	 h1 = 0, h2 = 0, k1, k2;
+
+	nb = len / 16;
+	blocks = (const uint64_t *)data;
+	tail = (const uint8_t *)(data + nb * 16);
+
+	for (i = 0; i < nb; i++) {
+		k1 = blocks[i * 2 + 0];
+		k2 = blocks[i * 2 + 1];
+
+		k1 *= c1;
+		k1 = (k1 << 31) | (k1 >> (64 - 31));
+		k1 *= c2;
+		h1 ^= k1;
+
+		h1 = (h1 << 27) | (h1 >> (64 - 27));
+		h1 += h2;
+		h1 = h1 * 5 + 0x52dce729;
+
+		k2 *= c2;
+		k2 = (k2 << 33) | (k2 >> (64 - 33));
+		k2 *= c1;
+		h2 ^= k2;
+
+		h2 = (h2 << 31) | (h2 >> (64 - 31));
+		h2 += h1;
+		h2 = h2 * 5 + 0x38495ab5;
+	}
+
+	k1 = k2 = 0;
+	switch (len & 15) {
+	case 15:
+		k2 ^= (uint64_t)(tail[14]) << 48;
+	case 14:
+		k2 ^= (uint64_t)(tail[13]) << 40;
+	case 13:
+		k2 ^= (uint64_t)(tail[12]) << 32;
+	case 12:
+		k2 ^= (uint64_t)(tail[11]) << 24;
+	case 11:
+		k2 ^= (uint64_t)(tail[10]) << 16;
+	case 10:
+		k2 ^= (uint64_t)(tail[9]) << 8;
+	case 9:
+		k2 ^= (uint64_t)(tail[8]) << 0;
+		k2 *= c2;
+		k2 = (k2 << 33) | (k2 >> (64 - 33));
+		k2 *= c1;
+		h2 ^= k2;
+	case 8:
+		k1 ^= (uint64_t)(tail[7]) << 56;
+	case 7:
+		k1 ^= (uint64_t)(tail[6]) << 48;
+	case 6:
+		k1 ^= (uint64_t)(tail[5]) << 40;
+	case 5:
+		k1 ^= (uint64_t)(tail[4]) << 32;
+	case 4:
+		k1 ^= (uint64_t)(tail[3]) << 24;
+	case 3:
+		k1 ^= (uint64_t)(tail[2]) << 16;
+	case 2:
+		k1 ^= (uint64_t)(tail[1]) << 8;
+	case 1:
+		k1 ^= (uint64_t)(tail[0]) << 0;
+		k1 *= c1;
+		k1 = (k1 << 31) | (k1 >> (64 - 31));
+		k1 *= c2;
+		h1 ^= k1;
+	};
+
+	h1 ^= len;
+	h2 ^= len;
+
+	h1 += h2;
+	h2 += h1;
+
+	h1 ^= h1 >> 33;
+	h1 *= 0xff51afd7ed558ccdULL;
+	h1 ^= h1 >> 33;
+	h1 *= 0xc4ceb9fe1a85ec53ULL;
+	h1 ^= h1 >> 33;
+
+	h2 ^= h2 >> 33;
+	h2 *= 0xff51afd7ed558ccdULL;
+	h2 ^= h2 >> 33;
+	h2 *= 0xc4ceb9fe1a85ec53ULL;
+	h2 ^= h2 >> 33;
+
+	h1 += h2;
+	h2 += h1;
+
+	((uint64_t *)out)[0] = h1;
+	((uint64_t *)out)[1] = h2;
+}
 
 dc_status_t
 suunto_solution_extract_dives (dc_device_t *abstract, const unsigned char data[], unsigned int size, dc_dive_callback_t callback, void *userdata)
 {
+
 	if (abstract && !ISINSTANCE (abstract))
 		return DC_STATUS_INVALIDARGS;
 
@@ -327,9 +463,19 @@ suunto_solution_extract_dives (dc_device_t *abstract, const unsigned char data[]
 		// to find the start of the current dive.
 		unsigned int peek = ringbuffer_increment (current, 2, RB_PROFILE_BEGIN, RB_PROFILE_END);
 		if (data[peek] == 0x80) {
+			suunto_solution_device_t *device = (suunto_solution_device_t*) abstract;
 			unsigned int len = ringbuffer_distance (previous, current, 0, RB_PROFILE_BEGIN, RB_PROFILE_END);
+			unsigned char fingerprint[16];
+
+			// Compute non-cryptographic hash from data.
+			suunto_solution_hash (buffer + idx, len, fingerprint);
+
+			// Compare hash values.
+			if (device->hasfingerprint &&
+			    memcmp (fingerprint, device->fingerprint, sizeof (device->fingerprint)) == 0)
+				return DC_STATUS_SUCCESS;
 
-			if (callback && !callback (buffer + idx, len, NULL, 0, userdata))
+			if (callback && !callback (buffer + idx, len, fingerprint, sizeof(fingerprint), userdata))
 				return DC_STATUS_SUCCESS;
 
 			previous = current;
