Etherios Cloud Connector very first porting for mbed. Tested in an LPC1768
Etherios Cloud Connector for Embedded v2.1.0.3 library for mbed. Early porting.
This port is centered mainly in the platform code. So it should work properly with the provided examples of send_data, device_request, data_points, RCI and firmware_update (stub implementation, not a real one... yet ;-)). Filesystem is not implemented yet, and some examples might need changes.
To run, it needs the following libraries: - mbed - mbed-rtos - EthernetInterface
Find more information (and the source code!) about Etherios Cloud Connector for Embedded here: http://www.etherios.com/products/devicecloud/support/connector and in: http://www.etherios.com
private/connector_firmware.h@0:1c358ea10753, 2013-12-03 (annotated)
- Committer:
- spastor
- Date:
- Tue Dec 03 13:34:02 2013 +0000
- Revision:
- 0:1c358ea10753
First commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
spastor | 0:1c358ea10753 | 1 | /* |
spastor | 0:1c358ea10753 | 2 | * Copyright (c) 2013 Digi International Inc., |
spastor | 0:1c358ea10753 | 3 | * All rights not expressly granted are reserved. |
spastor | 0:1c358ea10753 | 4 | * |
spastor | 0:1c358ea10753 | 5 | * This Source Code Form is subject to the terms of the Mozilla Public |
spastor | 0:1c358ea10753 | 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
spastor | 0:1c358ea10753 | 7 | * You can obtain one at http://mozilla.org/MPL/2.0/. |
spastor | 0:1c358ea10753 | 8 | * |
spastor | 0:1c358ea10753 | 9 | * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343 |
spastor | 0:1c358ea10753 | 10 | * ======================================================================= |
spastor | 0:1c358ea10753 | 11 | */ |
spastor | 0:1c358ea10753 | 12 | |
spastor | 0:1c358ea10753 | 13 | #define FW_ID_STRING_LENGTH 128 /* bytes */ |
spastor | 0:1c358ea10753 | 14 | |
spastor | 0:1c358ea10753 | 15 | /* time to send target list to keep download alive */ |
spastor | 0:1c358ea10753 | 16 | #define FW_TARGET_LIST_MSG_INTERVAL_IN_SECONDS 30 |
spastor | 0:1c358ea10753 | 17 | |
spastor | 0:1c358ea10753 | 18 | /** |
spastor | 0:1c358ea10753 | 19 | * Firmware Upgrade Facility Opcodes |
spastor | 0:1c358ea10753 | 20 | * @doc These are the valid opcodes for the Firmware Upgrade Facility |
spastor | 0:1c358ea10753 | 21 | */ |
spastor | 0:1c358ea10753 | 22 | typedef enum { |
spastor | 0:1c358ea10753 | 23 | fw_target_list_opcode, |
spastor | 0:1c358ea10753 | 24 | fw_info_request_opcode, |
spastor | 0:1c358ea10753 | 25 | fw_info_response_opcode, |
spastor | 0:1c358ea10753 | 26 | fw_download_request_opcode, |
spastor | 0:1c358ea10753 | 27 | fw_download_response_opcode, |
spastor | 0:1c358ea10753 | 28 | fw_binary_block_opcode, |
spastor | 0:1c358ea10753 | 29 | fw_binary_block_ack_opcode, |
spastor | 0:1c358ea10753 | 30 | fw_download_abort_opcode, |
spastor | 0:1c358ea10753 | 31 | fw_download_complete_opcode, |
spastor | 0:1c358ea10753 | 32 | fw_download_complete_response_opcode, |
spastor | 0:1c358ea10753 | 33 | fw_target_reset_opcode, |
spastor | 0:1c358ea10753 | 34 | fw_download_status_opcode, |
spastor | 0:1c358ea10753 | 35 | fw_error_opcode |
spastor | 0:1c358ea10753 | 36 | } fw_opcodes_t; |
spastor | 0:1c358ea10753 | 37 | |
spastor | 0:1c358ea10753 | 38 | typedef union { |
spastor | 0:1c358ea10753 | 39 | enum { |
spastor | 0:1c358ea10753 | 40 | fw_invalid_target, |
spastor | 0:1c358ea10753 | 41 | fw_invalid_opcode, |
spastor | 0:1c358ea10753 | 42 | fw_invalid_msg |
spastor | 0:1c358ea10753 | 43 | } error_status; |
spastor | 0:1c358ea10753 | 44 | |
spastor | 0:1c358ea10753 | 45 | enum { |
spastor | 0:1c358ea10753 | 46 | fw_user_abort, |
spastor | 0:1c358ea10753 | 47 | fw_device_error, |
spastor | 0:1c358ea10753 | 48 | fw_invalid_offset, |
spastor | 0:1c358ea10753 | 49 | fw_invalid_data, |
spastor | 0:1c358ea10753 | 50 | fw_hardware_error |
spastor | 0:1c358ea10753 | 51 | } abort_status; |
spastor | 0:1c358ea10753 | 52 | |
spastor | 0:1c358ea10753 | 53 | connector_firmware_status_t user_status; |
spastor | 0:1c358ea10753 | 54 | |
spastor | 0:1c358ea10753 | 55 | } fw_abort_status_t; |
spastor | 0:1c358ea10753 | 56 | |
spastor | 0:1c358ea10753 | 57 | /* Firmware message header format: |
spastor | 0:1c358ea10753 | 58 | * ------------------------ |
spastor | 0:1c358ea10753 | 59 | * | 0 | 1 | 3... | |
spastor | 0:1c358ea10753 | 60 | * ------------------------ |
spastor | 0:1c358ea10753 | 61 | * | opcode | target | data | |
spastor | 0:1c358ea10753 | 62 | * ------------------------ |
spastor | 0:1c358ea10753 | 63 | * |
spastor | 0:1c358ea10753 | 64 | */ |
spastor | 0:1c358ea10753 | 65 | enum fw_message { |
spastor | 0:1c358ea10753 | 66 | field_define(fw_message, opcode, uint8_t), |
spastor | 0:1c358ea10753 | 67 | field_define(fw_message, target, uint8_t), |
spastor | 0:1c358ea10753 | 68 | record_end(fw_message) |
spastor | 0:1c358ea10753 | 69 | }; |
spastor | 0:1c358ea10753 | 70 | #define FW_MESSAGE_HEADER_SIZE record_bytes(fw_message) |
spastor | 0:1c358ea10753 | 71 | #define FW_MESSAGE_RESPONSE_MAX_SIZE 16 |
spastor | 0:1c358ea10753 | 72 | |
spastor | 0:1c358ea10753 | 73 | enum fw_target_list_hdr { |
spastor | 0:1c358ea10753 | 74 | field_define(fw_target_list, opcode, uint8_t) |
spastor | 0:1c358ea10753 | 75 | }; |
spastor | 0:1c358ea10753 | 76 | |
spastor | 0:1c358ea10753 | 77 | /* target + version pairs format: */ |
spastor | 0:1c358ea10753 | 78 | enum fw_target_list{ |
spastor | 0:1c358ea10753 | 79 | field_define(fw_target_list, target, uint8_t), |
spastor | 0:1c358ea10753 | 80 | field_define(fw_target_list, version, uint32_t), |
spastor | 0:1c358ea10753 | 81 | record_end(fw_target_list) |
spastor | 0:1c358ea10753 | 82 | }; |
spastor | 0:1c358ea10753 | 83 | |
spastor | 0:1c358ea10753 | 84 | #define FW_VERSION_NUMBER(version) (MAKE32_4(version.major, version.minor, version.revision, version.build)) |
spastor | 0:1c358ea10753 | 85 | |
spastor | 0:1c358ea10753 | 86 | static size_t const target_list_header_size = field_named_data(fw_target_list, opcode, size); |
spastor | 0:1c358ea10753 | 87 | static size_t const target_list_size = record_bytes(fw_target_list); |
spastor | 0:1c358ea10753 | 88 | |
spastor | 0:1c358ea10753 | 89 | typedef struct { |
spastor | 0:1c358ea10753 | 90 | connector_data_t * connector_ptr; |
spastor | 0:1c358ea10753 | 91 | unsigned long last_fw_keepalive_sent_time; |
spastor | 0:1c358ea10753 | 92 | |
spastor | 0:1c358ea10753 | 93 | size_t desc_length; |
spastor | 0:1c358ea10753 | 94 | size_t spec_length; |
spastor | 0:1c358ea10753 | 95 | size_t response_size; |
spastor | 0:1c358ea10753 | 96 | connector_bool_t send_busy; |
spastor | 0:1c358ea10753 | 97 | connector_bool_t update_started; |
spastor | 0:1c358ea10753 | 98 | connector_bool_t fw_keepalive_start; |
spastor | 0:1c358ea10753 | 99 | connector_firmware_info_t target_info; |
spastor | 0:1c358ea10753 | 100 | |
spastor | 0:1c358ea10753 | 101 | uint8_t response_buffer[FW_MESSAGE_RESPONSE_MAX_SIZE + PACKET_EDP_FACILITY_SIZE]; |
spastor | 0:1c358ea10753 | 102 | uint8_t target_count; |
spastor | 0:1c358ea10753 | 103 | } connector_firmware_data_t; |
spastor | 0:1c358ea10753 | 104 | |
spastor | 0:1c358ea10753 | 105 | #if defined CONNECTOR_RCI_SERVICE |
spastor | 0:1c358ea10753 | 106 | static connector_status_t confirm_fw_version(connector_firmware_data_t * const fw_ptr, uint8_t target_number, connector_firmware_version_t const version) |
spastor | 0:1c358ea10753 | 107 | { |
spastor | 0:1c358ea10753 | 108 | connector_status_t result = connector_working; |
spastor | 0:1c358ea10753 | 109 | uint32_t const version_number = FW_VERSION_NUMBER(version); |
spastor | 0:1c358ea10753 | 110 | |
spastor | 0:1c358ea10753 | 111 | if (target_number == 0 && version_number != rci_get_firmware_target_zero_version()) |
spastor | 0:1c358ea10753 | 112 | { |
spastor | 0:1c358ea10753 | 113 | connector_data_t * const connector_ptr = fw_ptr->connector_ptr; |
spastor | 0:1c358ea10753 | 114 | connector_request_id_t request_id; |
spastor | 0:1c358ea10753 | 115 | |
spastor | 0:1c358ea10753 | 116 | connector_debug_printf("confirm_fw_version: 0x%X != FIRMWARE_TARGET_ZERO_VERSION (0x%X)\n", version_number, rci_get_firmware_target_zero_version()); |
spastor | 0:1c358ea10753 | 117 | request_id.firmware_request = connector_request_id_firmware_info; |
spastor | 0:1c358ea10753 | 118 | if (notify_error_status(connector_ptr->callback, connector_class_id_firmware, request_id, connector_bad_version) != connector_working) |
spastor | 0:1c358ea10753 | 119 | { |
spastor | 0:1c358ea10753 | 120 | result = connector_abort; |
spastor | 0:1c358ea10753 | 121 | } |
spastor | 0:1c358ea10753 | 122 | } |
spastor | 0:1c358ea10753 | 123 | return result; |
spastor | 0:1c358ea10753 | 124 | } |
spastor | 0:1c358ea10753 | 125 | #endif |
spastor | 0:1c358ea10753 | 126 | |
spastor | 0:1c358ea10753 | 127 | static connector_status_t get_fw_config(connector_firmware_data_t * const fw_ptr, |
spastor | 0:1c358ea10753 | 128 | connector_request_id_firmware_t const fw_request_id, |
spastor | 0:1c358ea10753 | 129 | void * const data) |
spastor | 0:1c358ea10753 | 130 | { |
spastor | 0:1c358ea10753 | 131 | |
spastor | 0:1c358ea10753 | 132 | connector_data_t * const connector_ptr = fw_ptr->connector_ptr; |
spastor | 0:1c358ea10753 | 133 | connector_status_t result = connector_working; |
spastor | 0:1c358ea10753 | 134 | |
spastor | 0:1c358ea10753 | 135 | unsigned long end_time_stamp = 0; |
spastor | 0:1c358ea10753 | 136 | |
spastor | 0:1c358ea10753 | 137 | { |
spastor | 0:1c358ea10753 | 138 | connector_request_id_t request_id; |
spastor | 0:1c358ea10753 | 139 | connector_callback_status_t status; |
spastor | 0:1c358ea10753 | 140 | |
spastor | 0:1c358ea10753 | 141 | request_id.firmware_request = fw_request_id; |
spastor | 0:1c358ea10753 | 142 | status = connector_callback(connector_ptr->callback, connector_class_id_firmware, request_id, data); |
spastor | 0:1c358ea10753 | 143 | |
spastor | 0:1c358ea10753 | 144 | if (get_system_time(connector_ptr, &end_time_stamp) != connector_working) |
spastor | 0:1c358ea10753 | 145 | { |
spastor | 0:1c358ea10753 | 146 | result = connector_abort; |
spastor | 0:1c358ea10753 | 147 | goto done; |
spastor | 0:1c358ea10753 | 148 | } |
spastor | 0:1c358ea10753 | 149 | |
spastor | 0:1c358ea10753 | 150 | switch (status) |
spastor | 0:1c358ea10753 | 151 | { |
spastor | 0:1c358ea10753 | 152 | case connector_callback_continue: |
spastor | 0:1c358ea10753 | 153 | break; |
spastor | 0:1c358ea10753 | 154 | case connector_callback_busy: |
spastor | 0:1c358ea10753 | 155 | result = connector_pending; |
spastor | 0:1c358ea10753 | 156 | break; |
spastor | 0:1c358ea10753 | 157 | case connector_callback_abort: |
spastor | 0:1c358ea10753 | 158 | case connector_callback_unrecognized: |
spastor | 0:1c358ea10753 | 159 | case connector_callback_error: |
spastor | 0:1c358ea10753 | 160 | result = connector_abort; |
spastor | 0:1c358ea10753 | 161 | goto done; |
spastor | 0:1c358ea10753 | 162 | } |
spastor | 0:1c358ea10753 | 163 | } |
spastor | 0:1c358ea10753 | 164 | |
spastor | 0:1c358ea10753 | 165 | if (result == connector_pending && fw_ptr->last_fw_keepalive_sent_time > 0) |
spastor | 0:1c358ea10753 | 166 | { |
spastor | 0:1c358ea10753 | 167 | /* |
spastor | 0:1c358ea10753 | 168 | * Check whether we need to send target list message |
spastor | 0:1c358ea10753 | 169 | * to keep connection alive. |
spastor | 0:1c358ea10753 | 170 | */ |
spastor | 0:1c358ea10753 | 171 | fw_ptr->fw_keepalive_start = ((end_time_stamp - fw_ptr->last_fw_keepalive_sent_time) >= FW_TARGET_LIST_MSG_INTERVAL_IN_SECONDS) ? connector_true : connector_false; |
spastor | 0:1c358ea10753 | 172 | } |
spastor | 0:1c358ea10753 | 173 | else |
spastor | 0:1c358ea10753 | 174 | { |
spastor | 0:1c358ea10753 | 175 | fw_ptr->fw_keepalive_start = connector_false; |
spastor | 0:1c358ea10753 | 176 | } |
spastor | 0:1c358ea10753 | 177 | |
spastor | 0:1c358ea10753 | 178 | done: |
spastor | 0:1c358ea10753 | 179 | return result; |
spastor | 0:1c358ea10753 | 180 | } |
spastor | 0:1c358ea10753 | 181 | |
spastor | 0:1c358ea10753 | 182 | static fw_abort_status_t get_abort_status_code(connector_firmware_status_t const status) |
spastor | 0:1c358ea10753 | 183 | { |
spastor | 0:1c358ea10753 | 184 | fw_abort_status_t code; |
spastor | 0:1c358ea10753 | 185 | |
spastor | 0:1c358ea10753 | 186 | code.abort_status = fw_user_abort; |
spastor | 0:1c358ea10753 | 187 | |
spastor | 0:1c358ea10753 | 188 | /* convert status to abort status code for abort message */ |
spastor | 0:1c358ea10753 | 189 | switch (status) |
spastor | 0:1c358ea10753 | 190 | { |
spastor | 0:1c358ea10753 | 191 | case connector_firmware_status_user_abort: |
spastor | 0:1c358ea10753 | 192 | code.abort_status = fw_user_abort; |
spastor | 0:1c358ea10753 | 193 | break; |
spastor | 0:1c358ea10753 | 194 | case connector_firmware_status_invalid_offset: |
spastor | 0:1c358ea10753 | 195 | code.abort_status = fw_invalid_offset; |
spastor | 0:1c358ea10753 | 196 | break; |
spastor | 0:1c358ea10753 | 197 | case connector_firmware_status_invalid_data: |
spastor | 0:1c358ea10753 | 198 | code.abort_status = fw_invalid_data; |
spastor | 0:1c358ea10753 | 199 | break; |
spastor | 0:1c358ea10753 | 200 | case connector_firmware_status_hardware_error: |
spastor | 0:1c358ea10753 | 201 | code.abort_status = fw_hardware_error; |
spastor | 0:1c358ea10753 | 202 | break; |
spastor | 0:1c358ea10753 | 203 | case connector_firmware_status_device_error: |
spastor | 0:1c358ea10753 | 204 | case connector_firmware_status_download_denied: |
spastor | 0:1c358ea10753 | 205 | case connector_firmware_status_download_invalid_size: |
spastor | 0:1c358ea10753 | 206 | case connector_firmware_status_download_invalid_version: |
spastor | 0:1c358ea10753 | 207 | case connector_firmware_status_download_unauthenticated: |
spastor | 0:1c358ea10753 | 208 | case connector_firmware_status_download_not_allowed: |
spastor | 0:1c358ea10753 | 209 | case connector_firmware_status_download_configured_to_reject: |
spastor | 0:1c358ea10753 | 210 | case connector_firmware_status_encountered_error: |
spastor | 0:1c358ea10753 | 211 | /* not abort status so default to device error */ |
spastor | 0:1c358ea10753 | 212 | code.abort_status = fw_device_error; |
spastor | 0:1c358ea10753 | 213 | break; |
spastor | 0:1c358ea10753 | 214 | case connector_firmware_status_success: |
spastor | 0:1c358ea10753 | 215 | ASSERT(connector_false); |
spastor | 0:1c358ea10753 | 216 | break; |
spastor | 0:1c358ea10753 | 217 | |
spastor | 0:1c358ea10753 | 218 | } |
spastor | 0:1c358ea10753 | 219 | return code; |
spastor | 0:1c358ea10753 | 220 | } |
spastor | 0:1c358ea10753 | 221 | |
spastor | 0:1c358ea10753 | 222 | /* abort and error message format: |
spastor | 0:1c358ea10753 | 223 | * -------------------------- |
spastor | 0:1c358ea10753 | 224 | * | 0 | 1 | 2 | |
spastor | 0:1c358ea10753 | 225 | * -------------------------- |
spastor | 0:1c358ea10753 | 226 | * | opcode | target | status | |
spastor | 0:1c358ea10753 | 227 | * -------------------------- |
spastor | 0:1c358ea10753 | 228 | * |
spastor | 0:1c358ea10753 | 229 | */ |
spastor | 0:1c358ea10753 | 230 | enum fw_abort { |
spastor | 0:1c358ea10753 | 231 | field_define(fw_abort, opcode, uint8_t), |
spastor | 0:1c358ea10753 | 232 | field_define(fw_abort, target, uint8_t), |
spastor | 0:1c358ea10753 | 233 | field_define(fw_abort, status, uint8_t), |
spastor | 0:1c358ea10753 | 234 | record_end(fw_abort) |
spastor | 0:1c358ea10753 | 235 | }; |
spastor | 0:1c358ea10753 | 236 | |
spastor | 0:1c358ea10753 | 237 | #define FW_ABORT_HEADER_SIZE record_bytes(fw_abort) |
spastor | 0:1c358ea10753 | 238 | |
spastor | 0:1c358ea10753 | 239 | static connector_status_t send_fw_message(connector_firmware_data_t * const fw_ptr) |
spastor | 0:1c358ea10753 | 240 | { |
spastor | 0:1c358ea10753 | 241 | |
spastor | 0:1c358ea10753 | 242 | connector_status_t result; |
spastor | 0:1c358ea10753 | 243 | |
spastor | 0:1c358ea10753 | 244 | result = tcp_initiate_send_facility_packet(fw_ptr->connector_ptr, fw_ptr->response_buffer, fw_ptr->response_size, E_MSG_FAC_FW_NUM, NULL, NULL); |
spastor | 0:1c358ea10753 | 245 | fw_ptr->send_busy = (result == connector_pending) ? connector_true : connector_false; |
spastor | 0:1c358ea10753 | 246 | return result; |
spastor | 0:1c358ea10753 | 247 | |
spastor | 0:1c358ea10753 | 248 | } |
spastor | 0:1c358ea10753 | 249 | |
spastor | 0:1c358ea10753 | 250 | static connector_status_t send_fw_abort(connector_firmware_data_t * const fw_ptr, uint8_t const target, uint8_t const msg_opcode, fw_abort_status_t const abort_status) |
spastor | 0:1c358ea10753 | 251 | { |
spastor | 0:1c358ea10753 | 252 | |
spastor | 0:1c358ea10753 | 253 | connector_status_t result; |
spastor | 0:1c358ea10753 | 254 | |
spastor | 0:1c358ea10753 | 255 | uint8_t * fw_abort = GET_PACKET_DATA_POINTER(fw_ptr->response_buffer, PACKET_EDP_FACILITY_SIZE); |
spastor | 0:1c358ea10753 | 256 | uint8_t abort_code = (uint8_t)abort_status.error_status; |
spastor | 0:1c358ea10753 | 257 | |
spastor | 0:1c358ea10753 | 258 | ASSERT(abort_status.error_status <= UCHAR_MAX); |
spastor | 0:1c358ea10753 | 259 | |
spastor | 0:1c358ea10753 | 260 | /* need to adjust abort status code in the fw_status_t */ |
spastor | 0:1c358ea10753 | 261 | if (msg_opcode != fw_error_opcode) |
spastor | 0:1c358ea10753 | 262 | { |
spastor | 0:1c358ea10753 | 263 | fw_abort_status_t status; |
spastor | 0:1c358ea10753 | 264 | status = get_abort_status_code(abort_status.user_status); |
spastor | 0:1c358ea10753 | 265 | |
spastor | 0:1c358ea10753 | 266 | ASSERT(status.abort_status <= UCHAR_MAX); |
spastor | 0:1c358ea10753 | 267 | abort_code = (uint8_t)status.abort_status; |
spastor | 0:1c358ea10753 | 268 | |
spastor | 0:1c358ea10753 | 269 | } |
spastor | 0:1c358ea10753 | 270 | |
spastor | 0:1c358ea10753 | 271 | ASSERT((sizeof fw_ptr->response_buffer - PACKET_EDP_FACILITY_SIZE) > FW_ABORT_HEADER_SIZE); |
spastor | 0:1c358ea10753 | 272 | |
spastor | 0:1c358ea10753 | 273 | /* build abort message */ |
spastor | 0:1c358ea10753 | 274 | message_store_u8(fw_abort, opcode, msg_opcode); |
spastor | 0:1c358ea10753 | 275 | message_store_u8(fw_abort, target, target); |
spastor | 0:1c358ea10753 | 276 | message_store_u8(fw_abort, status, abort_code); |
spastor | 0:1c358ea10753 | 277 | |
spastor | 0:1c358ea10753 | 278 | fw_ptr->response_size = FW_ABORT_HEADER_SIZE; |
spastor | 0:1c358ea10753 | 279 | result = send_fw_message(fw_ptr); |
spastor | 0:1c358ea10753 | 280 | |
spastor | 0:1c358ea10753 | 281 | if (fw_ptr->target_info.target_number == target) |
spastor | 0:1c358ea10753 | 282 | { |
spastor | 0:1c358ea10753 | 283 | fw_ptr->update_started = connector_false; |
spastor | 0:1c358ea10753 | 284 | } |
spastor | 0:1c358ea10753 | 285 | return result; |
spastor | 0:1c358ea10753 | 286 | |
spastor | 0:1c358ea10753 | 287 | } |
spastor | 0:1c358ea10753 | 288 | |
spastor | 0:1c358ea10753 | 289 | static connector_status_t process_fw_info_request(connector_firmware_data_t * const fw_ptr, uint8_t * const fw_message, uint16_t const length) |
spastor | 0:1c358ea10753 | 290 | { |
spastor | 0:1c358ea10753 | 291 | /* firmware info response message format: |
spastor | 0:1c358ea10753 | 292 | * --------------------------------------------------- |
spastor | 0:1c358ea10753 | 293 | * | 0 | 1 | 2 - 5 | 6 - 9 | 10 ... | |
spastor | 0:1c358ea10753 | 294 | * --------------------------------------------------- |
spastor | 0:1c358ea10753 | 295 | * | opcode | target | version | Available | Firmware | |
spastor | 0:1c358ea10753 | 296 | * | | | | code size | ID string | |
spastor | 0:1c358ea10753 | 297 | * --------------------------------------------------- |
spastor | 0:1c358ea10753 | 298 | * |
spastor | 0:1c358ea10753 | 299 | * Firmware ID string = [descr]0xa[file name spec] |
spastor | 0:1c358ea10753 | 300 | */ |
spastor | 0:1c358ea10753 | 301 | enum fw_info { |
spastor | 0:1c358ea10753 | 302 | field_define(fw_info, opcode, uint8_t), |
spastor | 0:1c358ea10753 | 303 | field_define(fw_info, target, uint8_t), |
spastor | 0:1c358ea10753 | 304 | field_define(fw_info, version, uint32_t), |
spastor | 0:1c358ea10753 | 305 | field_define(fw_info, code_size, uint32_t), |
spastor | 0:1c358ea10753 | 306 | record_end(fw_info) |
spastor | 0:1c358ea10753 | 307 | }; |
spastor | 0:1c358ea10753 | 308 | |
spastor | 0:1c358ea10753 | 309 | #define MAX_FW_INFO_REQUEST_LENGTH 2 |
spastor | 0:1c358ea10753 | 310 | |
spastor | 0:1c358ea10753 | 311 | connector_data_t * const connector_ptr = fw_ptr->connector_ptr; |
spastor | 0:1c358ea10753 | 312 | connector_status_t result = connector_idle; |
spastor | 0:1c358ea10753 | 313 | uint8_t const target = message_load_u8(fw_message, target); |
spastor | 0:1c358ea10753 | 314 | |
spastor | 0:1c358ea10753 | 315 | connector_debug_printf("Firmware Facility: process info request\n"); |
spastor | 0:1c358ea10753 | 316 | /* parse firmware info request |
spastor | 0:1c358ea10753 | 317 | * ----------------- |
spastor | 0:1c358ea10753 | 318 | * | 0 | 1 | |
spastor | 0:1c358ea10753 | 319 | * ----------------- |
spastor | 0:1c358ea10753 | 320 | * | opcode | target | |
spastor | 0:1c358ea10753 | 321 | * ----------------- |
spastor | 0:1c358ea10753 | 322 | */ |
spastor | 0:1c358ea10753 | 323 | fw_ptr->last_fw_keepalive_sent_time = 0; |
spastor | 0:1c358ea10753 | 324 | fw_ptr->fw_keepalive_start = connector_false; |
spastor | 0:1c358ea10753 | 325 | |
spastor | 0:1c358ea10753 | 326 | if (length != MAX_FW_INFO_REQUEST_LENGTH) |
spastor | 0:1c358ea10753 | 327 | { |
spastor | 0:1c358ea10753 | 328 | fw_abort_status_t fw_status; |
spastor | 0:1c358ea10753 | 329 | connector_debug_printf("process_fw_info_request: invalid message length\n"); |
spastor | 0:1c358ea10753 | 330 | |
spastor | 0:1c358ea10753 | 331 | fw_status.error_status = fw_invalid_msg; |
spastor | 0:1c358ea10753 | 332 | result = send_fw_abort(fw_ptr, target, fw_error_opcode, fw_status); |
spastor | 0:1c358ea10753 | 333 | goto done; |
spastor | 0:1c358ea10753 | 334 | |
spastor | 0:1c358ea10753 | 335 | } |
spastor | 0:1c358ea10753 | 336 | |
spastor | 0:1c358ea10753 | 337 | /* let's get and build target info response */ |
spastor | 0:1c358ea10753 | 338 | { |
spastor | 0:1c358ea10753 | 339 | connector_firmware_info_t * firmware_info = &fw_ptr->target_info; |
spastor | 0:1c358ea10753 | 340 | |
spastor | 0:1c358ea10753 | 341 | firmware_info->target_number = target; |
spastor | 0:1c358ea10753 | 342 | |
spastor | 0:1c358ea10753 | 343 | result = get_fw_config(fw_ptr, connector_request_id_firmware_info, firmware_info); |
spastor | 0:1c358ea10753 | 344 | if (result != connector_working) |
spastor | 0:1c358ea10753 | 345 | { |
spastor | 0:1c358ea10753 | 346 | goto done; |
spastor | 0:1c358ea10753 | 347 | } |
spastor | 0:1c358ea10753 | 348 | #if defined CONNECTOR_RCI_SERVICE |
spastor | 0:1c358ea10753 | 349 | else |
spastor | 0:1c358ea10753 | 350 | { |
spastor | 0:1c358ea10753 | 351 | result = confirm_fw_version(fw_ptr, firmware_info->target_number, firmware_info->version); |
spastor | 0:1c358ea10753 | 352 | } |
spastor | 0:1c358ea10753 | 353 | #endif |
spastor | 0:1c358ea10753 | 354 | fw_ptr->desc_length = strlen(firmware_info->description); |
spastor | 0:1c358ea10753 | 355 | fw_ptr->spec_length = strlen(firmware_info->filespec); |
spastor | 0:1c358ea10753 | 356 | |
spastor | 0:1c358ea10753 | 357 | if ((fw_ptr->desc_length + fw_ptr->spec_length) > (FW_ID_STRING_LENGTH -1)) |
spastor | 0:1c358ea10753 | 358 | { |
spastor | 0:1c358ea10753 | 359 | connector_request_id_t request_id; |
spastor | 0:1c358ea10753 | 360 | |
spastor | 0:1c358ea10753 | 361 | request_id.firmware_request = connector_request_id_firmware_info; |
spastor | 0:1c358ea10753 | 362 | connector_debug_printf("process_fw_info_request: description length = %lu + name spec length = %lu\n", |
spastor | 0:1c358ea10753 | 363 | (unsigned long int)fw_ptr->desc_length, (unsigned long int)fw_ptr->spec_length); |
spastor | 0:1c358ea10753 | 364 | notify_error_status(connector_ptr->callback, connector_class_id_firmware, request_id, connector_invalid_data_size); |
spastor | 0:1c358ea10753 | 365 | fw_ptr->desc_length = 0; |
spastor | 0:1c358ea10753 | 366 | fw_ptr->spec_length = 0; |
spastor | 0:1c358ea10753 | 367 | result = connector_abort; |
spastor | 0:1c358ea10753 | 368 | } |
spastor | 0:1c358ea10753 | 369 | } |
spastor | 0:1c358ea10753 | 370 | |
spastor | 0:1c358ea10753 | 371 | /* let's build a response. |
spastor | 0:1c358ea10753 | 372 | * build and send firmware info response |
spastor | 0:1c358ea10753 | 373 | */ |
spastor | 0:1c358ea10753 | 374 | { |
spastor | 0:1c358ea10753 | 375 | connector_firmware_info_t * firmware_info = &fw_ptr->target_info; |
spastor | 0:1c358ea10753 | 376 | |
spastor | 0:1c358ea10753 | 377 | uint8_t * edp_header; |
spastor | 0:1c358ea10753 | 378 | uint8_t * fw_info; |
spastor | 0:1c358ea10753 | 379 | uint8_t * start_ptr; |
spastor | 0:1c358ea10753 | 380 | size_t avail_length; |
spastor | 0:1c358ea10753 | 381 | |
spastor | 0:1c358ea10753 | 382 | edp_header = tcp_get_packet_buffer(connector_ptr, E_MSG_FAC_FW_NUM, &fw_info, &avail_length); |
spastor | 0:1c358ea10753 | 383 | if (edp_header == NULL) |
spastor | 0:1c358ea10753 | 384 | { |
spastor | 0:1c358ea10753 | 385 | result = connector_pending; |
spastor | 0:1c358ea10753 | 386 | goto done; |
spastor | 0:1c358ea10753 | 387 | } |
spastor | 0:1c358ea10753 | 388 | start_ptr = fw_info; |
spastor | 0:1c358ea10753 | 389 | |
spastor | 0:1c358ea10753 | 390 | ASSERT(avail_length > (record_bytes(fw_info) + fw_ptr->desc_length + fw_ptr->spec_length + 1)); |
spastor | 0:1c358ea10753 | 391 | |
spastor | 0:1c358ea10753 | 392 | message_store_u8(fw_info, opcode, fw_info_response_opcode); |
spastor | 0:1c358ea10753 | 393 | message_store_u8(fw_info, target, target); |
spastor | 0:1c358ea10753 | 394 | message_store_be32(fw_info, version, FW_VERSION_NUMBER(firmware_info->version)); |
spastor | 0:1c358ea10753 | 395 | message_store_be32(fw_info, code_size, INT32_C(0)); |
spastor | 0:1c358ea10753 | 396 | fw_info += record_bytes(fw_info); |
spastor | 0:1c358ea10753 | 397 | |
spastor | 0:1c358ea10753 | 398 | connector_debug_printf("firmware description = %d %s %s\n", fw_ptr->desc_length, firmware_info->description, firmware_info->filespec); |
spastor | 0:1c358ea10753 | 399 | if (firmware_info->description != NULL) |
spastor | 0:1c358ea10753 | 400 | { |
spastor | 0:1c358ea10753 | 401 | memcpy(fw_info, firmware_info->description, fw_ptr->desc_length); |
spastor | 0:1c358ea10753 | 402 | fw_info += fw_ptr->desc_length; |
spastor | 0:1c358ea10753 | 403 | } |
spastor | 0:1c358ea10753 | 404 | *fw_info++ = '\n'; |
spastor | 0:1c358ea10753 | 405 | |
spastor | 0:1c358ea10753 | 406 | if (firmware_info->filespec != NULL) |
spastor | 0:1c358ea10753 | 407 | { |
spastor | 0:1c358ea10753 | 408 | memcpy(fw_info, firmware_info->filespec, fw_ptr->spec_length); |
spastor | 0:1c358ea10753 | 409 | fw_info += fw_ptr->spec_length; |
spastor | 0:1c358ea10753 | 410 | } |
spastor | 0:1c358ea10753 | 411 | |
spastor | 0:1c358ea10753 | 412 | /* reset back to initial values */ |
spastor | 0:1c358ea10753 | 413 | firmware_info->version.major = 0; |
spastor | 0:1c358ea10753 | 414 | firmware_info->version.minor = 0; |
spastor | 0:1c358ea10753 | 415 | firmware_info->version.revision = 0; |
spastor | 0:1c358ea10753 | 416 | firmware_info->version.build = 0; |
spastor | 0:1c358ea10753 | 417 | fw_ptr->desc_length = 0; |
spastor | 0:1c358ea10753 | 418 | fw_ptr->spec_length = 0; |
spastor | 0:1c358ea10753 | 419 | |
spastor | 0:1c358ea10753 | 420 | { |
spastor | 0:1c358ea10753 | 421 | size_t const send_packet_length = (size_t)(fw_info-start_ptr); |
spastor | 0:1c358ea10753 | 422 | |
spastor | 0:1c358ea10753 | 423 | result = tcp_initiate_send_facility_packet(connector_ptr, edp_header, send_packet_length, E_MSG_FAC_FW_NUM, tcp_release_packet_buffer, NULL); |
spastor | 0:1c358ea10753 | 424 | |
spastor | 0:1c358ea10753 | 425 | if (result != connector_working) |
spastor | 0:1c358ea10753 | 426 | { |
spastor | 0:1c358ea10753 | 427 | tcp_release_packet_buffer(connector_ptr, edp_header, connector_working, NULL); |
spastor | 0:1c358ea10753 | 428 | } |
spastor | 0:1c358ea10753 | 429 | } |
spastor | 0:1c358ea10753 | 430 | } |
spastor | 0:1c358ea10753 | 431 | |
spastor | 0:1c358ea10753 | 432 | done: |
spastor | 0:1c358ea10753 | 433 | return result; |
spastor | 0:1c358ea10753 | 434 | } |
spastor | 0:1c358ea10753 | 435 | |
spastor | 0:1c358ea10753 | 436 | static connector_status_t process_fw_download_request(connector_firmware_data_t * const fw_ptr, uint8_t * fw_download_request, uint16_t const length) |
spastor | 0:1c358ea10753 | 437 | { |
spastor | 0:1c358ea10753 | 438 | #define FW_STRING_ID_ITEMS 2 |
spastor | 0:1c358ea10753 | 439 | |
spastor | 0:1c358ea10753 | 440 | /* Firmware download request message format: |
spastor | 0:1c358ea10753 | 441 | * ----------------------------------------------------------- |
spastor | 0:1c358ea10753 | 442 | * | 0 | 1 | 2 - 5 | 6 - 9 | 10... | |
spastor | 0:1c358ea10753 | 443 | * ----------------------------------------------------------- |
spastor | 0:1c358ea10753 | 444 | * | opcode | target | version | code size | firmware ID string | |
spastor | 0:1c358ea10753 | 445 | * ------------------------------------------------------------ |
spastor | 0:1c358ea10753 | 446 | * |
spastor | 0:1c358ea10753 | 447 | * Firmware ID string: [label]0x0a[file name spec]0xa[file name] |
spastor | 0:1c358ea10753 | 448 | * |
spastor | 0:1c358ea10753 | 449 | * Call the callback with these values and send download request response. |
spastor | 0:1c358ea10753 | 450 | */ |
spastor | 0:1c358ea10753 | 451 | enum fw_download_request { |
spastor | 0:1c358ea10753 | 452 | field_define(fw_download_request, opcode, uint8_t), |
spastor | 0:1c358ea10753 | 453 | field_define(fw_download_request, target, uint8_t), |
spastor | 0:1c358ea10753 | 454 | field_define(fw_download_request, version, uint32_t), |
spastor | 0:1c358ea10753 | 455 | field_define(fw_download_request, code_size, uint32_t), |
spastor | 0:1c358ea10753 | 456 | record_end(fw_download_request) |
spastor | 0:1c358ea10753 | 457 | }; |
spastor | 0:1c358ea10753 | 458 | |
spastor | 0:1c358ea10753 | 459 | |
spastor | 0:1c358ea10753 | 460 | /* Firmware download response message format: |
spastor | 0:1c358ea10753 | 461 | * --------------------------------- |
spastor | 0:1c358ea10753 | 462 | * | 0 | 1 | 2 | |
spastor | 0:1c358ea10753 | 463 | * --------------------------------- |
spastor | 0:1c358ea10753 | 464 | * | opcode | target | response type | |
spastor | 0:1c358ea10753 | 465 | * --------------------------------- |
spastor | 0:1c358ea10753 | 466 | * |
spastor | 0:1c358ea10753 | 467 | */ |
spastor | 0:1c358ea10753 | 468 | enum fw_download_response { |
spastor | 0:1c358ea10753 | 469 | field_define(fw_download_response, opcode, uint8_t), |
spastor | 0:1c358ea10753 | 470 | field_define(fw_download_response, target, uint8_t), |
spastor | 0:1c358ea10753 | 471 | field_define(fw_download_response, response_type, uint8_t), |
spastor | 0:1c358ea10753 | 472 | record_end(fw_download_response) |
spastor | 0:1c358ea10753 | 473 | }; |
spastor | 0:1c358ea10753 | 474 | |
spastor | 0:1c358ea10753 | 475 | connector_status_t result = connector_working; |
spastor | 0:1c358ea10753 | 476 | connector_firmware_download_start_t download_request; |
spastor | 0:1c358ea10753 | 477 | fw_abort_status_t response_status; |
spastor | 0:1c358ea10753 | 478 | size_t string_id_length; |
spastor | 0:1c358ea10753 | 479 | |
spastor | 0:1c358ea10753 | 480 | uint8_t abort_opcode = fw_download_abort_opcode; |
spastor | 0:1c358ea10753 | 481 | |
spastor | 0:1c358ea10753 | 482 | download_request.target_number = message_load_u8(fw_download_request, target); |
spastor | 0:1c358ea10753 | 483 | |
spastor | 0:1c358ea10753 | 484 | response_status.user_status = connector_firmware_status_device_error; |
spastor | 0:1c358ea10753 | 485 | if (length < record_bytes(fw_download_request)) |
spastor | 0:1c358ea10753 | 486 | { |
spastor | 0:1c358ea10753 | 487 | connector_debug_printf("process_fw_download_request: invalid message length\n"); |
spastor | 0:1c358ea10753 | 488 | abort_opcode = fw_error_opcode; |
spastor | 0:1c358ea10753 | 489 | response_status.error_status = fw_invalid_msg; |
spastor | 0:1c358ea10753 | 490 | goto error; |
spastor | 0:1c358ea10753 | 491 | } |
spastor | 0:1c358ea10753 | 492 | |
spastor | 0:1c358ea10753 | 493 | if (fw_ptr->update_started == connector_true) |
spastor | 0:1c358ea10753 | 494 | { |
spastor | 0:1c358ea10753 | 495 | connector_debug_printf("process_fw_download_request: cannot start another firmware update target %d\n", download_request.target_number); |
spastor | 0:1c358ea10753 | 496 | goto error; |
spastor | 0:1c358ea10753 | 497 | } |
spastor | 0:1c358ea10753 | 498 | |
spastor | 0:1c358ea10753 | 499 | /* Parse firmware download request. Then, call the callback |
spastor | 0:1c358ea10753 | 500 | * with these values and send download request response. |
spastor | 0:1c358ea10753 | 501 | */ |
spastor | 0:1c358ea10753 | 502 | #if (CONNECTOR_VERSION >= 0x02010000) |
spastor | 0:1c358ea10753 | 503 | download_request.code_size = message_load_be32(fw_download_request, code_size); |
spastor | 0:1c358ea10753 | 504 | #endif |
spastor | 0:1c358ea10753 | 505 | |
spastor | 0:1c358ea10753 | 506 | string_id_length = (size_t)(length - record_bytes(fw_download_request)); |
spastor | 0:1c358ea10753 | 507 | |
spastor | 0:1c358ea10753 | 508 | { |
spastor | 0:1c358ea10753 | 509 | char * string_id_ptr = (char *)fw_download_request; |
spastor | 0:1c358ea10753 | 510 | unsigned int i; |
spastor | 0:1c358ea10753 | 511 | |
spastor | 0:1c358ea10753 | 512 | string_id_ptr += record_bytes(fw_download_request); |
spastor | 0:1c358ea10753 | 513 | |
spastor | 0:1c358ea10753 | 514 | /* parse firmware ID String for label and filename spec |
spastor | 0:1c358ea10753 | 515 | * separated by 0x0a. |
spastor | 0:1c358ea10753 | 516 | */ |
spastor | 0:1c358ea10753 | 517 | for (i=0; i < FW_STRING_ID_ITEMS; i++) |
spastor | 0:1c358ea10753 | 518 | { |
spastor | 0:1c358ea10753 | 519 | char * end_ptr; |
spastor | 0:1c358ea10753 | 520 | |
spastor | 0:1c358ea10753 | 521 | end_ptr = strchr(string_id_ptr, '\n'); |
spastor | 0:1c358ea10753 | 522 | if (end_ptr != NULL) *end_ptr = '\0'; |
spastor | 0:1c358ea10753 | 523 | { |
spastor | 0:1c358ea10753 | 524 | size_t const label_length = (size_t)(end_ptr - string_id_ptr); |
spastor | 0:1c358ea10753 | 525 | string_id_length -= (UINT32_C(1) + label_length); |
spastor | 0:1c358ea10753 | 526 | } |
spastor | 0:1c358ea10753 | 527 | string_id_ptr++; |
spastor | 0:1c358ea10753 | 528 | } |
spastor | 0:1c358ea10753 | 529 | /* get filename */ |
spastor | 0:1c358ea10753 | 530 | download_request.filename = string_id_ptr; |
spastor | 0:1c358ea10753 | 531 | *(download_request.filename + string_id_length) = '\0'; |
spastor | 0:1c358ea10753 | 532 | } |
spastor | 0:1c358ea10753 | 533 | |
spastor | 0:1c358ea10753 | 534 | /* call callback */ |
spastor | 0:1c358ea10753 | 535 | download_request.status = connector_firmware_status_success; |
spastor | 0:1c358ea10753 | 536 | result = get_fw_config(fw_ptr, connector_request_id_firmware_download_start, &download_request); |
spastor | 0:1c358ea10753 | 537 | if (result == connector_working) response_status.user_status = download_request.status; |
spastor | 0:1c358ea10753 | 538 | |
spastor | 0:1c358ea10753 | 539 | error: |
spastor | 0:1c358ea10753 | 540 | if (result != connector_pending) |
spastor | 0:1c358ea10753 | 541 | { |
spastor | 0:1c358ea10753 | 542 | uint8_t * fw_download_response = GET_PACKET_DATA_POINTER(fw_ptr->response_buffer, PACKET_EDP_FACILITY_SIZE); |
spastor | 0:1c358ea10753 | 543 | |
spastor | 0:1c358ea10753 | 544 | if (response_status.user_status >= connector_firmware_status_user_abort) |
spastor | 0:1c358ea10753 | 545 | { |
spastor | 0:1c358ea10753 | 546 | send_fw_abort(fw_ptr, download_request.target_number, abort_opcode, response_status); |
spastor | 0:1c358ea10753 | 547 | goto done; |
spastor | 0:1c358ea10753 | 548 | } |
spastor | 0:1c358ea10753 | 549 | |
spastor | 0:1c358ea10753 | 550 | /* get a buffer for sending a response */ |
spastor | 0:1c358ea10753 | 551 | ASSERT((sizeof fw_ptr->response_buffer - PACKET_EDP_FACILITY_SIZE) > record_bytes(fw_download_response)); |
spastor | 0:1c358ea10753 | 552 | |
spastor | 0:1c358ea10753 | 553 | /* send firmware download response */ |
spastor | 0:1c358ea10753 | 554 | message_store_u8(fw_download_response, opcode, fw_download_response_opcode); |
spastor | 0:1c358ea10753 | 555 | message_store_u8(fw_download_response, target, download_request.target_number); |
spastor | 0:1c358ea10753 | 556 | message_store_u8(fw_download_response, response_type, download_request.status); |
spastor | 0:1c358ea10753 | 557 | |
spastor | 0:1c358ea10753 | 558 | fw_ptr->response_size = record_bytes(fw_download_response); |
spastor | 0:1c358ea10753 | 559 | |
spastor | 0:1c358ea10753 | 560 | send_fw_message(fw_ptr); |
spastor | 0:1c358ea10753 | 561 | if (download_request.status == connector_firmware_status_success) |
spastor | 0:1c358ea10753 | 562 | { |
spastor | 0:1c358ea10753 | 563 | fw_ptr->update_started = connector_true; |
spastor | 0:1c358ea10753 | 564 | fw_ptr->target_info.target_number = download_request.target_number; |
spastor | 0:1c358ea10753 | 565 | } |
spastor | 0:1c358ea10753 | 566 | |
spastor | 0:1c358ea10753 | 567 | } |
spastor | 0:1c358ea10753 | 568 | |
spastor | 0:1c358ea10753 | 569 | done: |
spastor | 0:1c358ea10753 | 570 | return result; |
spastor | 0:1c358ea10753 | 571 | } |
spastor | 0:1c358ea10753 | 572 | |
spastor | 0:1c358ea10753 | 573 | static connector_status_t process_fw_binary_block(connector_firmware_data_t * const fw_ptr, uint8_t * const fw_binary_block, uint16_t const length) |
spastor | 0:1c358ea10753 | 574 | { |
spastor | 0:1c358ea10753 | 575 | /* Firmware binary block message format: |
spastor | 0:1c358ea10753 | 576 | * -------------------------------------------------------- |
spastor | 0:1c358ea10753 | 577 | * | 0 | 1 | 2 | 3 - 6 | 7.. | |
spastor | 0:1c358ea10753 | 578 | * -------------------------------------------------------- |
spastor | 0:1c358ea10753 | 579 | * | opcode | target | Ack required | offset | binary data | |
spastor | 0:1c358ea10753 | 580 | * -------------------------------------------------------- |
spastor | 0:1c358ea10753 | 581 | * |
spastor | 0:1c358ea10753 | 582 | */ |
spastor | 0:1c358ea10753 | 583 | enum fw_binary_block { |
spastor | 0:1c358ea10753 | 584 | field_define(fw_binary_block, opcode, uint8_t), |
spastor | 0:1c358ea10753 | 585 | field_define(fw_binary_block, target, uint8_t), |
spastor | 0:1c358ea10753 | 586 | field_define(fw_binary_block, ack_required, uint8_t), |
spastor | 0:1c358ea10753 | 587 | field_define(fw_binary_block, offset, uint32_t), |
spastor | 0:1c358ea10753 | 588 | record_end(fw_binary_block) |
spastor | 0:1c358ea10753 | 589 | }; |
spastor | 0:1c358ea10753 | 590 | |
spastor | 0:1c358ea10753 | 591 | /* Firmware binary block acknowledge message format: |
spastor | 0:1c358ea10753 | 592 | * ----------------------------------- |
spastor | 0:1c358ea10753 | 593 | * | 0 | 1 | 2 - 5 | 6 | |
spastor | 0:1c358ea10753 | 594 | * ----------------------------------- |
spastor | 0:1c358ea10753 | 595 | * | opcode | target | offset | status | |
spastor | 0:1c358ea10753 | 596 | * ----------------------------------- |
spastor | 0:1c358ea10753 | 597 | * |
spastor | 0:1c358ea10753 | 598 | */ |
spastor | 0:1c358ea10753 | 599 | enum fw_binary_ack { |
spastor | 0:1c358ea10753 | 600 | field_define(fw_binary_ack, opcode, uint8_t), |
spastor | 0:1c358ea10753 | 601 | field_define(fw_binary_ack, target, uint8_t), |
spastor | 0:1c358ea10753 | 602 | field_define(fw_binary_ack, offset, uint32_t), |
spastor | 0:1c358ea10753 | 603 | field_define(fw_binary_ack, status, uint8_t), |
spastor | 0:1c358ea10753 | 604 | record_end(fw_binary_ack) |
spastor | 0:1c358ea10753 | 605 | }; |
spastor | 0:1c358ea10753 | 606 | connector_status_t result = connector_idle; |
spastor | 0:1c358ea10753 | 607 | |
spastor | 0:1c358ea10753 | 608 | uint8_t ack_required; |
spastor | 0:1c358ea10753 | 609 | connector_firmware_download_data_t download_data; |
spastor | 0:1c358ea10753 | 610 | |
spastor | 0:1c358ea10753 | 611 | /* Parse firmware binary block */ |
spastor | 0:1c358ea10753 | 612 | download_data.target_number = message_load_u8(fw_binary_block, target); |
spastor | 0:1c358ea10753 | 613 | |
spastor | 0:1c358ea10753 | 614 | if (fw_ptr->update_started == connector_false) |
spastor | 0:1c358ea10753 | 615 | { |
spastor | 0:1c358ea10753 | 616 | /* Ignore this packet since we have not started downloading. |
spastor | 0:1c358ea10753 | 617 | * We may already abort download request. |
spastor | 0:1c358ea10753 | 618 | */ |
spastor | 0:1c358ea10753 | 619 | goto done; |
spastor | 0:1c358ea10753 | 620 | } |
spastor | 0:1c358ea10753 | 621 | |
spastor | 0:1c358ea10753 | 622 | if ((fw_ptr->target_info.target_number != download_data.target_number) || (length < record_bytes(fw_binary_block))) |
spastor | 0:1c358ea10753 | 623 | { |
spastor | 0:1c358ea10753 | 624 | fw_abort_status_t fw_status; |
spastor | 0:1c358ea10753 | 625 | |
spastor | 0:1c358ea10753 | 626 | connector_debug_printf("process_fw_binary_block: invalid target or message length\n"); |
spastor | 0:1c358ea10753 | 627 | fw_status.error_status = fw_invalid_msg; |
spastor | 0:1c358ea10753 | 628 | result = send_fw_abort(fw_ptr, download_data.target_number, fw_error_opcode, fw_status); |
spastor | 0:1c358ea10753 | 629 | goto done; |
spastor | 0:1c358ea10753 | 630 | } |
spastor | 0:1c358ea10753 | 631 | |
spastor | 0:1c358ea10753 | 632 | /* Parse firmware binary block */ |
spastor | 0:1c358ea10753 | 633 | ack_required = message_load_u8(fw_binary_block, ack_required); |
spastor | 0:1c358ea10753 | 634 | download_data.image.offset = message_load_be32(fw_binary_block, offset); |
spastor | 0:1c358ea10753 | 635 | download_data.image.bytes_used = (size_t)(length - record_bytes(fw_binary_block)); |
spastor | 0:1c358ea10753 | 636 | |
spastor | 0:1c358ea10753 | 637 | download_data.image.data = (fw_binary_block + record_bytes(fw_binary_block)); |
spastor | 0:1c358ea10753 | 638 | download_data.status = connector_firmware_status_success; |
spastor | 0:1c358ea10753 | 639 | |
spastor | 0:1c358ea10753 | 640 | result = get_fw_config(fw_ptr, connector_request_id_firmware_download_data, &download_data); |
spastor | 0:1c358ea10753 | 641 | |
spastor | 0:1c358ea10753 | 642 | if (result == connector_working && download_data.status == connector_firmware_status_success) |
spastor | 0:1c358ea10753 | 643 | { |
spastor | 0:1c358ea10753 | 644 | |
spastor | 0:1c358ea10753 | 645 | if(ack_required) |
spastor | 0:1c358ea10753 | 646 | { |
spastor | 0:1c358ea10753 | 647 | uint8_t * fw_binary_ack = GET_PACKET_DATA_POINTER(fw_ptr->response_buffer, PACKET_EDP_FACILITY_SIZE); |
spastor | 0:1c358ea10753 | 648 | |
spastor | 0:1c358ea10753 | 649 | ASSERT((sizeof fw_ptr->response_buffer - PACKET_EDP_FACILITY_SIZE) > record_bytes(fw_binary_ack)); |
spastor | 0:1c358ea10753 | 650 | /* send firmware binary block acknowledge */ |
spastor | 0:1c358ea10753 | 651 | message_store_u8(fw_binary_ack, opcode, fw_binary_block_ack_opcode); |
spastor | 0:1c358ea10753 | 652 | message_store_u8(fw_binary_ack, target, download_data.target_number); |
spastor | 0:1c358ea10753 | 653 | message_store_be32(fw_binary_ack, offset, download_data.image.offset); |
spastor | 0:1c358ea10753 | 654 | message_store_u8(fw_binary_ack, status, connector_firmware_status_success); |
spastor | 0:1c358ea10753 | 655 | |
spastor | 0:1c358ea10753 | 656 | fw_ptr->response_size = record_bytes(fw_binary_ack); |
spastor | 0:1c358ea10753 | 657 | result = send_fw_message(fw_ptr); |
spastor | 0:1c358ea10753 | 658 | } |
spastor | 0:1c358ea10753 | 659 | } |
spastor | 0:1c358ea10753 | 660 | else if (result != connector_pending) |
spastor | 0:1c358ea10753 | 661 | { |
spastor | 0:1c358ea10753 | 662 | fw_abort_status_t fw_status; |
spastor | 0:1c358ea10753 | 663 | fw_status.user_status = download_data.status; |
spastor | 0:1c358ea10753 | 664 | result = send_fw_abort(fw_ptr, download_data.target_number, fw_download_abort_opcode, fw_status); |
spastor | 0:1c358ea10753 | 665 | } |
spastor | 0:1c358ea10753 | 666 | done: |
spastor | 0:1c358ea10753 | 667 | return result; |
spastor | 0:1c358ea10753 | 668 | } |
spastor | 0:1c358ea10753 | 669 | |
spastor | 0:1c358ea10753 | 670 | static connector_status_t process_fw_abort(connector_firmware_data_t * const fw_ptr, uint8_t * const fw_abort, uint16_t const length) |
spastor | 0:1c358ea10753 | 671 | { |
spastor | 0:1c358ea10753 | 672 | |
spastor | 0:1c358ea10753 | 673 | connector_status_t result = connector_working; |
spastor | 0:1c358ea10753 | 674 | |
spastor | 0:1c358ea10753 | 675 | /* parse firmware download abort */ |
spastor | 0:1c358ea10753 | 676 | if (length != FW_ABORT_HEADER_SIZE) |
spastor | 0:1c358ea10753 | 677 | { |
spastor | 0:1c358ea10753 | 678 | connector_debug_printf("process_fw_abort: invalid message length\n"); |
spastor | 0:1c358ea10753 | 679 | } |
spastor | 0:1c358ea10753 | 680 | else if (fw_ptr->update_started) |
spastor | 0:1c358ea10753 | 681 | { |
spastor | 0:1c358ea10753 | 682 | connector_firmware_download_abort_t request_data; |
spastor | 0:1c358ea10753 | 683 | uint8_t abort_status = message_load_u8(fw_abort, status); |
spastor | 0:1c358ea10753 | 684 | |
spastor | 0:1c358ea10753 | 685 | request_data.target_number = message_load_u8(fw_abort, target); |
spastor | 0:1c358ea10753 | 686 | switch (abort_status) |
spastor | 0:1c358ea10753 | 687 | { |
spastor | 0:1c358ea10753 | 688 | case fw_user_abort: |
spastor | 0:1c358ea10753 | 689 | request_data.status = connector_firmware_status_user_abort; |
spastor | 0:1c358ea10753 | 690 | break; |
spastor | 0:1c358ea10753 | 691 | case fw_device_error: |
spastor | 0:1c358ea10753 | 692 | request_data.status = connector_firmware_status_device_error; |
spastor | 0:1c358ea10753 | 693 | break; |
spastor | 0:1c358ea10753 | 694 | case fw_invalid_offset: |
spastor | 0:1c358ea10753 | 695 | request_data.status = connector_firmware_status_invalid_offset; |
spastor | 0:1c358ea10753 | 696 | break; |
spastor | 0:1c358ea10753 | 697 | case fw_invalid_data: |
spastor | 0:1c358ea10753 | 698 | request_data.status = connector_firmware_status_invalid_data; |
spastor | 0:1c358ea10753 | 699 | break; |
spastor | 0:1c358ea10753 | 700 | case fw_hardware_error: |
spastor | 0:1c358ea10753 | 701 | request_data.status = connector_firmware_status_hardware_error; |
spastor | 0:1c358ea10753 | 702 | break; |
spastor | 0:1c358ea10753 | 703 | default: |
spastor | 0:1c358ea10753 | 704 | ASSERT(connector_false); |
spastor | 0:1c358ea10753 | 705 | break; |
spastor | 0:1c358ea10753 | 706 | } |
spastor | 0:1c358ea10753 | 707 | |
spastor | 0:1c358ea10753 | 708 | /* call callback */ |
spastor | 0:1c358ea10753 | 709 | if (fw_ptr->target_info.target_number == request_data.target_number) |
spastor | 0:1c358ea10753 | 710 | { |
spastor | 0:1c358ea10753 | 711 | result = get_fw_config(fw_ptr, connector_request_id_firmware_download_abort, &request_data); |
spastor | 0:1c358ea10753 | 712 | if (result != connector_pending) |
spastor | 0:1c358ea10753 | 713 | { |
spastor | 0:1c358ea10753 | 714 | fw_ptr->update_started = connector_false; |
spastor | 0:1c358ea10753 | 715 | } |
spastor | 0:1c358ea10753 | 716 | fw_ptr->last_fw_keepalive_sent_time = 0; |
spastor | 0:1c358ea10753 | 717 | } |
spastor | 0:1c358ea10753 | 718 | } |
spastor | 0:1c358ea10753 | 719 | return result; |
spastor | 0:1c358ea10753 | 720 | |
spastor | 0:1c358ea10753 | 721 | } |
spastor | 0:1c358ea10753 | 722 | |
spastor | 0:1c358ea10753 | 723 | static connector_status_t process_fw_complete(connector_firmware_data_t * const fw_ptr, uint8_t * const fw_complete_request, uint16_t const length) |
spastor | 0:1c358ea10753 | 724 | { |
spastor | 0:1c358ea10753 | 725 | |
spastor | 0:1c358ea10753 | 726 | /* Firmware download complete message format: |
spastor | 0:1c358ea10753 | 727 | * ---------------------------------------- |
spastor | 0:1c358ea10753 | 728 | * | 0 | 1 | 2 - 5 | 6 - 9 | |
spastor | 0:1c358ea10753 | 729 | * ---------------------------------------- |
spastor | 0:1c358ea10753 | 730 | * | opcode | target | code size | checksum | |
spastor | 0:1c358ea10753 | 731 | * ---------------------------------------- |
spastor | 0:1c358ea10753 | 732 | * |
spastor | 0:1c358ea10753 | 733 | */ |
spastor | 0:1c358ea10753 | 734 | enum fw_complete_request { |
spastor | 0:1c358ea10753 | 735 | field_define(fw_complete_request, opcode, uint8_t), |
spastor | 0:1c358ea10753 | 736 | field_define(fw_complete_request, target, uint8_t), |
spastor | 0:1c358ea10753 | 737 | field_define(fw_complete_request, code_size, uint32_t), |
spastor | 0:1c358ea10753 | 738 | field_define(fw_complete_request, checksum, uint32_t), |
spastor | 0:1c358ea10753 | 739 | record_end(fw_complete_request) |
spastor | 0:1c358ea10753 | 740 | }; |
spastor | 0:1c358ea10753 | 741 | |
spastor | 0:1c358ea10753 | 742 | /* Firmware download complete response message format: |
spastor | 0:1c358ea10753 | 743 | * ------------------------------------------------- |
spastor | 0:1c358ea10753 | 744 | * | 0 | 1 | 2 - 5 | 6 - 9 | 10 | |
spastor | 0:1c358ea10753 | 745 | * -------------------------------------------------- |
spastor | 0:1c358ea10753 | 746 | * | opcode | target | version | calculated | status | |
spastor | 0:1c358ea10753 | 747 | * | | | | checksum | | |
spastor | 0:1c358ea10753 | 748 | * -------------------------------------------------- |
spastor | 0:1c358ea10753 | 749 | */ |
spastor | 0:1c358ea10753 | 750 | enum fw_complete_response { |
spastor | 0:1c358ea10753 | 751 | field_define(fw_complete_response, opcode, uint8_t), |
spastor | 0:1c358ea10753 | 752 | field_define(fw_complete_response, target, uint8_t), |
spastor | 0:1c358ea10753 | 753 | field_define(fw_complete_response, version, uint32_t), |
spastor | 0:1c358ea10753 | 754 | field_define(fw_complete_response, checksum, uint32_t), |
spastor | 0:1c358ea10753 | 755 | field_define(fw_complete_response, status, uint8_t), |
spastor | 0:1c358ea10753 | 756 | record_end(fw_complete_response) |
spastor | 0:1c358ea10753 | 757 | }; |
spastor | 0:1c358ea10753 | 758 | |
spastor | 0:1c358ea10753 | 759 | connector_status_t result = connector_working; |
spastor | 0:1c358ea10753 | 760 | connector_firmware_download_complete_t download_complete; |
spastor | 0:1c358ea10753 | 761 | |
spastor | 0:1c358ea10753 | 762 | download_complete.target_number = message_load_u8(fw_complete_request, target); |
spastor | 0:1c358ea10753 | 763 | download_complete.status = connector_firmware_download_success; |
spastor | 0:1c358ea10753 | 764 | |
spastor | 0:1c358ea10753 | 765 | if ((length != record_bytes(fw_complete_request)) || |
spastor | 0:1c358ea10753 | 766 | (fw_ptr->update_started == connector_false) || |
spastor | 0:1c358ea10753 | 767 | (fw_ptr->target_info.target_number != download_complete.target_number)) |
spastor | 0:1c358ea10753 | 768 | { |
spastor | 0:1c358ea10753 | 769 | fw_abort_status_t fw_status; |
spastor | 0:1c358ea10753 | 770 | |
spastor | 0:1c358ea10753 | 771 | connector_debug_printf("process_fw_complete: invalid message length, invalid target or no firmware update started\n"); |
spastor | 0:1c358ea10753 | 772 | fw_status.error_status = fw_invalid_msg; |
spastor | 0:1c358ea10753 | 773 | result = send_fw_abort(fw_ptr, download_complete.target_number, fw_error_opcode, fw_status); |
spastor | 0:1c358ea10753 | 774 | goto done; |
spastor | 0:1c358ea10753 | 775 | } |
spastor | 0:1c358ea10753 | 776 | |
spastor | 0:1c358ea10753 | 777 | |
spastor | 0:1c358ea10753 | 778 | /* call callback */ |
spastor | 0:1c358ea10753 | 779 | result = get_fw_config(fw_ptr, connector_request_id_firmware_download_complete, &download_complete); |
spastor | 0:1c358ea10753 | 780 | if (result == connector_working) |
spastor | 0:1c358ea10753 | 781 | { |
spastor | 0:1c358ea10753 | 782 | uint8_t * fw_complete_response = GET_PACKET_DATA_POINTER(fw_ptr->response_buffer, PACKET_EDP_FACILITY_SIZE); |
spastor | 0:1c358ea10753 | 783 | |
spastor | 0:1c358ea10753 | 784 | ASSERT((sizeof fw_ptr->response_buffer - PACKET_EDP_FACILITY_SIZE) > record_bytes(fw_complete_response)); |
spastor | 0:1c358ea10753 | 785 | |
spastor | 0:1c358ea10753 | 786 | /* send firmware download complete response */ |
spastor | 0:1c358ea10753 | 787 | message_store_u8(fw_complete_response, opcode, fw_download_complete_response_opcode); |
spastor | 0:1c358ea10753 | 788 | message_store_u8(fw_complete_response, target, download_complete.target_number); |
spastor | 0:1c358ea10753 | 789 | message_store_be32(fw_complete_response, version, INT32_C(0)); |
spastor | 0:1c358ea10753 | 790 | message_store_be32(fw_complete_response, checksum, INT32_C(0)); |
spastor | 0:1c358ea10753 | 791 | message_store_u8(fw_complete_response, status, download_complete.status); |
spastor | 0:1c358ea10753 | 792 | |
spastor | 0:1c358ea10753 | 793 | fw_ptr->last_fw_keepalive_sent_time = 0; |
spastor | 0:1c358ea10753 | 794 | fw_ptr->fw_keepalive_start = connector_false; |
spastor | 0:1c358ea10753 | 795 | |
spastor | 0:1c358ea10753 | 796 | fw_ptr->response_size = record_bytes(fw_complete_response); |
spastor | 0:1c358ea10753 | 797 | result = send_fw_message(fw_ptr); |
spastor | 0:1c358ea10753 | 798 | fw_ptr->update_started = connector_false; |
spastor | 0:1c358ea10753 | 799 | } |
spastor | 0:1c358ea10753 | 800 | else if (result != connector_pending) |
spastor | 0:1c358ea10753 | 801 | { |
spastor | 0:1c358ea10753 | 802 | fw_abort_status_t fw_status; |
spastor | 0:1c358ea10753 | 803 | |
spastor | 0:1c358ea10753 | 804 | fw_status.user_status = connector_firmware_status_user_abort; |
spastor | 0:1c358ea10753 | 805 | send_fw_abort(fw_ptr, download_complete.target_number, fw_download_abort_opcode, fw_status); |
spastor | 0:1c358ea10753 | 806 | } |
spastor | 0:1c358ea10753 | 807 | |
spastor | 0:1c358ea10753 | 808 | |
spastor | 0:1c358ea10753 | 809 | done: |
spastor | 0:1c358ea10753 | 810 | return result; |
spastor | 0:1c358ea10753 | 811 | |
spastor | 0:1c358ea10753 | 812 | } |
spastor | 0:1c358ea10753 | 813 | |
spastor | 0:1c358ea10753 | 814 | static connector_status_t process_target_reset(connector_firmware_data_t * const fw_ptr, uint8_t * const fw_message, uint16_t const length) |
spastor | 0:1c358ea10753 | 815 | { |
spastor | 0:1c358ea10753 | 816 | connector_status_t result; |
spastor | 0:1c358ea10753 | 817 | connector_firmware_reset_t firmware_reset; |
spastor | 0:1c358ea10753 | 818 | |
spastor | 0:1c358ea10753 | 819 | UNUSED_PARAMETER(length); |
spastor | 0:1c358ea10753 | 820 | connector_debug_printf("Firmware Facility: process target reset\n"); |
spastor | 0:1c358ea10753 | 821 | |
spastor | 0:1c358ea10753 | 822 | firmware_reset.target_number = message_load_u8(fw_message, target); |
spastor | 0:1c358ea10753 | 823 | |
spastor | 0:1c358ea10753 | 824 | result = get_fw_config(fw_ptr, connector_request_id_firmware_target_reset, &firmware_reset); |
spastor | 0:1c358ea10753 | 825 | |
spastor | 0:1c358ea10753 | 826 | return result; |
spastor | 0:1c358ea10753 | 827 | } |
spastor | 0:1c358ea10753 | 828 | |
spastor | 0:1c358ea10753 | 829 | static connector_status_t send_discovery_packet_callback(connector_data_t * const connector_ptr, uint8_t const * const packet, |
spastor | 0:1c358ea10753 | 830 | connector_status_t const send_status, void * const user_data) |
spastor | 0:1c358ea10753 | 831 | { |
spastor | 0:1c358ea10753 | 832 | connector_status_t result; |
spastor | 0:1c358ea10753 | 833 | connector_firmware_data_t * const fw_ptr = user_data; |
spastor | 0:1c358ea10753 | 834 | /* update fw download keepalive timing */ |
spastor | 0:1c358ea10753 | 835 | result = get_system_time(connector_ptr, &fw_ptr->last_fw_keepalive_sent_time); |
spastor | 0:1c358ea10753 | 836 | |
spastor | 0:1c358ea10753 | 837 | tcp_release_packet_buffer(connector_ptr, packet, send_status, user_data); |
spastor | 0:1c358ea10753 | 838 | |
spastor | 0:1c358ea10753 | 839 | return result; |
spastor | 0:1c358ea10753 | 840 | } |
spastor | 0:1c358ea10753 | 841 | |
spastor | 0:1c358ea10753 | 842 | static connector_status_t fw_discovery(connector_data_t * const connector_ptr, void * const facility_data, |
spastor | 0:1c358ea10753 | 843 | uint8_t * const packet, unsigned int * receive_timeout) |
spastor | 0:1c358ea10753 | 844 | { |
spastor | 0:1c358ea10753 | 845 | /* Firmware target list message format: |
spastor | 0:1c358ea10753 | 846 | * |
spastor | 0:1c358ea10753 | 847 | * -------------------------------------------------------- |
spastor | 0:1c358ea10753 | 848 | * | 0 | 1 | 2 - 5 | 6 ... | |
spastor | 0:1c358ea10753 | 849 | * ------------------------------------------------------- |
spastor | 0:1c358ea10753 | 850 | * | opcode | target | version | Additional target-version | |
spastor | 0:1c358ea10753 | 851 | * | | | | pairs | |
spastor | 0:1c358ea10753 | 852 | * ------------------------------------------------------- |
spastor | 0:1c358ea10753 | 853 | * |
spastor | 0:1c358ea10753 | 854 | */ |
spastor | 0:1c358ea10753 | 855 | |
spastor | 0:1c358ea10753 | 856 | connector_status_t result = connector_idle; |
spastor | 0:1c358ea10753 | 857 | connector_firmware_data_t * const fw_ptr = facility_data; |
spastor | 0:1c358ea10753 | 858 | |
spastor | 0:1c358ea10753 | 859 | UNUSED_PARAMETER(packet); |
spastor | 0:1c358ea10753 | 860 | UNUSED_PARAMETER(receive_timeout); |
spastor | 0:1c358ea10753 | 861 | |
spastor | 0:1c358ea10753 | 862 | /* Construct a target list message. |
spastor | 0:1c358ea10753 | 863 | * Get target count and then get version for each target to build target list message |
spastor | 0:1c358ea10753 | 864 | * |
spastor | 0:1c358ea10753 | 865 | */ |
spastor | 0:1c358ea10753 | 866 | |
spastor | 0:1c358ea10753 | 867 | if (fw_ptr->target_count > 0) |
spastor | 0:1c358ea10753 | 868 | { |
spastor | 0:1c358ea10753 | 869 | uint8_t * edp_header; |
spastor | 0:1c358ea10753 | 870 | uint8_t * fw_target_list; |
spastor | 0:1c358ea10753 | 871 | size_t avail_length; |
spastor | 0:1c358ea10753 | 872 | size_t discovery_length = 0; |
spastor | 0:1c358ea10753 | 873 | uint8_t target_number; |
spastor | 0:1c358ea10753 | 874 | |
spastor | 0:1c358ea10753 | 875 | /* get packet pointer for constructing target list info */ |
spastor | 0:1c358ea10753 | 876 | edp_header = tcp_get_packet_buffer(connector_ptr, E_MSG_FAC_FW_NUM, &fw_target_list, &avail_length); |
spastor | 0:1c358ea10753 | 877 | if (edp_header == NULL) |
spastor | 0:1c358ea10753 | 878 | { |
spastor | 0:1c358ea10753 | 879 | result = connector_pending; |
spastor | 0:1c358ea10753 | 880 | goto done; |
spastor | 0:1c358ea10753 | 881 | } |
spastor | 0:1c358ea10753 | 882 | |
spastor | 0:1c358ea10753 | 883 | message_store_u8(fw_target_list, opcode, fw_target_list_opcode); |
spastor | 0:1c358ea10753 | 884 | |
spastor | 0:1c358ea10753 | 885 | discovery_length = target_list_header_size; |
spastor | 0:1c358ea10753 | 886 | fw_target_list += discovery_length; |
spastor | 0:1c358ea10753 | 887 | |
spastor | 0:1c358ea10753 | 888 | for (target_number=0; target_number < fw_ptr->target_count; target_number++) |
spastor | 0:1c358ea10753 | 889 | { |
spastor | 0:1c358ea10753 | 890 | connector_firmware_info_t firmware_info; |
spastor | 0:1c358ea10753 | 891 | |
spastor | 0:1c358ea10753 | 892 | /* get the current firmware version for this target */ |
spastor | 0:1c358ea10753 | 893 | firmware_info.target_number = target_number; |
spastor | 0:1c358ea10753 | 894 | memset(&firmware_info.version, 0x00, sizeof firmware_info.version); |
spastor | 0:1c358ea10753 | 895 | /* call callback */ |
spastor | 0:1c358ea10753 | 896 | result = get_fw_config(fw_ptr, connector_request_id_firmware_info, &firmware_info); |
spastor | 0:1c358ea10753 | 897 | if (result == connector_working) |
spastor | 0:1c358ea10753 | 898 | { |
spastor | 0:1c358ea10753 | 899 | |
spastor | 0:1c358ea10753 | 900 | #if defined CONNECTOR_RCI_SERVICE |
spastor | 0:1c358ea10753 | 901 | /* coverity[uninit_use] */ |
spastor | 0:1c358ea10753 | 902 | result = confirm_fw_version(fw_ptr, firmware_info.target_number, firmware_info.version); |
spastor | 0:1c358ea10753 | 903 | if (result != connector_working) goto error; |
spastor | 0:1c358ea10753 | 904 | #endif |
spastor | 0:1c358ea10753 | 905 | message_store_u8(fw_target_list, target, firmware_info.target_number); |
spastor | 0:1c358ea10753 | 906 | message_store_be32(fw_target_list, version, FW_VERSION_NUMBER(firmware_info.version)); |
spastor | 0:1c358ea10753 | 907 | |
spastor | 0:1c358ea10753 | 908 | /* set up for next target pair info*/ |
spastor | 0:1c358ea10753 | 909 | fw_target_list += target_list_size; |
spastor | 0:1c358ea10753 | 910 | discovery_length += target_list_size; |
spastor | 0:1c358ea10753 | 911 | } |
spastor | 0:1c358ea10753 | 912 | else |
spastor | 0:1c358ea10753 | 913 | { |
spastor | 0:1c358ea10753 | 914 | goto error; |
spastor | 0:1c358ea10753 | 915 | } |
spastor | 0:1c358ea10753 | 916 | } |
spastor | 0:1c358ea10753 | 917 | |
spastor | 0:1c358ea10753 | 918 | result = tcp_initiate_send_facility_packet(connector_ptr, edp_header, discovery_length, |
spastor | 0:1c358ea10753 | 919 | E_MSG_FAC_FW_NUM, send_discovery_packet_callback, fw_ptr); |
spastor | 0:1c358ea10753 | 920 | error: |
spastor | 0:1c358ea10753 | 921 | if (result != connector_working) |
spastor | 0:1c358ea10753 | 922 | { |
spastor | 0:1c358ea10753 | 923 | tcp_release_packet_buffer(connector_ptr, edp_header, connector_working, NULL); |
spastor | 0:1c358ea10753 | 924 | } |
spastor | 0:1c358ea10753 | 925 | } |
spastor | 0:1c358ea10753 | 926 | |
spastor | 0:1c358ea10753 | 927 | done: |
spastor | 0:1c358ea10753 | 928 | return result; |
spastor | 0:1c358ea10753 | 929 | } |
spastor | 0:1c358ea10753 | 930 | |
spastor | 0:1c358ea10753 | 931 | static connector_status_t fw_process(connector_data_t * const connector_ptr, void * const facility_data, |
spastor | 0:1c358ea10753 | 932 | uint8_t * const edp_header, unsigned int * const receive_timeout) |
spastor | 0:1c358ea10753 | 933 | { |
spastor | 0:1c358ea10753 | 934 | connector_status_t result = connector_idle; |
spastor | 0:1c358ea10753 | 935 | connector_firmware_data_t * const fw_ptr = facility_data; |
spastor | 0:1c358ea10753 | 936 | uint8_t opcode; |
spastor | 0:1c358ea10753 | 937 | uint8_t target; |
spastor | 0:1c358ea10753 | 938 | uint8_t * fw_message; |
spastor | 0:1c358ea10753 | 939 | uint16_t length; |
spastor | 0:1c358ea10753 | 940 | |
spastor | 0:1c358ea10753 | 941 | if (edp_header == NULL) |
spastor | 0:1c358ea10753 | 942 | { |
spastor | 0:1c358ea10753 | 943 | if (fw_ptr->update_started) |
spastor | 0:1c358ea10753 | 944 | { |
spastor | 0:1c358ea10753 | 945 | result = connector_pending; |
spastor | 0:1c358ea10753 | 946 | } |
spastor | 0:1c358ea10753 | 947 | goto done; |
spastor | 0:1c358ea10753 | 948 | } |
spastor | 0:1c358ea10753 | 949 | |
spastor | 0:1c358ea10753 | 950 | if (fw_ptr->fw_keepalive_start) |
spastor | 0:1c358ea10753 | 951 | { |
spastor | 0:1c358ea10753 | 952 | result = fw_discovery(connector_ptr, facility_data, edp_header, receive_timeout); |
spastor | 0:1c358ea10753 | 953 | if (result == connector_working) |
spastor | 0:1c358ea10753 | 954 | { |
spastor | 0:1c358ea10753 | 955 | if (get_system_time(connector_ptr, &fw_ptr->last_fw_keepalive_sent_time) != connector_working) |
spastor | 0:1c358ea10753 | 956 | { |
spastor | 0:1c358ea10753 | 957 | result = connector_abort; |
spastor | 0:1c358ea10753 | 958 | goto done; |
spastor | 0:1c358ea10753 | 959 | } |
spastor | 0:1c358ea10753 | 960 | fw_ptr->fw_keepalive_start = connector_false; |
spastor | 0:1c358ea10753 | 961 | result = connector_pending; |
spastor | 0:1c358ea10753 | 962 | } |
spastor | 0:1c358ea10753 | 963 | goto done; |
spastor | 0:1c358ea10753 | 964 | } |
spastor | 0:1c358ea10753 | 965 | |
spastor | 0:1c358ea10753 | 966 | if (fw_ptr->send_busy == connector_true) |
spastor | 0:1c358ea10753 | 967 | { |
spastor | 0:1c358ea10753 | 968 | /* callback is already called for this message. |
spastor | 0:1c358ea10753 | 969 | * We're here because we were unable to send a response |
spastor | 0:1c358ea10753 | 970 | * message which already message is constructed in |
spastor | 0:1c358ea10753 | 971 | * fw_ptr->response_buffer. |
spastor | 0:1c358ea10753 | 972 | */ |
spastor | 0:1c358ea10753 | 973 | result = send_fw_message(fw_ptr); |
spastor | 0:1c358ea10753 | 974 | goto done; |
spastor | 0:1c358ea10753 | 975 | } |
spastor | 0:1c358ea10753 | 976 | |
spastor | 0:1c358ea10753 | 977 | length = message_load_be16(edp_header, length); |
spastor | 0:1c358ea10753 | 978 | if (length < FW_MESSAGE_HEADER_SIZE) |
spastor | 0:1c358ea10753 | 979 | { |
spastor | 0:1c358ea10753 | 980 | connector_debug_printf("fw_process: invalid packet size %d\n", length); |
spastor | 0:1c358ea10753 | 981 | goto done; |
spastor | 0:1c358ea10753 | 982 | } |
spastor | 0:1c358ea10753 | 983 | |
spastor | 0:1c358ea10753 | 984 | fw_message = GET_PACKET_DATA_POINTER(edp_header, PACKET_EDP_FACILITY_SIZE); |
spastor | 0:1c358ea10753 | 985 | opcode = message_load_u8(fw_message, opcode); |
spastor | 0:1c358ea10753 | 986 | target = message_load_u8(fw_message, target); |
spastor | 0:1c358ea10753 | 987 | |
spastor | 0:1c358ea10753 | 988 | if (target >= fw_ptr->target_count) |
spastor | 0:1c358ea10753 | 989 | { |
spastor | 0:1c358ea10753 | 990 | fw_abort_status_t fw_status; |
spastor | 0:1c358ea10753 | 991 | |
spastor | 0:1c358ea10753 | 992 | connector_debug_printf("fw_process: invalid target\n"); |
spastor | 0:1c358ea10753 | 993 | |
spastor | 0:1c358ea10753 | 994 | fw_status.error_status = fw_invalid_target; |
spastor | 0:1c358ea10753 | 995 | result = send_fw_abort(fw_ptr, target, fw_error_opcode, fw_status); |
spastor | 0:1c358ea10753 | 996 | goto done; |
spastor | 0:1c358ea10753 | 997 | } |
spastor | 0:1c358ea10753 | 998 | |
spastor | 0:1c358ea10753 | 999 | switch(opcode) |
spastor | 0:1c358ea10753 | 1000 | { |
spastor | 0:1c358ea10753 | 1001 | case fw_info_request_opcode: |
spastor | 0:1c358ea10753 | 1002 | result = process_fw_info_request(fw_ptr, fw_message, length); |
spastor | 0:1c358ea10753 | 1003 | break; |
spastor | 0:1c358ea10753 | 1004 | case fw_download_request_opcode: |
spastor | 0:1c358ea10753 | 1005 | result = process_fw_download_request(fw_ptr, fw_message, length); |
spastor | 0:1c358ea10753 | 1006 | break; |
spastor | 0:1c358ea10753 | 1007 | case fw_binary_block_opcode: |
spastor | 0:1c358ea10753 | 1008 | result = process_fw_binary_block(fw_ptr, fw_message, length); |
spastor | 0:1c358ea10753 | 1009 | break; |
spastor | 0:1c358ea10753 | 1010 | case fw_download_abort_opcode: |
spastor | 0:1c358ea10753 | 1011 | result = process_fw_abort(fw_ptr, fw_message, length); |
spastor | 0:1c358ea10753 | 1012 | fw_ptr->last_fw_keepalive_sent_time = 0; |
spastor | 0:1c358ea10753 | 1013 | fw_ptr->fw_keepalive_start = connector_false; |
spastor | 0:1c358ea10753 | 1014 | break; |
spastor | 0:1c358ea10753 | 1015 | case fw_download_complete_opcode: |
spastor | 0:1c358ea10753 | 1016 | if (fw_ptr->last_fw_keepalive_sent_time == 0) |
spastor | 0:1c358ea10753 | 1017 | { |
spastor | 0:1c358ea10753 | 1018 | /* start firmware keepalive which allow firmware download complete |
spastor | 0:1c358ea10753 | 1019 | * callback to start flash (which requires device to |
spastor | 0:1c358ea10753 | 1020 | * send target list message). |
spastor | 0:1c358ea10753 | 1021 | * |
spastor | 0:1c358ea10753 | 1022 | * Note. We only start firmware keepalive when we receive this complete |
spastor | 0:1c358ea10753 | 1023 | * code. Can we start when we receive block opcode? |
spastor | 0:1c358ea10753 | 1024 | */ |
spastor | 0:1c358ea10753 | 1025 | fw_ptr->last_fw_keepalive_sent_time = connector_ptr->edp_data.keepalive.last_tx_received_time; |
spastor | 0:1c358ea10753 | 1026 | } |
spastor | 0:1c358ea10753 | 1027 | result = process_fw_complete(fw_ptr, fw_message, length); |
spastor | 0:1c358ea10753 | 1028 | break; |
spastor | 0:1c358ea10753 | 1029 | case fw_target_reset_opcode: |
spastor | 0:1c358ea10753 | 1030 | result = process_target_reset(fw_ptr, fw_message, length); |
spastor | 0:1c358ea10753 | 1031 | fw_ptr->last_fw_keepalive_sent_time = 0; |
spastor | 0:1c358ea10753 | 1032 | fw_ptr->fw_keepalive_start = connector_false; |
spastor | 0:1c358ea10753 | 1033 | break; |
spastor | 0:1c358ea10753 | 1034 | default: |
spastor | 0:1c358ea10753 | 1035 | { |
spastor | 0:1c358ea10753 | 1036 | fw_abort_status_t fw_status; |
spastor | 0:1c358ea10753 | 1037 | fw_status.error_status = fw_invalid_opcode; |
spastor | 0:1c358ea10753 | 1038 | result = send_fw_abort(fw_ptr, target, fw_error_opcode, fw_status); |
spastor | 0:1c358ea10753 | 1039 | break; |
spastor | 0:1c358ea10753 | 1040 | } |
spastor | 0:1c358ea10753 | 1041 | } |
spastor | 0:1c358ea10753 | 1042 | |
spastor | 0:1c358ea10753 | 1043 | done: |
spastor | 0:1c358ea10753 | 1044 | return result; |
spastor | 0:1c358ea10753 | 1045 | } |
spastor | 0:1c358ea10753 | 1046 | |
spastor | 0:1c358ea10753 | 1047 | static connector_status_t connector_facility_firmware_delete(connector_data_t * const connector_ptr) |
spastor | 0:1c358ea10753 | 1048 | { |
spastor | 0:1c358ea10753 | 1049 | return del_facility_data(connector_ptr, E_MSG_FAC_FW_NUM); |
spastor | 0:1c358ea10753 | 1050 | } |
spastor | 0:1c358ea10753 | 1051 | |
spastor | 0:1c358ea10753 | 1052 | static connector_status_t connector_facility_firmware_init(connector_data_t * const connector_ptr, unsigned int const facility_index) |
spastor | 0:1c358ea10753 | 1053 | { |
spastor | 0:1c358ea10753 | 1054 | connector_status_t result = connector_working; |
spastor | 0:1c358ea10753 | 1055 | connector_firmware_data_t * fw_ptr; |
spastor | 0:1c358ea10753 | 1056 | |
spastor | 0:1c358ea10753 | 1057 | /* Add firmware access facility to Connector |
spastor | 0:1c358ea10753 | 1058 | * |
spastor | 0:1c358ea10753 | 1059 | * Make sure firmware access facility is not already created. If firmware |
spastor | 0:1c358ea10753 | 1060 | * access facility is already created, we probably reconnect to Device Cloud |
spastor | 0:1c358ea10753 | 1061 | * so just need to reset to initial state. |
spastor | 0:1c358ea10753 | 1062 | * |
spastor | 0:1c358ea10753 | 1063 | */ |
spastor | 0:1c358ea10753 | 1064 | fw_ptr = get_facility_data(connector_ptr, E_MSG_FAC_FW_NUM); |
spastor | 0:1c358ea10753 | 1065 | if (fw_ptr == NULL) |
spastor | 0:1c358ea10753 | 1066 | { |
spastor | 0:1c358ea10753 | 1067 | void * ptr; |
spastor | 0:1c358ea10753 | 1068 | result = add_facility_data(connector_ptr, facility_index, E_MSG_FAC_FW_NUM, &ptr, sizeof *fw_ptr); |
spastor | 0:1c358ea10753 | 1069 | |
spastor | 0:1c358ea10753 | 1070 | if (result != connector_working || ptr == NULL) |
spastor | 0:1c358ea10753 | 1071 | { |
spastor | 0:1c358ea10753 | 1072 | goto done; |
spastor | 0:1c358ea10753 | 1073 | } |
spastor | 0:1c358ea10753 | 1074 | fw_ptr = ptr; |
spastor | 0:1c358ea10753 | 1075 | } |
spastor | 0:1c358ea10753 | 1076 | fw_ptr->target_count = 0; |
spastor | 0:1c358ea10753 | 1077 | fw_ptr->target_info.target_number = 0; |
spastor | 0:1c358ea10753 | 1078 | fw_ptr->desc_length = 0; |
spastor | 0:1c358ea10753 | 1079 | fw_ptr->spec_length = 0; |
spastor | 0:1c358ea10753 | 1080 | fw_ptr->last_fw_keepalive_sent_time = 0; |
spastor | 0:1c358ea10753 | 1081 | fw_ptr->fw_keepalive_start = connector_false; |
spastor | 0:1c358ea10753 | 1082 | fw_ptr->send_busy = connector_false; |
spastor | 0:1c358ea10753 | 1083 | fw_ptr->update_started = connector_false; |
spastor | 0:1c358ea10753 | 1084 | fw_ptr->connector_ptr = connector_ptr; |
spastor | 0:1c358ea10753 | 1085 | |
spastor | 0:1c358ea10753 | 1086 | { |
spastor | 0:1c358ea10753 | 1087 | connector_firmware_count_t firmware_data; |
spastor | 0:1c358ea10753 | 1088 | |
spastor | 0:1c358ea10753 | 1089 | result = get_fw_config(fw_ptr, connector_request_id_firmware_target_count, &firmware_data); |
spastor | 0:1c358ea10753 | 1090 | if (result == connector_working) |
spastor | 0:1c358ea10753 | 1091 | { |
spastor | 0:1c358ea10753 | 1092 | /* coverity[uninit_use] */ |
spastor | 0:1c358ea10753 | 1093 | fw_ptr->target_count = firmware_data.count; |
spastor | 0:1c358ea10753 | 1094 | if (fw_ptr->target_count > 0) |
spastor | 0:1c358ea10753 | 1095 | { |
spastor | 0:1c358ea10753 | 1096 | size_t const buffer_size = sizeof connector_ptr->edp_data.send_packet.packet_buffer.buffer; |
spastor | 0:1c358ea10753 | 1097 | size_t const overhead = (PACKET_EDP_FACILITY_SIZE + target_list_header_size); |
spastor | 0:1c358ea10753 | 1098 | size_t const max_targets = (buffer_size - overhead) / target_list_size; |
spastor | 0:1c358ea10753 | 1099 | |
spastor | 0:1c358ea10753 | 1100 | /* get max count of targets that fit into the response buffer */ |
spastor | 0:1c358ea10753 | 1101 | if (fw_ptr->target_count > max_targets) |
spastor | 0:1c358ea10753 | 1102 | { |
spastor | 0:1c358ea10753 | 1103 | connector_request_id_t request_id; |
spastor | 0:1c358ea10753 | 1104 | |
spastor | 0:1c358ea10753 | 1105 | request_id.firmware_request = connector_request_id_firmware_target_count; |
spastor | 0:1c358ea10753 | 1106 | notify_error_status(connector_ptr->callback, connector_class_id_firmware, request_id, connector_invalid_data_range); |
spastor | 0:1c358ea10753 | 1107 | result = connector_abort; |
spastor | 0:1c358ea10753 | 1108 | goto done; |
spastor | 0:1c358ea10753 | 1109 | } |
spastor | 0:1c358ea10753 | 1110 | } |
spastor | 0:1c358ea10753 | 1111 | else |
spastor | 0:1c358ea10753 | 1112 | { |
spastor | 0:1c358ea10753 | 1113 | connector_debug_printf("fw_discovery: No target supported\n"); |
spastor | 0:1c358ea10753 | 1114 | } |
spastor | 0:1c358ea10753 | 1115 | } |
spastor | 0:1c358ea10753 | 1116 | } |
spastor | 0:1c358ea10753 | 1117 | |
spastor | 0:1c358ea10753 | 1118 | done: |
spastor | 0:1c358ea10753 | 1119 | return result; |
spastor | 0:1c358ea10753 | 1120 | } |
spastor | 0:1c358ea10753 | 1121 | |
spastor | 0:1c358ea10753 | 1122 |