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

Committer:
spastor
Date:
Tue Dec 03 13:34:02 2013 +0000
Revision:
0:1c358ea10753
First commit

Who changed what in which revision?

UserRevisionLine numberNew 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