This connects the bits and implements firmware upgrade for the OSTC3.
This code is inspired by JeanDo ostc-companion.
Signed-off-by: Anton Lundin glance@acc.umu.se --- include/libdivecomputer/hw_ostc3.h | 3 + src/hw_ostc3.c | 115 +++++++++++++++++++++++++++++++++++++ src/libdivecomputer.symbols | 1 + 3 files changed, 119 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 5cea5b9..e791277 100644 --- a/src/hw_ostc3.c +++ b/src/hw_ostc3.c @@ -930,3 +930,118 @@ hw_ostc3_device_upgrade_firmware (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; + // load, servicemode, erase, upload FZ, verify FZ, reprogram + progress.maximum = 3 + SZ_FIRMWARE * 2 / SZ_FIRMWARE_BLOCK; + device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + + if (!ISINSTANCE (abstract)) + return DC_STATUS_INVALIDARGS; + + hw_ostc3_device_display(abstract, " Loading FW..."); + + // 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; + } + + // Firmware loaded + progress.current++; + device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + + hw_ostc3_device_display(abstract, " Servicemode..."); + + // Set the device into servicemode + rc = hw_ostc3_service_mode(abstract); + if (rc != DC_STATUS_SUCCESS) { + free (firmware); + ERROR (context, "Failed to put device into servicemode"); + return rc; + } + + // Service mode done + progress.current++; + device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + + hw_ostc3_device_display(abstract, " Erasing FW..."); + rc = hw_ostc3_device_erase_range(device, FIRMWARE_AREA, SZ_FIRMWARE); + if (rc != DC_STATUS_SUCCESS) { + free (firmware); + ERROR (context, "Failed to erase old firmware"); + return rc; + } + + // Memory erased + progress.current++; + device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + + hw_ostc3_device_display(abstract, " Uploading..."); + + for(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_device_write_block (abstract, FIRMWARE_AREA + len, firmware->data + len, SZ_FIRMWARE_BLOCK); + if (rc != DC_STATUS_SUCCESS) { + free(firmware); + ERROR (context, "Failed to write block to device"); + return rc; + } + // One block uploaded + progress.current++; + device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + } + + hw_ostc3_device_display (abstract, " Verifying..."); + + for(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_device_read_block (device, FIRMWARE_AREA + len, block, sizeof(block)); + if (rc != DC_STATUS_SUCCESS || memcmp (firmware->data + len, block, sizeof (block)) != 0) { + hw_ostc3_device_display (abstract, " Verify FAILED"); + free (firmware); + ERROR (context, "Failed verify."); + return DC_STATUS_IO; + } + // One block verified + progress.current++; + device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + } + + hw_ostc3_device_display(abstract, " Programming..."); + + rc = hw_ostc3_device_upgrade_firmware(abstract, firmware->checksum); + if (rc != DC_STATUS_SUCCESS) { + free (firmware); + ERROR (context, "Failed to start programing"); + return rc; + } + + // Finished! + return DC_STATUS_SUCCESS; +} diff --git a/src/libdivecomputer.symbols b/src/libdivecomputer.symbols index 14a96a8..4984942 100644 --- a/src/libdivecomputer.symbols +++ b/src/libdivecomputer.symbols @@ -157,6 +157,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