Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FXAS21002 FXOS8700Q
lwm2m-source.cpp
00001 // ---------------------------------------------------------------------------- 00002 // Copyright 2016-2017 ARM Ltd. 00003 // 00004 // SPDX-License-Identifier: Apache-2.0 00005 // 00006 // Licensed under the Apache License, Version 2.0 (the "License"); 00007 // you may not use this file except in compliance with the License. 00008 // You may obtain a copy of the License at 00009 // 00010 // http://www.apache.org/licenses/LICENSE-2.0 00011 // 00012 // Unless required by applicable law or agreed to in writing, software 00013 // distributed under the License is distributed on an "AS IS" BASIS, 00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 // See the License for the specific language governing permissions and 00016 // limitations under the License. 00017 // ---------------------------------------------------------------------------- 00018 // Note: this macro is needed on armcc to get the the PRI*32 macros 00019 // from inttypes.h in a C++ code. 00020 #ifndef __STDC_FORMAT_MACROS 00021 #define __STDC_FORMAT_MACROS 00022 #endif 00023 00024 #include <inttypes.h> 00025 00026 #include "update-lwm2m-mbed-apis.h" 00027 #include "update-client-common/arm_uc_common.h" 00028 #include "update-client-lwm2m/lwm2m-source.h" 00029 #include "update-client-lwm2m/FirmwareUpdateResource.h" 00030 #include "update-client-lwm2m/DeviceMetadataResource.h" 00031 #include "update-client-common/arm_uc_config.h" 00032 00033 /* error management */ 00034 static arm_uc_error_t arm_ucs_lwm2m_error = {ERR_NONE}; 00035 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetError(void) { return arm_ucs_lwm2m_error; } 00036 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_SetError(arm_uc_error_t an_error) { return (arm_ucs_lwm2m_error = an_error); } 00037 00038 /* forward declaration */ 00039 static void ARM_UCS_PackageCallback(const uint8_t *buffer, uint16_t length); 00040 00041 /* local copy of the received manifest */ 00042 static uint8_t *arm_ucs_manifest_buffer = NULL; 00043 static uint16_t arm_ucs_manifest_length = 0; 00044 00045 /* callback function pointer and struct */ 00046 static void (*ARM_UCS_EventHandler)(uintptr_t event) = 0; 00047 static arm_uc_callback_t callbackNodeManifest = { NULL, 0, NULL, 0 }; 00048 static arm_uc_callback_t callbackNodeNotification = { NULL, 0, NULL, 0 }; 00049 00050 #if defined(ARM_UC_FEATURE_FW_SOURCE_COAP) && (ARM_UC_FEATURE_FW_SOURCE_COAP == 1) 00051 static bool arm_uc_get_data_request_transaction_ongoing = false; 00052 static size_t arm_uc_received_file_size = 0; 00053 static size_t arm_uc_total_file_size = 0; 00054 static void arm_uc_get_data_req_callback(const uint8_t *buffer, size_t buffer_size, size_t total_size, bool last_block, 00055 void *context); 00056 static void arm_uc_get_data_req_error_callback(get_data_req_error_t error_code, void *context); 00057 00058 #define ARM_UCS_DEFAULT_COST (900) 00059 #define ARM_UCS_HASH_LENGTH (40) 00060 00061 // The hub uses a double buffer system to speed up firmware download and storage 00062 #define BUFFER_SIZE_MAX (ARM_UC_BUFFER_SIZE / 2) // define size of the double buffers 00063 00064 #if BUFFER_SIZE_MAX < SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE 00065 #error MBED_CLOUD_CLIENT_UPDATE_BUFFER must be at least double the size of SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE 00066 #endif 00067 00068 // Set proper Storage buffer size with requirements: 00069 // 1. Storage buffer size >= Block size (SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE) 00070 // 1. & 2 AND is >= page size (BUFFER_SIZE_MAX) 00071 // 2. & 3. AND is multiple of Block size (X * SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE) 00072 #define STORAGE_BUFFER_SIZE max_storage(SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE, BUFFER_SIZE_MAX) 00073 // 1. 2. 3. 00074 #define max_storage(X,Y) ((X) > (Y) ? (X) : ( (Y%X==0) ? (Y) :(BLOCK_MULTIPLIER(X,Y)*X))) 00075 00076 #define BLOCK_MULTIPLIER(X,Y) ((Y/X)+1) 00077 00078 static uint8_t storage_message[STORAGE_BUFFER_SIZE]; 00079 static arm_uc_buffer_t storage_buffer = { 00080 .size_max = STORAGE_BUFFER_SIZE, 00081 .size = 0, 00082 .ptr = storage_message 00083 }; 00084 00085 static arm_uc_buffer_t *output_buffer_ptr = NULL; 00086 static char *copy_full_url = NULL; 00087 static DownloadType download_type = FIRMWARE_DOWNLOAD; //default FIRMWARE = COAP download using filepath of server; 00088 00089 #endif // ARM_UC_FEATURE_FW_SOURCE_COAP 00090 00091 /** 00092 * @brief Get driver version. 00093 * @return Driver version. 00094 */ 00095 uint32_t ARM_UCS_LWM2M_SOURCE_GetVersion(void) 00096 { 00097 return 0; 00098 } 00099 00100 /** 00101 * @brief Get Source capabilities. 00102 * @return Struct containing capabilites. See definition above. 00103 */ 00104 ARM_SOURCE_CAPABILITIES ARM_UCS_LWM2M_SOURCE_GetCapabilities(void) 00105 { 00106 ARM_SOURCE_CAPABILITIES result; 00107 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_GetCapabilities:"); 00108 00109 result.notify = 0; 00110 result.manifest_default = 0; 00111 result.manifest_url = 0; 00112 result.firmware = 0; 00113 result.keytable = 0; 00114 00115 /* the event handler must be set before module can be used */ 00116 if (ARM_UCS_EventHandler != 0) { 00117 result.notify = 1; 00118 result.manifest_default = 1; 00119 result.manifest_url = 1; 00120 #if defined(ARM_UC_FEATURE_FW_SOURCE_COAP) && (ARM_UC_FEATURE_FW_SOURCE_COAP == 1) 00121 result.firmware = 1; 00122 #endif 00123 result.keytable = 1; 00124 } 00125 00126 return result; 00127 } 00128 00129 /** 00130 * @brief Initialize Source. 00131 * @details Function pointer to event handler is passed as argument. 00132 * 00133 * @param cb_event Function pointer to event handler. See events above. 00134 * @return Error code. 00135 */ 00136 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_Initialize(ARM_SOURCE_SignalEvent_t cb_event) 00137 { 00138 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_Initialize: %p", cb_event); 00139 ARM_UC_INIT_ERROR(result, SRCE_ERR_INVALID_PARAMETER); 00140 00141 #if defined(ARM_UC_FEATURE_FW_SOURCE_COAP) && (ARM_UC_FEATURE_FW_SOURCE_COAP == 1) 00142 arm_uc_get_data_request_transaction_ongoing = false; 00143 arm_uc_received_file_size = 0; 00144 arm_uc_total_file_size = 0; 00145 #endif 00146 00147 if (cb_event != 0) { 00148 /* store callback handler */ 00149 ARM_UCS_EventHandler = cb_event; 00150 00151 /* Initialize LWM2M Firmware Update Object */ 00152 FirmwareUpdateResource::Initialize(); 00153 00154 /* Register callback handler */ 00155 FirmwareUpdateResource::addPackageCallback(ARM_UCS_PackageCallback); 00156 00157 DeviceMetadataResource::Initialize(); 00158 00159 ARM_UC_SET_ERROR(result, ERR_NONE); 00160 } 00161 00162 if (ARM_UC_IS_ERROR(result)) { 00163 ARM_UCS_LWM2M_SOURCE_SetError(result); 00164 } 00165 return result; 00166 } 00167 00168 /** 00169 * @brief Uninitialized Source. 00170 * @return Error code. 00171 */ 00172 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_Uninitialize(void) 00173 { 00174 ARM_UC_INIT_ERROR(retval, ERR_NONE); 00175 DeviceMetadataResource::Uninitialize(); 00176 FirmwareUpdateResource::Uninitialize(); 00177 00178 return retval; 00179 } 00180 00181 /** 00182 * @brief Cost estimation for retrieving manifest from the default location. 00183 * @details The estimation can vary over time and should not be cached too long. 00184 * 0x00000000 - The manifest is already downloaded. 00185 * 0xFFFFFFFF - Cannot retrieve manifest from this Source. 00186 * 00187 * @param cost Pointer to variable for the return value. 00188 * @return Error code. 00189 */ 00190 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestDefaultCost(uint32_t *cost) 00191 { 00192 ARM_UC_INIT_ERROR(result, SRCE_ERR_INVALID_PARAMETER); 00193 00194 if (cost != 0) { 00195 /* set cost to 0 when manifest is cached */ 00196 if (arm_ucs_manifest_buffer && arm_ucs_manifest_length) { 00197 *cost = 0; 00198 } 00199 /* set cost to 0xFFFFFFFF when manifest has been read */ 00200 else { 00201 *cost = 0xFFFFFFFF; 00202 } 00203 00204 ARM_UC_SET_ERROR(result, ERR_NONE); 00205 } 00206 00207 if (ARM_UC_IS_ERROR(result)) { 00208 ARM_UCS_LWM2M_SOURCE_SetError(result); 00209 } 00210 return result; 00211 } 00212 00213 /** 00214 * @brief Retrieve manifest from the default location. 00215 * @details Manifest is stored in supplied buffer. 00216 * Event is generated once manifest is in buffer. 00217 * 00218 * @param buffer Struct containing byte array, maximum size, and actual size. 00219 * @return Error code. 00220 */ 00221 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestDefault(arm_uc_buffer_t *buffer, 00222 uint32_t offset) 00223 { 00224 ARM_UC_INIT_ERROR(result, SRCE_ERR_INVALID_PARAMETER); 00225 00226 /* copy manifest from cache into buffer */ 00227 if ((buffer != NULL) && 00228 (buffer->ptr != NULL) && 00229 (arm_ucs_manifest_buffer != NULL) && 00230 (arm_ucs_manifest_length != 0) && 00231 (offset < arm_ucs_manifest_length)) { 00232 /* remaining length based on offset request */ 00233 uint16_t length = arm_ucs_manifest_length - offset; 00234 00235 /* set actual length based on buffer size */ 00236 if (length > buffer->size_max) { 00237 length = buffer->size_max; 00238 } 00239 00240 /* size check */ 00241 if (length > 0) { 00242 /* copy manifest from local buffer to external buffer */ 00243 memcpy(buffer->ptr, &arm_ucs_manifest_buffer[offset], length); 00244 buffer->size = length; 00245 00246 /* delete local buffer once the entire manifest has been read */ 00247 if (offset + length >= arm_ucs_manifest_length) { 00248 delete[] arm_ucs_manifest_buffer; 00249 arm_ucs_manifest_buffer = NULL; 00250 arm_ucs_manifest_length = 0; 00251 } 00252 00253 ARM_UC_SET_ERROR(result, ERR_NONE); 00254 00255 /* signal event handler that manifest has been copied to buffer */ 00256 if (ARM_UCS_EventHandler) { 00257 ARM_UC_PostCallback(&callbackNodeManifest, 00258 ARM_UCS_EventHandler, 00259 EVENT_MANIFEST); 00260 } 00261 } 00262 } 00263 00264 if (ARM_UC_IS_ERROR(result)) { 00265 ARM_UCS_LWM2M_SOURCE_SetError(result); 00266 } 00267 return result; 00268 } 00269 00270 static void ARM_UCS_PackageCallback(const uint8_t *buffer, uint16_t length) 00271 { 00272 uint32_t event_code = EVENT_ERROR; 00273 00274 if (arm_ucs_manifest_buffer) { 00275 UC_SRCE_ERR_MSG("received new manifest before reading the old one"); 00276 00277 /* delete old buffer to make space for the new one */ 00278 delete[] arm_ucs_manifest_buffer; 00279 arm_ucs_manifest_length = 0; 00280 } 00281 00282 /* allocate a local buffer of the same size as the manifest */ 00283 arm_ucs_manifest_buffer = new uint8_t[length]; 00284 00285 if (arm_ucs_manifest_buffer) { 00286 /* copy manifest from payload to local buffer */ 00287 memcpy(arm_ucs_manifest_buffer, buffer, length); 00288 arm_ucs_manifest_length = length; 00289 00290 event_code = EVENT_NOTIFICATION; 00291 } 00292 00293 /* signal event handler with result */ 00294 if (ARM_UCS_EventHandler) { 00295 ARM_UC_PostCallback(&callbackNodeNotification, 00296 ARM_UCS_EventHandler, 00297 event_code); 00298 } 00299 } 00300 00301 00302 /** 00303 * @brief Cost estimation for retrieving firmware from URL. 00304 * @details The estimation can vary over time and should not be cached too long. 00305 * 0x00000000 - The firmware is already downloaded. 00306 * 0xFFFFFFFF - Cannot retrieve firmware from this Source. 00307 * 00308 * @param uri URI struct with firmware location. 00309 * @param cost Pointer to variable for the return value. 00310 * @return Error code. 00311 */ 00312 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetFirmwareURLCost(arm_uc_uri_t *uri, 00313 uint32_t *cost) 00314 { 00315 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_GetFirmwareURLCost"); 00316 00317 ARM_UC_INIT_ERROR(result, SRCE_ERR_INVALID_PARAMETER); 00318 00319 #if defined(ARM_UC_FEATURE_FW_SOURCE_COAP) && (ARM_UC_FEATURE_FW_SOURCE_COAP == 1) 00320 /* not supported - return default cost regardless of actual uri location */ 00321 if ((uri != 0) && (cost != 0)) { 00322 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_GetFirmwareURLCost uri and cost"); 00323 *cost = ARM_UCS_DEFAULT_COST; 00324 result.code = ERR_NONE ; 00325 } 00326 #else 00327 /* not supported */ 00328 if (cost != 0) { 00329 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_GetFirmwareURLCost cost 0xFFFFFFFF"); 00330 *cost = 0xFFFFFFFF; 00331 result.code = ERR_NONE ; 00332 } 00333 #endif 00334 if (ARM_UC_IS_ERROR(result)) { 00335 ARM_UCS_LWM2M_SOURCE_SetError(result); 00336 } 00337 return result; 00338 } 00339 00340 00341 /** 00342 * @brief Retrieve firmware fragment. 00343 * @details Firmware fragment is stored in supplied buffer. 00344 * Event is generated once fragment is in buffer. 00345 * 00346 * @param uri URI struct with firmware location. 00347 * @param buffer Struct containing byte array, maximum size, and actual size. 00348 * @param offset Firmware offset to retrieve fragment from. 00349 * @return Error code. 00350 */ 00351 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment(arm_uc_uri_t *uri, 00352 arm_uc_buffer_t *buffer, 00353 uint32_t offset) 00354 { 00355 00356 arm_uc_error_t retval = { .code = SRCE_ERR_INVALID_PARAMETER }; 00357 #if defined(ARM_UC_FEATURE_FW_SOURCE_COAP) && (ARM_UC_FEATURE_FW_SOURCE_COAP == 1) 00358 if (uri == NULL || buffer == NULL || FirmwareUpdateResource::getM2MInterface() == NULL) { 00359 return retval; 00360 } 00361 00362 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment: %s %s, buffer size: %" PRIu32 ", buffer max: %" PRIu32 00363 " offset: %" PRIu32, (const char *)uri->ptr, uri->path, buffer->size, buffer->size_max, offset); 00364 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment: total file size %" PRIu32 ", received file size %" PRIu32, 00365 (uint32_t)arm_uc_total_file_size, (uint32_t)arm_uc_received_file_size); 00366 00367 /* 00368 * NOTE: we are using M2MInterface API "get_data_request()" asynchronously, so first call to GetFirmwareFragment() 00369 * will not return anything in the buffer. Instead we will get COAP blocks into callback arm_uc_get_data_req_callback() 00370 * where we will copy those to our internal storage_buffer. When storage_buffer has enough data 00371 * (more or eq than buffer->size_max == Storage Page size) we will copy data from it to output buffer 00372 * and indicate to Hub state machine using event EVENT_FIRMWARE 00373 */ 00374 if (offset == 0) { 00375 // First fragment 00376 storage_buffer.size = 0; 00377 arm_uc_received_file_size = 0; 00378 arm_uc_total_file_size = 0; 00379 } else if (arm_uc_received_file_size == 0) { 00380 // The received file size was reset to zero indicating that we have received the full payload 00381 // as indicated by the server but we are asked to carry on downloading from the given offset. 00382 // This indicates a mismatch between the actual payload size in the server and that given in the manifest. 00383 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment: payload size indicated in manifest is bigger than that reported by server!"); 00384 if (ARM_UCS_EventHandler) { 00385 ARM_UC_PostCallback(&callbackNodeManifest, 00386 ARM_UCS_EventHandler, 00387 EVENT_ERROR); 00388 } 00389 return retval; 00390 } 00391 00392 output_buffer_ptr = buffer; 00393 free(copy_full_url); 00394 copy_full_url = (char *)malloc(arm_uc_calculate_full_uri_length(uri)); 00395 if (copy_full_url == NULL) { 00396 //TODO to return SRCE_ERR_OUT_OF_MEMORY 00397 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment: ERROR OUT OF MEMORY for uri copy!"); 00398 return retval; 00399 } 00400 if (uri->scheme == URI_SCHEME_COAPS) { 00401 strcpy(copy_full_url, UC_COAPS_STRING); 00402 } else if (uri->scheme == URI_SCHEME_HTTP) { 00403 strcpy(copy_full_url, UC_HTTP_STRING); 00404 } else { 00405 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment: Not Supported SCHEME! length of copy url: %u", 00406 sizeof(copy_full_url)); 00407 return retval; 00408 } 00409 strcat(copy_full_url, (const char *)uri->ptr); 00410 strcat(copy_full_url, uri->path); 00411 00412 if ((arm_uc_received_file_size == arm_uc_total_file_size && 00413 arm_uc_received_file_size != 0)) { 00414 00415 // If last block - write to buffer and complete 00416 if (storage_buffer.ptr && 00417 (arm_uc_received_file_size == arm_uc_total_file_size)) { 00418 memcpy(buffer->ptr, storage_buffer.ptr, storage_buffer.size); 00419 buffer->size = storage_buffer.size; 00420 memmove(storage_buffer.ptr, storage_buffer.ptr + storage_buffer.size, (storage_buffer.size_max - storage_buffer.size)); 00421 storage_buffer.size -= buffer->size; 00422 } 00423 00424 // We were waiting for one more state machine cycle for previous write to complete 00425 // Now we can return with EVENT_FIRMWARE so that main state machine changes properly 00426 if (ARM_UCS_EventHandler) { 00427 ARM_UC_PostCallback(&callbackNodeManifest, 00428 ARM_UCS_EventHandler, 00429 EVENT_FIRMWARE); 00430 } 00431 retval.code = ERR_NONE; 00432 arm_uc_received_file_size = 0; 00433 arm_uc_total_file_size = 0; 00434 } else if (!arm_uc_get_data_request_transaction_ongoing) { 00435 // We need to get request for next block of data 00436 UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment: Issue new get request for uri: %s, offset: %" PRIu32, 00437 copy_full_url, (uint32_t)arm_uc_received_file_size); 00438 if (FirmwareUpdateResource::getM2MInterface()) { 00439 00440 FirmwareUpdateResource::getM2MInterface()->get_data_request(download_type, 00441 copy_full_url, 00442 arm_uc_received_file_size, 00443 true, 00444 arm_uc_get_data_req_callback, 00445 arm_uc_get_data_req_error_callback, 00446 FirmwareUpdateResource::getM2MInterface()); 00447 00448 arm_uc_get_data_request_transaction_ongoing = true; 00449 00450 retval.code = ERR_NONE; 00451 } 00452 } else { 00453 // There is not enough data in Storage buffer yet 00454 // AND We have Async get_data_request already ongoing 00455 // -> Do nothing we should not get here? 00456 // This can happen if GetFirmwareFragment is called again before 00457 // the previous get completed with buffer and EVENT_FIRMWARE 00458 UC_SRCE_ERR_MSG("Internal error: BLOCK - data request already ongoing"); 00459 } 00460 if (ARM_UC_IS_ERROR(retval)) { 00461 ARM_UCS_LWM2M_SOURCE_SetError(retval); 00462 } 00463 return retval; 00464 #else 00465 (void) uri; 00466 (void) buffer; 00467 (void) offset; 00468 return retval; 00469 #endif //ARM_UC_FEATURE_FW_SOURCE_COAP 00470 } 00471 00472 #if defined(ARM_UC_FEATURE_FW_SOURCE_COAP) && (ARM_UC_FEATURE_FW_SOURCE_COAP == 1) 00473 void arm_uc_get_data_req_callback(const uint8_t *buffer, size_t buffer_size, size_t total_size, bool last_block, 00474 void *context) 00475 { 00476 (void)last_block; 00477 00478 UC_SRCE_TRACE("get_data_req_callback: %" PRIu32 ", %" PRIu32, (uint32_t)buffer_size, (uint32_t)total_size); 00479 M2MInterface *interface = (M2MInterface *)context; 00480 00481 if (arm_uc_received_file_size == 0) { 00482 arm_uc_total_file_size = total_size; 00483 } 00484 00485 arm_uc_received_file_size += buffer_size; 00486 UC_SRCE_TRACE("get_data_req_callback: received %" PRIu32 "/%" PRIu32, (uint32_t)arm_uc_received_file_size, 00487 (uint32_t)arm_uc_total_file_size); 00488 00489 if (arm_uc_received_file_size == arm_uc_total_file_size) { 00490 UC_SRCE_TRACE("get_data_req_callback: transfer completed\n"); 00491 } 00492 00493 /* 00494 * FLOW: 00495 * 1. If there is space in Storage buffer for the incoming buffer -> copy buffer to storage buffer 00496 * 2. Else signal error event EVENT_ERROR_BUFFER_SIZE 00497 */ 00498 // Check there is space available in the storage buffer 00499 if (storage_buffer.size_max - storage_buffer.size >= buffer_size) { 00500 memcpy(storage_buffer.ptr + storage_buffer.size, buffer, buffer_size); 00501 storage_buffer.size += buffer_size; 00502 } else { 00503 // Error - no space available, signal it to source manager 00504 UC_SRCE_TRACE("arm_uc_get_data_req_callback: Storage Buffer OVERFLOW ERROR!! \n"); 00505 if (ARM_UCS_EventHandler) { 00506 ARM_UC_PostCallback(&callbackNodeManifest, 00507 ARM_UCS_EventHandler, 00508 EVENT_ERROR_BUFFER_SIZE); 00509 } 00510 return; 00511 } 00512 00513 /* 00514 * FLOW: 00515 * 1. If there is enough data in storage-buffer now to complete to output buffer, copy now and indicate with EVENT_FIRMWARE 00516 * to continue to write -cycle 00517 * 2. Else if this is the last block of data, copy the remaining (<size_max) to output buffer and indicate with 00518 * EVENT_FIRMWARE to continue to write-cycle 00519 * 3. Else Request new block of data using API get_data_request 00520 */ 00521 if (storage_buffer.size >= output_buffer_ptr->size_max) { 00522 // 1. We have received into Storage buffer at least one page size of data 00523 // -> Let's return it to UC Hub so that it can be written 00524 UC_SRCE_TRACE("arm_uc_get_data_req_callback: return with Storage buffer size: %" PRIu32 ", buffer size: %" PRIu32, 00525 storage_buffer.size, output_buffer_ptr->size_max); 00526 if (storage_buffer.ptr) { 00527 memcpy(output_buffer_ptr->ptr, storage_buffer.ptr, output_buffer_ptr->size_max); 00528 //storage_buffer.ptr += buffer->size_max; 00529 memmove(storage_buffer.ptr, storage_buffer.ptr + output_buffer_ptr->size_max, 00530 (storage_buffer.size_max - output_buffer_ptr->size_max)); 00531 storage_buffer.size -= output_buffer_ptr->size_max; 00532 output_buffer_ptr->size = output_buffer_ptr->size_max; 00533 } 00534 00535 if (ARM_UCS_EventHandler) { 00536 ARM_UC_PostCallback(&callbackNodeManifest, 00537 ARM_UCS_EventHandler, 00538 EVENT_FIRMWARE); 00539 } 00540 arm_uc_get_data_request_transaction_ongoing = false; 00541 } else if (arm_uc_received_file_size == arm_uc_total_file_size && 00542 arm_uc_received_file_size != 0) { 00543 00544 // 2. this is the last block of data - copy to output buffer and complete with EVENT_FIRMWARE 00545 if (storage_buffer.ptr && 00546 (arm_uc_received_file_size == arm_uc_total_file_size)) { 00547 memcpy(output_buffer_ptr->ptr, storage_buffer.ptr, storage_buffer.size); 00548 output_buffer_ptr->size = storage_buffer.size; 00549 00550 memmove(storage_buffer.ptr, storage_buffer.ptr + storage_buffer.size, (storage_buffer.size_max - storage_buffer.size)); 00551 storage_buffer.size = 0; 00552 } 00553 00554 // We were waiting for one more state machine cycle for previous write to complete 00555 // Now we can return with EVENT_FIRMWARE so that main state machine changes properly 00556 if (ARM_UCS_EventHandler) { 00557 ARM_UC_PostCallback(&callbackNodeManifest, 00558 ARM_UCS_EventHandler, 00559 EVENT_FIRMWARE); 00560 } 00561 arm_uc_get_data_request_transaction_ongoing = false; 00562 free(copy_full_url); 00563 copy_full_url = NULL; 00564 arm_uc_received_file_size = 0; 00565 arm_uc_total_file_size = 0; 00566 } else { 00567 // 3. We want to issue new get data 00568 UC_SRCE_TRACE("arm_uc_get_data_req_callback: Issue new get request for uri: %s, offset: %" PRIu32, copy_full_url, 00569 (uint32_t)arm_uc_received_file_size); 00570 interface->get_data_request(download_type, 00571 copy_full_url, 00572 arm_uc_received_file_size, 00573 true, 00574 arm_uc_get_data_req_callback, 00575 arm_uc_get_data_req_error_callback, 00576 interface); 00577 arm_uc_get_data_request_transaction_ongoing = true; 00578 } 00579 #ifdef ARM_UC_COAP_DATA_PRINTOUT 00580 if (buffer) { 00581 uint32_t i = 0; 00582 int row_len = 40; 00583 uint32_t max_length = 2048; 00584 00585 while (i < buffer_size && i < max_length) { 00586 if (i + row_len > buffer_size) { 00587 row_len = buffer_size - i; 00588 } 00589 UC_SRCE_TRACE("Payload:\t\t%s", tr_array(buffer + i, row_len)); // in HEX 00590 00591 i += row_len; 00592 } 00593 00594 } 00595 #endif 00596 } 00597 00598 void arm_uc_get_data_req_error_callback(get_data_req_error_t error_code, void *context) 00599 { 00600 UC_SRCE_TRACE("get_data_req_error_callback: ERROR: %u\n", error_code); 00601 arm_uc_received_file_size = 0; 00602 arm_uc_total_file_size = 0; 00603 arm_uc_get_data_request_transaction_ongoing = false; 00604 free(copy_full_url); 00605 copy_full_url = NULL; 00606 download_type = FIRMWARE_DOWNLOAD; 00607 if (ARM_UCS_EventHandler) { 00608 ARM_UC_PostCallback(&callbackNodeManifest, 00609 ARM_UCS_EventHandler, 00610 EVENT_ERROR); 00611 } 00612 } 00613 #endif //ARM_UC_FEATURE_FW_SOURCE_COAP 00614 00615 /*****************************************************************************/ 00616 /* Capabilities not supported by this source */ 00617 /*****************************************************************************/ 00618 00619 /** 00620 * @brief Cost estimation for retrieving manifest from URL. 00621 * @details The estimation can vary over time and should not be cached too long. 00622 * 0x00000000 - The manifest is already downloaded. 00623 * 0xFFFFFFFF - Cannot retrieve manifest from this Source. 00624 * 00625 * @param uri URI struct with manifest location. 00626 * @param cost Pointer to variable for the return value. 00627 * @return Error code. 00628 */ 00629 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestURLCost(arm_uc_uri_t *uri, 00630 uint32_t *cost) 00631 { 00632 (void) uri; 00633 (void) cost; 00634 00635 ARM_UC_INIT_ERROR(result, SRCE_ERR_INVALID_PARAMETER); 00636 00637 /* not supported - return default cost regardless of actual uri location */ 00638 if (cost) { 00639 *cost = 0xFFFFFFFF; 00640 ARM_UC_SET_ERROR(result, ERR_NONE); 00641 } 00642 00643 if (ARM_UC_IS_ERROR(result)) { 00644 ARM_UCS_LWM2M_SOURCE_SetError(result); 00645 } 00646 return result; 00647 } 00648 00649 /** 00650 * @brief Cost estimation for retrieving key table from URL. 00651 * @details The estimation can vary over time and should not be cached too long. 00652 * 0x00000000 - The firmware is already downloaded. 00653 * 0xFFFFFFFF - Cannot retrieve firmware from this Source. 00654 * 00655 * @param uri URI struct with keytable location. 00656 * @param cost Pointer to variable for the return value. 00657 * @return Error code. 00658 */ 00659 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetKeytableURLCost(arm_uc_uri_t *uri, 00660 uint32_t *cost) 00661 { 00662 (void) uri; 00663 (void) cost; 00664 00665 ARM_UC_INIT_ERROR(result, SRCE_ERR_INVALID_PARAMETER); 00666 00667 /* not supported - return default cost regardless of actual uri location */ 00668 if ((uri != 0) && (cost != 0)) { 00669 *cost = 0xFFFFFFFF; 00670 ARM_UC_SET_ERROR(result, ERR_NONE); 00671 } 00672 00673 if (ARM_UC_IS_ERROR(result)) { 00674 ARM_UCS_LWM2M_SOURCE_SetError(result); 00675 } 00676 return result; 00677 } 00678 00679 /** 00680 * @brief Retrieve manifest from URL. 00681 * @details Manifest is stored in supplied buffer. 00682 * Event is generated once manifest is in buffer. 00683 * 00684 * @param uri URI struct with manifest location. 00685 * @param buffer Struct containing byte array, maximum size, and actual size. 00686 * 00687 * @return Error code. 00688 */ 00689 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestURL(arm_uc_uri_t *uri, 00690 arm_uc_buffer_t *buffer, 00691 uint32_t offset) 00692 { 00693 (void) uri; 00694 (void) buffer; 00695 (void) offset; 00696 00697 ARM_UC_INIT_ERROR(retval, SRCE_ERR_INVALID_PARAMETER); 00698 00699 if (ARM_UC_IS_ERROR(retval)) { 00700 ARM_UCS_LWM2M_SOURCE_SetError(retval); 00701 } 00702 return retval; 00703 } 00704 00705 /** 00706 * @brief Retrieve a key table from a URL. 00707 * @details Key table is stored in supplied buffer. 00708 * Event is generated once fragment is in buffer. 00709 * 00710 * @param uri URI struct with keytable location. 00711 * @param buffer Struct containing byte array, maximum size, and actual size. 00712 * @return Error code. 00713 */ 00714 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetKeytableURL(arm_uc_uri_t *uri, 00715 arm_uc_buffer_t *buffer) 00716 { 00717 (void) uri; 00718 (void) buffer; 00719 00720 ARM_UC_INIT_ERROR(retval, SRCE_ERR_INVALID_PARAMETER); 00721 00722 if (ARM_UC_IS_ERROR(retval)) { 00723 ARM_UCS_LWM2M_SOURCE_SetError(retval); 00724 } 00725 return retval; 00726 }
Generated on Tue Jul 12 2022 20:20:59 by
