Simple interface for Mbed Cloud Client

Dependents:  

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lwm2m-source.cpp Source File

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 
00019 #include "update-client-common/arm_uc_common.h"
00020 #include "update-client-lwm2m/lwm2m-source.h"
00021 #include "update-client-lwm2m/FirmwareUpdateResource.h"
00022 #include "update-client-lwm2m/DeviceMetadataResource.h"
00023 
00024 
00025 /* forward declaration */
00026 static void ARM_UCS_PackageCallback(const uint8_t* buffer, uint16_t length);
00027 
00028 /* local copy of the received manifest */
00029 static uint8_t* arm_ucs_manifest_buffer = NULL;
00030 static uint16_t arm_ucs_manifest_length = 0;
00031 
00032 /* callback function pointer and struct */
00033 static void (*ARM_UCS_EventHandler)(uint32_t event) = 0;
00034 static arm_uc_callback_t callbackNodeManifest = { NULL, 0, NULL, 0 };
00035 static arm_uc_callback_t callbackNodeNotification = { NULL, 0, NULL, 0 };
00036 
00037 /**
00038  * @brief Get driver version.
00039  * @return Driver version.
00040  */
00041 uint32_t ARM_UCS_LWM2M_SOURCE_GetVersion(void)
00042 {
00043     return 0;
00044 }
00045 
00046 /**
00047  * @brief Get Source capabilities.
00048  * @return Struct containing capabilites. See definition above.
00049  */
00050 ARM_SOURCE_CAPABILITIES ARM_UCS_LWM2M_SOURCE_GetCapabilities(void)
00051 {
00052     ARM_SOURCE_CAPABILITIES result = { .notify = 0,
00053                                        .manifest_default = 0,
00054                                        .manifest_url = 0,
00055                                        .firmware = 0,
00056                                        .keytable = 0 };
00057 
00058     /* the event handler must be set before module can be used */
00059     if (ARM_UCS_EventHandler != 0)
00060     {
00061         result.notify = 1;
00062         result.manifest_default = 1;
00063     }
00064 
00065     return result;
00066 }
00067 
00068 /**
00069  * @brief Initialize Source.
00070  * @details Function pointer to event handler is passed as argument.
00071  *
00072  * @param cb_event Function pointer to event handler. See events above.
00073  * @return Error code.
00074  */
00075 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_Initialize(ARM_SOURCE_SignalEvent_t cb_event)
00076 {
00077     UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_Initialize: %p", cb_event);
00078 
00079     arm_uc_error_t result = { .code = SRCE_ERR_INVALID_PARAMETER };
00080 
00081     if (cb_event != 0)
00082     {
00083         /* store callback handler */
00084         ARM_UCS_EventHandler = cb_event;
00085 
00086         /* Initialize LWM2M Firmware Update Object */
00087         FirmwareUpdateResource::Initialize();
00088 
00089         /* Register callback handler */
00090         FirmwareUpdateResource::addPackageCallback(ARM_UCS_PackageCallback);
00091 
00092         DeviceMetadataResource::Initialize();
00093 
00094         result.code = SRCE_ERR_NONE;
00095     }
00096 
00097     return result;
00098 }
00099 
00100 /**
00101  * @brief Uninitialized Source.
00102  * @return Error code.
00103  */
00104 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_Uninitialize(void)
00105 {
00106     arm_uc_error_t retval = { .code = SRCE_ERR_NONE };
00107     DeviceMetadataResource::Uninitialize();
00108     FirmwareUpdateResource::Uninitialize();
00109 
00110     return retval;
00111 }
00112 
00113 /**
00114  * @brief Cost estimation for retrieving manifest from the default location.
00115  * @details The estimation can vary over time and should not be cached too long.
00116  *          0x00000000 - The manifest is already downloaded.
00117  *          0xFFFFFFFF - Cannot retrieve manifest from this Source.
00118  *
00119  * @param cost Pointer to variable for the return value.
00120  * @return Error code.
00121  */
00122 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestDefaultCost(uint32_t* cost)
00123 {
00124     arm_uc_error_t result = { .code = SRCE_ERR_INVALID_PARAMETER };
00125 
00126     if (cost != 0)
00127     {
00128         /* set cost to 0 when manifest is cached */
00129         if (arm_ucs_manifest_buffer && arm_ucs_manifest_length)
00130         {
00131             *cost = 0;
00132         }
00133         /* set cost to 0xFFFFFFFF when manifest has been read */
00134         else
00135         {
00136             *cost = 0xFFFFFFFF;
00137         }
00138 
00139         result.code = SRCE_ERR_NONE;
00140     }
00141 
00142     return result;
00143 }
00144 
00145 /**
00146  * @brief Retrieve manifest from the default location.
00147  * @details Manifest is stored in supplied buffer.
00148  *          Event is generated once manifest is in buffer.
00149  *
00150  * @param buffer Struct containing byte array, maximum size, and actual size.
00151  * @return Error code.
00152  */
00153 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestDefault(arm_uc_buffer_t* buffer,
00154                                                        uint32_t offset)
00155 {
00156     arm_uc_error_t result = { .code = SRCE_ERR_INVALID_PARAMETER };
00157 
00158     /* copy manifest from cache into buffer */
00159     if ((buffer != NULL) &&
00160         (buffer->ptr != NULL) &&
00161         (arm_ucs_manifest_buffer != NULL) &&
00162         (arm_ucs_manifest_length != 0) &&
00163         (offset < arm_ucs_manifest_length))
00164     {
00165         /* remaining length based on offset request */
00166         uint16_t length = arm_ucs_manifest_length - offset;
00167 
00168         /* set actual length based on buffer size */
00169         if (length > buffer->size_max)
00170         {
00171             length = buffer->size_max;
00172         }
00173 
00174         /* size check */
00175         if (length > 0)
00176         {
00177             /* copy manifest from local buffer to external buffer */
00178             memcpy(buffer->ptr, &arm_ucs_manifest_buffer[offset], length);
00179             buffer->size = length;
00180 
00181             /* delete local buffer once the entire manifest has been read */
00182             if (offset + length >= arm_ucs_manifest_length)
00183             {
00184                 delete[] arm_ucs_manifest_buffer;
00185                 arm_ucs_manifest_buffer = NULL;
00186                 arm_ucs_manifest_length = 0;
00187             }
00188 
00189             result.code = SRCE_ERR_NONE;
00190 
00191             /* signal event handler that manifest has been copied to buffer */
00192             if (ARM_UCS_EventHandler)
00193             {
00194                 ARM_UC_PostCallback(&callbackNodeManifest,
00195                                     ARM_UCS_EventHandler,
00196                                     EVENT_MANIFEST);
00197             }
00198         }
00199     }
00200 
00201     return result;
00202 }
00203 
00204 static void ARM_UCS_PackageCallback(const uint8_t* buffer, uint16_t length)
00205 {
00206     uint32_t event_code = EVENT_ERROR;
00207 
00208     if (arm_ucs_manifest_buffer)
00209     {
00210         UC_SRCE_ERR_MSG("received new manifest before reading the old one");
00211 
00212         /* delete old buffer to make space for the new one */
00213         delete[] arm_ucs_manifest_buffer;
00214         arm_ucs_manifest_length = 0;
00215     }
00216 
00217     /* allocate a local buffer of the same size as the manifest */
00218     arm_ucs_manifest_buffer = new uint8_t[length];
00219 
00220     if (arm_ucs_manifest_buffer)
00221     {
00222         /* copy manifest from payload to local buffer */
00223         memcpy(arm_ucs_manifest_buffer, buffer, length);
00224         arm_ucs_manifest_length = length;
00225 
00226         event_code = EVENT_NOTIFICATION;
00227     }
00228 
00229     /* signal event handler with result */
00230     if (ARM_UCS_EventHandler)
00231     {
00232         ARM_UC_PostCallback(&callbackNodeNotification,
00233                             ARM_UCS_EventHandler,
00234                             event_code);
00235     }
00236 }
00237 
00238 /*****************************************************************************/
00239 /* Capabilities not supported by this source                                 */
00240 /*****************************************************************************/
00241 
00242 /**
00243  * @brief Cost estimation for retrieving manifest from URL.
00244  * @details The estimation can vary over time and should not be cached too long.
00245  *          0x00000000 - The manifest is already downloaded.
00246  *          0xFFFFFFFF - Cannot retrieve manifest from this Source.
00247  *
00248  * @param uri URI struct with manifest location.
00249  * @param cost Pointer to variable for the return value.
00250  * @return Error code.
00251  */
00252 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestURLCost(arm_uc_uri_t* uri,
00253                                                        uint32_t* cost)
00254 {
00255     (void) uri;
00256     (void) cost;
00257 
00258     arm_uc_error_t result = { .code = SRCE_ERR_INVALID_PARAMETER };
00259 
00260     /* not supported - return default cost regardless of actual uri location */
00261     if (cost)
00262     {
00263         *cost = 0xFFFFFFFF;
00264         result.code = SRCE_ERR_NONE;
00265     }
00266 
00267     return result;
00268 }
00269 
00270 /**
00271  * @brief Cost estimation for retrieving firmware from URL.
00272  * @details The estimation can vary over time and should not be cached too long.
00273  *          0x00000000 - The firmware is already downloaded.
00274  *          0xFFFFFFFF - Cannot retrieve firmware from this Source.
00275  *
00276  * @param uri URI struct with firmware location.
00277  * @param cost Pointer to variable for the return value.
00278  * @return Error code.
00279  */
00280 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetFirmwareURLCost(arm_uc_uri_t* uri,
00281                                                        uint32_t* cost)
00282 {
00283     (void) uri;
00284     (void) cost;
00285 
00286     arm_uc_error_t result = { .code = SRCE_ERR_INVALID_PARAMETER };
00287 
00288     /* not supported - return default cost regardless of actual uri location */
00289     if (cost != 0)
00290     {
00291         *cost = 0xFFFFFFFF;
00292         result.code = SRCE_ERR_NONE;
00293     }
00294 
00295     return result;
00296 }
00297 
00298 /**
00299  * @brief Cost estimation for retrieving key table from URL.
00300  * @details The estimation can vary over time and should not be cached too long.
00301  *          0x00000000 - The firmware is already downloaded.
00302  *          0xFFFFFFFF - Cannot retrieve firmware from this Source.
00303  *
00304  * @param uri URI struct with keytable location.
00305  * @param cost Pointer to variable for the return value.
00306  * @return Error code.
00307  */
00308 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetKeytableURLCost(arm_uc_uri_t* uri,
00309                                                        uint32_t* cost)
00310 {
00311     (void) uri;
00312     (void) cost;
00313 
00314     arm_uc_error_t result = { .code = SRCE_ERR_INVALID_PARAMETER };
00315 
00316     /* not supported - return default cost regardless of actual uri location */
00317     if ((uri != 0) && (cost != 0))
00318     {
00319         *cost = 0xFFFFFFFF;
00320         result.code = SRCE_ERR_NONE;
00321     }
00322 
00323     return result;
00324 }
00325 
00326 /**
00327  * @brief Retrieve manifest from URL.
00328  * @details Manifest is stored in supplied buffer.
00329  *          Event is generated once manifest is in buffer.
00330  *
00331  * @param uri URI struct with manifest location.
00332  * @param buffer Struct containing byte array, maximum size, and actual size.
00333  *
00334  * @return Error code.
00335  */
00336 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestURL(arm_uc_uri_t* uri,
00337                                                    arm_uc_buffer_t* buffer,
00338                                                    uint32_t offset)
00339 {
00340     (void) uri;
00341     (void) buffer;
00342     (void) offset;
00343 
00344     arm_uc_error_t retval = { .code = SRCE_ERR_INVALID_PARAMETER };
00345 
00346     return retval;
00347 }
00348 
00349 /**
00350  * @brief Retrieve firmware fragment.
00351  * @details Firmware fragment is stored in supplied buffer.
00352  *          Event is generated once fragment is in buffer.
00353  *
00354  * @param uri URI struct with firmware location.
00355  * @param buffer Struct containing byte array, maximum size, and actual size.
00356  * @param offset Firmware offset to retrieve fragment from.
00357  * @return Error code.
00358  */
00359 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment(arm_uc_uri_t* uri,
00360                                                         arm_uc_buffer_t* buffer,
00361                                                         uint32_t offset)
00362 {
00363     (void) uri;
00364     (void) buffer;
00365     (void) offset;
00366 
00367     arm_uc_error_t retval = { .code = SRCE_ERR_INVALID_PARAMETER };
00368 
00369     return retval;
00370 }
00371 
00372 /**
00373  * @brief Retrieve a key table from a URL.
00374  * @details Key table is stored in supplied buffer.
00375  *          Event is generated once fragment is in buffer.
00376  *
00377  * @param uri URI struct with keytable location.
00378  * @param buffer Struct containing byte array, maximum size, and actual size.
00379  * @return Error code.
00380  */
00381 arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetKeytableURL(arm_uc_uri_t* uri,
00382                                                    arm_uc_buffer_t* buffer)
00383 {
00384     (void) uri;
00385     (void) buffer;
00386 
00387     arm_uc_error_t retval = { .code = SRCE_ERR_INVALID_PARAMETER };
00388 
00389     return retval;
00390 }
00391 
00392 ARM_UPDATE_SOURCE ARM_UCS_LWM2M_SOURCE =
00393 {
00394     .GetVersion             = ARM_UCS_LWM2M_SOURCE_GetVersion,
00395     .GetCapabilities        = ARM_UCS_LWM2M_SOURCE_GetCapabilities,
00396     .Initialize             = ARM_UCS_LWM2M_SOURCE_Initialize,
00397     .Uninitialize           = ARM_UCS_LWM2M_SOURCE_Uninitialize,
00398     .GetManifestDefaultCost = ARM_UCS_LWM2M_SOURCE_GetManifestDefaultCost,
00399     .GetManifestURLCost     = ARM_UCS_LWM2M_SOURCE_GetManifestURLCost,
00400     .GetFirmwareURLCost     = ARM_UCS_LWM2M_SOURCE_GetFirmwareURLCost,
00401     .GetKeytableURLCost     = ARM_UCS_LWM2M_SOURCE_GetKeytableURLCost,
00402     .GetManifestDefault     = ARM_UCS_LWM2M_SOURCE_GetManifestDefault,
00403     .GetManifestURL         = ARM_UCS_LWM2M_SOURCE_GetManifestURL,
00404     .GetFirmwareFragment    = ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment,
00405     .GetKeytableURL         = ARM_UCS_LWM2M_SOURCE_GetKeytableURL
00406 };