This function triggers a reboot into the bootloader which flashes the new firmware to Prom.
This code is inspired by JeanDo ostc-companion.
Reviewed-by: Jef Driesen jef@libdivecomputer.org Signed-off-by: Anton Lundin glance@acc.umu.se --- src/hw_ostc3.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-)
diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c index 35df0c7..06e3827 100644 --- a/src/hw_ostc3.c +++ b/src/hw_ostc3.c @@ -57,6 +57,7 @@ #define S_ERASE 0x42 #define S_READY 0x4C #define READY 0x4D +#define S_UPGRADE 0x50 #define HEADER 0x61 #define CLOCK 0x62 #define CUSTOMTEXT 0x63 @@ -73,6 +74,7 @@ typedef enum hw_ostc3_state_t { OPEN, DOWNLOAD, SERVICE, + REBOOTING, } hw_ostc3_state_t;
typedef struct hw_ostc3_device_t { @@ -329,7 +331,7 @@ hw_ostc3_device_close (dc_device_t *abstract) dc_status_t rc = DC_STATUS_SUCCESS;
// Send the exit command - if (device->state != OPEN) { + if (device->state != REBOOTING && device->state != OPEN) { rc = hw_ostc3_transfer (device, NULL, EXIT, NULL, 0, NULL, 0); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to send the command."); @@ -917,3 +919,31 @@ hw_ostc3_firmware_block_write (hw_ostc3_device_t *device, unsigned int addr, uns
return hw_ostc3_transfer (device, NULL, S_BLOCK_WRITE, buffer, sizeof(buffer), NULL, 0); } + +static dc_status_t +hw_ostc3_firmware_upgrade (dc_device_t *abstract, unsigned int checksum) +{ + 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); + unsigned char buffer[5]; + array_uint32_le_set(buffer, checksum); + + // Compute a one byte checksum, so the device can validate the firmware image. + buffer[4] = 0x55; + for(int i = 0; i < 4; i++) { + buffer[4] ^= buffer[i]; + buffer[4] = (buffer[4]<<1 | buffer[4]>>7); + } + + rc = hw_ostc3_transfer(device, NULL, S_UPGRADE, buffer, sizeof(buffer), NULL, 0); + if (rc != DC_STATUS_SUCCESS) { + ERROR (context, "Failed to send flash firmware command"); + return rc; + } + + // Now the device resets, and if everything is well, it reprograms. + device->state = REBOOTING; + + return DC_STATUS_SUCCESS; +}