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.
Diff: mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/source/lwm2m-source.cpp
- Revision:
- 0:276e7a263c35
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/source/lwm2m-source.cpp Mon Jul 02 06:30:39 2018 +0000 @@ -0,0 +1,406 @@ +// ---------------------------------------------------------------------------- +// Copyright 2016-2017 ARM Ltd. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ---------------------------------------------------------------------------- + +#include "update-client-common/arm_uc_common.h" +#include "update-client-lwm2m/lwm2m-source.h" +#include "update-client-lwm2m/FirmwareUpdateResource.h" +#include "update-client-lwm2m/DeviceMetadataResource.h" + + +/* forward declaration */ +static void ARM_UCS_PackageCallback(const uint8_t* buffer, uint16_t length); + +/* local copy of the received manifest */ +static uint8_t* arm_ucs_manifest_buffer = NULL; +static uint16_t arm_ucs_manifest_length = 0; + +/* callback function pointer and struct */ +static void (*ARM_UCS_EventHandler)(uint32_t event) = 0; +static arm_uc_callback_t callbackNodeManifest = { NULL, 0, NULL, 0 }; +static arm_uc_callback_t callbackNodeNotification = { NULL, 0, NULL, 0 }; + +/** + * @brief Get driver version. + * @return Driver version. + */ +uint32_t ARM_UCS_LWM2M_SOURCE_GetVersion(void) +{ + return 0; +} + +/** + * @brief Get Source capabilities. + * @return Struct containing capabilites. See definition above. + */ +ARM_SOURCE_CAPABILITIES ARM_UCS_LWM2M_SOURCE_GetCapabilities(void) +{ + ARM_SOURCE_CAPABILITIES result = { .notify = 0, + .manifest_default = 0, + .manifest_url = 0, + .firmware = 0, + .keytable = 0 }; + + /* the event handler must be set before module can be used */ + if (ARM_UCS_EventHandler != 0) + { + result.notify = 1; + result.manifest_default = 1; + } + + return result; +} + +/** + * @brief Initialize Source. + * @details Function pointer to event handler is passed as argument. + * + * @param cb_event Function pointer to event handler. See events above. + * @return Error code. + */ +arm_uc_error_t ARM_UCS_LWM2M_SOURCE_Initialize(ARM_SOURCE_SignalEvent_t cb_event) +{ + UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_Initialize: %p", cb_event); + + arm_uc_error_t result = { .code = SRCE_ERR_INVALID_PARAMETER }; + + if (cb_event != 0) + { + /* store callback handler */ + ARM_UCS_EventHandler = cb_event; + + /* Initialize LWM2M Firmware Update Object */ + FirmwareUpdateResource::Initialize(); + + /* Register callback handler */ + FirmwareUpdateResource::addPackageCallback(ARM_UCS_PackageCallback); + + DeviceMetadataResource::Initialize(); + + result.code = SRCE_ERR_NONE; + } + + return result; +} + +/** + * @brief Uninitialized Source. + * @return Error code. + */ +arm_uc_error_t ARM_UCS_LWM2M_SOURCE_Uninitialize(void) +{ + arm_uc_error_t retval = { .code = SRCE_ERR_NONE }; + DeviceMetadataResource::Uninitialize(); + FirmwareUpdateResource::Uninitialize(); + + return retval; +} + +/** + * @brief Cost estimation for retrieving manifest from the default location. + * @details The estimation can vary over time and should not be cached too long. + * 0x00000000 - The manifest is already downloaded. + * 0xFFFFFFFF - Cannot retrieve manifest from this Source. + * + * @param cost Pointer to variable for the return value. + * @return Error code. + */ +arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestDefaultCost(uint32_t* cost) +{ + arm_uc_error_t result = { .code = SRCE_ERR_INVALID_PARAMETER }; + + if (cost != 0) + { + /* set cost to 0 when manifest is cached */ + if (arm_ucs_manifest_buffer && arm_ucs_manifest_length) + { + *cost = 0; + } + /* set cost to 0xFFFFFFFF when manifest has been read */ + else + { + *cost = 0xFFFFFFFF; + } + + result.code = SRCE_ERR_NONE; + } + + return result; +} + +/** + * @brief Retrieve manifest from the default location. + * @details Manifest is stored in supplied buffer. + * Event is generated once manifest is in buffer. + * + * @param buffer Struct containing byte array, maximum size, and actual size. + * @return Error code. + */ +arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestDefault(arm_uc_buffer_t* buffer, + uint32_t offset) +{ + arm_uc_error_t result = { .code = SRCE_ERR_INVALID_PARAMETER }; + + /* copy manifest from cache into buffer */ + if ((buffer != NULL) && + (buffer->ptr != NULL) && + (arm_ucs_manifest_buffer != NULL) && + (arm_ucs_manifest_length != 0) && + (offset < arm_ucs_manifest_length)) + { + /* remaining length based on offset request */ + uint16_t length = arm_ucs_manifest_length - offset; + + /* set actual length based on buffer size */ + if (length > buffer->size_max) + { + length = buffer->size_max; + } + + /* size check */ + if (length > 0) + { + /* copy manifest from local buffer to external buffer */ + memcpy(buffer->ptr, &arm_ucs_manifest_buffer[offset], length); + buffer->size = length; + + /* delete local buffer once the entire manifest has been read */ + if (offset + length >= arm_ucs_manifest_length) + { + delete[] arm_ucs_manifest_buffer; + arm_ucs_manifest_buffer = NULL; + arm_ucs_manifest_length = 0; + } + + result.code = SRCE_ERR_NONE; + + /* signal event handler that manifest has been copied to buffer */ + if (ARM_UCS_EventHandler) + { + ARM_UC_PostCallback(&callbackNodeManifest, + ARM_UCS_EventHandler, + EVENT_MANIFEST); + } + } + } + + return result; +} + +static void ARM_UCS_PackageCallback(const uint8_t* buffer, uint16_t length) +{ + uint32_t event_code = EVENT_ERROR; + + if (arm_ucs_manifest_buffer) + { + UC_SRCE_ERR_MSG("received new manifest before reading the old one"); + + /* delete old buffer to make space for the new one */ + delete[] arm_ucs_manifest_buffer; + arm_ucs_manifest_length = 0; + } + + /* allocate a local buffer of the same size as the manifest */ + arm_ucs_manifest_buffer = new uint8_t[length]; + + if (arm_ucs_manifest_buffer) + { + /* copy manifest from payload to local buffer */ + memcpy(arm_ucs_manifest_buffer, buffer, length); + arm_ucs_manifest_length = length; + + event_code = EVENT_NOTIFICATION; + } + + /* signal event handler with result */ + if (ARM_UCS_EventHandler) + { + ARM_UC_PostCallback(&callbackNodeNotification, + ARM_UCS_EventHandler, + event_code); + } +} + +/*****************************************************************************/ +/* Capabilities not supported by this source */ +/*****************************************************************************/ + +/** + * @brief Cost estimation for retrieving manifest from URL. + * @details The estimation can vary over time and should not be cached too long. + * 0x00000000 - The manifest is already downloaded. + * 0xFFFFFFFF - Cannot retrieve manifest from this Source. + * + * @param uri URI struct with manifest location. + * @param cost Pointer to variable for the return value. + * @return Error code. + */ +arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestURLCost(arm_uc_uri_t* uri, + uint32_t* cost) +{ + (void) uri; + (void) cost; + + arm_uc_error_t result = { .code = SRCE_ERR_INVALID_PARAMETER }; + + /* not supported - return default cost regardless of actual uri location */ + if (cost) + { + *cost = 0xFFFFFFFF; + result.code = SRCE_ERR_NONE; + } + + return result; +} + +/** + * @brief Cost estimation for retrieving firmware from URL. + * @details The estimation can vary over time and should not be cached too long. + * 0x00000000 - The firmware is already downloaded. + * 0xFFFFFFFF - Cannot retrieve firmware from this Source. + * + * @param uri URI struct with firmware location. + * @param cost Pointer to variable for the return value. + * @return Error code. + */ +arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetFirmwareURLCost(arm_uc_uri_t* uri, + uint32_t* cost) +{ + (void) uri; + (void) cost; + + arm_uc_error_t result = { .code = SRCE_ERR_INVALID_PARAMETER }; + + /* not supported - return default cost regardless of actual uri location */ + if (cost != 0) + { + *cost = 0xFFFFFFFF; + result.code = SRCE_ERR_NONE; + } + + return result; +} + +/** + * @brief Cost estimation for retrieving key table from URL. + * @details The estimation can vary over time and should not be cached too long. + * 0x00000000 - The firmware is already downloaded. + * 0xFFFFFFFF - Cannot retrieve firmware from this Source. + * + * @param uri URI struct with keytable location. + * @param cost Pointer to variable for the return value. + * @return Error code. + */ +arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetKeytableURLCost(arm_uc_uri_t* uri, + uint32_t* cost) +{ + (void) uri; + (void) cost; + + arm_uc_error_t result = { .code = SRCE_ERR_INVALID_PARAMETER }; + + /* not supported - return default cost regardless of actual uri location */ + if ((uri != 0) && (cost != 0)) + { + *cost = 0xFFFFFFFF; + result.code = SRCE_ERR_NONE; + } + + return result; +} + +/** + * @brief Retrieve manifest from URL. + * @details Manifest is stored in supplied buffer. + * Event is generated once manifest is in buffer. + * + * @param uri URI struct with manifest location. + * @param buffer Struct containing byte array, maximum size, and actual size. + * + * @return Error code. + */ +arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestURL(arm_uc_uri_t* uri, + arm_uc_buffer_t* buffer, + uint32_t offset) +{ + (void) uri; + (void) buffer; + (void) offset; + + arm_uc_error_t retval = { .code = SRCE_ERR_INVALID_PARAMETER }; + + return retval; +} + +/** + * @brief Retrieve firmware fragment. + * @details Firmware fragment is stored in supplied buffer. + * Event is generated once fragment is in buffer. + * + * @param uri URI struct with firmware location. + * @param buffer Struct containing byte array, maximum size, and actual size. + * @param offset Firmware offset to retrieve fragment from. + * @return Error code. + */ +arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment(arm_uc_uri_t* uri, + arm_uc_buffer_t* buffer, + uint32_t offset) +{ + (void) uri; + (void) buffer; + (void) offset; + + arm_uc_error_t retval = { .code = SRCE_ERR_INVALID_PARAMETER }; + + return retval; +} + +/** + * @brief Retrieve a key table from a URL. + * @details Key table is stored in supplied buffer. + * Event is generated once fragment is in buffer. + * + * @param uri URI struct with keytable location. + * @param buffer Struct containing byte array, maximum size, and actual size. + * @return Error code. + */ +arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetKeytableURL(arm_uc_uri_t* uri, + arm_uc_buffer_t* buffer) +{ + (void) uri; + (void) buffer; + + arm_uc_error_t retval = { .code = SRCE_ERR_INVALID_PARAMETER }; + + return retval; +} + +ARM_UPDATE_SOURCE ARM_UCS_LWM2M_SOURCE = +{ + .GetVersion = ARM_UCS_LWM2M_SOURCE_GetVersion, + .GetCapabilities = ARM_UCS_LWM2M_SOURCE_GetCapabilities, + .Initialize = ARM_UCS_LWM2M_SOURCE_Initialize, + .Uninitialize = ARM_UCS_LWM2M_SOURCE_Uninitialize, + .GetManifestDefaultCost = ARM_UCS_LWM2M_SOURCE_GetManifestDefaultCost, + .GetManifestURLCost = ARM_UCS_LWM2M_SOURCE_GetManifestURLCost, + .GetFirmwareURLCost = ARM_UCS_LWM2M_SOURCE_GetFirmwareURLCost, + .GetKeytableURLCost = ARM_UCS_LWM2M_SOURCE_GetKeytableURLCost, + .GetManifestDefault = ARM_UCS_LWM2M_SOURCE_GetManifestDefault, + .GetManifestURL = ARM_UCS_LWM2M_SOURCE_GetManifestURL, + .GetFirmwareFragment = ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment, + .GetKeytableURL = ARM_UCS_LWM2M_SOURCE_GetKeytableURL +};