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