[PATCH 10/11] Firmware upgrade for OSTC3

Anton Lundin glance at acc.umu.se
Fri Nov 21 12:28:37 PST 2014


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 at acc.umu.se>
---
 include/libdivecomputer/hw_ostc3.h |   3 +
 src/hw_ostc3.c                     | 119 ++++++++++++++++++++++++++++++++++++-
 src/libdivecomputer.symbols        |   1 +
 3 files changed, 121 insertions(+), 2 deletions(-)

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 5ca26f2..64a861b 100644
--- a/src/hw_ostc3.c
+++ b/src/hw_ostc3.c
@@ -79,6 +79,7 @@ typedef struct hw_ostc3_device_t {
 		OPEN,
 		DOWNLOAD,
 		SERVICE,
+		REBOOTING,
 	} state;
 } hw_ostc3_device_t;
 
@@ -319,7 +320,7 @@ hw_ostc3_device_close (dc_device_t *abstract)
 		return DC_STATUS_INVALIDARGS;
 
 	// Send the exit command
-	if (device->state != OPEN) {
+	if (device->state != REBOOTING && device->state != OPEN) {
 		status = hw_ostc3_transfer (device, NULL, EXIT, NULL, 0, NULL, 0);
 		if (status != DC_STATUS_SUCCESS) {
 			ERROR (abstract->context, "Failed to send the command.");
@@ -987,7 +988,121 @@ hw_ostc3_device_upgrade_firmware (dc_device_t *abstract, unsigned int checksum)
 	// Now the device resets, and if everything is well, it reprograms.
 	serial_sleep (device->port, 500);
 
-	// FIXME: How should we force the application to close the device here?
+	device->state = REBOOTING;
 
 	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;
+
+	if (device->state == OPEN) {
+		if ((rc = hw_ostc3_device_service_mode(abstract)) != DC_STATUS_SUCCESS)
+			return rc;
+	} else if (device->state != SERVICE) {
+		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);
+
+	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, " 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;
+	}
+
+	// Programing done!
+	progress.current++;
+	device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
+
+	// 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
-- 
1.9.1



More information about the devel mailing list