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
arm_uc_source_http.c
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 00019 #include "update-client-common/arm_uc_config.h" 00020 00021 #if defined(ARM_UC_FEATURE_FW_SOURCE_HTTP) && (ARM_UC_FEATURE_FW_SOURCE_HTTP == 1) 00022 00023 // HTTP streaming of downloads. 00024 // ---------------------------- 00025 // Implements an update source for update client use. 00026 // Keeps the fragment-get interface for all types, but replaces it under the 00027 // hood with pre-fetch and caching of the requested data. 00028 // The pre-fetch entails requesting the server for the remainder of the resource, 00029 // rather than just the fragment mentioned, and allowing the HTTP/TCP stack 00030 // to do the work of buffering it. The caching entails keeping track of the 00031 // current state of the buffered fetch, and returning the fragment as read 00032 // from the buffered stream if appropriate, or re-requesting the data if there 00033 // is no match between the request and the cached state, or the socket has 00034 // been broken and the buffer is unavailable. 00035 // Note that streaming is not necessarily always the correct approach, there 00036 // might on occasion be cause to force the fragment approach, related to 00037 // available transports, or link properties. 00038 00039 #include "update-client-source-http/arm_uc_source_http.h" 00040 00041 #include "update-client-source-http-socket/arm_uc_http_socket.h" 00042 00043 #include <time.h> 00044 #include <stdio.h> 00045 #include <stdbool.h> 00046 #include "update-client-source-http/arm_uc_source_http_extra.h" 00047 00048 // TRACE. 00049 // ------ 00050 00051 // to disable extra trace, uncomment UC_SRCE_TRACE_ENTRY/VERBOSE/EXIT(...) 00052 // or to enable extra trace, uncomment UC_SRCE_TRACE_ENTRY/VERBOSE/EXIT UC_SRCE_TRACE 00053 #define UC_SRCE_TRACE_ENTRY(...) 00054 #define UC_SRCE_TRACE_VERBOSE(...) 00055 #define UC_SRCE_TRACE_EXIT(...) 00056 //#define UC_SRCE_TRACE_ENTRY UC_SRCE_TRACE 00057 //#define UC_SRCE_TRACE_VERBOSE UC_SRCE_TRACE 00058 //#define UC_SRCE_TRACE_EXIT UC_SRCE_TRACE 00059 00060 // DATA & CONFIG. 00061 // -------------- 00062 00063 // current version of this driver. 00064 #define DRIVER_VER 0x00010000 00065 00066 // default cost is lowered compared to fragment sources. 00067 #define ARM_UCS_HTTP_DEFAULT_COST (700) 00068 #define ARM_UCS_HTTP_HASH_LENGTH (40) 00069 00070 typedef struct _ARM_UCS_Http_Configuration { 00071 arm_uc_uri_t manifest; 00072 uint32_t interval; 00073 uint32_t currentCost; 00074 time_t lastPoll; 00075 int8_t hash[ARM_UCS_HTTP_HASH_LENGTH]; 00076 void (*eventHandler)(uintptr_t event); 00077 } ARM_UCS_Http_Configuration_t; 00078 00079 static ARM_UCS_Http_Configuration_t default_config = { 00080 .manifest = { 00081 .size_max = 0, 00082 .size = 0, 00083 .ptr = NULL, 00084 .scheme = URI_SCHEME_NONE, 00085 .port = 0, 00086 .host = NULL, 00087 .path = NULL 00088 }, 00089 .interval = 0, 00090 .currentCost = 0xFFFFFFFF, 00091 .lastPoll = 0, 00092 .hash = { 0 }, 00093 .eventHandler = 0 00094 }; 00095 00096 typedef enum { 00097 STATE_UCS_HTTP_IDLE, 00098 STATE_UCS_HTTP_MANIFEST, 00099 STATE_UCS_HTTP_FIRMWARE, 00100 STATE_UCS_HTTP_FIRMWARE_RELOAD, 00101 STATE_UCS_HTTP_KEYTABLE, 00102 STATE_UCS_HTTP_HASH 00103 } arm_ucs_http_state_t; 00104 00105 #define MAX_RETRY 3 00106 00107 typedef struct { 00108 arm_ucs_http_state_t stateHttp; 00109 arm_uc_uri_t *uri; 00110 arm_uc_buffer_t *buffer; 00111 uint32_t offset; 00112 uint8_t retryCount; 00113 } arm_ucs_state_t; 00114 00115 static arm_ucs_state_t arm_ucs_state; 00116 00117 static arm_uc_http_socket_context_t arm_uc_http_socket_context = { 0 }; 00118 00119 // HELPERS. 00120 // -------- 00121 00122 /* Helper function for resetting internal state */ 00123 static inline void uc_state_reset() 00124 { 00125 arm_ucs_state.stateHttp = STATE_UCS_HTTP_IDLE; 00126 arm_ucs_state.uri = NULL; 00127 arm_ucs_state.buffer = NULL; 00128 arm_ucs_state.offset = 0; 00129 arm_ucs_state.retryCount = 0; 00130 } 00131 00132 /* Helper function for checking if the stored hash is all zeros */ 00133 static inline bool hash_is_zero() 00134 { 00135 bool result = true; 00136 for (uint32_t index = 0; index < ARM_UCS_HTTP_HASH_LENGTH; index++) { 00137 if (default_config.hash[index] != 0) { 00138 result = false; 00139 break; 00140 } 00141 } 00142 return result; 00143 } 00144 00145 static arm_uc_error_t arm_ucs_http_error = {ERR_NONE}; 00146 arm_uc_error_t ARM_UCS_Http_GetError(void) { return arm_ucs_http_error; } 00147 arm_uc_error_t ARM_UCS_Http_SetError(arm_uc_error_t an_error) { return (arm_ucs_http_error = an_error); } 00148 00149 00150 // FORWARD DECLARATIONS. 00151 // --------------------- 00152 00153 arm_uc_error_t ARM_UCS_Http_Get(arm_uc_uri_t *uri, 00154 arm_uc_buffer_t *buffer, 00155 uint32_t offset, 00156 arm_ucs_http_state_t newHttpState); 00157 00158 /******************************************************************************/ 00159 /* ARM Update Client Source Extra */ 00160 /******************************************************************************/ 00161 00162 /** 00163 * @brief Set URI location for the default manifest. 00164 * @details The default manifest is polled regularly and generates a 00165 * notification upon change. The URI struct and the content pointer to 00166 * must be valid throughout the lifetime of the application. 00167 * 00168 * @param uri URI struct with manifest location. 00169 * @return Error code. 00170 */ 00171 arm_uc_error_t ARM_UCS_Http_SetDefaultManifestURL(arm_uc_uri_t *uri) 00172 { 00173 UC_SRCE_TRACE_ENTRY(">> %s", __func__); 00174 00175 /* check scheme is http */ 00176 if ((uri == NULL) || (uri->scheme != URI_SCHEME_HTTP)) { 00177 ARM_UCS_Http_SetError((arm_uc_error_t) {SRCE_ERR_INVALID_PARAMETER}); 00178 return ARM_UC_ERROR(SRCE_ERR_INVALID_PARAMETER); 00179 } else { 00180 /* copy pointers to local struct */ 00181 default_config.manifest = *uri; 00182 return ARM_UC_ERROR(ERR_NONE); 00183 } 00184 } 00185 00186 /** 00187 * @brief Set polling interval for notification generation. 00188 * @details The default manifest location is polled with this interval. 00189 * 00190 * @param seconds Seconds between each poll. 00191 * @return Error code. 00192 */ 00193 arm_uc_error_t ARM_UCS_Http_SetPollingInterval(uint32_t seconds) 00194 { 00195 UC_SRCE_TRACE_ENTRY(">> %s", __func__); 00196 00197 default_config.interval = seconds; 00198 00199 return ARM_UC_ERROR(ERR_NONE); 00200 } 00201 00202 /** 00203 * @brief Main function for the Source. 00204 * @details This function will query the default manifest location and generate 00205 * a notification if it has changed since the last time it was checked. 00206 * The number of queries generated is bound by the polling interval. 00207 * 00208 * This function should be used on systems with timed callbacks. 00209 * 00210 * @return Seconds until the next polling interval. 00211 */ 00212 uint32_t ARM_UCS_Http_CallMultipleTimes(arm_uc_buffer_t *hash_buffer) 00213 { 00214 UC_SRCE_TRACE_ENTRY(">> %s", __func__); 00215 00216 uint32_t result = default_config.interval; 00217 time_t unixtime = time(NULL); 00218 uint32_t elapsed = unixtime - default_config.lastPoll; 00219 00220 if ((default_config.eventHandler == NULL) || 00221 (arm_ucs_state.stateHttp != STATE_UCS_HTTP_IDLE) || 00222 (hash_buffer == NULL)) { 00223 return default_config.interval; 00224 } 00225 00226 if (elapsed >= default_config.interval) { 00227 UC_SRCE_TRACE_VERBOSE("%s interval elapsed", __func__); 00228 00229 // poll default URI 00230 default_config.lastPoll = unixtime; 00231 00232 // get resource hash 00233 arm_ucs_state.stateHttp = STATE_UCS_HTTP_HASH; 00234 arm_ucs_state.buffer = hash_buffer; 00235 00236 arm_uc_error_t retval = ARM_UCS_HttpSocket_GetHash(&default_config.manifest, 00237 arm_ucs_state.buffer); 00238 if (ARM_UC_IS_ERROR(retval)) { 00239 uc_state_reset(); 00240 return default_config.interval; 00241 } 00242 } else { 00243 result = (elapsed > 0) ? default_config.interval - elapsed : default_config.interval; 00244 } 00245 00246 return result; 00247 } 00248 00249 // EXTRA INTERFACE. 00250 // ---------------- 00251 00252 ARM_UCS_HTTPSourceExtra_t ARM_UCS_HTTPSourceExtra = { 00253 .SetDefaultManifestURL = ARM_UCS_Http_SetDefaultManifestURL, 00254 .SetPollingInterval = ARM_UCS_Http_SetPollingInterval, 00255 .CallMultipleTimes = ARM_UCS_Http_CallMultipleTimes 00256 }; 00257 00258 /******************************************************************************/ 00259 /* ARM Update Client Source */ 00260 /******************************************************************************/ 00261 00262 void ARM_UCS_Http_ProcessHash() 00263 { 00264 UC_SRCE_TRACE_ENTRY(">> %s", __func__); 00265 00266 #if ARM_UC_SOURCE_MANAGER_TRACE_ENABLE 00267 printf("hash: "); 00268 for (uint32_t index = 0; index < arm_ucs_state.buffer->size; index++) { 00269 printf("%c", arm_ucs_state.buffer->ptr[index]); 00270 } 00271 printf("\r\n"); 00272 #endif 00273 00274 bool hashIsNew = false; 00275 bool firstBoot = hash_is_zero(); 00276 00277 /* compare hash with previous check */ 00278 for (uint32_t index = 0; index < arm_ucs_state.buffer->size; index++) { 00279 /* compare hash */ 00280 if (default_config.hash[index] != arm_ucs_state.buffer->ptr[index]) { 00281 /* store new hash */ 00282 default_config.hash[index] = arm_ucs_state.buffer->ptr[index]; 00283 hashIsNew = true; 00284 } 00285 } 00286 00287 /* Request complete, reset state */ 00288 uc_state_reset(); 00289 arm_uc_http_socket_end_resume(); 00290 00291 /* Signal that a new manifest is available if the hash is non-zero 00292 and different from the last check. 00293 */ 00294 if (hashIsNew && !firstBoot) { 00295 if (default_config.eventHandler) { 00296 default_config.eventHandler(EVENT_NOTIFICATION); 00297 } 00298 } 00299 } 00300 00301 static void ARM_UCS_Http_HTTPEvent(uintptr_t event) 00302 { 00303 UC_SRCE_TRACE_ENTRY(">> %s", __func__); 00304 00305 switch (event) { 00306 /* Hash received, process it */ 00307 case UCS_HTTP_EVENT_HASH: 00308 UC_SRCE_TRACE("UCS_HTTP_EVENT_HASH"); 00309 00310 ARM_UCS_Http_ProcessHash(); 00311 break; 00312 00313 /* Download complete */ 00314 case UCS_HTTP_EVENT_DOWNLOAD: { 00315 UC_SRCE_TRACE("UCS_HTTP_EVENT_DOWNLOAD"); 00316 00317 /* cache state before resetting it */ 00318 arm_ucs_http_state_t previous_state = arm_ucs_state.stateHttp; 00319 00320 /* reset internal state */ 00321 uc_state_reset(); 00322 00323 /* signal successful download based on request */ 00324 if (default_config.eventHandler) { 00325 if (previous_state == STATE_UCS_HTTP_MANIFEST) { 00326 default_config.eventHandler(EVENT_MANIFEST); 00327 } else if (previous_state == STATE_UCS_HTTP_FIRMWARE) { 00328 default_config.eventHandler(EVENT_FIRMWARE); 00329 } else if (previous_state == STATE_UCS_HTTP_KEYTABLE) { 00330 default_config.eventHandler(EVENT_KEYTABLE); 00331 } else { 00332 default_config.eventHandler(EVENT_ERROR); 00333 } 00334 } 00335 } 00336 break; 00337 00338 /* Socket error */ 00339 case UCS_HTTP_EVENT_ERROR: { 00340 UC_SRCE_TRACE("UCS_HTTP_EVENT_ERROR"); 00341 00342 /* Treat polling as retry when reading hash */ 00343 if (arm_ucs_state.stateHttp == STATE_UCS_HTTP_HASH) { 00344 /* If the stored hash is zero, this error is most likely 00345 generated due to the default manifest not being uploaded 00346 yet. Mark the stored hash as non-zero, so the first time 00347 the device successfully retrieves a hash we download the 00348 manifest. 00349 */ 00350 if (hash_is_zero()) { 00351 default_config.hash[0] = 0xFF; 00352 } 00353 /* reset state but don't take any further action */ 00354 uc_state_reset(); 00355 } else { 00356 /* reset internal state */ 00357 uc_state_reset(); 00358 00359 /* generate error event */ 00360 if (default_config.eventHandler) { 00361 default_config.eventHandler(EVENT_ERROR_SOURCE); 00362 } 00363 } 00364 } 00365 break; 00366 00367 /* supplied buffer not large enough */ 00368 case UCS_HTTP_EVENT_ERROR_BUFFER_SIZE: { 00369 /* reset internal state */ 00370 uc_state_reset(); 00371 00372 /* generate error event */ 00373 if (default_config.eventHandler) { 00374 default_config.eventHandler(EVENT_ERROR_BUFFER_SIZE); 00375 } 00376 } 00377 break; 00378 00379 default: 00380 UC_SRCE_ERR_MSG("%s Unknown event", __func__); 00381 break; 00382 } 00383 } 00384 00385 /** 00386 * @brief Get driver version. 00387 * @return Driver version. 00388 */ 00389 uint32_t ARM_UCS_Http_GetVersion(void) 00390 { 00391 UC_SRCE_TRACE_ENTRY(">> %s", __func__); 00392 return DRIVER_VER; 00393 } 00394 00395 /** 00396 * @brief Get Source capabilities. 00397 * @return Struct containing capabilites. See definition above. 00398 */ 00399 ARM_SOURCE_CAPABILITIES ARM_UCS_Http_GetCapabilities(void) 00400 { 00401 UC_SRCE_TRACE_ENTRY(">> %s", __func__); 00402 00403 ARM_SOURCE_CAPABILITIES result = { 00404 .notify = 0, 00405 .manifest_default = 0, 00406 .manifest_url = 0, 00407 .firmware = 0, 00408 .keytable = 0 00409 }; 00410 00411 /* the event handler must be set before module can be used */ 00412 if (default_config.eventHandler != 0) { 00413 result.manifest_url = 1; 00414 result.firmware = 1; 00415 result.keytable = 1; 00416 00417 /* notification requires that the default manifest is set */ 00418 if ((default_config.manifest.port != 0) || (default_config.interval != 0)) { 00419 result.notify = 1; 00420 result.manifest_default = 1; 00421 } 00422 } 00423 00424 return result; 00425 } 00426 00427 /** 00428 * @brief Initialize Source. 00429 * @details Function pointer to event handler is passed as argument. 00430 * 00431 * @param cb_event Function pointer to event handler. See events above. 00432 * @return Error code. 00433 */ 00434 arm_uc_error_t ARM_UCS_Http_Initialize(ARM_SOURCE_SignalEvent_t cb_event) 00435 { 00436 UC_SRCE_TRACE_ENTRY(">> %s", __func__); 00437 ARM_UC_INIT_ERROR(status, SRCE_ERR_INVALID_PARAMETER); 00438 00439 if (cb_event != NULL) { 00440 default_config.currentCost = ARM_UCS_HTTP_DEFAULT_COST; 00441 default_config.eventHandler = cb_event; 00442 00443 /* register http callback handler */ 00444 ARM_UCS_HttpSocket_Initialize( 00445 &arm_uc_http_socket_context, 00446 ARM_UCS_Http_HTTPEvent); 00447 00448 ARM_UC_SET_ERROR(status, ERR_NONE); 00449 } 00450 uc_state_reset(); 00451 if (ARM_UC_IS_ERROR(status)) { 00452 ARM_UCS_Http_SetError(status); 00453 } 00454 return status; 00455 } 00456 00457 /** 00458 * @brief Uninitialized Source. 00459 * @return Error code. 00460 */ 00461 arm_uc_error_t ARM_UCS_Http_Uninitialize(void) 00462 { 00463 UC_SRCE_TRACE_ENTRY(">> %s", __func__); 00464 ARM_UCS_Http_SetError((arm_uc_error_t) {SRCE_ERR_INVALID_PARAMETER}); 00465 return ARM_UC_ERROR(SRCE_ERR_INVALID_PARAMETER); 00466 } 00467 00468 // COSTS. 00469 // ------ 00470 00471 /** 00472 * @brief Cost estimation for retrieving manifest from the default location. 00473 * @details The estimation can vary over time and should not be cached too long. 00474 * 0x00000000 - The manifest is already downloaded. 00475 * 0xFFFFFFFF - Cannot retrieve manifest from this Source. 00476 * 00477 * @param cost Pointer to variable for the return value. 00478 * @return Error code. 00479 */ 00480 arm_uc_error_t ARM_UCS_Http_GetManifestDefaultCost( 00481 uint32_t *a_cost_p) 00482 { 00483 UC_SRCE_TRACE_ENTRY(">> %s", __func__); 00484 ARM_UC_INIT_ERROR(status, SRCE_ERR_INVALID_PARAMETER); 00485 00486 if (a_cost_p != 0) { 00487 *a_cost_p = default_config.currentCost; 00488 ARM_UC_SET_ERROR(status, ERR_NONE); 00489 } 00490 if (ARM_UC_IS_ERROR(status)) { 00491 ARM_UCS_Http_SetError(status); 00492 } 00493 return status; 00494 } 00495 00496 /** 00497 * @brief Cost estimation for retrieving unspecified resource from URL. 00498 * @details The estimation can vary over time and should not be cached too long. 00499 * 0x00000000 - The manifest is already downloaded. 00500 * 0xFFFFFFFF - Cannot retrieve manifest from this Source. 00501 * @param uri URI struct with manifest location. 00502 * @param cost Pointer to variable for the return value. 00503 * @return Error code. 00504 */ 00505 arm_uc_error_t ARM_UCS_Http_GetCost( 00506 arm_uc_uri_t *a_uri_p, 00507 uint32_t *a_cost_p) 00508 { 00509 UC_SRCE_TRACE_ENTRY(">> %s", __func__); 00510 ARM_UC_INIT_ERROR(status, SRCE_ERR_INVALID_PARAMETER); 00511 00512 /* return default cost regardless of actual uri location */ 00513 if ((a_uri_p != NULL) && (a_cost_p != NULL)) { 00514 *a_cost_p = default_config.currentCost; 00515 ARM_UC_SET_ERROR(status, ERR_NONE); 00516 } 00517 /* return no-path cost if URL is invalid */ 00518 else if (a_cost_p != NULL) { 00519 *a_cost_p = 0xFFFFFFFF; 00520 } 00521 if (ARM_UC_IS_ERROR(status)) { 00522 ARM_UCS_Http_SetError(status); 00523 } 00524 return status; 00525 } 00526 00527 /* @brief Cost estimation for retrieving manifest from URL. 00528 * @details The estimation can vary over time and should not be cached too long. 00529 * 0x00000000 - The manifest is already downloaded. 00530 * 0xFFFFFFFF - Cannot retrieve manifest from this Source. 00531 * 00532 * @param uri URI struct with manifest location. 00533 * @param cost Pointer to variable for the return value. 00534 * @return Error code. 00535 */ 00536 arm_uc_error_t ARM_UCS_Http_GetManifestURLCost(arm_uc_uri_t *uri, uint32_t *cost) 00537 { 00538 UC_SRCE_TRACE_ENTRY(">> %s", __func__); 00539 return ARM_UCS_Http_GetCost(uri, cost); 00540 } 00541 00542 /** 00543 * @brief Cost estimation for retrieving firmware from URL. 00544 * @details The estimation can vary over time and should not be cached too long. 00545 * 0x00000000 - The firmware is already downloaded. 00546 * 0xFFFFFFFF - Cannot retrieve firmware from this Source. 00547 * 00548 * @param uri URI struct with firmware location. 00549 * @param cost Pointer to variable for the return value. 00550 * @return Error code. 00551 */ 00552 arm_uc_error_t ARM_UCS_Http_GetFirmwareURLCost(arm_uc_uri_t *uri, uint32_t *cost) 00553 { 00554 UC_SRCE_TRACE_ENTRY(">> %s", __func__); 00555 return ARM_UCS_Http_GetCost(uri, cost); 00556 } 00557 00558 /** 00559 * @brief Cost estimation for retrieving key table from URL. 00560 * @details The estimation can vary over time and should not be cached too long. 00561 * 0x00000000 - The firmware is already downloaded. 00562 * 0xFFFFFFFF - Cannot retrieve firmware from this Source. 00563 * 00564 * @param uri URI struct with keytable location. 00565 * @param cost Pointer to variable for the return value. 00566 * @return Error code. 00567 */ 00568 arm_uc_error_t ARM_UCS_Http_GetKeytableURLCost(arm_uc_uri_t *uri, uint32_t *cost) 00569 { 00570 UC_SRCE_TRACE_ENTRY(">> %s", __func__); 00571 return ARM_UCS_Http_GetCost(uri, cost); 00572 } 00573 00574 // GETTING RESOURCES. 00575 // ------------------ 00576 00577 /** 00578 * @brief (Internal) Retrieve resource according to the given parameters 00579 * in arm_ucs_state and store the returned data in the buffer in arm_ucs_state. 00580 * @param uri URI struct with resource location. 00581 * @param buffer Struct containing byte array, maximum size, and actual size. 00582 * @param offset Offset to retrieve fragment from. 00583 * @param newHttpState The intended new http state to be assigned to arm_ucs_state.stateHttp 00584 */ 00585 00586 arm_uc_error_t ARM_UCS_Http_Get(arm_uc_uri_t *uri, 00587 arm_uc_buffer_t *buffer, 00588 uint32_t offset, 00589 arm_ucs_http_state_t newHttpState) 00590 { 00591 UC_SRCE_TRACE_ENTRY(">> %s", __func__); 00592 ARM_UC_INIT_ERROR(status, SRCE_ERR_INVALID_PARAMETER); 00593 00594 // Call the socket layer to get the requested data 00595 00596 // check current state 00597 if (default_config.eventHandler == 0) { 00598 UC_SRCE_ERR_MSG("Uninitialized"); 00599 return ARM_UC_ERROR(SRCE_ERR_UNINITIALIZED); 00600 } 00601 if (arm_ucs_state.stateHttp != STATE_UCS_HTTP_IDLE) { 00602 UC_SRCE_ERR_MSG("Busy"); 00603 return ARM_UC_ERROR(SRCE_ERR_BUSY); 00604 } 00605 00606 // assign new state 00607 arm_ucs_state.stateHttp = newHttpState; 00608 arm_ucs_state.uri = uri; 00609 arm_ucs_state.buffer = buffer; 00610 arm_ucs_state.offset = offset; 00611 00612 // never returns an error because all Get does is installs the thread. 00613 while (ARM_UC_IS_ERROR(status) && (arm_ucs_state.retryCount++ < MAX_RETRY)) { 00614 // restore buffer size on retry 00615 arm_ucs_state.buffer->size = arm_ucs_state.buffer->size_max; 00616 00617 switch (arm_ucs_state.stateHttp) { 00618 case STATE_UCS_HTTP_MANIFEST: 00619 case STATE_UCS_HTTP_FIRMWARE: 00620 if (arm_ucs_state.buffer != 0 && arm_ucs_state.uri != 0) { 00621 status = ARM_UCS_HttpSocket_GetFragment(arm_ucs_state.uri, 00622 arm_ucs_state.buffer, 00623 arm_ucs_state.offset); 00624 } 00625 break; 00626 case STATE_UCS_HTTP_KEYTABLE: 00627 if (arm_ucs_state.buffer != 0 && arm_ucs_state.uri != 0) { 00628 status = ARM_UCS_HttpSocket_GetFile(arm_ucs_state.uri, 00629 arm_ucs_state.buffer); 00630 } 00631 break; 00632 default: 00633 UC_SRCE_ERR_MSG("Invalid request parameter"); 00634 ARM_UC_SET_ERROR(status, SRCE_ERR_INVALID_PARAMETER); 00635 break; 00636 } 00637 } 00638 00639 if (ARM_UC_IS_ERROR(status)) { 00640 uc_state_reset(); 00641 } 00642 if (ARM_UC_IS_ERROR(status)) { 00643 ARM_UCS_Http_SetError(status); 00644 } 00645 return status; 00646 } 00647 00648 /** 00649 * @brief Retrieve manifest from the default location. 00650 * @details Manifest is stored in supplied buffer. 00651 * Event is generated once manifest is in buffer. 00652 * 00653 * @param buffer Struct containing byte array, maximum size, and actual size. 00654 * @return Error code. 00655 */ 00656 arm_uc_error_t ARM_UCS_Http_GetManifestDefault(arm_uc_buffer_t *buffer, uint32_t offset) 00657 { 00658 UC_SRCE_TRACE_ENTRY(">> %s", __func__); 00659 return ARM_UCS_Http_Get(&default_config.manifest, buffer, offset, STATE_UCS_HTTP_MANIFEST); 00660 } 00661 00662 /** 00663 * @brief Retrieve manifest from URL. 00664 * @details Manifest is stored in supplied buffer. 00665 * Event is generated once manifest is in buffer. 00666 * 00667 * @param uri URI struct with manifest location. 00668 * @param buffer Struct containing byte array, maximum size, and actual size. 00669 * 00670 * @return Error code. 00671 */ 00672 arm_uc_error_t ARM_UCS_Http_GetManifestURL(arm_uc_uri_t *uri, arm_uc_buffer_t *buffer, uint32_t offset) 00673 { 00674 UC_SRCE_TRACE_ENTRY(">> %s", __func__); 00675 return ARM_UCS_Http_Get(uri, buffer, offset, STATE_UCS_HTTP_MANIFEST); 00676 } 00677 00678 /** 00679 * @brief Retrieve firmware fragment. 00680 * @details Firmware fragment is stored in supplied buffer. 00681 * Event is generated once fragment is in buffer. 00682 * 00683 * @param uri URI struct with firmware location. 00684 * @param buffer Struct containing byte array, maximum size, and actual size. 00685 * @param offset Firmware offset to retrieve fragment from. 00686 * @return Error code. 00687 */ 00688 arm_uc_error_t ARM_UCS_Http_GetFirmwareFragment(arm_uc_uri_t *uri, arm_uc_buffer_t *buffer, uint32_t offset) 00689 { 00690 UC_SRCE_TRACE_ENTRY(">> %s", __func__); 00691 return ARM_UCS_Http_Get(uri, buffer, offset, STATE_UCS_HTTP_FIRMWARE); 00692 } 00693 00694 /** 00695 * @brief Retrieve a key table from a URL. 00696 * @details Key table is stored in supplied buffer. 00697 * Event is generated once fragment is in buffer. 00698 * 00699 * @param uri URI struct with keytable location. 00700 * @param buffer Struct containing byte array, maximum size, and actual size. 00701 * @return Error code. 00702 */ 00703 arm_uc_error_t ARM_UCS_Http_GetKeytableURL(arm_uc_uri_t *uri, arm_uc_buffer_t *buffer) 00704 { 00705 UC_SRCE_TRACE_ENTRY(">> %s", __func__); 00706 return ARM_UCS_Http_Get(uri, buffer, UINT32_MAX, STATE_UCS_HTTP_KEYTABLE); 00707 } 00708 00709 // SOURCE INTERFACE. 00710 // ----------------- 00711 00712 ARM_UPDATE_SOURCE ARM_UCS_HTTPSource = { 00713 .GetVersion = ARM_UCS_Http_GetVersion, 00714 .GetCapabilities = ARM_UCS_Http_GetCapabilities, 00715 .Initialize = ARM_UCS_Http_Initialize, 00716 .Uninitialize = ARM_UCS_Http_Uninitialize, 00717 .GetManifestDefaultCost = ARM_UCS_Http_GetManifestDefaultCost, 00718 .GetManifestURLCost = ARM_UCS_Http_GetManifestURLCost, 00719 .GetFirmwareURLCost = ARM_UCS_Http_GetFirmwareURLCost, 00720 .GetKeytableURLCost = ARM_UCS_Http_GetKeytableURLCost, 00721 .GetManifestDefault = ARM_UCS_Http_GetManifestDefault, 00722 .GetManifestURL = ARM_UCS_Http_GetManifestURL, 00723 .GetFirmwareFragment = ARM_UCS_Http_GetFirmwareFragment, 00724 .GetKeytableURL = ARM_UCS_Http_GetKeytableURL 00725 }; 00726 00727 #endif // ARM_UC_FEATURE_FW_SOURCE_HTTP 00728
Generated on Tue Jul 12 2022 20:20:57 by
