From ce82829284ea0888008c89ce082c7512c8d663ee Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 23 Feb 2016 22:13:25 +0100 Subject: [PATCH 1/3] Fix a memory leak. A new buffer is allocated for each dive, but only the last one is freed. Since the code is already prepared to simply re-use the same buffer, there is no need to allocate those extra buffers. --- src/suunto_eonsteel.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/suunto_eonsteel.c b/src/suunto_eonsteel.c index ec7cfe3..e1c9846 100644 --- a/src/suunto_eonsteel.c +++ b/src/suunto_eonsteel.c @@ -672,9 +672,6 @@ suunto_eonsteel_device_foreach(dc_device_t *abstract, dc_dive_callback_t callbac break; if (!callback(dc_buffer_get_data(file), dc_buffer_get_size(file), NULL, 0, userdata)) skip = 1; - - // We've used up the buffer, so create a new one - file = dc_buffer_new(0); } progress.current++; device_event_emit(abstract, DC_EVENT_PROGRESS, &progress); From 76c52b582a6298b66bdba742eae987b27dca0e40 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 23 Feb 2016 22:52:31 +0100 Subject: [PATCH 2/3] Add support for the fingerprint feature. --- src/suunto_eonsteel.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/suunto_eonsteel.c b/src/suunto_eonsteel.c index e1c9846..9debc6a 100644 --- a/src/suunto_eonsteel.c +++ b/src/suunto_eonsteel.c @@ -52,6 +52,7 @@ typedef struct suunto_eonsteel_device_t { libusb_device_handle *handle; unsigned int magic; unsigned short seq; + unsigned char fingerprint[4]; } suunto_eonsteel_device_t; // The EON Steel implements a small filesystem @@ -81,13 +82,14 @@ struct directory_entry { #define READDIR_CMD 0x0910 #define DIR_CLOSE_CMD 0x0a10 +static dc_status_t suunto_eonsteel_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size); static dc_status_t suunto_eonsteel_device_foreach(dc_device_t *abstract, dc_dive_callback_t callback, void *userdata); static dc_status_t suunto_eonsteel_device_close(dc_device_t *abstract); static const dc_device_vtable_t suunto_eonsteel_device_vtable = { sizeof(suunto_eonsteel_device_t), DC_FAMILY_SUUNTO_EONSTEEL, - NULL, /* set_fingerprint */ + suunto_eonsteel_device_set_fingerprint, /* set_fingerprint */ NULL, /* read */ NULL, /* write */ NULL, /* dump */ @@ -570,6 +572,7 @@ suunto_eonsteel_device_open(dc_device_t **out, dc_context_t *context, const char // Set up the magic handshake fields eon->magic = INIT_MAGIC; eon->seq = INIT_SEQ; + memset (eon->fingerprint, 0, sizeof (eon->fingerprint)); if (libusb_init(&eon->ctx)) { ERROR(context, "libusb_init() failed"); @@ -619,6 +622,22 @@ static int count_dir_entries(struct directory_entry *de) return count; } +static dc_status_t +suunto_eonsteel_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size) +{ + suunto_eonsteel_device_t *device = (suunto_eonsteel_device_t *) abstract; + + if (size && size != sizeof (device->fingerprint)) + return DC_STATUS_INVALIDARGS; + + if (size) + memcpy (device->fingerprint, data, sizeof (device->fingerprint)); + else + memset (device->fingerprint, 0, sizeof (device->fingerprint)); + + return DC_STATUS_SUCCESS; +} + static dc_status_t suunto_eonsteel_device_foreach(dc_device_t *abstract, dc_dive_callback_t callback, void *userdata) { @@ -642,6 +661,8 @@ suunto_eonsteel_device_foreach(dc_device_t *abstract, dc_dive_callback_t callbac int len; struct directory_entry *next = de->next; unsigned char buf[4]; + const unsigned char *data = NULL; + unsigned int size = 0; if (device_is_cancelled(abstract)) skip = 1; @@ -668,9 +689,16 @@ suunto_eonsteel_device_foreach(dc_device_t *abstract, dc_dive_callback_t callbac rc = read_file(eon, pathname, file); if (rc < 0) break; - if (!callback) + + data = dc_buffer_get_data(file); + size = dc_buffer_get_size(file); + + if (memcmp (data, eon->fingerprint, sizeof (eon->fingerprint)) == 0) { + skip = 1; break; - if (!callback(dc_buffer_get_data(file), dc_buffer_get_size(file), NULL, 0, userdata)) + } + + if (callback && !callback(data, size, data, sizeof(eon->fingerprint), userdata)) skip = 1; } progress.current++; From d40cdb4755ee478530a09f297836f310d7423678 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Sun, 24 Apr 2016 19:14:52 +0200 Subject: [PATCH 3/3] Add the devinfo event. The devinfo event with the device serial number is required for the fingerprint feature. Without this event, applications won't be able to load (or save) the correct fingerprint. All necessary information is already available in the initial handshake packet. --- src/array.c | 14 ++++++++++++++ src/array.h | 3 +++ src/suunto_eonsteel.c | 11 ++++++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/array.c b/src/array.c index 26a6c1b..13a73e5 100644 --- a/src/array.c +++ b/src/array.c @@ -146,6 +146,20 @@ array_convert_hex2bin (const unsigned char input[], unsigned int isize, unsigned return 0; } +unsigned int +array_convert_str2num (const unsigned char data[], unsigned int size) +{ + unsigned int value = 0; + for (unsigned int i = 0; i < size; ++i) { + if (data[i] < '0' || data[i] > '9') + break; + value *= 10; + value += data[i] - '0'; + } + + return value; +} + unsigned int array_uint_be (const unsigned char data[], unsigned int n) { diff --git a/src/array.h b/src/array.h index 49e8ab1..cd0a3a1 100644 --- a/src/array.h +++ b/src/array.h @@ -49,6 +49,9 @@ array_convert_bin2hex (const unsigned char input[], unsigned int isize, unsigned int array_convert_hex2bin (const unsigned char input[], unsigned int isize, unsigned char output[], unsigned int osize); +unsigned int +array_convert_str2num (const unsigned char data[], unsigned int size); + unsigned int array_uint_be (const unsigned char data[], unsigned int n); diff --git a/src/suunto_eonsteel.c b/src/suunto_eonsteel.c index 9debc6a..079c353 100644 --- a/src/suunto_eonsteel.c +++ b/src/suunto_eonsteel.c @@ -52,6 +52,7 @@ typedef struct suunto_eonsteel_device_t { libusb_device_handle *handle; unsigned int magic; unsigned short seq; + unsigned char version[0x30]; unsigned char fingerprint[4]; } suunto_eonsteel_device_t; @@ -544,7 +545,7 @@ static int initialize_eonsteel(suunto_eonsteel_device_t *eon) ERROR(eon->base.context, "Failed to send initialization command"); return -1; } - if (receive_header(eon, &hdr, buf, sizeof(buf)) < 0) { + if (receive_header(eon, &hdr, eon->version, sizeof(eon->version)) < 0) { ERROR(eon->base.context, "Failed to receive initial reply"); return -1; } @@ -572,6 +573,7 @@ suunto_eonsteel_device_open(dc_device_t **out, dc_context_t *context, const char // Set up the magic handshake fields eon->magic = INIT_MAGIC; eon->seq = INIT_SEQ; + memset (eon->version, 0, sizeof (eon->version)); memset (eon->fingerprint, 0, sizeof (eon->fingerprint)); if (libusb_init(&eon->ctx)) { @@ -652,6 +654,13 @@ suunto_eonsteel_device_foreach(dc_device_t *abstract, dc_dive_callback_t callbac if (get_file_list(eon, &de) < 0) return DC_STATUS_IO; + // Emit a device info event. + dc_event_devinfo_t devinfo; + devinfo.model = 0; + devinfo.firmware = array_uint32_be (eon->version + 0x20); + devinfo.serial = array_convert_str2num(eon->version + 0x10, 16); + device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo); + file = dc_buffer_new(0); progress.maximum = count_dir_entries(de); progress.current = 0;