[PATCH] parser: add DC_FIELD_DEVINFO field type for parse-time device information

Linus Torvalds torvalds at linux-foundation.org
Wed Oct 22 12:40:59 PDT 2014

From: Linus Torvalds <torvalds at linux-foundation.org>
Date: Wed, 22 Oct 2014 12:11:12 -0700
Subject: [PATCH] Use the new DC_FIELD_DEVINFO callback if it exists

This gets dive ID and divecomputer device information in a sane string format.

Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>

Jef and the libdivecomputer mailing list cc'd, because this whole patch to 
subsurface only makes sense if the libdivecomputer part of it gets 

So I'm sending this out not to be applied by Dirk, but to show how simple 
the new DC_FIELD_DEVINFO model is to use, and how subsurface can trivially 
use it.

With this patch, my Suunto EON Steel backend to liobdivecomputer "just 
works". Even without this patch it worked for getting dives and profiles, 
but this is the part that is needed to actually get dive computer serial 
numbers etc.

Also notice how this can actually work *together* with the old 
DC_EVENT_DEVINFO interface. In particular, say that you have an old 
backend that used the DC_EVENT_DEVINFO interface, but wants to give a 
*real* serial number, not the broken numeric-only one that 

Such a backend could just add the new DC_FIELD_DEVINFO support, and 
subsurface will continue to use the old "deviceid" that was generated by 
DC_EVENT_DEVINFO - so that device ID's don't change in your logbook - but 
can automatically now pick up properly formatted serial numbers (of 
hardware versions etc). And it would "just work".

The point being that this doesn't break the old interface, and it's 
actually designed to work in conjunction with it. It's also designed so 
that applications that haven't been changed (including versions of 
subsurface that do not have this patch) to use the new DC_FIELD_DEVINFO 
interface won't even notice.

They'll get all the old information, and they aren't broken by any of 
this. They can't take advantage of the new info, and they won't get EON 
Steel serial numbers etc, but they'll work fine.

 libdivecomputer.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/libdivecomputer.c b/libdivecomputer.c
index ff8d0eb93bda..5da49577ba2c 100644
--- a/libdivecomputer.c
+++ b/libdivecomputer.c
@@ -397,6 +397,28 @@ static uint32_t calculate_diveid(const unsigned char *fingerprint, unsigned int
 	return csum[0];
+static uint32_t calculate_string_hash(const char *str)
+	return calculate_diveid(str, strlen(str));
+static void parse_devinfo(struct dive *dive, dc_field_devinfo_t *info)
+	// Our dive ID is the string hash of the dive_id string
+	if (info->dive_id && !dive->dc.diveid)
+		dive->dc.diveid = calculate_string_hash(info->dive_id);
+	// Our "device ID" is the string hash of the serial number
+	if (info->serial && !dive->dc.deviceid)
+		dive->dc.deviceid = calculate_string_hash(info->serial);
+	// If we have a deviceid either from the above or from the
+	// original DC_EVENT_DEVINFO, and we now have serial numbers
+	// or fw/hw versions, fill that into the device node
+	if (dive->dc.deviceid && (info->serial || info->fw_version))
+		create_device_node(dive->dc.model, dive->dc.deviceid, info->serial, info->fw_version, "");
 /* 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,
@@ -494,6 +516,14 @@ static int dive_cb(const unsigned char *data, unsigned int size,
 	dive->dc.surface_pressure.mbar = rint(surface_pressure * 1000.0);
+	// The dive parsing may give us more device information
+	dc_field_devinfo_t devinfo = { NULL };
+	rc = dc_parser_get_field(parser, DC_FIELD_DEVINFO, 0, &devinfo);
+	if (rc == DC_STATUS_SUCCESS)
+		parse_devinfo(dive, &devinfo);
 	rc = parse_gasmixes(devdata, dive, parser, ngases, data);
 	if (rc != DC_STATUS_SUCCESS) {
 		dev_info(devdata, translate("gettextFromC", "Error parsing the gas mix"));

More information about the subsurface mailing list