From 02d8c0f04a7691b3368109634a3ac48c7cae0f97 Mon Sep 17 00:00:00 2001 From: Anton Lundin Date: Sun, 9 Nov 2014 20:44:41 +0100 Subject: [PATCH] Firmware upgrade for OSTC3 This connects the bits and implements firmware upgrade for the OSTC3. This code is inspired by JeanDo ostc-companion. Reviewed-by: Jef Driesen Signed-off-by: Anton Lundin --- include/libdivecomputer/hw_ostc3.h | 3 + src/hw_ostc3.c | 127 +++++++++++++++++++++++++++++ src/libdivecomputer.symbols | 1 + 3 files changed, 131 insertions(+) diff --git a/include/libdivecomputer/hw_ostc3.h b/include/libdivecomputer/hw_ostc3.h index 267b7e3..bc56a9d 100644 --- a/include/libdivecomputer/hw_ostc3.h +++ b/include/libdivecomputer/hw_ostc3.h @@ -58,6 +58,9 @@ hw_ostc3_device_config_write (dc_device_t *abstract, unsigned int config, const dc_status_t hw_ostc3_device_config_reset (dc_device_t *abstract); +dc_status_t +hw_ostc3_device_fwupdate (dc_device_t *abstract, const char *filename); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c index 7ebd8c5..33e4de6 100644 --- a/src/hw_ostc3.c +++ b/src/hw_ostc3.c @@ -33,6 +33,10 @@ #include "array.h" #include "aes.h" +#ifdef _MSC_VER +#define snprintf _snprintf +#endif + #define ISINSTANCE(device) dc_device_isinstance((device), &hw_ostc3_device_vtable) #define EXITCODE(rc) \ @@ -947,3 +951,126 @@ hw_ostc3_firmware_upgrade (dc_device_t *abstract, unsigned int checksum) return DC_STATUS_SUCCESS; } + + +dc_status_t +hw_ostc3_device_fwupdate (dc_device_t *abstract, const char *filename) +{ + dc_status_t rc = DC_STATUS_SUCCESS; + hw_ostc3_device_t *device = (hw_ostc3_device_t *) abstract; + dc_context_t *context = (abstract ? abstract->context : NULL); + + // Enable progress notifications. + dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER; + + if (!ISINSTANCE (abstract)) + return DC_STATUS_INVALIDARGS; + + // load, erase, upload FZ, verify FZ, reprogram + progress.maximum = 3 + SZ_FIRMWARE * 2 / SZ_FIRMWARE_BLOCK; + device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + + // Allocate memory for the firmware data. + hw_ostc3_firmware_t *firmware = (hw_ostc3_firmware_t *) malloc (sizeof (hw_ostc3_firmware_t)); + if (firmware == NULL) { + ERROR (context, "Failed to allocate memory."); + return DC_STATUS_NOMEMORY; + } + + // Read the hex file. + rc = hw_ostc3_firmware_readfile (firmware, context, filename); + if (rc != DC_STATUS_SUCCESS) { + free (firmware); + return rc; + } + + // Make sure the device is in service mode + if (device->state == OPEN) { + rc = hw_ostc3_device_init_service (device); + if (rc != DC_STATUS_SUCCESS) { + free (firmware); + return rc; + } + } else if (device->state != SERVICE) { + free (firmware); + return DC_STATUS_INVALIDARGS; + } + + // Device open and firmware loaded + progress.current++; + device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + + hw_ostc3_device_display (abstract, " Erasing FW..."); + + rc = hw_ostc3_firmware_erase (device, FIRMWARE_AREA, SZ_FIRMWARE); + if (rc != DC_STATUS_SUCCESS) { + ERROR (context, "Failed to erase old firmware"); + free (firmware); + return rc; + } + + // Memory erased + progress.current++; + device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + + hw_ostc3_device_display (abstract, " Uploading..."); + + for (unsigned int len = 0; len < SZ_FIRMWARE; len += SZ_FIRMWARE_BLOCK) { + char status[16]; // Status message on the display + snprintf (status, 16, " Uploading %2d%%", (100 * len) / SZ_FIRMWARE); + hw_ostc3_device_display (abstract, status); + + rc = hw_ostc3_firmware_block_write (device, FIRMWARE_AREA + len, firmware->data + len, SZ_FIRMWARE_BLOCK); + if (rc != DC_STATUS_SUCCESS) { + ERROR (context, "Failed to write block to device"); + free(firmware); + return rc; + } + // One block uploaded + progress.current++; + device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + } + + hw_ostc3_device_display (abstract, " Verifying..."); + + for (unsigned int len = 0; len < SZ_FIRMWARE; len += SZ_FIRMWARE_BLOCK) { + unsigned char block[SZ_FIRMWARE_BLOCK]; + char status[16]; // Status message on the display + snprintf (status, 16, " Verifying %2d%%", (100 * len) / SZ_FIRMWARE); + hw_ostc3_device_display (abstract, status); + + rc = hw_ostc3_firmware_block_read (device, FIRMWARE_AREA + len, block, sizeof (block)); + if (rc != DC_STATUS_SUCCESS) { + ERROR (context, "Failed to read block."); + free (firmware); + return rc; + } + if (memcmp (firmware->data + len, block, sizeof (block)) != 0) { + ERROR (context, "Failed verify."); + hw_ostc3_device_display (abstract, " Verify FAILED"); + free (firmware); + return DC_STATUS_PROTOCOL; + } + // One block verified + progress.current++; + device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + } + + hw_ostc3_device_display (abstract, " Programming..."); + + rc = hw_ostc3_firmware_upgrade (abstract, firmware->checksum); + if (rc != DC_STATUS_SUCCESS) { + ERROR (context, "Failed to start programing"); + free (firmware); + return rc; + } + + // Programing done! + progress.current++; + device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + + free (firmware); + + // Finished! + return DC_STATUS_SUCCESS; +} diff --git a/src/libdivecomputer.symbols b/src/libdivecomputer.symbols index 8dfd7be..8109f96 100644 --- a/src/libdivecomputer.symbols +++ b/src/libdivecomputer.symbols @@ -160,6 +160,7 @@ hw_ostc3_device_customtext hw_ostc3_device_config_read hw_ostc3_device_config_write hw_ostc3_device_config_reset +hw_ostc3_device_fwupdate zeagle_n2ition3_device_open atomics_cobalt_device_open atomics_cobalt_device_version