Mbed Cloud example program for workshop in W27 2018.

Dependencies:   MMA7660 LM75B

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FirmwareUpdateResource.cpp Source File

FirmwareUpdateResource.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-lwm2m/FirmwareUpdateResource.h"
00020 
00021 #include "update-client-common/arm_uc_common.h"
00022 
00023 #include <stdio.h>
00024 
00025 #define ARM_UCS_LWM2M_INTERNAL_ERROR (-1)
00026 #define ARM_UCS_LWM2M_INTERNAL_SUCCESS (0)
00027 
00028 namespace FirmwareUpdateResource {
00029 
00030     /* send delayed response */
00031     enum {
00032         ResourcePackage,
00033         ResourcePackageURI,
00034         ResourceUpdate
00035     };
00036 
00037     static void packageCallback(void* _parameters);
00038     static void packageURICallback(void* _parameters);
00039     static void updateCallback(void*);
00040     static void notificationCallback(void);
00041     static void sendDelayedResponseTask(uint32_t parameter);
00042 
00043     /* LWM2M Firmware Update Object */
00044     static M2MObject* updateObject = NULL;
00045 
00046     /* LWM2M Firmware Update Object resources */
00047     static M2MResource* resourcePackage = NULL;
00048     static M2MResource* resourcePackageURI = NULL;
00049     static M2MResource* resourceUpdate = NULL;
00050     static M2MResource* resourceState = NULL;
00051     static M2MResource* resourceResult = NULL;
00052     static M2MResource* resourceName = NULL;
00053     static M2MResource* resourceVersion = NULL;
00054 
00055     /* function pointers to callback functions */
00056     static void (*externalPackageCallback)(const uint8_t* buffer, uint16_t length) = NULL;
00057     static void (*externalPackageURICallback)(const uint8_t* buffer, uint16_t length) = NULL;
00058     static void (*externalUpdateCallback)(void) = NULL;
00059     static void (*externalNotificationCallback)(void) = NULL;
00060 
00061     /* Callback structs for delayed response.
00062      *
00063      * There needs to be one per callback type to avoid collisions between different operations.
00064      */
00065     static arm_uc_callback_t callbackNodePackage = { NULL, 0, NULL, 0 };
00066     static arm_uc_callback_t callbackNodePackageURI = { NULL, 0, NULL, 0 };
00067     static arm_uc_callback_t callbackNodeResourceUpdate = { NULL, 0, NULL, 0 };
00068 }
00069 
00070 /**
00071  * @brief Initialize LWM2M Firmware Update Object
00072  * @details Sets up LWM2M object with accompanying resources.
00073  */
00074 void FirmwareUpdateResource::Initialize(void)
00075 {
00076     static bool initialized = false;
00077 
00078     if (!initialized)
00079     {
00080         initialized = true;
00081 
00082         /* The LWM2M Firmware Update Object is at /5 */
00083         updateObject = M2MInterfaceFactory::create_object("5");
00084 
00085         if (updateObject)
00086         {
00087             /* Create first (and only) instance /5/0 */
00088             M2MObjectInstance* updateInstance = updateObject->create_object_instance();
00089 
00090             if (updateInstance)
00091             {
00092                 /* Set observable so the Portal can read it */
00093                 updateInstance->set_observable(true);
00094 
00095                 /* Default values are non-standard, but the standard has no
00096                    values for indicating that the device is initializing.
00097                 */
00098                 uint8_t defaultValue[] = {"-1"};
00099                 uint8_t defaultVersion[] = {"-1"};
00100 
00101                 /* Create Package resource /5/0/0 */
00102                 resourcePackage = updateInstance->create_dynamic_resource(
00103                                     "0", "Package", M2MResourceInstance::OPAQUE, false);
00104                 if (resourcePackage)
00105                 {
00106                     /* This should be PUT according to the standard but
00107                        Connector client doesn't support callbacks for PUT.
00108                     */
00109                     resourcePackage->set_operation(M2MBase::POST_ALLOWED);
00110                     resourcePackage->set_execute_function(packageCallback);
00111 
00112                     /* The delayed response if for processing heavier loads */
00113                     resourcePackage->set_delayed_response(true);
00114                 }
00115 
00116                 /* Create Package URI resource /5/0/1 */
00117                 resourcePackageURI = updateInstance->create_dynamic_resource(
00118                                     "1", "PackageURI", M2MResourceInstance::STRING, false);
00119                 if (resourcePackageURI)
00120                 {
00121                     resourcePackageURI->set_operation(M2MBase::POST_ALLOWED);
00122                     resourcePackageURI->set_execute_function(packageURICallback);
00123                     resourcePackageURI->set_delayed_response(true);
00124                 }
00125 
00126                 /* Create Update resource /5/0/2 */
00127                 resourceUpdate = updateInstance->create_dynamic_resource(
00128                                     "2", "Update", M2MResourceInstance::BOOLEAN, false);
00129                 if (resourceUpdate)
00130                 {
00131                     resourceUpdate->set_operation(M2MBase::POST_ALLOWED);
00132                     resourceUpdate->set_execute_function(updateCallback);
00133                     resourceUpdate->set_delayed_response(true);
00134                 }
00135 
00136                 /* Create State resource /5/0/3 */
00137                 resourceState = updateInstance->create_dynamic_resource(
00138                                     "3", "State", M2MResourceInstance::INTEGER, true);
00139                 if (resourceState)
00140                 {
00141                     resourceState->set_operation(M2MBase::GET_ALLOWED);
00142                     resourceState->set_notification_sent_callback(notificationCallback);
00143                     resourceState->set_value(defaultValue, sizeof(defaultValue) - 1);
00144                 }
00145 
00146                 /* Create Update Result resource /5/0/5 */
00147                 resourceResult = updateInstance->create_dynamic_resource(
00148                                     "5", "UpdateResult", M2MResourceInstance::INTEGER, true);
00149                 if (resourceResult)
00150                 {
00151                     resourceResult->set_operation(M2MBase::GET_ALLOWED);
00152                     resourceResult->set_notification_sent_callback(notificationCallback);
00153                     resourceResult->set_value(defaultValue, sizeof(defaultValue) - 1);
00154                 }
00155 
00156                 /* Create PkgName resource /5/0/6 */
00157                 resourceName = updateInstance->create_dynamic_resource(
00158                                     "6", "PkgName", M2MResourceInstance::STRING, true);
00159                 if (resourceName)
00160                 {
00161                     resourceName->set_operation(M2MBase::GET_ALLOWED);
00162                     resourceName->set_value(defaultVersion, sizeof(defaultVersion) - 1);
00163                 }
00164 
00165                 /* Create PkgVersion resource /5/0/7 */
00166                 resourceVersion = updateInstance->create_dynamic_resource(
00167                                     "7", "PkgVersion", M2MResourceInstance::STRING, true);
00168                 if (resourceVersion)
00169                 {
00170                     resourceVersion->set_operation(M2MBase::GET_ALLOWED);
00171                     resourceVersion->set_value(defaultVersion, sizeof(defaultVersion) - 1);
00172                 }
00173             }
00174         }
00175     }
00176 }
00177 
00178 M2MObject* FirmwareUpdateResource::getObject()
00179 {
00180     Initialize();
00181 
00182     return updateObject;
00183 }
00184 
00185 void FirmwareUpdateResource::packageCallback(void* _parameters)
00186 {
00187     UC_SRCE_TRACE("FirmwareUpdateResource::packageCallback");
00188 
00189     if (_parameters && externalPackageCallback)
00190     {
00191         /* recast parameter */
00192         M2MResource::M2MExecuteParameter* parameters =
00193             static_cast<M2MResource::M2MExecuteParameter*>(_parameters);
00194 
00195         /* read payload */
00196         const uint8_t* buffer = parameters->get_argument_value();
00197         uint16_t length = parameters->get_argument_value_length();
00198 
00199         /* invoke external callback function */
00200         externalPackageCallback(buffer, length);
00201 
00202         /* schedule delayed response */
00203         ARM_UC_PostCallback(&callbackNodePackage,
00204                             FirmwareUpdateResource::sendDelayedResponseTask,
00205                             FirmwareUpdateResource::ResourcePackage);
00206     }
00207 }
00208 
00209 void FirmwareUpdateResource::packageURICallback(void* _parameters)
00210 {
00211     UC_SRCE_TRACE("FirmwareUpdateResource::packageURICallback");
00212 
00213     if (_parameters && externalPackageURICallback)
00214     {
00215         /* recast parameter */
00216         M2MResource::M2MExecuteParameter* parameters =
00217             static_cast<M2MResource::M2MExecuteParameter*>(_parameters);
00218 
00219         /* read payload */
00220         const uint8_t* buffer = parameters->get_argument_value();
00221         uint16_t length = parameters->get_argument_value_length();
00222 
00223         /* invoke external callback function */
00224         externalPackageURICallback(buffer, length);
00225 
00226         /* schedule delayed response */
00227         ARM_UC_PostCallback(&callbackNodePackageURI,
00228                             FirmwareUpdateResource::sendDelayedResponseTask,
00229                             FirmwareUpdateResource::ResourcePackageURI);
00230     }
00231 }
00232 
00233 void FirmwareUpdateResource::updateCallback(void* _parameters)
00234 {
00235     UC_SRCE_TRACE("FirmwareUpdateResource::updateCallback");
00236 
00237     (void) _parameters;
00238 
00239     if (externalUpdateCallback)
00240     {
00241         /* invoke external callback function */
00242         externalUpdateCallback();
00243 
00244         /* schedule delayed response */
00245         ARM_UC_PostCallback(&callbackNodeResourceUpdate,
00246                             FirmwareUpdateResource::sendDelayedResponseTask,
00247                             FirmwareUpdateResource::ResourceUpdate);
00248     }
00249 }
00250 
00251 void FirmwareUpdateResource::notificationCallback(void)
00252 {
00253     UC_SRCE_TRACE("FirmwareUpdateResource::notificationCallback");
00254 
00255     if (externalNotificationCallback)
00256     {
00257         externalNotificationCallback();
00258     }
00259 }
00260 
00261 void FirmwareUpdateResource::sendDelayedResponseTask(uint32_t parameter)
00262 {
00263     UC_SRCE_TRACE("FirmwareUpdateResource::sendDelayedResponseTask");
00264 
00265     switch (parameter)
00266     {
00267         case FirmwareUpdateResource::ResourcePackage:
00268             UC_SRCE_TRACE("resourcePackage->send_delayed_post_response");
00269             resourcePackage->send_delayed_post_response();
00270             break;
00271         case FirmwareUpdateResource::ResourcePackageURI:
00272             UC_SRCE_TRACE("resourcePackageURI->send_delayed_post_response");
00273             resourcePackageURI->send_delayed_post_response();
00274             break;
00275         case FirmwareUpdateResource::ResourceUpdate:
00276             UC_SRCE_TRACE("resourceUpdate->send_delayed_post_response");
00277             resourceUpdate->send_delayed_post_response();
00278             break;
00279         default:
00280             UC_SRCE_ERR_MSG("unsupported resource");
00281             break;
00282     }
00283 }
00284 
00285 /*****************************************************************************/
00286 /* Update Client Source                                                      */
00287 /*****************************************************************************/
00288 
00289 /* Add callback for resource /5/0/0, Package */
00290 int32_t FirmwareUpdateResource::addPackageCallback(void (*cb)(const uint8_t* buffer, uint16_t length))
00291 {
00292     UC_SRCE_TRACE("FirmwareUpdateResource::addPackageCallback: %p", cb);
00293 
00294     externalPackageCallback = cb;
00295 
00296     return ARM_UCS_LWM2M_INTERNAL_SUCCESS;
00297 }
00298 
00299 /* Add callback for resource /5/0/1, Package URI */
00300 int32_t FirmwareUpdateResource::addPackageURICallback(void (*cb)(const uint8_t* buffer, uint16_t length))
00301 {
00302     UC_SRCE_TRACE("FirmwareUpdateResource::addPackageURICallback: %p", cb);
00303 
00304     externalPackageURICallback = cb;
00305 
00306     return ARM_UCS_LWM2M_INTERNAL_SUCCESS;
00307 }
00308 
00309 /* Add callback for resource /5/0/2, Update */
00310 int32_t FirmwareUpdateResource::addUpdateCallback(void (*cb)(void))
00311 {
00312     UC_SRCE_TRACE("FirmwareUpdateResource::addUpdateCallback: %p", cb);
00313 
00314     externalUpdateCallback = cb;
00315 
00316     return ARM_UCS_LWM2M_INTERNAL_SUCCESS;
00317 }
00318 
00319 /* Add callback for when send{State, UpdateResult} is done */
00320 int32_t FirmwareUpdateResource::addNotificationCallback(void (*cb)(void))
00321 {
00322     UC_SRCE_TRACE("FirmwareUpdateResource::addNotificationCallback: %p", cb);
00323 
00324     externalNotificationCallback = cb;
00325 
00326     return ARM_UCS_LWM2M_INTERNAL_SUCCESS;
00327 }
00328 
00329 /*****************************************************************************/
00330 /* Update Client Status                                                      */
00331 /*****************************************************************************/
00332 
00333 /* Send state for resource /5/0/3, State */
00334 int32_t FirmwareUpdateResource::sendState(arm_ucs_lwm2m_state_t state)
00335 {
00336     UC_SRCE_TRACE("FirmwareUpdateResource::sendState");
00337 
00338     int32_t result = ARM_UCS_LWM2M_INTERNAL_ERROR;
00339 
00340     if (state <= ARM_UCS_LWM2M_STATE_LAST)
00341     {
00342         /* valid states: 0-3 */
00343         uint8_t value[2];
00344         snprintf((char*)value, 2, "%d", state);
00345         resourceState->set_value(value, 1);
00346 
00347         result = ARM_UCS_LWM2M_INTERNAL_SUCCESS;
00348     }
00349 
00350     return result;
00351 }
00352 
00353 /* Send result for resource /5/0/5, Update Result */
00354 int32_t FirmwareUpdateResource::sendUpdateResult(arm_ucs_lwm2m_result_t updateResult)
00355 {
00356     UC_SRCE_TRACE("FirmwareUpdateResource::sendUpdateResult");
00357 
00358     int32_t result = ARM_UCS_LWM2M_INTERNAL_ERROR;
00359 
00360     if (updateResult <= ARM_UCS_LWM2M_RESULT_LAST)
00361     {
00362         /* valid results: 0-8 */
00363         uint8_t value[2];
00364         snprintf((char*)value, 2, "%d", updateResult);
00365         resourceResult->set_value(value, 1);
00366 
00367         result = ARM_UCS_LWM2M_INTERNAL_SUCCESS;
00368     }
00369 
00370     return result;
00371 }
00372 
00373 /* Send name for resource /5/0/6 PkgName */
00374 int32_t FirmwareUpdateResource::sendPkgName(const uint8_t* name, uint16_t length)
00375 {
00376     UC_SRCE_TRACE("FirmwareUpdateResource::sendPkgName");
00377 
00378     int32_t result = ARM_UCS_LWM2M_INTERNAL_ERROR;
00379 
00380     /* the maximum length is defined in the OMA LWM2M standard. */
00381     if ((name != NULL) && (length <= 255))
00382     {
00383         uint8_t value[64] = { 0 };
00384         uint8_t index = 0;
00385 
00386         /* convert to printable characters using lookup table */
00387         for ( ; (index < 32) && (index < length); index++)
00388         {
00389             value[2 * index    ] = arm_uc_hex_table[name[index] >> 4];
00390             value[2 * index + 1] = arm_uc_hex_table[name[index] & 0x0F];
00391         }
00392 
00393         resourceName->set_value(value, 2 * index);
00394 
00395         result = ARM_UCS_LWM2M_INTERNAL_SUCCESS;
00396     }
00397 
00398     return result;
00399 }
00400 
00401 /* Send version for resource /5/0/7, PkgVersion */
00402 int32_t FirmwareUpdateResource::sendPkgVersion(uint64_t version)
00403 {
00404     UC_SRCE_TRACE("FirmwareUpdateResource::sendPkgVersion");
00405 
00406     uint8_t value[21] = { 0 };
00407     uint8_t length = snprintf((char*) value, 21, "%llu" , version);
00408     resourceVersion->set_value(value, length);
00409 
00410     return ARM_UCS_LWM2M_INTERNAL_SUCCESS;
00411 }
00412