Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_uc_source_http.c Source File

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