leo hendrickson / Mbed OS example-Ethernet-mbed-Cloud-connect
Committer:
leothedragon
Date:
Tue May 04 08:55:12 2021 +0000
Revision:
0:8f0bb79ddd48
nmn

Who changed what in which revision?

UserRevisionLine numberNew contents of line
leothedragon 0:8f0bb79ddd48 1 // ----------------------------------------------------------------------------
leothedragon 0:8f0bb79ddd48 2 // Copyright 2016-2017 ARM Ltd.
leothedragon 0:8f0bb79ddd48 3 //
leothedragon 0:8f0bb79ddd48 4 // SPDX-License-Identifier: Apache-2.0
leothedragon 0:8f0bb79ddd48 5 //
leothedragon 0:8f0bb79ddd48 6 // Licensed under the Apache License, Version 2.0 (the "License");
leothedragon 0:8f0bb79ddd48 7 // you may not use this file except in compliance with the License.
leothedragon 0:8f0bb79ddd48 8 // You may obtain a copy of the License at
leothedragon 0:8f0bb79ddd48 9 //
leothedragon 0:8f0bb79ddd48 10 // http://www.apache.org/licenses/LICENSE-2.0
leothedragon 0:8f0bb79ddd48 11 //
leothedragon 0:8f0bb79ddd48 12 // Unless required by applicable law or agreed to in writing, software
leothedragon 0:8f0bb79ddd48 13 // distributed under the License is distributed on an "AS IS" BASIS,
leothedragon 0:8f0bb79ddd48 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
leothedragon 0:8f0bb79ddd48 15 // See the License for the specific language governing permissions and
leothedragon 0:8f0bb79ddd48 16 // limitations under the License.
leothedragon 0:8f0bb79ddd48 17 // ----------------------------------------------------------------------------
leothedragon 0:8f0bb79ddd48 18 // Note: this macro is needed on armcc to get the the PRI*32 macros
leothedragon 0:8f0bb79ddd48 19 // from inttypes.h in a C++ code.
leothedragon 0:8f0bb79ddd48 20 #ifndef __STDC_FORMAT_MACROS
leothedragon 0:8f0bb79ddd48 21 #define __STDC_FORMAT_MACROS
leothedragon 0:8f0bb79ddd48 22 #endif
leothedragon 0:8f0bb79ddd48 23
leothedragon 0:8f0bb79ddd48 24 #include <inttypes.h>
leothedragon 0:8f0bb79ddd48 25
leothedragon 0:8f0bb79ddd48 26 #include "update-lwm2m-mbed-apis.h"
leothedragon 0:8f0bb79ddd48 27 #include "update-client-common/arm_uc_common.h"
leothedragon 0:8f0bb79ddd48 28 #include "update-client-lwm2m/lwm2m-source.h"
leothedragon 0:8f0bb79ddd48 29 #include "update-client-lwm2m/FirmwareUpdateResource.h"
leothedragon 0:8f0bb79ddd48 30 #include "update-client-lwm2m/DeviceMetadataResource.h"
leothedragon 0:8f0bb79ddd48 31 #include "update-client-common/arm_uc_config.h"
leothedragon 0:8f0bb79ddd48 32
leothedragon 0:8f0bb79ddd48 33 /* error management */
leothedragon 0:8f0bb79ddd48 34 static arm_uc_error_t arm_ucs_lwm2m_error = {ERR_NONE};
leothedragon 0:8f0bb79ddd48 35 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetError(void) { return arm_ucs_lwm2m_error; }
leothedragon 0:8f0bb79ddd48 36 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_SetError(arm_uc_error_t an_error) { return (arm_ucs_lwm2m_error = an_error); }
leothedragon 0:8f0bb79ddd48 37
leothedragon 0:8f0bb79ddd48 38 /* forward declaration */
leothedragon 0:8f0bb79ddd48 39 static void ARM_UCS_PackageCallback(const uint8_t *buffer, uint16_t length);
leothedragon 0:8f0bb79ddd48 40
leothedragon 0:8f0bb79ddd48 41 /* local copy of the received manifest */
leothedragon 0:8f0bb79ddd48 42 static uint8_t *arm_ucs_manifest_buffer = NULL;
leothedragon 0:8f0bb79ddd48 43 static uint16_t arm_ucs_manifest_length = 0;
leothedragon 0:8f0bb79ddd48 44
leothedragon 0:8f0bb79ddd48 45 /* callback function pointer and struct */
leothedragon 0:8f0bb79ddd48 46 static void (*ARM_UCS_EventHandler)(uintptr_t event) = 0;
leothedragon 0:8f0bb79ddd48 47 static arm_uc_callback_t callbackNodeManifest = { NULL, 0, NULL, 0 };
leothedragon 0:8f0bb79ddd48 48 static arm_uc_callback_t callbackNodeNotification = { NULL, 0, NULL, 0 };
leothedragon 0:8f0bb79ddd48 49
leothedragon 0:8f0bb79ddd48 50 #if defined(ARM_UC_FEATURE_FW_SOURCE_COAP) && (ARM_UC_FEATURE_FW_SOURCE_COAP == 1)
leothedragon 0:8f0bb79ddd48 51 static bool arm_uc_get_data_request_transaction_ongoing = false;
leothedragon 0:8f0bb79ddd48 52 static size_t arm_uc_received_file_size = 0;
leothedragon 0:8f0bb79ddd48 53 static size_t arm_uc_total_file_size = 0;
leothedragon 0:8f0bb79ddd48 54 static void arm_uc_get_data_req_callback(const uint8_t *buffer, size_t buffer_size, size_t total_size, bool last_block,
leothedragon 0:8f0bb79ddd48 55 void *context);
leothedragon 0:8f0bb79ddd48 56 static void arm_uc_get_data_req_error_callback(get_data_req_error_t error_code, void *context);
leothedragon 0:8f0bb79ddd48 57
leothedragon 0:8f0bb79ddd48 58 #define ARM_UCS_DEFAULT_COST (900)
leothedragon 0:8f0bb79ddd48 59 #define ARM_UCS_HASH_LENGTH (40)
leothedragon 0:8f0bb79ddd48 60
leothedragon 0:8f0bb79ddd48 61 // The hub uses a double buffer system to speed up firmware download and storage
leothedragon 0:8f0bb79ddd48 62 #define BUFFER_SIZE_MAX (ARM_UC_BUFFER_SIZE / 2) // define size of the double buffers
leothedragon 0:8f0bb79ddd48 63
leothedragon 0:8f0bb79ddd48 64 #if BUFFER_SIZE_MAX < SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
leothedragon 0:8f0bb79ddd48 65 #error MBED_CLOUD_CLIENT_UPDATE_BUFFER must be at least double the size of SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
leothedragon 0:8f0bb79ddd48 66 #endif
leothedragon 0:8f0bb79ddd48 67
leothedragon 0:8f0bb79ddd48 68 // Set proper Storage buffer size with requirements:
leothedragon 0:8f0bb79ddd48 69 // 1. Storage buffer size >= Block size (SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE)
leothedragon 0:8f0bb79ddd48 70 // 1. & 2 AND is >= page size (BUFFER_SIZE_MAX)
leothedragon 0:8f0bb79ddd48 71 // 2. & 3. AND is multiple of Block size (X * SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE)
leothedragon 0:8f0bb79ddd48 72 #define STORAGE_BUFFER_SIZE max_storage(SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE, BUFFER_SIZE_MAX)
leothedragon 0:8f0bb79ddd48 73 // 1. 2. 3.
leothedragon 0:8f0bb79ddd48 74 #define max_storage(X,Y) ((X) > (Y) ? (X) : ( (Y%X==0) ? (Y) :(BLOCK_MULTIPLIER(X,Y)*X)))
leothedragon 0:8f0bb79ddd48 75
leothedragon 0:8f0bb79ddd48 76 #define BLOCK_MULTIPLIER(X,Y) ((Y/X)+1)
leothedragon 0:8f0bb79ddd48 77
leothedragon 0:8f0bb79ddd48 78 static uint8_t storage_message[STORAGE_BUFFER_SIZE];
leothedragon 0:8f0bb79ddd48 79 static arm_uc_buffer_t storage_buffer = {
leothedragon 0:8f0bb79ddd48 80 .size_max = STORAGE_BUFFER_SIZE,
leothedragon 0:8f0bb79ddd48 81 .size = 0,
leothedragon 0:8f0bb79ddd48 82 .ptr = storage_message
leothedragon 0:8f0bb79ddd48 83 };
leothedragon 0:8f0bb79ddd48 84
leothedragon 0:8f0bb79ddd48 85 static arm_uc_buffer_t *output_buffer_ptr = NULL;
leothedragon 0:8f0bb79ddd48 86 static char *copy_full_url = NULL;
leothedragon 0:8f0bb79ddd48 87 static DownloadType download_type = FIRMWARE_DOWNLOAD; //default FIRMWARE = COAP download using filepath of server;
leothedragon 0:8f0bb79ddd48 88
leothedragon 0:8f0bb79ddd48 89 #endif // ARM_UC_FEATURE_FW_SOURCE_COAP
leothedragon 0:8f0bb79ddd48 90
leothedragon 0:8f0bb79ddd48 91 /**
leothedragon 0:8f0bb79ddd48 92 * @brief Get driver version.
leothedragon 0:8f0bb79ddd48 93 * @return Driver version.
leothedragon 0:8f0bb79ddd48 94 */
leothedragon 0:8f0bb79ddd48 95 uint32_t ARM_UCS_LWM2M_SOURCE_GetVersion(void)
leothedragon 0:8f0bb79ddd48 96 {
leothedragon 0:8f0bb79ddd48 97 return 0;
leothedragon 0:8f0bb79ddd48 98 }
leothedragon 0:8f0bb79ddd48 99
leothedragon 0:8f0bb79ddd48 100 /**
leothedragon 0:8f0bb79ddd48 101 * @brief Get Source capabilities.
leothedragon 0:8f0bb79ddd48 102 * @return Struct containing capabilites. See definition above.
leothedragon 0:8f0bb79ddd48 103 */
leothedragon 0:8f0bb79ddd48 104 ARM_SOURCE_CAPABILITIES ARM_UCS_LWM2M_SOURCE_GetCapabilities(void)
leothedragon 0:8f0bb79ddd48 105 {
leothedragon 0:8f0bb79ddd48 106 ARM_SOURCE_CAPABILITIES result;
leothedragon 0:8f0bb79ddd48 107 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_GetCapabilities:");
leothedragon 0:8f0bb79ddd48 108
leothedragon 0:8f0bb79ddd48 109 result.notify = 0;
leothedragon 0:8f0bb79ddd48 110 result.manifest_default = 0;
leothedragon 0:8f0bb79ddd48 111 result.manifest_url = 0;
leothedragon 0:8f0bb79ddd48 112 result.firmware = 0;
leothedragon 0:8f0bb79ddd48 113 result.keytable = 0;
leothedragon 0:8f0bb79ddd48 114
leothedragon 0:8f0bb79ddd48 115 /* the event handler must be set before module can be used */
leothedragon 0:8f0bb79ddd48 116 if (ARM_UCS_EventHandler != 0) {
leothedragon 0:8f0bb79ddd48 117 result.notify = 1;
leothedragon 0:8f0bb79ddd48 118 result.manifest_default = 1;
leothedragon 0:8f0bb79ddd48 119 result.manifest_url = 1;
leothedragon 0:8f0bb79ddd48 120 #if defined(ARM_UC_FEATURE_FW_SOURCE_COAP) && (ARM_UC_FEATURE_FW_SOURCE_COAP == 1)
leothedragon 0:8f0bb79ddd48 121 result.firmware = 1;
leothedragon 0:8f0bb79ddd48 122 #endif
leothedragon 0:8f0bb79ddd48 123 result.keytable = 1;
leothedragon 0:8f0bb79ddd48 124 }
leothedragon 0:8f0bb79ddd48 125
leothedragon 0:8f0bb79ddd48 126 return result;
leothedragon 0:8f0bb79ddd48 127 }
leothedragon 0:8f0bb79ddd48 128
leothedragon 0:8f0bb79ddd48 129 /**
leothedragon 0:8f0bb79ddd48 130 * @brief Initialize Source.
leothedragon 0:8f0bb79ddd48 131 * @details Function pointer to event handler is passed as argument.
leothedragon 0:8f0bb79ddd48 132 *
leothedragon 0:8f0bb79ddd48 133 * @param cb_event Function pointer to event handler. See events above.
leothedragon 0:8f0bb79ddd48 134 * @return Error code.
leothedragon 0:8f0bb79ddd48 135 */
leothedragon 0:8f0bb79ddd48 136 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_Initialize(ARM_SOURCE_SignalEvent_t cb_event)
leothedragon 0:8f0bb79ddd48 137 {
leothedragon 0:8f0bb79ddd48 138 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_Initialize: %p", cb_event);
leothedragon 0:8f0bb79ddd48 139 ARM_UC_INIT_ERROR(result, SRCE_ERR_INVALID_PARAMETER);
leothedragon 0:8f0bb79ddd48 140
leothedragon 0:8f0bb79ddd48 141 #if defined(ARM_UC_FEATURE_FW_SOURCE_COAP) && (ARM_UC_FEATURE_FW_SOURCE_COAP == 1)
leothedragon 0:8f0bb79ddd48 142 arm_uc_get_data_request_transaction_ongoing = false;
leothedragon 0:8f0bb79ddd48 143 arm_uc_received_file_size = 0;
leothedragon 0:8f0bb79ddd48 144 arm_uc_total_file_size = 0;
leothedragon 0:8f0bb79ddd48 145 #endif
leothedragon 0:8f0bb79ddd48 146
leothedragon 0:8f0bb79ddd48 147 if (cb_event != 0) {
leothedragon 0:8f0bb79ddd48 148 /* store callback handler */
leothedragon 0:8f0bb79ddd48 149 ARM_UCS_EventHandler = cb_event;
leothedragon 0:8f0bb79ddd48 150
leothedragon 0:8f0bb79ddd48 151 /* Initialize LWM2M Firmware Update Object */
leothedragon 0:8f0bb79ddd48 152 FirmwareUpdateResource::Initialize();
leothedragon 0:8f0bb79ddd48 153
leothedragon 0:8f0bb79ddd48 154 /* Register callback handler */
leothedragon 0:8f0bb79ddd48 155 FirmwareUpdateResource::addPackageCallback(ARM_UCS_PackageCallback);
leothedragon 0:8f0bb79ddd48 156
leothedragon 0:8f0bb79ddd48 157 DeviceMetadataResource::Initialize();
leothedragon 0:8f0bb79ddd48 158
leothedragon 0:8f0bb79ddd48 159 ARM_UC_SET_ERROR(result, ERR_NONE);
leothedragon 0:8f0bb79ddd48 160 }
leothedragon 0:8f0bb79ddd48 161
leothedragon 0:8f0bb79ddd48 162 if (ARM_UC_IS_ERROR(result)) {
leothedragon 0:8f0bb79ddd48 163 ARM_UCS_LWM2M_SOURCE_SetError(result);
leothedragon 0:8f0bb79ddd48 164 }
leothedragon 0:8f0bb79ddd48 165 return result;
leothedragon 0:8f0bb79ddd48 166 }
leothedragon 0:8f0bb79ddd48 167
leothedragon 0:8f0bb79ddd48 168 /**
leothedragon 0:8f0bb79ddd48 169 * @brief Uninitialized Source.
leothedragon 0:8f0bb79ddd48 170 * @return Error code.
leothedragon 0:8f0bb79ddd48 171 */
leothedragon 0:8f0bb79ddd48 172 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_Uninitialize(void)
leothedragon 0:8f0bb79ddd48 173 {
leothedragon 0:8f0bb79ddd48 174 ARM_UC_INIT_ERROR(retval, ERR_NONE);
leothedragon 0:8f0bb79ddd48 175 DeviceMetadataResource::Uninitialize();
leothedragon 0:8f0bb79ddd48 176 FirmwareUpdateResource::Uninitialize();
leothedragon 0:8f0bb79ddd48 177
leothedragon 0:8f0bb79ddd48 178 return retval;
leothedragon 0:8f0bb79ddd48 179 }
leothedragon 0:8f0bb79ddd48 180
leothedragon 0:8f0bb79ddd48 181 /**
leothedragon 0:8f0bb79ddd48 182 * @brief Cost estimation for retrieving manifest from the default location.
leothedragon 0:8f0bb79ddd48 183 * @details The estimation can vary over time and should not be cached too long.
leothedragon 0:8f0bb79ddd48 184 * 0x00000000 - The manifest is already downloaded.
leothedragon 0:8f0bb79ddd48 185 * 0xFFFFFFFF - Cannot retrieve manifest from this Source.
leothedragon 0:8f0bb79ddd48 186 *
leothedragon 0:8f0bb79ddd48 187 * @param cost Pointer to variable for the return value.
leothedragon 0:8f0bb79ddd48 188 * @return Error code.
leothedragon 0:8f0bb79ddd48 189 */
leothedragon 0:8f0bb79ddd48 190 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestDefaultCost(uint32_t *cost)
leothedragon 0:8f0bb79ddd48 191 {
leothedragon 0:8f0bb79ddd48 192 ARM_UC_INIT_ERROR(result, SRCE_ERR_INVALID_PARAMETER);
leothedragon 0:8f0bb79ddd48 193
leothedragon 0:8f0bb79ddd48 194 if (cost != 0) {
leothedragon 0:8f0bb79ddd48 195 /* set cost to 0 when manifest is cached */
leothedragon 0:8f0bb79ddd48 196 if (arm_ucs_manifest_buffer && arm_ucs_manifest_length) {
leothedragon 0:8f0bb79ddd48 197 *cost = 0;
leothedragon 0:8f0bb79ddd48 198 }
leothedragon 0:8f0bb79ddd48 199 /* set cost to 0xFFFFFFFF when manifest has been read */
leothedragon 0:8f0bb79ddd48 200 else {
leothedragon 0:8f0bb79ddd48 201 *cost = 0xFFFFFFFF;
leothedragon 0:8f0bb79ddd48 202 }
leothedragon 0:8f0bb79ddd48 203
leothedragon 0:8f0bb79ddd48 204 ARM_UC_SET_ERROR(result, ERR_NONE);
leothedragon 0:8f0bb79ddd48 205 }
leothedragon 0:8f0bb79ddd48 206
leothedragon 0:8f0bb79ddd48 207 if (ARM_UC_IS_ERROR(result)) {
leothedragon 0:8f0bb79ddd48 208 ARM_UCS_LWM2M_SOURCE_SetError(result);
leothedragon 0:8f0bb79ddd48 209 }
leothedragon 0:8f0bb79ddd48 210 return result;
leothedragon 0:8f0bb79ddd48 211 }
leothedragon 0:8f0bb79ddd48 212
leothedragon 0:8f0bb79ddd48 213 /**
leothedragon 0:8f0bb79ddd48 214 * @brief Retrieve manifest from the default location.
leothedragon 0:8f0bb79ddd48 215 * @details Manifest is stored in supplied buffer.
leothedragon 0:8f0bb79ddd48 216 * Event is generated once manifest is in buffer.
leothedragon 0:8f0bb79ddd48 217 *
leothedragon 0:8f0bb79ddd48 218 * @param buffer Struct containing byte array, maximum size, and actual size.
leothedragon 0:8f0bb79ddd48 219 * @return Error code.
leothedragon 0:8f0bb79ddd48 220 */
leothedragon 0:8f0bb79ddd48 221 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestDefault(arm_uc_buffer_t *buffer,
leothedragon 0:8f0bb79ddd48 222 uint32_t offset)
leothedragon 0:8f0bb79ddd48 223 {
leothedragon 0:8f0bb79ddd48 224 ARM_UC_INIT_ERROR(result, SRCE_ERR_INVALID_PARAMETER);
leothedragon 0:8f0bb79ddd48 225
leothedragon 0:8f0bb79ddd48 226 /* copy manifest from cache into buffer */
leothedragon 0:8f0bb79ddd48 227 if ((buffer != NULL) &&
leothedragon 0:8f0bb79ddd48 228 (buffer->ptr != NULL) &&
leothedragon 0:8f0bb79ddd48 229 (arm_ucs_manifest_buffer != NULL) &&
leothedragon 0:8f0bb79ddd48 230 (arm_ucs_manifest_length != 0) &&
leothedragon 0:8f0bb79ddd48 231 (offset < arm_ucs_manifest_length)) {
leothedragon 0:8f0bb79ddd48 232 /* remaining length based on offset request */
leothedragon 0:8f0bb79ddd48 233 uint16_t length = arm_ucs_manifest_length - offset;
leothedragon 0:8f0bb79ddd48 234
leothedragon 0:8f0bb79ddd48 235 /* set actual length based on buffer size */
leothedragon 0:8f0bb79ddd48 236 if (length > buffer->size_max) {
leothedragon 0:8f0bb79ddd48 237 length = buffer->size_max;
leothedragon 0:8f0bb79ddd48 238 }
leothedragon 0:8f0bb79ddd48 239
leothedragon 0:8f0bb79ddd48 240 /* size check */
leothedragon 0:8f0bb79ddd48 241 if (length > 0) {
leothedragon 0:8f0bb79ddd48 242 /* copy manifest from local buffer to external buffer */
leothedragon 0:8f0bb79ddd48 243 memcpy(buffer->ptr, &arm_ucs_manifest_buffer[offset], length);
leothedragon 0:8f0bb79ddd48 244 buffer->size = length;
leothedragon 0:8f0bb79ddd48 245
leothedragon 0:8f0bb79ddd48 246 /* delete local buffer once the entire manifest has been read */
leothedragon 0:8f0bb79ddd48 247 if (offset + length >= arm_ucs_manifest_length) {
leothedragon 0:8f0bb79ddd48 248 delete[] arm_ucs_manifest_buffer;
leothedragon 0:8f0bb79ddd48 249 arm_ucs_manifest_buffer = NULL;
leothedragon 0:8f0bb79ddd48 250 arm_ucs_manifest_length = 0;
leothedragon 0:8f0bb79ddd48 251 }
leothedragon 0:8f0bb79ddd48 252
leothedragon 0:8f0bb79ddd48 253 ARM_UC_SET_ERROR(result, ERR_NONE);
leothedragon 0:8f0bb79ddd48 254
leothedragon 0:8f0bb79ddd48 255 /* signal event handler that manifest has been copied to buffer */
leothedragon 0:8f0bb79ddd48 256 if (ARM_UCS_EventHandler) {
leothedragon 0:8f0bb79ddd48 257 ARM_UC_PostCallback(&callbackNodeManifest,
leothedragon 0:8f0bb79ddd48 258 ARM_UCS_EventHandler,
leothedragon 0:8f0bb79ddd48 259 EVENT_MANIFEST);
leothedragon 0:8f0bb79ddd48 260 }
leothedragon 0:8f0bb79ddd48 261 }
leothedragon 0:8f0bb79ddd48 262 }
leothedragon 0:8f0bb79ddd48 263
leothedragon 0:8f0bb79ddd48 264 if (ARM_UC_IS_ERROR(result)) {
leothedragon 0:8f0bb79ddd48 265 ARM_UCS_LWM2M_SOURCE_SetError(result);
leothedragon 0:8f0bb79ddd48 266 }
leothedragon 0:8f0bb79ddd48 267 return result;
leothedragon 0:8f0bb79ddd48 268 }
leothedragon 0:8f0bb79ddd48 269
leothedragon 0:8f0bb79ddd48 270 static void ARM_UCS_PackageCallback(const uint8_t *buffer, uint16_t length)
leothedragon 0:8f0bb79ddd48 271 {
leothedragon 0:8f0bb79ddd48 272 uint32_t event_code = EVENT_ERROR;
leothedragon 0:8f0bb79ddd48 273
leothedragon 0:8f0bb79ddd48 274 if (arm_ucs_manifest_buffer) {
leothedragon 0:8f0bb79ddd48 275 UC_SRCE_ERR_MSG("received new manifest before reading the old one");
leothedragon 0:8f0bb79ddd48 276
leothedragon 0:8f0bb79ddd48 277 /* delete old buffer to make space for the new one */
leothedragon 0:8f0bb79ddd48 278 delete[] arm_ucs_manifest_buffer;
leothedragon 0:8f0bb79ddd48 279 arm_ucs_manifest_length = 0;
leothedragon 0:8f0bb79ddd48 280 }
leothedragon 0:8f0bb79ddd48 281
leothedragon 0:8f0bb79ddd48 282 /* allocate a local buffer of the same size as the manifest */
leothedragon 0:8f0bb79ddd48 283 arm_ucs_manifest_buffer = new uint8_t[length];
leothedragon 0:8f0bb79ddd48 284
leothedragon 0:8f0bb79ddd48 285 if (arm_ucs_manifest_buffer) {
leothedragon 0:8f0bb79ddd48 286 /* copy manifest from payload to local buffer */
leothedragon 0:8f0bb79ddd48 287 memcpy(arm_ucs_manifest_buffer, buffer, length);
leothedragon 0:8f0bb79ddd48 288 arm_ucs_manifest_length = length;
leothedragon 0:8f0bb79ddd48 289
leothedragon 0:8f0bb79ddd48 290 event_code = EVENT_NOTIFICATION;
leothedragon 0:8f0bb79ddd48 291 }
leothedragon 0:8f0bb79ddd48 292
leothedragon 0:8f0bb79ddd48 293 /* signal event handler with result */
leothedragon 0:8f0bb79ddd48 294 if (ARM_UCS_EventHandler) {
leothedragon 0:8f0bb79ddd48 295 ARM_UC_PostCallback(&callbackNodeNotification,
leothedragon 0:8f0bb79ddd48 296 ARM_UCS_EventHandler,
leothedragon 0:8f0bb79ddd48 297 event_code);
leothedragon 0:8f0bb79ddd48 298 }
leothedragon 0:8f0bb79ddd48 299 }
leothedragon 0:8f0bb79ddd48 300
leothedragon 0:8f0bb79ddd48 301
leothedragon 0:8f0bb79ddd48 302 /**
leothedragon 0:8f0bb79ddd48 303 * @brief Cost estimation for retrieving firmware from URL.
leothedragon 0:8f0bb79ddd48 304 * @details The estimation can vary over time and should not be cached too long.
leothedragon 0:8f0bb79ddd48 305 * 0x00000000 - The firmware is already downloaded.
leothedragon 0:8f0bb79ddd48 306 * 0xFFFFFFFF - Cannot retrieve firmware from this Source.
leothedragon 0:8f0bb79ddd48 307 *
leothedragon 0:8f0bb79ddd48 308 * @param uri URI struct with firmware location.
leothedragon 0:8f0bb79ddd48 309 * @param cost Pointer to variable for the return value.
leothedragon 0:8f0bb79ddd48 310 * @return Error code.
leothedragon 0:8f0bb79ddd48 311 */
leothedragon 0:8f0bb79ddd48 312 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetFirmwareURLCost(arm_uc_uri_t *uri,
leothedragon 0:8f0bb79ddd48 313 uint32_t *cost)
leothedragon 0:8f0bb79ddd48 314 {
leothedragon 0:8f0bb79ddd48 315 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_GetFirmwareURLCost");
leothedragon 0:8f0bb79ddd48 316
leothedragon 0:8f0bb79ddd48 317 ARM_UC_INIT_ERROR(result, SRCE_ERR_INVALID_PARAMETER);
leothedragon 0:8f0bb79ddd48 318
leothedragon 0:8f0bb79ddd48 319 #if defined(ARM_UC_FEATURE_FW_SOURCE_COAP) && (ARM_UC_FEATURE_FW_SOURCE_COAP == 1)
leothedragon 0:8f0bb79ddd48 320 /* not supported - return default cost regardless of actual uri location */
leothedragon 0:8f0bb79ddd48 321 if ((uri != 0) && (cost != 0)) {
leothedragon 0:8f0bb79ddd48 322 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_GetFirmwareURLCost uri and cost");
leothedragon 0:8f0bb79ddd48 323 *cost = ARM_UCS_DEFAULT_COST;
leothedragon 0:8f0bb79ddd48 324 result.code = ERR_NONE ;
leothedragon 0:8f0bb79ddd48 325 }
leothedragon 0:8f0bb79ddd48 326 #else
leothedragon 0:8f0bb79ddd48 327 /* not supported */
leothedragon 0:8f0bb79ddd48 328 if (cost != 0) {
leothedragon 0:8f0bb79ddd48 329 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_GetFirmwareURLCost cost 0xFFFFFFFF");
leothedragon 0:8f0bb79ddd48 330 *cost = 0xFFFFFFFF;
leothedragon 0:8f0bb79ddd48 331 result.code = ERR_NONE ;
leothedragon 0:8f0bb79ddd48 332 }
leothedragon 0:8f0bb79ddd48 333 #endif
leothedragon 0:8f0bb79ddd48 334 if (ARM_UC_IS_ERROR(result)) {
leothedragon 0:8f0bb79ddd48 335 ARM_UCS_LWM2M_SOURCE_SetError(result);
leothedragon 0:8f0bb79ddd48 336 }
leothedragon 0:8f0bb79ddd48 337 return result;
leothedragon 0:8f0bb79ddd48 338 }
leothedragon 0:8f0bb79ddd48 339
leothedragon 0:8f0bb79ddd48 340
leothedragon 0:8f0bb79ddd48 341 /**
leothedragon 0:8f0bb79ddd48 342 * @brief Retrieve firmware fragment.
leothedragon 0:8f0bb79ddd48 343 * @details Firmware fragment is stored in supplied buffer.
leothedragon 0:8f0bb79ddd48 344 * Event is generated once fragment is in buffer.
leothedragon 0:8f0bb79ddd48 345 *
leothedragon 0:8f0bb79ddd48 346 * @param uri URI struct with firmware location.
leothedragon 0:8f0bb79ddd48 347 * @param buffer Struct containing byte array, maximum size, and actual size.
leothedragon 0:8f0bb79ddd48 348 * @param offset Firmware offset to retrieve fragment from.
leothedragon 0:8f0bb79ddd48 349 * @return Error code.
leothedragon 0:8f0bb79ddd48 350 */
leothedragon 0:8f0bb79ddd48 351 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment(arm_uc_uri_t *uri,
leothedragon 0:8f0bb79ddd48 352 arm_uc_buffer_t *buffer,
leothedragon 0:8f0bb79ddd48 353 uint32_t offset)
leothedragon 0:8f0bb79ddd48 354 {
leothedragon 0:8f0bb79ddd48 355
leothedragon 0:8f0bb79ddd48 356 arm_uc_error_t retval = { .code = SRCE_ERR_INVALID_PARAMETER };
leothedragon 0:8f0bb79ddd48 357 #if defined(ARM_UC_FEATURE_FW_SOURCE_COAP) && (ARM_UC_FEATURE_FW_SOURCE_COAP == 1)
leothedragon 0:8f0bb79ddd48 358 if (uri == NULL || buffer == NULL || FirmwareUpdateResource::getM2MInterface() == NULL) {
leothedragon 0:8f0bb79ddd48 359 return retval;
leothedragon 0:8f0bb79ddd48 360 }
leothedragon 0:8f0bb79ddd48 361
leothedragon 0:8f0bb79ddd48 362 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment: %s %s, buffer size: %" PRIu32 ", buffer max: %" PRIu32
leothedragon 0:8f0bb79ddd48 363 " offset: %" PRIu32, (const char *)uri->ptr, uri->path, buffer->size, buffer->size_max, offset);
leothedragon 0:8f0bb79ddd48 364 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment: total file size %" PRIu32 ", received file size %" PRIu32,
leothedragon 0:8f0bb79ddd48 365 (uint32_t)arm_uc_total_file_size, (uint32_t)arm_uc_received_file_size);
leothedragon 0:8f0bb79ddd48 366
leothedragon 0:8f0bb79ddd48 367 /*
leothedragon 0:8f0bb79ddd48 368 * NOTE: we are using M2MInterface API "get_data_request()" asynchronously, so first call to GetFirmwareFragment()
leothedragon 0:8f0bb79ddd48 369 * will not return anything in the buffer. Instead we will get COAP blocks into callback arm_uc_get_data_req_callback()
leothedragon 0:8f0bb79ddd48 370 * where we will copy those to our internal storage_buffer. When storage_buffer has enough data
leothedragon 0:8f0bb79ddd48 371 * (more or eq than buffer->size_max == Storage Page size) we will copy data from it to output buffer
leothedragon 0:8f0bb79ddd48 372 * and indicate to Hub state machine using event EVENT_FIRMWARE
leothedragon 0:8f0bb79ddd48 373 */
leothedragon 0:8f0bb79ddd48 374 if (offset == 0) {
leothedragon 0:8f0bb79ddd48 375 // First fragment
leothedragon 0:8f0bb79ddd48 376 storage_buffer.size = 0;
leothedragon 0:8f0bb79ddd48 377 arm_uc_received_file_size = 0;
leothedragon 0:8f0bb79ddd48 378 arm_uc_total_file_size = 0;
leothedragon 0:8f0bb79ddd48 379 } else if (arm_uc_received_file_size == 0) {
leothedragon 0:8f0bb79ddd48 380 // The received file size was reset to zero indicating that we have received the full payload
leothedragon 0:8f0bb79ddd48 381 // as indicated by the server but we are asked to carry on downloading from the given offset.
leothedragon 0:8f0bb79ddd48 382 // This indicates a mismatch between the actual payload size in the server and that given in the manifest.
leothedragon 0:8f0bb79ddd48 383 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment: payload size indicated in manifest is bigger than that reported by server!");
leothedragon 0:8f0bb79ddd48 384 if (ARM_UCS_EventHandler) {
leothedragon 0:8f0bb79ddd48 385 ARM_UC_PostCallback(&callbackNodeManifest,
leothedragon 0:8f0bb79ddd48 386 ARM_UCS_EventHandler,
leothedragon 0:8f0bb79ddd48 387 EVENT_ERROR);
leothedragon 0:8f0bb79ddd48 388 }
leothedragon 0:8f0bb79ddd48 389 return retval;
leothedragon 0:8f0bb79ddd48 390 }
leothedragon 0:8f0bb79ddd48 391
leothedragon 0:8f0bb79ddd48 392 output_buffer_ptr = buffer;
leothedragon 0:8f0bb79ddd48 393 free(copy_full_url);
leothedragon 0:8f0bb79ddd48 394 copy_full_url = (char *)malloc(arm_uc_calculate_full_uri_length(uri));
leothedragon 0:8f0bb79ddd48 395 if (copy_full_url == NULL) {
leothedragon 0:8f0bb79ddd48 396 //TODO to return SRCE_ERR_OUT_OF_MEMORY
leothedragon 0:8f0bb79ddd48 397 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment: ERROR OUT OF MEMORY for uri copy!");
leothedragon 0:8f0bb79ddd48 398 return retval;
leothedragon 0:8f0bb79ddd48 399 }
leothedragon 0:8f0bb79ddd48 400 if (uri->scheme == URI_SCHEME_COAPS) {
leothedragon 0:8f0bb79ddd48 401 strcpy(copy_full_url, UC_COAPS_STRING);
leothedragon 0:8f0bb79ddd48 402 } else if (uri->scheme == URI_SCHEME_HTTP) {
leothedragon 0:8f0bb79ddd48 403 strcpy(copy_full_url, UC_HTTP_STRING);
leothedragon 0:8f0bb79ddd48 404 } else {
leothedragon 0:8f0bb79ddd48 405 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment: Not Supported SCHEME! length of copy url: %u",
leothedragon 0:8f0bb79ddd48 406 sizeof(copy_full_url));
leothedragon 0:8f0bb79ddd48 407 return retval;
leothedragon 0:8f0bb79ddd48 408 }
leothedragon 0:8f0bb79ddd48 409 strcat(copy_full_url, (const char *)uri->ptr);
leothedragon 0:8f0bb79ddd48 410 strcat(copy_full_url, uri->path);
leothedragon 0:8f0bb79ddd48 411
leothedragon 0:8f0bb79ddd48 412 if ((arm_uc_received_file_size == arm_uc_total_file_size &&
leothedragon 0:8f0bb79ddd48 413 arm_uc_received_file_size != 0)) {
leothedragon 0:8f0bb79ddd48 414
leothedragon 0:8f0bb79ddd48 415 // If last block - write to buffer and complete
leothedragon 0:8f0bb79ddd48 416 if (storage_buffer.ptr &&
leothedragon 0:8f0bb79ddd48 417 (arm_uc_received_file_size == arm_uc_total_file_size)) {
leothedragon 0:8f0bb79ddd48 418 memcpy(buffer->ptr, storage_buffer.ptr, storage_buffer.size);
leothedragon 0:8f0bb79ddd48 419 buffer->size = storage_buffer.size;
leothedragon 0:8f0bb79ddd48 420 memmove(storage_buffer.ptr, storage_buffer.ptr + storage_buffer.size, (storage_buffer.size_max - storage_buffer.size));
leothedragon 0:8f0bb79ddd48 421 storage_buffer.size -= buffer->size;
leothedragon 0:8f0bb79ddd48 422 }
leothedragon 0:8f0bb79ddd48 423
leothedragon 0:8f0bb79ddd48 424 // We were waiting for one more state machine cycle for previous write to complete
leothedragon 0:8f0bb79ddd48 425 // Now we can return with EVENT_FIRMWARE so that main state machine changes properly
leothedragon 0:8f0bb79ddd48 426 if (ARM_UCS_EventHandler) {
leothedragon 0:8f0bb79ddd48 427 ARM_UC_PostCallback(&callbackNodeManifest,
leothedragon 0:8f0bb79ddd48 428 ARM_UCS_EventHandler,
leothedragon 0:8f0bb79ddd48 429 EVENT_FIRMWARE);
leothedragon 0:8f0bb79ddd48 430 }
leothedragon 0:8f0bb79ddd48 431 retval.code = ERR_NONE;
leothedragon 0:8f0bb79ddd48 432 arm_uc_received_file_size = 0;
leothedragon 0:8f0bb79ddd48 433 arm_uc_total_file_size = 0;
leothedragon 0:8f0bb79ddd48 434 } else if (!arm_uc_get_data_request_transaction_ongoing) {
leothedragon 0:8f0bb79ddd48 435 // We need to get request for next block of data
leothedragon 0:8f0bb79ddd48 436 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment: Issue new get request for uri: %s, offset: %" PRIu32,
leothedragon 0:8f0bb79ddd48 437 copy_full_url, (uint32_t)arm_uc_received_file_size);
leothedragon 0:8f0bb79ddd48 438 if (FirmwareUpdateResource::getM2MInterface()) {
leothedragon 0:8f0bb79ddd48 439
leothedragon 0:8f0bb79ddd48 440 FirmwareUpdateResource::getM2MInterface()->get_data_request(download_type,
leothedragon 0:8f0bb79ddd48 441 copy_full_url,
leothedragon 0:8f0bb79ddd48 442 arm_uc_received_file_size,
leothedragon 0:8f0bb79ddd48 443 true,
leothedragon 0:8f0bb79ddd48 444 arm_uc_get_data_req_callback,
leothedragon 0:8f0bb79ddd48 445 arm_uc_get_data_req_error_callback,
leothedragon 0:8f0bb79ddd48 446 FirmwareUpdateResource::getM2MInterface());
leothedragon 0:8f0bb79ddd48 447
leothedragon 0:8f0bb79ddd48 448 arm_uc_get_data_request_transaction_ongoing = true;
leothedragon 0:8f0bb79ddd48 449
leothedragon 0:8f0bb79ddd48 450 retval.code = ERR_NONE;
leothedragon 0:8f0bb79ddd48 451 }
leothedragon 0:8f0bb79ddd48 452 } else {
leothedragon 0:8f0bb79ddd48 453 // There is not enough data in Storage buffer yet
leothedragon 0:8f0bb79ddd48 454 // AND We have Async get_data_request already ongoing
leothedragon 0:8f0bb79ddd48 455 // -> Do nothing we should not get here?
leothedragon 0:8f0bb79ddd48 456 // This can happen if GetFirmwareFragment is called again before
leothedragon 0:8f0bb79ddd48 457 // the previous get completed with buffer and EVENT_FIRMWARE
leothedragon 0:8f0bb79ddd48 458 UC_SRCE_ERR_MSG("Internal error: BLOCK - data request already ongoing");
leothedragon 0:8f0bb79ddd48 459 }
leothedragon 0:8f0bb79ddd48 460 if (ARM_UC_IS_ERROR(retval)) {
leothedragon 0:8f0bb79ddd48 461 ARM_UCS_LWM2M_SOURCE_SetError(retval);
leothedragon 0:8f0bb79ddd48 462 }
leothedragon 0:8f0bb79ddd48 463 return retval;
leothedragon 0:8f0bb79ddd48 464 #else
leothedragon 0:8f0bb79ddd48 465 (void) uri;
leothedragon 0:8f0bb79ddd48 466 (void) buffer;
leothedragon 0:8f0bb79ddd48 467 (void) offset;
leothedragon 0:8f0bb79ddd48 468 return retval;
leothedragon 0:8f0bb79ddd48 469 #endif //ARM_UC_FEATURE_FW_SOURCE_COAP
leothedragon 0:8f0bb79ddd48 470 }
leothedragon 0:8f0bb79ddd48 471
leothedragon 0:8f0bb79ddd48 472 #if defined(ARM_UC_FEATURE_FW_SOURCE_COAP) && (ARM_UC_FEATURE_FW_SOURCE_COAP == 1)
leothedragon 0:8f0bb79ddd48 473 void arm_uc_get_data_req_callback(const uint8_t *buffer, size_t buffer_size, size_t total_size, bool last_block,
leothedragon 0:8f0bb79ddd48 474 void *context)
leothedragon 0:8f0bb79ddd48 475 {
leothedragon 0:8f0bb79ddd48 476 (void)last_block;
leothedragon 0:8f0bb79ddd48 477
leothedragon 0:8f0bb79ddd48 478 UC_SRCE_TRACE("get_data_req_callback: %" PRIu32 ", %" PRIu32, (uint32_t)buffer_size, (uint32_t)total_size);
leothedragon 0:8f0bb79ddd48 479 M2MInterface *interface = (M2MInterface *)context;
leothedragon 0:8f0bb79ddd48 480
leothedragon 0:8f0bb79ddd48 481 if (arm_uc_received_file_size == 0) {
leothedragon 0:8f0bb79ddd48 482 arm_uc_total_file_size = total_size;
leothedragon 0:8f0bb79ddd48 483 }
leothedragon 0:8f0bb79ddd48 484
leothedragon 0:8f0bb79ddd48 485 arm_uc_received_file_size += buffer_size;
leothedragon 0:8f0bb79ddd48 486 UC_SRCE_TRACE("get_data_req_callback: received %" PRIu32 "/%" PRIu32, (uint32_t)arm_uc_received_file_size,
leothedragon 0:8f0bb79ddd48 487 (uint32_t)arm_uc_total_file_size);
leothedragon 0:8f0bb79ddd48 488
leothedragon 0:8f0bb79ddd48 489 if (arm_uc_received_file_size == arm_uc_total_file_size) {
leothedragon 0:8f0bb79ddd48 490 UC_SRCE_TRACE("get_data_req_callback: transfer completed\n");
leothedragon 0:8f0bb79ddd48 491 }
leothedragon 0:8f0bb79ddd48 492
leothedragon 0:8f0bb79ddd48 493 /*
leothedragon 0:8f0bb79ddd48 494 * FLOW:
leothedragon 0:8f0bb79ddd48 495 * 1. If there is space in Storage buffer for the incoming buffer -> copy buffer to storage buffer
leothedragon 0:8f0bb79ddd48 496 * 2. Else signal error event EVENT_ERROR_BUFFER_SIZE
leothedragon 0:8f0bb79ddd48 497 */
leothedragon 0:8f0bb79ddd48 498 // Check there is space available in the storage buffer
leothedragon 0:8f0bb79ddd48 499 if (storage_buffer.size_max - storage_buffer.size >= buffer_size) {
leothedragon 0:8f0bb79ddd48 500 memcpy(storage_buffer.ptr + storage_buffer.size, buffer, buffer_size);
leothedragon 0:8f0bb79ddd48 501 storage_buffer.size += buffer_size;
leothedragon 0:8f0bb79ddd48 502 } else {
leothedragon 0:8f0bb79ddd48 503 // Error - no space available, signal it to source manager
leothedragon 0:8f0bb79ddd48 504 UC_SRCE_TRACE("arm_uc_get_data_req_callback: Storage Buffer OVERFLOW ERROR!! \n");
leothedragon 0:8f0bb79ddd48 505 if (ARM_UCS_EventHandler) {
leothedragon 0:8f0bb79ddd48 506 ARM_UC_PostCallback(&callbackNodeManifest,
leothedragon 0:8f0bb79ddd48 507 ARM_UCS_EventHandler,
leothedragon 0:8f0bb79ddd48 508 EVENT_ERROR_BUFFER_SIZE);
leothedragon 0:8f0bb79ddd48 509 }
leothedragon 0:8f0bb79ddd48 510 return;
leothedragon 0:8f0bb79ddd48 511 }
leothedragon 0:8f0bb79ddd48 512
leothedragon 0:8f0bb79ddd48 513 /*
leothedragon 0:8f0bb79ddd48 514 * FLOW:
leothedragon 0:8f0bb79ddd48 515 * 1. If there is enough data in storage-buffer now to complete to output buffer, copy now and indicate with EVENT_FIRMWARE
leothedragon 0:8f0bb79ddd48 516 * to continue to write -cycle
leothedragon 0:8f0bb79ddd48 517 * 2. Else if this is the last block of data, copy the remaining (<size_max) to output buffer and indicate with
leothedragon 0:8f0bb79ddd48 518 * EVENT_FIRMWARE to continue to write-cycle
leothedragon 0:8f0bb79ddd48 519 * 3. Else Request new block of data using API get_data_request
leothedragon 0:8f0bb79ddd48 520 */
leothedragon 0:8f0bb79ddd48 521 if (storage_buffer.size >= output_buffer_ptr->size_max) {
leothedragon 0:8f0bb79ddd48 522 // 1. We have received into Storage buffer at least one page size of data
leothedragon 0:8f0bb79ddd48 523 // -> Let's return it to UC Hub so that it can be written
leothedragon 0:8f0bb79ddd48 524 UC_SRCE_TRACE("arm_uc_get_data_req_callback: return with Storage buffer size: %" PRIu32 ", buffer size: %" PRIu32,
leothedragon 0:8f0bb79ddd48 525 storage_buffer.size, output_buffer_ptr->size_max);
leothedragon 0:8f0bb79ddd48 526 if (storage_buffer.ptr) {
leothedragon 0:8f0bb79ddd48 527 memcpy(output_buffer_ptr->ptr, storage_buffer.ptr, output_buffer_ptr->size_max);
leothedragon 0:8f0bb79ddd48 528 //storage_buffer.ptr += buffer->size_max;
leothedragon 0:8f0bb79ddd48 529 memmove(storage_buffer.ptr, storage_buffer.ptr + output_buffer_ptr->size_max,
leothedragon 0:8f0bb79ddd48 530 (storage_buffer.size_max - output_buffer_ptr->size_max));
leothedragon 0:8f0bb79ddd48 531 storage_buffer.size -= output_buffer_ptr->size_max;
leothedragon 0:8f0bb79ddd48 532 output_buffer_ptr->size = output_buffer_ptr->size_max;
leothedragon 0:8f0bb79ddd48 533 }
leothedragon 0:8f0bb79ddd48 534
leothedragon 0:8f0bb79ddd48 535 if (ARM_UCS_EventHandler) {
leothedragon 0:8f0bb79ddd48 536 ARM_UC_PostCallback(&callbackNodeManifest,
leothedragon 0:8f0bb79ddd48 537 ARM_UCS_EventHandler,
leothedragon 0:8f0bb79ddd48 538 EVENT_FIRMWARE);
leothedragon 0:8f0bb79ddd48 539 }
leothedragon 0:8f0bb79ddd48 540 arm_uc_get_data_request_transaction_ongoing = false;
leothedragon 0:8f0bb79ddd48 541 } else if (arm_uc_received_file_size == arm_uc_total_file_size &&
leothedragon 0:8f0bb79ddd48 542 arm_uc_received_file_size != 0) {
leothedragon 0:8f0bb79ddd48 543
leothedragon 0:8f0bb79ddd48 544 // 2. this is the last block of data - copy to output buffer and complete with EVENT_FIRMWARE
leothedragon 0:8f0bb79ddd48 545 if (storage_buffer.ptr &&
leothedragon 0:8f0bb79ddd48 546 (arm_uc_received_file_size == arm_uc_total_file_size)) {
leothedragon 0:8f0bb79ddd48 547 memcpy(output_buffer_ptr->ptr, storage_buffer.ptr, storage_buffer.size);
leothedragon 0:8f0bb79ddd48 548 output_buffer_ptr->size = storage_buffer.size;
leothedragon 0:8f0bb79ddd48 549
leothedragon 0:8f0bb79ddd48 550 memmove(storage_buffer.ptr, storage_buffer.ptr + storage_buffer.size, (storage_buffer.size_max - storage_buffer.size));
leothedragon 0:8f0bb79ddd48 551 storage_buffer.size = 0;
leothedragon 0:8f0bb79ddd48 552 }
leothedragon 0:8f0bb79ddd48 553
leothedragon 0:8f0bb79ddd48 554 // We were waiting for one more state machine cycle for previous write to complete
leothedragon 0:8f0bb79ddd48 555 // Now we can return with EVENT_FIRMWARE so that main state machine changes properly
leothedragon 0:8f0bb79ddd48 556 if (ARM_UCS_EventHandler) {
leothedragon 0:8f0bb79ddd48 557 ARM_UC_PostCallback(&callbackNodeManifest,
leothedragon 0:8f0bb79ddd48 558 ARM_UCS_EventHandler,
leothedragon 0:8f0bb79ddd48 559 EVENT_FIRMWARE);
leothedragon 0:8f0bb79ddd48 560 }
leothedragon 0:8f0bb79ddd48 561 arm_uc_get_data_request_transaction_ongoing = false;
leothedragon 0:8f0bb79ddd48 562 free(copy_full_url);
leothedragon 0:8f0bb79ddd48 563 copy_full_url = NULL;
leothedragon 0:8f0bb79ddd48 564 arm_uc_received_file_size = 0;
leothedragon 0:8f0bb79ddd48 565 arm_uc_total_file_size = 0;
leothedragon 0:8f0bb79ddd48 566 } else {
leothedragon 0:8f0bb79ddd48 567 // 3. We want to issue new get data
leothedragon 0:8f0bb79ddd48 568 UC_SRCE_TRACE("arm_uc_get_data_req_callback: Issue new get request for uri: %s, offset: %" PRIu32, copy_full_url,
leothedragon 0:8f0bb79ddd48 569 (uint32_t)arm_uc_received_file_size);
leothedragon 0:8f0bb79ddd48 570 interface->get_data_request(download_type,
leothedragon 0:8f0bb79ddd48 571 copy_full_url,
leothedragon 0:8f0bb79ddd48 572 arm_uc_received_file_size,
leothedragon 0:8f0bb79ddd48 573 true,
leothedragon 0:8f0bb79ddd48 574 arm_uc_get_data_req_callback,
leothedragon 0:8f0bb79ddd48 575 arm_uc_get_data_req_error_callback,
leothedragon 0:8f0bb79ddd48 576 interface);
leothedragon 0:8f0bb79ddd48 577 arm_uc_get_data_request_transaction_ongoing = true;
leothedragon 0:8f0bb79ddd48 578 }
leothedragon 0:8f0bb79ddd48 579 #ifdef ARM_UC_COAP_DATA_PRINTOUT
leothedragon 0:8f0bb79ddd48 580 if (buffer) {
leothedragon 0:8f0bb79ddd48 581 uint32_t i = 0;
leothedragon 0:8f0bb79ddd48 582 int row_len = 40;
leothedragon 0:8f0bb79ddd48 583 uint32_t max_length = 2048;
leothedragon 0:8f0bb79ddd48 584
leothedragon 0:8f0bb79ddd48 585 while (i < buffer_size && i < max_length) {
leothedragon 0:8f0bb79ddd48 586 if (i + row_len > buffer_size) {
leothedragon 0:8f0bb79ddd48 587 row_len = buffer_size - i;
leothedragon 0:8f0bb79ddd48 588 }
leothedragon 0:8f0bb79ddd48 589 UC_SRCE_TRACE("Payload:\t\t%s", tr_array(buffer + i, row_len)); // in HEX
leothedragon 0:8f0bb79ddd48 590
leothedragon 0:8f0bb79ddd48 591 i += row_len;
leothedragon 0:8f0bb79ddd48 592 }
leothedragon 0:8f0bb79ddd48 593
leothedragon 0:8f0bb79ddd48 594 }
leothedragon 0:8f0bb79ddd48 595 #endif
leothedragon 0:8f0bb79ddd48 596 }
leothedragon 0:8f0bb79ddd48 597
leothedragon 0:8f0bb79ddd48 598 void arm_uc_get_data_req_error_callback(get_data_req_error_t error_code, void *context)
leothedragon 0:8f0bb79ddd48 599 {
leothedragon 0:8f0bb79ddd48 600 UC_SRCE_TRACE("get_data_req_error_callback: ERROR: %u\n", error_code);
leothedragon 0:8f0bb79ddd48 601 arm_uc_received_file_size = 0;
leothedragon 0:8f0bb79ddd48 602 arm_uc_total_file_size = 0;
leothedragon 0:8f0bb79ddd48 603 arm_uc_get_data_request_transaction_ongoing = false;
leothedragon 0:8f0bb79ddd48 604 free(copy_full_url);
leothedragon 0:8f0bb79ddd48 605 copy_full_url = NULL;
leothedragon 0:8f0bb79ddd48 606 download_type = FIRMWARE_DOWNLOAD;
leothedragon 0:8f0bb79ddd48 607 if (ARM_UCS_EventHandler) {
leothedragon 0:8f0bb79ddd48 608 ARM_UC_PostCallback(&callbackNodeManifest,
leothedragon 0:8f0bb79ddd48 609 ARM_UCS_EventHandler,
leothedragon 0:8f0bb79ddd48 610 EVENT_ERROR);
leothedragon 0:8f0bb79ddd48 611 }
leothedragon 0:8f0bb79ddd48 612 }
leothedragon 0:8f0bb79ddd48 613 #endif //ARM_UC_FEATURE_FW_SOURCE_COAP
leothedragon 0:8f0bb79ddd48 614
leothedragon 0:8f0bb79ddd48 615 /*****************************************************************************/
leothedragon 0:8f0bb79ddd48 616 /* Capabilities not supported by this source */
leothedragon 0:8f0bb79ddd48 617 /*****************************************************************************/
leothedragon 0:8f0bb79ddd48 618
leothedragon 0:8f0bb79ddd48 619 /**
leothedragon 0:8f0bb79ddd48 620 * @brief Cost estimation for retrieving manifest from URL.
leothedragon 0:8f0bb79ddd48 621 * @details The estimation can vary over time and should not be cached too long.
leothedragon 0:8f0bb79ddd48 622 * 0x00000000 - The manifest is already downloaded.
leothedragon 0:8f0bb79ddd48 623 * 0xFFFFFFFF - Cannot retrieve manifest from this Source.
leothedragon 0:8f0bb79ddd48 624 *
leothedragon 0:8f0bb79ddd48 625 * @param uri URI struct with manifest location.
leothedragon 0:8f0bb79ddd48 626 * @param cost Pointer to variable for the return value.
leothedragon 0:8f0bb79ddd48 627 * @return Error code.
leothedragon 0:8f0bb79ddd48 628 */
leothedragon 0:8f0bb79ddd48 629 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestURLCost(arm_uc_uri_t *uri,
leothedragon 0:8f0bb79ddd48 630 uint32_t *cost)
leothedragon 0:8f0bb79ddd48 631 {
leothedragon 0:8f0bb79ddd48 632 (void) uri;
leothedragon 0:8f0bb79ddd48 633 (void) cost;
leothedragon 0:8f0bb79ddd48 634
leothedragon 0:8f0bb79ddd48 635 ARM_UC_INIT_ERROR(result, SRCE_ERR_INVALID_PARAMETER);
leothedragon 0:8f0bb79ddd48 636
leothedragon 0:8f0bb79ddd48 637 /* not supported - return default cost regardless of actual uri location */
leothedragon 0:8f0bb79ddd48 638 if (cost) {
leothedragon 0:8f0bb79ddd48 639 *cost = 0xFFFFFFFF;
leothedragon 0:8f0bb79ddd48 640 ARM_UC_SET_ERROR(result, ERR_NONE);
leothedragon 0:8f0bb79ddd48 641 }
leothedragon 0:8f0bb79ddd48 642
leothedragon 0:8f0bb79ddd48 643 if (ARM_UC_IS_ERROR(result)) {
leothedragon 0:8f0bb79ddd48 644 ARM_UCS_LWM2M_SOURCE_SetError(result);
leothedragon 0:8f0bb79ddd48 645 }
leothedragon 0:8f0bb79ddd48 646 return result;
leothedragon 0:8f0bb79ddd48 647 }
leothedragon 0:8f0bb79ddd48 648
leothedragon 0:8f0bb79ddd48 649 /**
leothedragon 0:8f0bb79ddd48 650 * @brief Cost estimation for retrieving key table from URL.
leothedragon 0:8f0bb79ddd48 651 * @details The estimation can vary over time and should not be cached too long.
leothedragon 0:8f0bb79ddd48 652 * 0x00000000 - The firmware is already downloaded.
leothedragon 0:8f0bb79ddd48 653 * 0xFFFFFFFF - Cannot retrieve firmware from this Source.
leothedragon 0:8f0bb79ddd48 654 *
leothedragon 0:8f0bb79ddd48 655 * @param uri URI struct with keytable location.
leothedragon 0:8f0bb79ddd48 656 * @param cost Pointer to variable for the return value.
leothedragon 0:8f0bb79ddd48 657 * @return Error code.
leothedragon 0:8f0bb79ddd48 658 */
leothedragon 0:8f0bb79ddd48 659 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetKeytableURLCost(arm_uc_uri_t *uri,
leothedragon 0:8f0bb79ddd48 660 uint32_t *cost)
leothedragon 0:8f0bb79ddd48 661 {
leothedragon 0:8f0bb79ddd48 662 (void) uri;
leothedragon 0:8f0bb79ddd48 663 (void) cost;
leothedragon 0:8f0bb79ddd48 664
leothedragon 0:8f0bb79ddd48 665 ARM_UC_INIT_ERROR(result, SRCE_ERR_INVALID_PARAMETER);
leothedragon 0:8f0bb79ddd48 666
leothedragon 0:8f0bb79ddd48 667 /* not supported - return default cost regardless of actual uri location */
leothedragon 0:8f0bb79ddd48 668 if ((uri != 0) && (cost != 0)) {
leothedragon 0:8f0bb79ddd48 669 *cost = 0xFFFFFFFF;
leothedragon 0:8f0bb79ddd48 670 ARM_UC_SET_ERROR(result, ERR_NONE);
leothedragon 0:8f0bb79ddd48 671 }
leothedragon 0:8f0bb79ddd48 672
leothedragon 0:8f0bb79ddd48 673 if (ARM_UC_IS_ERROR(result)) {
leothedragon 0:8f0bb79ddd48 674 ARM_UCS_LWM2M_SOURCE_SetError(result);
leothedragon 0:8f0bb79ddd48 675 }
leothedragon 0:8f0bb79ddd48 676 return result;
leothedragon 0:8f0bb79ddd48 677 }
leothedragon 0:8f0bb79ddd48 678
leothedragon 0:8f0bb79ddd48 679 /**
leothedragon 0:8f0bb79ddd48 680 * @brief Retrieve manifest from URL.
leothedragon 0:8f0bb79ddd48 681 * @details Manifest is stored in supplied buffer.
leothedragon 0:8f0bb79ddd48 682 * Event is generated once manifest is in buffer.
leothedragon 0:8f0bb79ddd48 683 *
leothedragon 0:8f0bb79ddd48 684 * @param uri URI struct with manifest location.
leothedragon 0:8f0bb79ddd48 685 * @param buffer Struct containing byte array, maximum size, and actual size.
leothedragon 0:8f0bb79ddd48 686 *
leothedragon 0:8f0bb79ddd48 687 * @return Error code.
leothedragon 0:8f0bb79ddd48 688 */
leothedragon 0:8f0bb79ddd48 689 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestURL(arm_uc_uri_t *uri,
leothedragon 0:8f0bb79ddd48 690 arm_uc_buffer_t *buffer,
leothedragon 0:8f0bb79ddd48 691 uint32_t offset)
leothedragon 0:8f0bb79ddd48 692 {
leothedragon 0:8f0bb79ddd48 693 (void) uri;
leothedragon 0:8f0bb79ddd48 694 (void) buffer;
leothedragon 0:8f0bb79ddd48 695 (void) offset;
leothedragon 0:8f0bb79ddd48 696
leothedragon 0:8f0bb79ddd48 697 ARM_UC_INIT_ERROR(retval, SRCE_ERR_INVALID_PARAMETER);
leothedragon 0:8f0bb79ddd48 698
leothedragon 0:8f0bb79ddd48 699 if (ARM_UC_IS_ERROR(retval)) {
leothedragon 0:8f0bb79ddd48 700 ARM_UCS_LWM2M_SOURCE_SetError(retval);
leothedragon 0:8f0bb79ddd48 701 }
leothedragon 0:8f0bb79ddd48 702 return retval;
leothedragon 0:8f0bb79ddd48 703 }
leothedragon 0:8f0bb79ddd48 704
leothedragon 0:8f0bb79ddd48 705 /**
leothedragon 0:8f0bb79ddd48 706 * @brief Retrieve a key table from a URL.
leothedragon 0:8f0bb79ddd48 707 * @details Key table is stored in supplied buffer.
leothedragon 0:8f0bb79ddd48 708 * Event is generated once fragment is in buffer.
leothedragon 0:8f0bb79ddd48 709 *
leothedragon 0:8f0bb79ddd48 710 * @param uri URI struct with keytable location.
leothedragon 0:8f0bb79ddd48 711 * @param buffer Struct containing byte array, maximum size, and actual size.
leothedragon 0:8f0bb79ddd48 712 * @return Error code.
leothedragon 0:8f0bb79ddd48 713 */
leothedragon 0:8f0bb79ddd48 714 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetKeytableURL(arm_uc_uri_t *uri,
leothedragon 0:8f0bb79ddd48 715 arm_uc_buffer_t *buffer)
leothedragon 0:8f0bb79ddd48 716 {
leothedragon 0:8f0bb79ddd48 717 (void) uri;
leothedragon 0:8f0bb79ddd48 718 (void) buffer;
leothedragon 0:8f0bb79ddd48 719
leothedragon 0:8f0bb79ddd48 720 ARM_UC_INIT_ERROR(retval, SRCE_ERR_INVALID_PARAMETER);
leothedragon 0:8f0bb79ddd48 721
leothedragon 0:8f0bb79ddd48 722 if (ARM_UC_IS_ERROR(retval)) {
leothedragon 0:8f0bb79ddd48 723 ARM_UCS_LWM2M_SOURCE_SetError(retval);
leothedragon 0:8f0bb79ddd48 724 }
leothedragon 0:8f0bb79ddd48 725 return retval;
leothedragon 0:8f0bb79ddd48 726 }