From 3287e3bd5de82caa2edfee6fa3c8c49c2f07e8c2 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 14 Feb 2019 22:15:46 +0100 Subject: [PATCH 1/7] Update the list of the Ratio dive computers There were quite a few models missing in the list. And because the lowest iX3M model number has changed, the iX3M detection needed to be updated as well. --- src/descriptor.c | 14 +++++++++++++- src/divesystem_idive.c | 9 +++------ src/divesystem_idive_parser.c | 13 +++++-------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/descriptor.c b/src/descriptor.c index 1c533db..545dcf7 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -313,20 +313,32 @@ static const dc_descriptor_t g_descriptors[] = { {"DiveSystem", "iDive Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x09, DC_TRANSPORT_SERIAL, NULL}, {"DiveSystem", "iDive X3M", DC_FAMILY_DIVESYSTEM_IDIVE, 0x0A, DC_TRANSPORT_SERIAL, NULL}, {"DiveSystem", "iDive Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x0B, DC_TRANSPORT_SERIAL, NULL}, + {"Ratio", "iX3M Pro ", DC_FAMILY_DIVESYSTEM_IDIVE, 0x21, DC_TRANSPORT_SERIAL, NULL}, {"Ratio", "iX3M Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x22, DC_TRANSPORT_SERIAL, NULL}, {"Ratio", "iX3M Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x23, DC_TRANSPORT_SERIAL, NULL}, {"Ratio", "iX3M Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x24, DC_TRANSPORT_SERIAL, NULL}, {"Ratio", "iX3M Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x25, DC_TRANSPORT_SERIAL, NULL}, + {"Ratio", "iX3M Fancy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x26, DC_TRANSPORT_SERIAL, NULL}, + {"Ratio", "iX3M Pro Fancy",DC_FAMILY_DIVESYSTEM_IDIVE, 0x31, DC_TRANSPORT_SERIAL, NULL}, {"Ratio", "iX3M Pro Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x32, DC_TRANSPORT_SERIAL, NULL}, + {"Ratio", "iX3M Pro Pro", DC_FAMILY_DIVESYSTEM_IDIVE, 0x33, DC_TRANSPORT_SERIAL, NULL}, {"Ratio", "iX3M Pro Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x34, DC_TRANSPORT_SERIAL, NULL}, {"Ratio", "iX3M Pro Tech+",DC_FAMILY_DIVESYSTEM_IDIVE, 0x35, DC_TRANSPORT_SERIAL, NULL}, + {"Ratio", "iX3M Pro Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x36, DC_TRANSPORT_SERIAL, NULL}, {"Ratio", "iDive Free", DC_FAMILY_DIVESYSTEM_IDIVE, 0x40, DC_TRANSPORT_SERIAL, NULL}, + {"Ratio", "iDive Fancy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x41, DC_TRANSPORT_SERIAL, NULL}, {"Ratio", "iDive Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x42, DC_TRANSPORT_SERIAL, NULL}, + {"Ratio", "iDive Pro", DC_FAMILY_DIVESYSTEM_IDIVE, 0x43, DC_TRANSPORT_SERIAL, NULL}, {"Ratio", "iDive Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x44, DC_TRANSPORT_SERIAL, NULL}, {"Ratio", "iDive Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x45, DC_TRANSPORT_SERIAL, NULL}, + {"Ratio", "iDive Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x46, DC_TRANSPORT_SERIAL, NULL}, + {"Ratio", "iDive Color Free", DC_FAMILY_DIVESYSTEM_IDIVE, 0x50, DC_TRANSPORT_SERIAL, NULL}, + {"Ratio", "iDive Color Fancy",DC_FAMILY_DIVESYSTEM_IDIVE, 0x51, DC_TRANSPORT_SERIAL, NULL}, {"Ratio", "iDive Color Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x52, DC_TRANSPORT_SERIAL, NULL}, + {"Ratio", "iDive Color Pro", DC_FAMILY_DIVESYSTEM_IDIVE, 0x53, DC_TRANSPORT_SERIAL, NULL}, {"Ratio", "iDive Color Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x54, DC_TRANSPORT_SERIAL, NULL}, - {"Ratio", "iDive Color Tech", DC_FAMILY_DIVESYSTEM_IDIVE, 0x55, DC_TRANSPORT_SERIAL, NULL}, + {"Ratio", "iDive Color Tech+",DC_FAMILY_DIVESYSTEM_IDIVE, 0x55, DC_TRANSPORT_SERIAL, NULL}, + {"Ratio", "iDive Color Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x56, DC_TRANSPORT_SERIAL, NULL}, {"Seac", "Jack", DC_FAMILY_DIVESYSTEM_IDIVE, 0x1000, DC_TRANSPORT_SERIAL, NULL}, {"Seac", "Guru", DC_FAMILY_DIVESYSTEM_IDIVE, 0x1002, DC_TRANSPORT_SERIAL, NULL}, /* Cochran Commander */ diff --git a/src/divesystem_idive.c b/src/divesystem_idive.c index f827b52..2303186 100644 --- a/src/divesystem_idive.c +++ b/src/divesystem_idive.c @@ -30,10 +30,7 @@ #define ISINSTANCE(device) dc_device_isinstance((device), &divesystem_idive_device_vtable) -#define IX3M_EASY 0x22 -#define IX3M_DEEP 0x23 -#define IX3M_TEC 0x24 -#define IX3M_REB 0x25 +#define ISIX3M(model) ((model) >= 0x21) #define MAXRETRIES 9 @@ -374,7 +371,7 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb unsigned int errcode = 0; const divesystem_idive_commands_t *commands = &idive; - if (device->model >= IX3M_EASY) { + if (ISIX3M(device->model)) { commands = &ix3m; } @@ -400,7 +397,7 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb vendor.size = commands->id.size; device_event_emit (abstract, DC_EVENT_VENDOR, &vendor); - if (device->model >= IX3M_EASY) { + if (ISIX3M(device->model)) { // Detect the APOS4 firmware. unsigned int apos4 = (devinfo.firmware / 10000000) >= 4; if (apos4) { diff --git a/src/divesystem_idive_parser.c b/src/divesystem_idive_parser.c index adfb48a..66f77dc 100644 --- a/src/divesystem_idive_parser.c +++ b/src/divesystem_idive_parser.c @@ -30,10 +30,7 @@ #define ISINSTANCE(parser) dc_device_isinstance((parser), &divesystem_idive_parser_vtable) -#define IX3M_EASY 0x22 -#define IX3M_DEEP 0x23 -#define IX3M_TEC 0x24 -#define IX3M_REB 0x25 +#define ISIX3M(model) ((model) >= 0x21) #define SZ_HEADER_IDIVE 0x32 #define SZ_SAMPLE_IDIVE 0x2A @@ -103,7 +100,7 @@ divesystem_idive_parser_create (dc_parser_t **out, dc_context_t *context, unsign // Set the default values. parser->model = model; - if (model >= IX3M_EASY) { + if (ISIX3M(model)) { parser->headersize = SZ_HEADER_IX3M; } else { parser->headersize = SZ_HEADER_IDIVE; @@ -206,7 +203,7 @@ divesystem_idive_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *date // Detect the APOS4 firmware. unsigned int firmware = 0; unsigned int apos4 = 0; - if (parser->model >= IX3M_EASY) { + if (ISIX3M(parser->model)) { firmware = array_uint32_le(abstract->data + 0x2A); apos4 = (firmware / 10000000) >= 4; } else { @@ -297,7 +294,7 @@ divesystem_idive_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, tank->gasmix = DC_GASMIX_UNKNOWN; break; case DC_FIELD_ATMOSPHERIC: - if (parser->model >= IX3M_EASY) { + if (ISIX3M(parser->model)) { *((double *) value) = array_uint16_le (data + 11) / 10000.0; } else { *((double *) value) = array_uint16_le (data + 11) / 1000.0; @@ -363,7 +360,7 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba unsigned int apos4 = 0; unsigned int nsamples = array_uint16_le (data + 1); unsigned int samplesize = SZ_SAMPLE_IDIVE; - if (parser->model >= IX3M_EASY) { + if (ISIX3M(parser->model)) { // Detect the APOS4 firmware. firmware = array_uint32_le(data + 0x2A); apos4 = (firmware / 10000000) >= 4; From d876542d39a27ed39d38f7d80d52e6460c541843 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 21 Feb 2019 21:54:58 +0100 Subject: [PATCH 2/7] Don't pass a NULL pointer to memcpy The memcpy and related functions expects a valid pointer, even if the size is zero. Most libc implementations will handle a NULL pointer just fine, but that's not guaranteed. Simply skip the call when there is nothing to copy. --- src/divesystem_idive.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/divesystem_idive.c b/src/divesystem_idive.c index 2303186..180ccb6 100644 --- a/src/divesystem_idive.c +++ b/src/divesystem_idive.c @@ -319,7 +319,9 @@ divesystem_idive_packet (divesystem_idive_device_t *device, const unsigned char goto error; } - memcpy(answer, packet + 1, length - 2); + if (length > 2) { + memcpy (answer, packet + 1, length - 2); + } error: if (errorcode) { From ec14ee2b772b60f72dbf5b01ecba97fc86c8adac Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 21 Feb 2019 22:16:58 +0100 Subject: [PATCH 3/7] Use symbolic constants for the commands --- src/divesystem_idive.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/divesystem_idive.c b/src/divesystem_idive.c index 180ccb6..b9e4efc 100644 --- a/src/divesystem_idive.c +++ b/src/divesystem_idive.c @@ -39,6 +39,16 @@ #define ACK 0x06 #define NAK 0x15 +#define CMD_IDIVE_ID 0x10 +#define CMD_IDIVE_RANGE 0x98 +#define CMD_IDIVE_HEADER 0xA0 +#define CMD_IDIVE_SAMPLE 0xA8 + +#define CMD_IX3M_ID 0x11 +#define CMD_IX3M_RANGE 0x78 +#define CMD_IX3M_HEADER 0x79 +#define CMD_IX3M_SAMPLE 0x7A + #define ERR_INVALID_CMD 0x10 #define ERR_INVALID_LENGTH 0x20 #define ERR_INVALID_DATA 0x30 @@ -86,26 +96,26 @@ static const dc_device_vtable_t divesystem_idive_device_vtable = { }; static const divesystem_idive_commands_t idive = { - {0x10, 0x0A}, - {0x98, 0x04}, - {0xA0, 0x32}, - {0xA8, 0x2A}, + {CMD_IDIVE_ID, 0x0A}, + {CMD_IDIVE_RANGE, 0x04}, + {CMD_IDIVE_HEADER, 0x32}, + {CMD_IDIVE_SAMPLE, 0x2A}, 1, }; static const divesystem_idive_commands_t ix3m = { - {0x11, 0x1A}, - {0x78, 0x04}, - {0x79, 0x36}, - {0x7A, 0x36}, + {CMD_IX3M_ID, 0x1A}, + {CMD_IX3M_RANGE, 0x04}, + {CMD_IX3M_HEADER, 0x36}, + {CMD_IX3M_SAMPLE, 0x36}, 1, }; static const divesystem_idive_commands_t ix3m_apos4 = { - {0x11, 0x1A}, - {0x78, 0x04}, - {0x79, 0x36}, - {0x7A, 0x40}, + {CMD_IX3M_ID, 0x1A}, + {CMD_IX3M_RANGE, 0x04}, + {CMD_IX3M_HEADER, 0x36}, + {CMD_IX3M_SAMPLE, 0x40}, 3, }; From 4bbebe7c32a1ca45709fd90753d0ccba96cd3076 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Wed, 16 Jan 2019 21:15:43 +0100 Subject: [PATCH 4/7] Add clock synchronization support The Ratio dive computers support synchronizing the internal clock. One complication is that recent firmware versions (4.0.56 or 4.1.10) support two timezones (home and abroad), while the libdivecomputer api only supports one timezone. To deal with this, the most recent firmware versions (4.0.58 or 4.1.12) will interprete an invalid timezone index (0xFF) as leaving the timezone unchanged. If the firmware doesn't support the dual timezone command, or if the firmware doesn't have the invalid timezone index modification yet, then a fallback to the single timezone command is provided. Note that in the latter case the side effect is that both timezones will be changed! --- src/divesystem_idive.c | 131 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 130 insertions(+), 1 deletion(-) diff --git a/src/divesystem_idive.c b/src/divesystem_idive.c index b9e4efc..1119b23 100644 --- a/src/divesystem_idive.c +++ b/src/divesystem_idive.c @@ -28,6 +28,8 @@ #include "checksum.h" #include "array.h" +#define C_ARRAY_SIZE(array) (sizeof (array) / sizeof *(array)) + #define ISINSTANCE(device) dc_device_isinstance((device), &divesystem_idive_device_vtable) #define ISIX3M(model) ((model) >= 0x21) @@ -48,6 +50,7 @@ #define CMD_IX3M_RANGE 0x78 #define CMD_IX3M_HEADER 0x79 #define CMD_IX3M_SAMPLE 0x7A +#define CMD_IX3M_TIMESYNC 0x13 #define ERR_INVALID_CMD 0x10 #define ERR_INVALID_LENGTH 0x20 @@ -60,6 +63,10 @@ #define NSTEPS 1000 #define STEP(i,n) (NSTEPS * (i) / (n)) +#define EPOCH 1199145600 /* 2008-01-01 00:00:00 */ + +#define TZ_IDX_UNCHANGED 0xFF + typedef struct divesystem_idive_command_t { unsigned char cmd; unsigned int size; @@ -82,6 +89,7 @@ typedef struct divesystem_idive_device_t { static dc_status_t divesystem_idive_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size); static dc_status_t divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata); +static dc_status_t divesystem_idive_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime); static const dc_device_vtable_t divesystem_idive_device_vtable = { sizeof(divesystem_idive_device_t), @@ -91,7 +99,7 @@ static const dc_device_vtable_t divesystem_idive_device_vtable = { NULL, /* write */ NULL, /* dump */ divesystem_idive_device_foreach, /* foreach */ - NULL, /* timesync */ + divesystem_idive_device_timesync, /* timesync */ NULL /* close */ }; @@ -523,3 +531,124 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb return DC_STATUS_SUCCESS; } + +static dc_status_t +divesystem_idive_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime) +{ + dc_status_t rc = DC_STATUS_SUCCESS; + divesystem_idive_device_t *device = (divesystem_idive_device_t *) abstract; + unsigned int errcode = 0; + + static const signed char tz_array[] = { + -12, 0, /* UTC-12 */ + -11, 0, /* UTC-11 */ + -10, 0, /* UTC-10 */ + -9, 30, /* UTC-9:30 */ + -9, 0, /* UTC-9 */ + -8, 0, /* UTC-8 */ + -7, 0, /* UTC-7 */ + -6, 0, /* UTC-6 */ + -5, 0, /* UTC-5 */ + -4, 30, /* UTC-4:30 */ + -4, 0, /* UTC-4 */ + -3, 30, /* UTC-3:30 */ + -3, 0, /* UTC-3 */ + -2, 0, /* UTC-2 */ + -1, 0, /* UTC-1 */ + 0, 0, /* UTC */ + 1, 0, /* UTC+1 */ + 2, 0, /* UTC+2 */ + 3, 0, /* UTC+3 */ + 3, 30, /* UTC+3:30 */ + 4, 0, /* UTC+4 */ + 4, 30, /* UTC+4:30 */ + 5, 0, /* UTC+5 */ + 5, 30, /* UTC+5:30 */ + 5, 45, /* UTC+5:45 */ + 6, 0, /* UTC+6 */ + 6, 30, /* UTC+6:30 */ + 7, 0, /* UTC+7 */ + 8, 0, /* UTC+8 */ + 8, 45, /* UTC+8:45 */ + 9, 0, /* UTC+9 */ + 9, 30, /* UTC+9:30 */ + 9, 45, /* UTC+9:45 */ + 10, 0, /* UTC+10 */ + 10, 30, /* UTC+10:30 */ + 11, 0, /* UTC+11 */ + 11, 30, /* UTC+11:30 */ + 12, 0, /* UTC+12 */ + 12, 45, /* UTC+12:45 */ + 13, 0, /* UTC+13 */ + 13, 45, /* UTC+13:45 */ + 14, 0 /* UTC+14 */ + }; + + if (!ISIX3M(device->model)) { + return DC_STATUS_UNSUPPORTED; + } + + if (datetime == NULL) { + ERROR (abstract->context, "Invalid parameter specified."); + return DC_STATUS_INVALIDARGS; + } + + // Get the UTC timestamp. + dc_ticks_t timestamp = dc_datetime_mktime(datetime); + if (timestamp == -1) { + ERROR (abstract->context, "Invalid date/time value specified."); + return DC_STATUS_INVALIDARGS; + } + + // Adjust the epoch. + timestamp -= EPOCH; + + // Find the timezone index. + size_t tz_idx = C_ARRAY_SIZE(tz_array); + for (size_t i = 0; i < C_ARRAY_SIZE(tz_array); i += 2) { + int timezone = tz_array[i] * 3600; + if (timezone < 0) { + timezone -= tz_array[i + 1] * 60; + } else { + timezone += tz_array[i + 1] * 60; + } + + if (timezone == datetime->timezone) { + tz_idx = i; + break; + } + } + if (tz_idx >= C_ARRAY_SIZE(tz_array)) { + ERROR (abstract->context, "Invalid timezone value specified."); + return DC_STATUS_INVALIDARGS; + } + + // Adjust the timezone index. + tz_idx /= 2; + + // Send the command. + unsigned char command[] = { + CMD_IX3M_TIMESYNC, + (timestamp >> 0) & 0xFF, + (timestamp >> 8) & 0xFF, + (timestamp >> 16) & 0xFF, + (timestamp >> 24) & 0xFF, + tz_idx, // Home timezone + TZ_IDX_UNCHANGED}; // Travel timezone + rc = divesystem_idive_transfer (device, command, sizeof(command), NULL, 0, &errcode); + if (rc != DC_STATUS_SUCCESS) { + if (errcode == ERR_INVALID_LENGTH || errcode == ERR_INVALID_DATA) { + // Fallback to the variant without the second timezone if the + // firmware doesn't support two timezones (ERR_INVALID_LENGTH) or + // leaving the timezone unchanged (ERR_INVALID_DATA). + rc = divesystem_idive_transfer (device, command, sizeof(command) - 1, NULL, 0, &errcode); + if (rc != DC_STATUS_SUCCESS) { + return rc; + } + } else { + return rc; + } + } + + return DC_STATUS_SUCCESS; +} From f05f60c4ad4332a076cfcf86348b3bf24a676594 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Sat, 22 Dec 2018 21:28:48 +0100 Subject: [PATCH 5/7] Skip empty logbook entries On certain devices, for example the Aeris Elite T3, the logbook ringbuffer can sometimes contain an empty logbook entry in between the valid entries. Because the presence of such an empty entry is currently being interpreted as having reached the last valid entry, the download is aborted. The result is that all remaining valid entries, located after the empty entry, can't be downloaded. This can be avoided by skipping the empty entry instead of aborting the download. --- src/oceanic_common.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/oceanic_common.c b/src/oceanic_common.c index bdc2f79..4a42300 100644 --- a/src/oceanic_common.c +++ b/src/oceanic_common.c @@ -304,8 +304,7 @@ oceanic_common_device_logbook (dc_device_t *abstract, dc_event_progress_t *progr // fix this here. if (array_isequal (logbooks + offset, layout->rb_logbook_entry_size, 0xFF)) { WARNING (abstract->context, "Uninitialized logbook entries detected!"); - offset += layout->rb_logbook_entry_size; - break; + continue; } // Compare the fingerprint to identify previously downloaded entries. @@ -364,6 +363,12 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr // Move to the start of the current entry. entry -= layout->rb_logbook_entry_size; + // Skip uninitialized entries. + if (array_isequal (logbooks + entry, layout->rb_logbook_entry_size, 0xFF)) { + WARNING (abstract->context, "Skipping uninitialized logbook entry!"); + continue; + } + // Get the profile pointers. unsigned int rb_entry_first = get_profile_first (logbooks + entry, layout, pagesize); unsigned int rb_entry_last = get_profile_last (logbooks + entry, layout, pagesize); @@ -442,6 +447,12 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr // Move to the start of the current entry. entry -= layout->rb_logbook_entry_size; + // Skip uninitialized entries. + if (array_isequal (logbooks + entry, layout->rb_logbook_entry_size, 0xFF)) { + WARNING (abstract->context, "Skipping uninitialized logbook entry!"); + continue; + } + // Get the profile pointers. unsigned int rb_entry_first = get_profile_first (logbooks + entry, layout, pagesize); unsigned int rb_entry_last = get_profile_last (logbooks + entry, layout, pagesize); From 2ea24cf04313edeb7fc20d5aeaa88320bc81e003 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Wed, 23 Jan 2019 20:55:59 +0100 Subject: [PATCH 6/7] Add filters for BLE communication This is mainly for future use and reference, because there is still no built-in support for BLE communication available. --- src/descriptor.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/descriptor.c b/src/descriptor.c index 545dcf7..03049f0 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -420,11 +420,17 @@ static int dc_filter_uwatec (dc_transport_t transport, const void *userdata) {0x2e6c, 0x3211}, // G2 Console {0xc251, 0x2006}, // Aladin Square }; + static const char *bluetooth[] = { + "G2", + "Aladin", + }; if (transport == DC_TRANSPORT_IRDA) { return dc_filter_internal_name ((const char *) userdata, irda, C_ARRAY_SIZE(irda)); } else if (transport == DC_TRANSPORT_USBHID) { return dc_filter_internal_usb ((const dc_usb_desc_t *) userdata, usbhid, C_ARRAY_SIZE(usbhid)); + } else if (transport == DC_TRANSPORT_BLE) { + return dc_filter_internal_name ((const char *) userdata, bluetooth, C_ARRAY_SIZE(bluetooth)); } return 1; @@ -436,9 +442,15 @@ static int dc_filter_suunto (dc_transport_t transport, const void *userdata) {0x1493, 0x0030}, // Eon Steel {0x1493, 0x0033}, // Eon Core }; + static const char *bluetooth[] = { + "EON Steel", + "EON Core", + }; if (transport == DC_TRANSPORT_USBHID) { return dc_filter_internal_usb ((const dc_usb_desc_t *) userdata, usbhid, C_ARRAY_SIZE(usbhid)); + } else if (transport == DC_TRANSPORT_BLE) { + return dc_filter_internal_name ((const char *) userdata, bluetooth, C_ARRAY_SIZE(bluetooth)); } return 1; @@ -446,7 +458,7 @@ static int dc_filter_suunto (dc_transport_t transport, const void *userdata) static int dc_filter_hw (dc_transport_t transport, const void *userdata) { - if (transport == DC_TRANSPORT_BLUETOOTH) { + if (transport == DC_TRANSPORT_BLUETOOTH || transport == DC_TRANSPORT_BLE) { return strncasecmp ((const char *) userdata, "OSTC", 4) == 0 || strncasecmp ((const char *) userdata, "FROG", 4) == 0; } else if (transport == DC_TRANSPORT_SERIAL) { @@ -466,7 +478,7 @@ static int dc_filter_shearwater (dc_transport_t transport, const void *userdata) "Teric", }; - if (transport == DC_TRANSPORT_BLUETOOTH) { + if (transport == DC_TRANSPORT_BLUETOOTH || transport == DC_TRANSPORT_BLE) { return dc_filter_internal_name ((const char *) userdata, bluetooth, C_ARRAY_SIZE(bluetooth)); } else if (transport == DC_TRANSPORT_SERIAL) { return dc_filter_internal_rfcomm ((const char *) userdata); From 530b28bf6f4e7602fc435d55750b91b6a4a71ccd Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Wed, 27 Feb 2019 19:48:01 +0100 Subject: [PATCH 7/7] Ignore zero tank pressure values When the connection with the transmitter is lost, the OSTC records a zero value for the tank pressure. --- src/hw_ostc_parser.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hw_ostc_parser.c b/src/hw_ostc_parser.c index f377684..f84e611 100644 --- a/src/hw_ostc_parser.c +++ b/src/hw_ostc_parser.c @@ -916,9 +916,11 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call break; case 6: // Tank pressure value = array_uint16_le (data + offset); - sample.pressure.tank = tank; - sample.pressure.value = value / 10.0; - if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata); + if (value != 0) { + sample.pressure.tank = tank; + sample.pressure.value = value / 10.0; + if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata); + } break; default: // Not yet used. break;