From: Linus Torvalds torvalds@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@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 applied.
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 DC_EVENT_DEVINFO supports.
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); #endif
+#ifdef DC_FIELD_DEVINFO + // 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); +#endif + rc = parse_gasmixes(devdata, dive, parser, ngases, data); if (rc != DC_STATUS_SUCCESS) { dev_info(devdata, translate("gettextFromC", "Error parsing the gas mix"));