From 34bc6b1613fee3d72a2940dfdd5acad6def434fb Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 3 Nov 2022 21:31:24 +0100 Subject: [PATCH 1/5] Use the macro for encoding firmware versions This makes it a bit easer to quickly locate the workarounds for specific firmware versions. --- src/hw_ostc3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c index e8dc223..467a64d 100644 --- a/src/hw_ostc3.c +++ b/src/hw_ostc3.c @@ -770,7 +770,7 @@ hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, voi if (!compact) { // Workaround for a bug in older firmware versions. unsigned int firmware = array_uint16_be (header + offset + 0x30); - if (firmware < 93) + if (firmware < OSTC3FW(0,93)) length -= 3; } if (length < RB_LOGBOOK_SIZE_FULL) { @@ -818,7 +818,7 @@ hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, voi if (!compact) { // Workaround for a bug in older firmware versions. unsigned int firmware = array_uint16_be (header + offset + 0x30); - if (firmware < 93) + if (firmware < OSTC3FW(0,93)) length -= 3; } From c578e0a158a107c43b5af235c007d583cfbe11f6 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 3 Nov 2022 21:37:09 +0100 Subject: [PATCH 2/5] Use symbolic constants for the header offsets --- src/hw_ostc3.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c index 467a64d..2b4c262 100644 --- a/src/hw_ostc3.c +++ b/src/hw_ostc3.c @@ -89,6 +89,16 @@ #define NODELAY 0 #define TIMEOUT 400 +#define HDR_COMPACT_LENGTH 0 // 3 bytes +#define HDR_COMPACT_SUMMARY 3 // 10 bytes +#define HDR_COMPACT_NUMBER 13 // 2 bytes + +#define HDR_FULL_LENGTH 9 // 3 bytes +#define HDR_FULL_SUMMARY 12 // 10 bytes +#define HDR_FULL_NUMBER 80 // 2 bytes + +#define HDR_FULL_FIRMWARE 48 // 2 bytes + typedef enum hw_ostc3_state_t { OPEN, DOWNLOAD, @@ -155,16 +165,16 @@ static const dc_device_vtable_t hw_ostc3_device_vtable = { static const hw_ostc3_logbook_t hw_ostc3_logbook_compact = { RB_LOGBOOK_SIZE_COMPACT, /* size */ - 0, /* profile */ - 3, /* fingerprint */ - 13, /* number */ + HDR_COMPACT_LENGTH, /* profile */ + HDR_COMPACT_SUMMARY, /* fingerprint */ + HDR_COMPACT_NUMBER, /* number */ }; static const hw_ostc3_logbook_t hw_ostc3_logbook_full = { RB_LOGBOOK_SIZE_FULL, /* size */ - 9, /* profile */ - 12, /* fingerprint */ - 80, /* number */ + HDR_FULL_LENGTH, /* profile */ + HDR_FULL_SUMMARY, /* fingerprint */ + HDR_FULL_NUMBER, /* number */ }; @@ -769,7 +779,7 @@ hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, voi unsigned int length = RB_LOGBOOK_SIZE_FULL + array_uint24_le (header + offset + logbook->profile) - 3; if (!compact) { // Workaround for a bug in older firmware versions. - unsigned int firmware = array_uint16_be (header + offset + 0x30); + unsigned int firmware = array_uint16_be (header + offset + HDR_FULL_FIRMWARE); if (firmware < OSTC3FW(0,93)) length -= 3; } @@ -817,7 +827,7 @@ hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, voi unsigned int length = RB_LOGBOOK_SIZE_FULL + array_uint24_le (header + offset + logbook->profile) - 3; if (!compact) { // Workaround for a bug in older firmware versions. - unsigned int firmware = array_uint16_be (header + offset + 0x30); + unsigned int firmware = array_uint16_be (header + offset + HDR_FULL_FIRMWARE); if (firmware < OSTC3FW(0,93)) length -= 3; } @@ -853,7 +863,7 @@ hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, voi // A profile containing only the 2 byte end-of-profile // marker is considered a valid empty profile. } else if (length < RB_LOGBOOK_SIZE_FULL + 5 + 2 || - array_uint24_le (profile + RB_LOGBOOK_SIZE_FULL) + delta != array_uint24_le (profile + 9)) { + array_uint24_le (profile + RB_LOGBOOK_SIZE_FULL) + delta != array_uint24_le (profile + HDR_FULL_LENGTH)) { // If there is more data available, then there should be a // valid profile header containing a length matching the // length in the dive header. @@ -861,7 +871,7 @@ hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, voi length = RB_LOGBOOK_SIZE_FULL; } - if (callback && !callback (profile, length, profile + 12, sizeof (device->fingerprint), userdata)) + if (callback && !callback (profile, length, profile + HDR_FULL_SUMMARY, sizeof (device->fingerprint), userdata)) break; } From a99d990117c8806cb566b6a602317cd5976900ae Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 27 Oct 2022 20:14:29 +0200 Subject: [PATCH 3/5] Verify the fields of the compact header When downloading the compact headers (which is the default for recent hwOS firmware), it's not possible to compare the entire dive header, but we can at least the check the fields that are available. Also return an error if the verification fails. --- src/hw_ostc3.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c index 2b4c262..cfb25d7 100644 --- a/src/hw_ostc3.c +++ b/src/hw_ostc3.c @@ -92,10 +92,12 @@ #define HDR_COMPACT_LENGTH 0 // 3 bytes #define HDR_COMPACT_SUMMARY 3 // 10 bytes #define HDR_COMPACT_NUMBER 13 // 2 bytes +#define HDR_COMPACT_VERSION 15 // 1 byte #define HDR_FULL_LENGTH 9 // 3 bytes #define HDR_FULL_SUMMARY 12 // 10 bytes #define HDR_FULL_NUMBER 80 // 2 bytes +#define HDR_FULL_VERSION 8 // 1 byte #define HDR_FULL_FIRMWARE 48 // 2 bytes @@ -844,11 +846,16 @@ hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, voi } // Verify the header in the logbook and profile are identical. - if (!compact && memcmp (profile, header + offset, logbook->size) != 0) { + if (compact ? + memcmp (profile + HDR_FULL_LENGTH, header + offset + HDR_COMPACT_LENGTH, 3) != 0 || + memcmp (profile + HDR_FULL_SUMMARY, header + offset + HDR_COMPACT_SUMMARY, 10) != 0 || + memcmp (profile + HDR_FULL_NUMBER, header + offset + HDR_COMPACT_NUMBER, 2) != 0 || + memcmp (profile + HDR_FULL_VERSION, header + offset + HDR_COMPACT_VERSION, 1) != 0 : + memcmp (profile, header + offset, RB_LOGBOOK_SIZE_FULL) != 0) { ERROR (abstract->context, "Unexpected profile header."); free (profile); free (header); - return rc; + return DC_STATUS_DATAFORMAT; } // Detect invalid profile data. From 89ae8b94cfb10e44d04bad37a0db2cbbae8bf8c0 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 27 Oct 2022 22:02:21 +0200 Subject: [PATCH 4/5] Fix the detection of empty dive profiles Not only the two byte end-of-profile marker 0xFDFD is a valid empty dive profile, but also a profile with the length field present and set to 8 bytes. In that case the actual length will be just 5 bytes. --- src/hw_ostc3.c | 2 +- src/hw_ostc_parser.c | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c index cfb25d7..7b87587 100644 --- a/src/hw_ostc3.c +++ b/src/hw_ostc3.c @@ -869,7 +869,7 @@ hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, voi } else if (length == RB_LOGBOOK_SIZE_FULL + 2) { // A profile containing only the 2 byte end-of-profile // marker is considered a valid empty profile. - } else if (length < RB_LOGBOOK_SIZE_FULL + 5 + 2 || + } else if (length < RB_LOGBOOK_SIZE_FULL + 5 || array_uint24_le (profile + RB_LOGBOOK_SIZE_FULL) + delta != array_uint24_le (profile + HDR_FULL_LENGTH)) { // If there is more data available, then there should be a // valid profile header containing a length matching the diff --git a/src/hw_ostc_parser.c b/src/hw_ostc_parser.c index 90994f8..d745ef8 100644 --- a/src/hw_ostc_parser.c +++ b/src/hw_ostc_parser.c @@ -20,6 +20,7 @@ */ #include +#include #include "libdivecomputer/units.h" @@ -679,8 +680,10 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call const hw_ostc_layout_t *layout = parser->layout; // Exit if no profile data available. - if (size == header || (size == header + 2 && - data[header] == 0xFD && data[header + 1] == 0xFD)) { + const unsigned char empty[] = {0x08, 0x00, 0x00, 0xFD, 0xFD}; + if (size == header || + (size == header + 2 && memcmp(data + header, empty + 3, 2) == 0) || + (size == header + 5 && memcmp(data + header, empty, 5) == 0)) { parser->cached = PROFILE; return DC_STATUS_SUCCESS; } From 9508401971d3644289d8efedf4d01c107f6f5bfc Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 28 Oct 2022 22:12:04 +0200 Subject: [PATCH 5/5] Fix the download of dives without a profile At the moment, trying to download an old dive for which the profile data has already been overwritten with newer data fails. This used to work fine, but around hwOS firmware v3.10, the behaviour described in commit 76187c550a806fe422920eb8795fa687244513f1 changed. When downloading the compact/full headers, the firmware always sends the headers without inspecting their content. Next, libdivecomputer uses the length field in these headers to determine how many bytes to expect when downloading the dive. However, when downloading the entire dive, the hwOS firmware now checks whether the profile data of the dive is still available. If that's no longer the case, the firmware sends a modified dive header (with the begin/end pointer fields reset to zero, and the length field reduced to 8 bytes), along with an empty dive profile. Since libdivecomputer expects to receive the full profile as indicated in the original header, the download fails with a timeout. To workaround this problem, download the dive data in two steps. First, download the 256 byte header and check whether it has been modified. If that's the case, reduce the length to that of the 5 byte empty profile. The header check is also updated to exclude the modified fields. For the progress events, just pretend the full profile has been downloaded. --- src/hw_ostc3.c | 110 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 77 insertions(+), 33 deletions(-) diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c index 7b87587..07b7d8f 100644 --- a/src/hw_ostc3.c +++ b/src/hw_ostc3.c @@ -99,6 +99,7 @@ #define HDR_FULL_NUMBER 80 // 2 bytes #define HDR_FULL_VERSION 8 // 1 byte +#define HDR_FULL_POINTERS 2 // 6 bytes #define HDR_FULL_FIRMWARE 48 // 2 bytes typedef enum hw_ostc3_state_t { @@ -128,6 +129,7 @@ typedef struct hw_ostc3_logbook_t { unsigned int profile; unsigned int fingerprint; unsigned int number; + unsigned int version; } hw_ostc3_logbook_t; typedef struct hw_ostc3_firmware_t { @@ -170,6 +172,7 @@ static const hw_ostc3_logbook_t hw_ostc3_logbook_compact = { HDR_COMPACT_LENGTH, /* profile */ HDR_COMPACT_SUMMARY, /* fingerprint */ HDR_COMPACT_NUMBER, /* number */ + HDR_COMPACT_VERSION, /* version */ }; static const hw_ostc3_logbook_t hw_ostc3_logbook_full = { @@ -177,6 +180,7 @@ static const hw_ostc3_logbook_t hw_ostc3_logbook_full = { HDR_FULL_LENGTH, /* profile */ HDR_FULL_SUMMARY, /* fingerprint */ HDR_FULL_NUMBER, /* number */ + HDR_FULL_VERSION, /* version */ }; @@ -291,10 +295,15 @@ hw_ostc3_transfer (hw_ostc3_device_t *device, unsigned int isize, unsigned char output[], unsigned int osize, + unsigned int *actual, unsigned int delay) { dc_device_t *abstract = (dc_device_t *) device; dc_status_t status = DC_STATUS_SUCCESS; + unsigned int length = osize; + + if (cmd == DIVE && length < RB_LOGBOOK_SIZE_FULL) + return DC_STATUS_INVALIDARGS; if (device_is_cancelled (abstract)) return DC_STATUS_CANCELLED; @@ -357,11 +366,44 @@ hw_ostc3_transfer (hw_ostc3_device_t *device, } if (output) { - // Read the output data packet. - status = hw_ostc3_read (device, progress, output, osize); - if (status != DC_STATUS_SUCCESS) { - ERROR (abstract->context, "Failed to receive the answer."); - return status; + if (cmd == DIVE) { + // Read the dive header. + status = hw_ostc3_read (device, progress, output, RB_LOGBOOK_SIZE_FULL); + if (status != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to receive the dive header."); + return status; + } + + // When the hwOS firmware detects the dive profile is no longer + // valid, it sends a modified dive header (with the begin/end + // pointer fields reset to zero, and the length field reduced to 8 + // bytes), along with an empty dive profile. Detect this condition + // and adjust the expected length. + if (array_isequal (output + HDR_FULL_POINTERS, 6, 0x00) && + array_uint24_le (output + HDR_FULL_LENGTH) == 8 && + length > RB_LOGBOOK_SIZE_FULL + 5) { + length = RB_LOGBOOK_SIZE_FULL + 5; + } + + // Read the dive profile. + status = hw_ostc3_read (device, progress, output + RB_LOGBOOK_SIZE_FULL, length - RB_LOGBOOK_SIZE_FULL); + if (status != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to receive the dive profile."); + return status; + } + + // Update and emit a progress event. + if (progress && osize > length) { + progress->current += osize - length; + device_event_emit ((dc_device_t *) device, DC_EVENT_PROGRESS, progress); + } + } else { + // Read the output data packet. + status = hw_ostc3_read (device, progress, output, length); + if (status != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to receive the answer."); + return status; + } } } @@ -385,6 +427,9 @@ hw_ostc3_transfer (hw_ostc3_device_t *device, } } + if (actual) + *actual = length; + return DC_STATUS_SUCCESS; } @@ -457,9 +502,9 @@ hw_ostc3_device_id (hw_ostc3_device_t *device, unsigned char data[], unsigned in // Send the command. unsigned char hardware[SZ_HARDWARE2] = {0}; - status = hw_ostc3_transfer (device, NULL, HARDWARE2, NULL, 0, hardware, SZ_HARDWARE2, NODELAY); + status = hw_ostc3_transfer (device, NULL, HARDWARE2, NULL, 0, hardware, SZ_HARDWARE2, NULL, NODELAY); if (status == DC_STATUS_UNSUPPORTED) { - status = hw_ostc3_transfer (device, NULL, HARDWARE, NULL, 0, hardware + 1, SZ_HARDWARE, NODELAY); + status = hw_ostc3_transfer (device, NULL, HARDWARE, NULL, 0, hardware + 1, SZ_HARDWARE, NULL, NODELAY); } if (status != DC_STATUS_SUCCESS) return status; @@ -481,7 +526,7 @@ hw_ostc3_device_init_download (hw_ostc3_device_t *device) dc_context_t *context = (abstract ? abstract->context : NULL); // Send the init command. - dc_status_t status = hw_ostc3_transfer (device, NULL, INIT, NULL, 0, NULL, 0, NODELAY); + dc_status_t status = hw_ostc3_transfer (device, NULL, INIT, NULL, 0, NULL, 0, NULL, NODELAY); if (status != DC_STATUS_SUCCESS) { ERROR (context, "Failed to send the command."); return status; @@ -574,7 +619,7 @@ hw_ostc3_device_init (hw_ostc3_device_t *device, hw_ostc3_state_t state) // Read the version information. unsigned char version[SZ_VERSION] = {0}; - rc = hw_ostc3_transfer (device, NULL, IDENTITY, NULL, 0, version, sizeof(version), NODELAY); + rc = hw_ostc3_transfer (device, NULL, IDENTITY, NULL, 0, version, sizeof(version), NULL, NODELAY); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to read the version information."); return rc; @@ -604,7 +649,7 @@ hw_ostc3_device_close (dc_device_t *abstract) // Send the exit command if (device->state == DOWNLOAD || device->state == SERVICE) { - rc = hw_ostc3_transfer (device, NULL, EXIT, NULL, 0, NULL, 0, NODELAY); + rc = hw_ostc3_transfer (device, NULL, EXIT, NULL, 0, NULL, 0, NULL, NODELAY); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to send the command."); dc_status_set_error(&status, rc); @@ -648,7 +693,7 @@ hw_ostc3_device_version (dc_device_t *abstract, unsigned char data[], unsigned i return rc; // Send the command. - rc = hw_ostc3_transfer (device, NULL, IDENTITY, NULL, 0, data, size, NODELAY); + rc = hw_ostc3_transfer (device, NULL, IDENTITY, NULL, 0, data, size, NULL, NODELAY); if (rc != DC_STATUS_SUCCESS) return rc; @@ -721,11 +766,11 @@ hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, voi // This is slower, but also works for older firmware versions. unsigned int compact = 1; rc = hw_ostc3_transfer (device, &progress, COMPACT, - NULL, 0, header, RB_LOGBOOK_SIZE_COMPACT * RB_LOGBOOK_COUNT, NODELAY); + NULL, 0, header, RB_LOGBOOK_SIZE_COMPACT * RB_LOGBOOK_COUNT, NULL, NODELAY); if (rc == DC_STATUS_UNSUPPORTED) { compact = 0; rc = hw_ostc3_transfer (device, &progress, HEADER, - NULL, 0, header, RB_LOGBOOK_SIZE_FULL * RB_LOGBOOK_COUNT, NODELAY); + NULL, 0, header, RB_LOGBOOK_SIZE_FULL * RB_LOGBOOK_COUNT, NULL, NODELAY); } if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to read the header."); @@ -837,7 +882,7 @@ hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, voi // Download the dive. unsigned char number[1] = {idx}; rc = hw_ostc3_transfer (device, &progress, DIVE, - number, sizeof (number), profile, length, NODELAY); + number, sizeof (number), profile, length, &length, NODELAY); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to read the dive."); free (profile); @@ -846,12 +891,11 @@ hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, voi } // Verify the header in the logbook and profile are identical. - if (compact ? - memcmp (profile + HDR_FULL_LENGTH, header + offset + HDR_COMPACT_LENGTH, 3) != 0 || - memcmp (profile + HDR_FULL_SUMMARY, header + offset + HDR_COMPACT_SUMMARY, 10) != 0 || - memcmp (profile + HDR_FULL_NUMBER, header + offset + HDR_COMPACT_NUMBER, 2) != 0 || - memcmp (profile + HDR_FULL_VERSION, header + offset + HDR_COMPACT_VERSION, 1) != 0 : - memcmp (profile, header + offset, RB_LOGBOOK_SIZE_FULL) != 0) { + if (memcmp (profile + HDR_FULL_VERSION, header + offset + logbook->version, 1) != 0 || + compact ? + memcmp (profile + HDR_FULL_SUMMARY, header + offset + HDR_COMPACT_SUMMARY, 10) != 0 || + memcmp (profile + HDR_FULL_NUMBER, header + offset + HDR_COMPACT_NUMBER, 2) != 0 : + memcmp (profile + HDR_FULL_SUMMARY, header + offset + HDR_FULL_SUMMARY, RB_LOGBOOK_SIZE_FULL - HDR_FULL_SUMMARY) != 0) { ERROR (abstract->context, "Unexpected profile header."); free (profile); free (header); @@ -907,7 +951,7 @@ hw_ostc3_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime) unsigned char packet[6] = { datetime->hour, datetime->minute, datetime->second, datetime->month, datetime->day, datetime->year - 2000}; - rc = hw_ostc3_transfer (device, NULL, CLOCK, packet, sizeof (packet), NULL, 0, NODELAY); + rc = hw_ostc3_transfer (device, NULL, CLOCK, packet, sizeof (packet), NULL, 0, NULL, NODELAY); if (rc != DC_STATUS_SUCCESS) return rc; @@ -935,7 +979,7 @@ hw_ostc3_device_display (dc_device_t *abstract, const char *text) return rc; // Send the command. - rc = hw_ostc3_transfer (device, NULL, DISPLAY, packet, sizeof (packet), NULL, 0, NODELAY); + rc = hw_ostc3_transfer (device, NULL, DISPLAY, packet, sizeof (packet), NULL, 0, NULL, NODELAY); if (rc != DC_STATUS_SUCCESS) return rc; @@ -963,7 +1007,7 @@ hw_ostc3_device_customtext (dc_device_t *abstract, const char *text) return rc; // Send the command. - rc = hw_ostc3_transfer (device, NULL, CUSTOMTEXT, packet, sizeof (packet), NULL, 0, NODELAY); + rc = hw_ostc3_transfer (device, NULL, CUSTOMTEXT, packet, sizeof (packet), NULL, 0, NULL, NODELAY); if (rc != DC_STATUS_SUCCESS) return rc; @@ -989,7 +1033,7 @@ hw_ostc3_device_config_read (dc_device_t *abstract, unsigned int config, unsigne // Send the command. unsigned char command[1] = {config}; - rc = hw_ostc3_transfer (device, NULL, READ, command, sizeof (command), data, size, NODELAY); + rc = hw_ostc3_transfer (device, NULL, READ, command, sizeof (command), data, size, NULL, NODELAY); if (rc != DC_STATUS_SUCCESS) return rc; @@ -1016,7 +1060,7 @@ hw_ostc3_device_config_write (dc_device_t *abstract, unsigned int config, const // Send the command. unsigned char command[SZ_CONFIG + 1] = {config}; memcpy(command + 1, data, size); - rc = hw_ostc3_transfer (device, NULL, WRITE, command, size + 1, NULL, 0, NODELAY); + rc = hw_ostc3_transfer (device, NULL, WRITE, command, size + 1, NULL, 0, NULL, NODELAY); if (rc != DC_STATUS_SUCCESS) return rc; @@ -1036,7 +1080,7 @@ hw_ostc3_device_config_reset (dc_device_t *abstract) return rc; // Send the command. - rc = hw_ostc3_transfer (device, NULL, RESET, NULL, 0, NULL, 0, NODELAY); + rc = hw_ostc3_transfer (device, NULL, RESET, NULL, 0, NULL, 0, NULL, NODELAY); if (rc != DC_STATUS_SUCCESS) return rc; @@ -1262,7 +1306,7 @@ hw_ostc3_firmware_erase (hw_ostc3_device_t *device, unsigned int addr, unsigned array_uint24_be_set (buffer, addr); buffer[3] = blocks; - return hw_ostc3_transfer (device, NULL, S_ERASE, buffer, sizeof (buffer), NULL, 0, delay); + return hw_ostc3_transfer (device, NULL, S_ERASE, buffer, sizeof (buffer), NULL, 0, NULL, delay); } static dc_status_t @@ -1272,7 +1316,7 @@ hw_ostc3_firmware_block_read (hw_ostc3_device_t *device, unsigned int addr, unsi array_uint24_be_set (buffer, addr); array_uint24_be_set (buffer + 3, block_size); - return hw_ostc3_transfer (device, NULL, S_BLOCK_READ, buffer, sizeof (buffer), block, block_size, NODELAY); + return hw_ostc3_transfer (device, NULL, S_BLOCK_READ, buffer, sizeof (buffer), block, block_size, NULL, NODELAY); } static dc_status_t @@ -1287,7 +1331,7 @@ hw_ostc3_firmware_block_write1 (hw_ostc3_device_t *device, unsigned int addr, co array_uint24_be_set (buffer, addr); memcpy (buffer + 3, block, block_size); - return hw_ostc3_transfer (device, NULL, S_BLOCK_WRITE, buffer, 3 + block_size, NULL, 0, TIMEOUT); + return hw_ostc3_transfer (device, NULL, S_BLOCK_WRITE, buffer, 3 + block_size, NULL, 0, NULL, TIMEOUT); } static dc_status_t @@ -1306,7 +1350,7 @@ hw_ostc3_firmware_block_write2 (hw_ostc3_device_t *device, unsigned int address, array_uint24_be_set (buffer, address); memcpy (buffer + 3, data + nbytes, SZ_FIRMWARE_BLOCK2); - status = hw_ostc3_transfer (device, NULL, S_BLOCK_WRITE2, buffer, sizeof(buffer), NULL, 0, NODELAY); + status = hw_ostc3_transfer (device, NULL, S_BLOCK_WRITE2, buffer, sizeof(buffer), NULL, 0, NULL, NODELAY); if (status != DC_STATUS_SUCCESS) { return status; } @@ -1347,7 +1391,7 @@ hw_ostc3_firmware_upgrade (dc_device_t *abstract, unsigned int checksum) buffer[4] = (buffer[4]<<1 | buffer[4]>>7); } - rc = hw_ostc3_transfer (device, NULL, S_UPGRADE, buffer, sizeof (buffer), NULL, 0, NODELAY); + rc = hw_ostc3_transfer (device, NULL, S_UPGRADE, buffer, sizeof (buffer), NULL, 0, NULL, NODELAY); if (rc != DC_STATUS_SUCCESS) { ERROR (context, "Failed to send flash firmware command"); return rc; @@ -1529,7 +1573,7 @@ hw_ostc3_device_fwupdate4 (dc_device_t *abstract, const char *filename) // Read the firmware version info. unsigned char fwinfo[SZ_FWINFO] = {0}; status = hw_ostc3_transfer (device, NULL, S_FWINFO, - data + offset + 4, 1, fwinfo, sizeof(fwinfo), NODELAY); + data + offset + 4, 1, fwinfo, sizeof(fwinfo), NULL, NODELAY); if (status != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to read the firmware info."); goto error; @@ -1542,7 +1586,7 @@ hw_ostc3_device_fwupdate4 (dc_device_t *abstract, const char *filename) !array_isequal(fwinfo, sizeof(fwinfo), 0xFF)) { status = hw_ostc3_transfer (device, &progress, S_UPLOAD, - data + offset, length, NULL, 0, usecs / 1000); + data + offset, length, NULL, 0, NULL, usecs / 1000); if (status != DC_STATUS_SUCCESS) { goto error; }