[修改] 增加freeRTOS

1. 版本FreeRTOSv202212.01,命名为kernel;
This commit is contained in:
2023-05-06 16:43:01 +00:00
commit a345df017b
20944 changed files with 11094377 additions and 0 deletions

View File

@ -0,0 +1,878 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota.h
* @brief OTA Agent Interface
*/
#ifndef OTA_H
#define OTA_H
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/* Standard includes. */
/* For FILE type in OtaFileContext_t.*/
#include <stdio.h>
#include <stdint.h>
/* OTA Library Interface include. */
#include "ota_private.h"
#include "ota_os_interface.h"
#include "ota_mqtt_interface.h"
#include "ota_http_interface.h"
#include "ota_platform_interface.h"
/**
* @ingroup ota_helpers
* @brief Evaluates to the length of a constant string defined like 'static const char str[]= "xyz";
*/
#define CONST_STRLEN( s ) ( ( ( uint32_t ) sizeof( s ) ) - 1UL )
#define OTA_FILE_SIG_KEY_STR_MAX_LENGTH 32 /*!< Maximum length of the file signature key. */
/**
* @ingroup ota_helpers
* @brief The OTA signature algorithm string is specified by the PAL.
*
*/
/* MISRA Ref 8.6.1 [External linkage] */
/* More details at: https://github.com/aws/ota-for-aws-iot-embedded-sdk/blob/main/MISRA.md#rule-86 */
/* coverity[misra_c_2012_rule_8_6_violation] */
extern const char OTA_JsonFileSignatureKey[ OTA_FILE_SIG_KEY_STR_MAX_LENGTH ];
/*-------------------------- OTA enumerated types --------------------------*/
/**
* @ingroup ota_enum_types
* @brief The OTA API return status.
* OTA agent error codes are in the upper 8 bits of the 32 bit OTA error word, OtaErr_t.
*/
typedef enum OtaErr
{
OtaErrNone = 0, /*!< @brief No error occurred during the operation. */
OtaErrUninitialized, /*!< @brief The error code has not yet been set by a logic path. */
OtaErrPanic, /*!< @brief Unrecoverable Firmware error. Probably should log error and reboot. */
OtaErrInvalidArg, /*!< @brief API called with invalid argument. */
OtaErrAgentStopped, /*!< @brief Returned when operations are performed that requires OTA Agent running & its stopped. */
OtaErrSignalEventFailed, /*!< @brief Failed to send event to OTA state machine. */
OtaErrRequestJobFailed, /*!< @brief Failed to request the job document. */
OtaErrInitFileTransferFailed, /*!< @brief Failed to update the OTA job status. */
OtaErrRequestFileBlockFailed, /*!< @brief Failed to request file block. */
OtaErrCleanupControlFailed, /*!< @brief Failed to clean up the control plane. */
OtaErrCleanupDataFailed, /*!< @brief Failed to clean up the data plane. */
OtaErrUpdateJobStatusFailed, /*!< @brief Failed to update the OTA job status. */
OtaErrJobParserError, /*!< @brief An error occurred during job document parsing. See reason sub-code. */
OtaErrInvalidDataProtocol, /*!< @brief Job does not have a valid protocol for data transfer. */
OtaErrMomentumAbort, /*!< @brief Too many OTA stream requests without any response. */
OtaErrDowngradeNotAllowed, /*!< @brief Firmware version is older than the previous version. */
OtaErrSameFirmwareVersion, /*!< @brief Firmware version is the same as previous. New firmware could have failed to commit. */
OtaErrImageStateMismatch, /*!< @brief The OTA job was in Self Test but the platform image state was not. Possible tampering. */
OtaErrNoActiveJob, /*!< @brief Attempt to set final image state without an active job. */
OtaErrUserAbort, /*!< @brief User aborted the active OTA. */
OtaErrFailedToEncodeCbor, /*!< @brief Failed to encode CBOR object for requesting data block from streaming service. */
OtaErrFailedToDecodeCbor, /*!< @brief Failed to decode CBOR object from streaming service response. */
OtaErrActivateFailed, /*!< @brief Failed to activate the new image. */
OtaErrFileSizeOverflow /*!< @brief Firmware file size greater than the max allowed size. */
} OtaErr_t;
/**
* @ingroup ota_enum_types
* @brief OTA Agent states.
*
* The current state of the OTA Task (OTA Agent).
*
* @note There is currently support only for a single OTA context.
*/
typedef enum OtaState
{
OtaAgentStateNoTransition = -1,
OtaAgentStateInit = 0,
OtaAgentStateReady,
OtaAgentStateRequestingJob,
OtaAgentStateWaitingForJob,
OtaAgentStateCreatingFile,
OtaAgentStateRequestingFileBlock,
OtaAgentStateWaitingForFileBlock,
OtaAgentStateClosingFile,
OtaAgentStateSuspended,
OtaAgentStateShuttingDown,
OtaAgentStateStopped,
OtaAgentStateAll
} OtaState_t;
/**
* @ingroup ota_enum_types
* @brief OTA job document parser error codes.
*/
typedef enum OtaJobParseErr
{
OtaJobParseErrUnknown = -1, /* @brief The error code has not yet been set by a logic path. */
OtaJobParseErrNone = 0, /* @brief Signifies no error has occurred. */
OtaJobParseErrNullJob, /* @brief A null job was reported (no job ID). */
OtaJobParseErrUpdateCurrentJob, /* @brief We're already busy with the reported job ID. */
OtaJobParseErrZeroFileSize, /* @brief Job document specified a zero sized file. This is not allowed. */
OtaJobParseErrNonConformingJobDoc, /* @brief The job document failed to fulfill the model requirements. */
OtaJobParseErrBadModelInitParams, /* @brief There was an invalid initialization parameter used in the document model. */
OtaJobParseErrNoContextAvailable, /* @brief There was not an OTA context available. */
OtaJobParseErrNoActiveJobs /* @brief No active jobs are available in the service. */
} OtaJobParseErr_t;
/**
* @ingroup ota_enum_types
* @brief OTA Job callback events.
*
* After an OTA update image is received and authenticated, the agent calls the user
* callback (set with the @ref OTA_Init API) with the value OtaJobEventActivate to
* signal that the device must be rebooted to activate the new image. When the device
* boots, if the OTA job status is in self test mode, the agent calls the user callback
* with the value OtaJobEventStartTest, signaling that any additional self tests
* should be performed.
*
* If the OTA receive fails for any reason, the agent calls the user callback with
* the value OtaJobEventFail instead to allow the user to log the failure and take
* any action deemed appropriate by the user code.
*
* See the OtaImageState_t type for more information.
*/
typedef enum OtaJobEvent
{
OtaJobEventActivate = 0, /*!< @brief OTA receive is authenticated and ready to activate. */
OtaJobEventFail = 1, /*!< @brief OTA receive failed. Unable to use this update. */
OtaJobEventStartTest = 2, /*!< @brief OTA job is now in self test, perform user tests. */
OtaJobEventProcessed = 3, /*!< @brief OTA event queued by OTA_SignalEvent is processed. */
OtaJobEventSelfTestFailed = 4, /*!< @brief OTA self-test failed for current job. */
OtaJobEventParseCustomJob = 5, /*!< @brief OTA event for parsing custom job document. */
OtaJobEventReceivedJob = 6, /*!< @brief OTA event when a new valid AFT-OTA job is received. */
OtaJobEventUpdateComplete = 7, /*!< @brief OTA event when the update is completed. */
OtaJobEventNoActiveJob = 8, /*!< @brief OTA event when no active job is pending. */
OtaLastJobEvent = OtaJobEventStartTest
} OtaJobEvent_t;
/**
* @ingroup ota_enum_types
* @brief Gives the status of the job operation.
*
*/
typedef enum
{
JobStatusInProgress = 0,
JobStatusFailed,
JobStatusSucceeded,
JobStatusRejected, /* Not possible today using the "get next job" feature. FUTURE! */
JobStatusFailedWithVal, /* This shows 2 numeric reason codes. */
NumJobStatusMappings
} OtaJobStatus_t;
/**
* @ingroup ota_struct_types
* @brief OTA Job document.
* @note This is provided as context to the app callback, #OtaAppCallback_t,
* to provide information of a custom job that cannot be parsed.
*
* Structure representing OTA job document.
*/
typedef struct OtaJobDocument
{
const uint8_t * pJobDocJson; /*!< @brief Job document in JSON format. */
size_t jobDocLength; /*!< @brief Job document length in bytes. */
const uint8_t * pJobId; /*!< @brief Job ID associated with the job document. */
size_t jobIdLength; /*!< @brief Length of job ID in bytes. */
uint32_t fileTypeId; /*!< @brief File Type ID from the job document. */
OtaJobParseErr_t parseErr; /*!< @brief Job parsing status. */
OtaJobStatus_t status; /*!< @brief Job status. */
int32_t reason; /*!< @brief Job status reason. */
int32_t subReason; /*!< @brief Job status subreason. */
} OtaJobDocument_t;
/*------------------------- OTA callbacks --------------------------*/
/**
* @ingroup ota_callback_types
* @brief OTA update complete callback function typedef.
*
* The user must register a callback function when initializing the OTA Agent. This
* callback is used to notify the main application when the OTA update job is complete.
* Typically, it is used to reset the device after a successful update by calling
* @ref OTA_ActivateNewImage and may also be used to kick off user specified self tests
* during the Self Test phase.
*
* The callback function is called with one of the following arguments:
*
* OtaJobEventActivate OTA update is authenticated and ready to activate.
* OtaJobEventFail OTA update failed. Unable to use this update.
* OtaJobEventStartTest OTA job is now ready for optional user self tests.
* OtaJobEventProcessed Event OTA got from user has been handled.
* OtaJobEventSelfTestFailed OTA update failed in self-test.
* OtaJobEventParseCustomJob OTA got an unknown job from cloud, need user to check
* if it's a custom job.
* OtaJobEventReceivedJob OTA event when a new valid job is received.
* OtaJobEventUpdateComplete OTA event when the update is completed.
* OtaJobEventNoActiveJob OTA event when no active job is pending.
*
* When OtaJobEventActivate is received, the job status details have been updated with
* the state as ready for Self Test. After reboot, the new firmware will (normally) be
* notified that it is in the Self Test phase via the callback and the application may
* then optionally run its own tests before committing the new image.
*
* If the callback function is called with a result of OtaJobEventFail, the OTA update
* job has failed in some way and should be rejected.
*
* When OtaJobEventStartTest is received, the load is first boot after OTA.
* Users can set the image state to OtaImageStateAccepted if the load is verified.
*
* When OtaJobEventProcessed is received, the event (OtaAgentEventReceivedJobDocument) sent
* from user has been handled. User can free the buffer when receiving this callback.
*
* When OtaJobEventSelfTestFailed is received, that means the load is failed on verification.
* And the device is going to reboot after this callback.
*
* When OtaJobEventParseCustomJob is received, that means OTA received an unknown job from cloud.
* User can parse the job by casting pData to OtaJobDocument_t, then check the pJobDocJson and
* pJobId in the document. User should set the result to parseErr if it's a custom job.
*
* When OtaJobEventReceivedJob is received, that means OTA has addressed the json file provided by
* user successfully. Let user know to handler the buffer.
*
* When OtaJobEventUpdateComplete is received, that means OTA has downloaded a full image for the
* file type which is different from configOTA_FIRMWARE_UPDATE_FILE_TYPE_ID.
*
* When OtaJobEventNoActiveJob is received, that means OTA has received a job document without valid
* job ID and job document key.
*
* @param[in] eEvent An OTA update event from the OtaJobEvent_t enum.
*
* @param[in] pData Optional data related to the event.
*
* eEvent|Structure of pData|Variable in pData
* ------|-----|-----------
* OtaJobEventActivate|OtaJobDocument_t|status and reason
* OtaJobEventFail|OtaJobDocument_t|status, reason and subReason
* OtaJobEventStartTest|NULL|nothing
* OtaJobEventProcessed|OtaEventData_t|data buffer inputed from user by OTA_SignalEvent
* OtaJobEventSelfTestFailed|NULL|nothing
* OtaJobEventParseCustomJob|OtaJobDocument_t|pJobId, jobIdLength, pJobDocJson, and jobDocLength
* OtaJobEventReceivedJob|OtaJobDocument_t|pJobId, jobIdLength, pJobDocJson, jobDocLength, and fileTypeId
* OtaJobEventUpdateComplete|OtaJobDocument_t|status, reason and subReason
* OtaJobEventNoActiveJob|NULL|nothing
*
*/
typedef void (* OtaAppCallback_t)( OtaJobEvent_t eEvent,
void * pData );
/*--------------------------- OTA structs ----------------------------*/
/**
* @ingroup ota_struct_types
* @brief OTA Interface for referencing different components.
*
* Information about the different interfaces used to initialize
* the OTA agent with references to components.
*/
typedef struct OtaInterface
{
OtaOSInterface_t os; /*!< @brief OS interface to store event, timers and memory operations. */
OtaMqttInterface_t mqtt; /*!< @brief MQTT interface that references the publish subscribe methods and callbacks. */
OtaHttpInterface_t http; /*!< @brief HTTP interface to request data. */
OtaPalInterface_t pal; /*!< @brief OTA PAL callback structure. */
} OtaInterfaces_t;
/**
* @ingroup ota_struct_types
* @brief OTA Application Buffer size information.
*
* File key signature information to verify the authenticity of the incoming file
*/
typedef struct OtaAppBuffer
{
uint8_t * pUpdateFilePath; /*!< @brief Path to store the files. */
uint16_t updateFilePathsize; /*!< @brief Maximum size of the file path. */
uint8_t * pCertFilePath; /*!< @brief Path to certificate file. */
uint16_t certFilePathSize; /*!< @brief Maximum size of the certificate file path. */
uint8_t * pStreamName; /*!< @brief Name of stream to download the files. */
uint16_t streamNameSize; /*!< @brief Maximum size of the stream name. */
uint8_t * pDecodeMemory; /*!< @brief Place to store the decoded files. */
uint32_t decodeMemorySize; /*!< @brief Maximum size of the decoded files buffer. */
uint8_t * pFileBitmap; /*!< @brief Bitmap of the parameters received. */
uint16_t fileBitmapSize; /*!< @brief Maximum size of the bitmap. */
uint8_t * pUrl; /*!< @brief Presigned url to download files from S3. */
uint16_t urlSize; /*!< @brief Maximum size of the URL. */
uint8_t * pAuthScheme; /*!< @brief Authentication scheme used to validate download. */
uint16_t authSchemeSize; /*!< @brief Maximum size of the auth scheme. */
} OtaAppBuffer_t;
/**
* @ingroup ota_private_struct_types
* @brief The OTA agent is a singleton today. The structure keeps it nice and organized.
*/
typedef struct OtaAgentContext
{
OtaState_t state; /*!< State of the OTA agent. */
uint8_t pThingName[ otaconfigMAX_THINGNAME_LEN + 1U ]; /*!< Thing name + zero terminator. */
OtaFileContext_t fileContext; /*!< Static array of OTA file structures. */
uint32_t fileIndex; /*!< Index of current file in the array. */
uint32_t serverFileID; /*!< Variable to store current file ID passed down */
uint8_t pActiveJobName[ OTA_JOB_ID_MAX_SIZE ]; /*!< The currently active job name. We only allow one at a time. */
uint8_t * pClientTokenFromJob; /*!< The clientToken field from the latest update job. */
uint32_t timestampFromJob; /*!< Timestamp received from the latest job document. */
OtaImageState_t imageState; /*!< The current application image state. */
uint32_t numOfBlocksToReceive; /*!< Number of data blocks to receive per data request. */
OtaAgentStatistics_t statistics; /*!< The OTA agent statistics block. */
uint32_t requestMomentum; /*!< The number of requests sent before a response was received. */
const OtaInterfaces_t * pOtaInterface; /*!< Collection of all interfaces used by the agent. */
OtaAppCallback_t OtaAppCallback; /*!< OTA App callback. */
uint8_t unsubscribeOnShutdown; /*!< Flag to indicate if unsubscribe from job topics should be done at shutdown. */
uint8_t isOtaInterfaceInited; /*!< Flag to indicate if pOtaInterface is initialized. */
} OtaAgentContext_t;
/*------------------------- OTA Public API --------------------------*/
/**
* @brief OTA Agent initialization function.
*
* Initialize the OTA engine by starting the OTA Agent ("OTA Task") in the system. This function must
* be called with the connection client context before calling @ref OTA_CheckForUpdate. Only one
* OTA Agent may exist.
*
* @param[in] pOtaBuffer Buffers used by the agent to store different params.
* @param[in] pOtaInterfaces A pointer to the OS context.
* @param[in] pThingName A pointer to a C string holding the Thing name.
* @param[in] OtaAppCallback Static callback function for when an OTA job is complete. This function will have
* input of the state of the OTA image after download and during self-test.
* @return OtaErr_t The state of the OTA Agent upon return from the OtaState_t enum.
* If the agent was successfully initialized and ready to operate, the state will be
* OtaAgentStateReady. Otherwise, it will be one of the other OtaState_t enum values.
*
* <b>Example</b>
* @code{c}
* // Application callback when the OTA agent has completed the job
* // or is in self test mode. For example see [demos](https://github.com/aws/aws-iot-device-sdk-embedded-C/tree/main/demos/ota)
* void otaAppCallback( OtaJobEvent_t event,
* const void * pData );
*
* // Optional: User buffer to pass down to the OTA Agent. These
* // buffers are assumed to be initialized previously, example:
* // uint8_t updateFilePath[ OTA_MAX_FILE_PATH_SIZE ];
* OtaAppBuffer_t otaBuffer =
* {
* .pUpdateFilePath = updateFilePath,
* .updateFilePathsize = OTA_MAX_FILE_PATH_SIZE,
* .pCertFilePath = certFilePath,
* .certFilePathSize = OTA_MAX_FILE_PATH_SIZE,
* .pDecodeMemory = decodeMem,
* .decodeMemorySize = otaconfigFILE_BLOCK_SIZE,
* .pFileBitmap = bitmap,
* .fileBitmapSize = OTA_MAX_BLOCK_BITMAP_SIZE,
* .pUrl = updateUrl,
* .urlSize = OTA_MAX_URL_SIZE,
* .pAuthScheme = authScheme,
* .authSchemeSize = OTA_MAX_AUTH_SCHEME_SIZE
* };
*
* // OTA interface context required for library interface functions
* // The functions set by these interfaces are assumed to be defined
* // For more information see [demos](https://github.com/aws/aws-iot-device-sdk-embedded-C/tree/main/demos/ota)
* OtaInterfaces_t pOtaInterfaces =
* {
* // Initialize OTA library OS Interface.
* .os.event.init = Posix_OtaInitEvent;
* .os.event.send = Posix_OtaSendEvent;
* ...
* // Initialize the OTA library MQTT Interface.
* .mqtt.subscribe = mqttSubscribe;
* .mqtt.publish = mqttPublish;
* .mqtt.unsubscribe = mqttUnsubscribe;
* // Initialize the OTA library HTTP Interface.
* .http.init = httpInit;
* .http.request = httpRequest;
* .http.deinit = httpDeinit;
* // Initialize the OTA library PAL Interface.
* .pal.getPlatformImageState = otaPal_GetPlatformImageState;
* .pal.setPlatformImageState = otaPal_SetPlatformImageState;
* }
*
* // OTA library error status.
* OtaErr_t otaErr = OtaErrNone;
*
* // Unique client identifier
* char * pClientIdentifier = "uniqueClientID";
*
* otaErr = OTA_Init( &otaBuffer,
* &otaInterfaces,
* ( const uint8_t * ) pClientIdentifier,
* otaAppCallback ) ) != OtaErrNone )
* if( otaErr == OtaErrNone )
* {
* // Do something with the OTA agent.
* }
* @endcode
*/
/* @[declare_ota_init] */
OtaErr_t OTA_Init( const OtaAppBuffer_t * pOtaBuffer,
const OtaInterfaces_t * pOtaInterfaces,
const uint8_t * pThingName,
OtaAppCallback_t OtaAppCallback );
/* @[declare_ota_init] */
/**
* @brief Signal to the OTA Agent to shut down.
*
* Signals the OTA agent task to shut down. The OTA agent will unsubscribe from all MQTT job
* notification topics, stop in progress OTA jobs, if any, and clear all resources.
*
* OTA needs a processing task running OTA_EventProcessingTask to handle shutdown event, or
* OTA will shutdown after the processing task is created and scheduled.
*
* @param[in] ticksToWait The number of ticks to wait for the OTA Agent to complete the shutdown process.
* If this is set to zero, the function will return immediately without waiting. The actual state is
* returned to the caller. The agent does not sleep for this while but used for busy looping.
*
* @param[in] unsubscribeFlag Flag to indicate if unsubscribe operations should be performed from the job topics when
* shutdown is called. If the flag is 0 then unsubscribe operations are not called for job topics If application
* requires it to be unsubscribed from the job topics then flag must be set to 1 when calling OTA_Shutdown.
*
* @return One of the OTA agent states from the OtaState_t enum.
* A normal shutdown will return OtaAgentStateNotReady. Otherwise, refer to the OtaState_t enum for details.
*
* <b>Example</b>
* @code{c}
* // ticksToWait used for busy looping until shutdown. Actual delay may depend on the agent priority,
* // and platform.
* uint32_t ticksToWait = 100;
*
* // If it is required that the unsubscribe operations are not
* //performed while shutting down set this to 0.
* uint8_t unsubscribe = 1;
*
* OTA_Shutdown(ticksToWait, unsubscribe);
* ...
*
* if( OTA_GetState() != OtaAgentStateStopped )
* {
* // Optional: Disconnect MQTT and HTTP connections
* // required by the OTA agent and other tasks.
* }
* @endcode
*/
/* @[declare_ota_shutdown] */
OtaState_t OTA_Shutdown( uint32_t ticksToWait,
uint8_t unsubscribeFlag );
/* @[declare_ota_shutdown] */
/**
* @brief Get the current state of the OTA agent.
*
* @return The current state of the OTA agent.
*
* <b>Example</b>
* Check if OTA agent is in suspended state.
* @code{c}
* // OTA Agent state
* OtaState_t state = OTA_GetState();
*
* while( state != OtaAgentStateSuspended )
* {
* // Do something while the agent is back to
* // the desired state.
* state = OTA_GetState();
* }
* @endcode
*/
/* @[declare_ota_getstate] */
OtaState_t OTA_GetState( void );
/* @[declare_ota_getstate] */
/**
* @brief Activate the newest MCU image received via OTA.
*
* This function should reset the MCU and cause a reboot of the system to execute the newly updated
* firmware. It should be called by the user code sometime after the OtaJobEventActivate event
* is passed to the users application via the OTA Job Complete Callback mechanism. Refer to the
* @ref OTA_Init function for more information about configuring the callback.
*
* @return OtaErrNone if successful, otherwise an error code prefixed with 'OtaErr' from the
* list above.
*
* <b>Example</b>
* @code{c}
* static void otaAppCallback( OtaJobEvent_t event,
* const void * pData )
* {
* OtaErr_t otaErr = OtaErrNone;
* if( event == OtaJobEventActivate )
* {
* // Activate the new firmware image.
* // This calls the platform specific code required to
* // activate the received OTA update firmware.
* otaErr = OTA_ActivateNewImage();
* if( otaErr == OtaErrActivateFailed )
* {
* // Handle Image activation failure by requesting manual response, sending
* // error logs or retrying activation.
* }
* }
*
* // Handle other events
* }
* @endcode
*/
/* @[declare_ota_activatenewimage] */
OtaErr_t OTA_ActivateNewImage( void );
/* @[declare_ota_activatenewimage] */
/**
* @brief Set the state of the current MCU image.
*
* The states are OtaImageStateTesting, OtaImageStateAccepted, OtaImageStateAborted or
* OtaImageStateRejected; see OtaImageState_t documentation. This will update the status of the
* current image and publish to the active job status topic.
*
* @param[in] state The state to set of the OTA image.
*
* @return OtaErrNone if successful, otherwise an error code prefixed with 'OtaErr' from the
* list above.
*
* <b>Example</b>
* Set image state to reflect new image is accepted in application callback.
*
* @code{c}
* static void otaAppCallback( OtaJobEvent_t event,
* const void * pData )
* {
* OtaErr_t otaErr = OtaErrNone;
*
* if( event == OtaJobEventStartTest )
* {
* err = OTA_SetImageState( OtaImageStateAccepted );
* if( err != OtaErrNone )
* {
* // Handle failure or retry setting the image state.
* }
* }
*
* // Handle other events
* }
* @endcode
*/
/* @[declare_ota_setimagestate] */
OtaErr_t OTA_SetImageState( OtaImageState_t state );
/* @[declare_ota_setimagestate] */
/**
* @brief Get the state of the currently running MCU image.
*
* The states are OtaImageStateTesting, OtaImageStateAccepted, OtaImageStateAborted or
* OtaImageStateRejected; see OtaImageState_t documentation.
*
* @return The state of the current context's OTA image.
*/
/* @[declare_ota_getimagestate] */
OtaImageState_t OTA_GetImageState( void );
/* @[declare_ota_getimagestate] */
/**
* @brief Request for the next available OTA job from the job service.
*
* @return OtaErrNone if successful, otherwise an error code prefixed with 'OtaErr' from the
* list above.
*/
/* @[declare_ota_checkforupdate] */
OtaErr_t OTA_CheckForUpdate( void );
/* @[declare_ota_checkforupdate] */
/**
* @brief Suspend OTA agent operations .
*
* @return OtaErrNone if successful, otherwise an error code prefixed with 'OtaErr' from the
* list above.
*
* <b>Example</b>
* Suspend the OTA agent when a network error occurs.
* @code{c}
* void handleNetworkErrors()
* {
* OtaErr_t otaErr = OtaErrNone;
* int16_t suspendTimeout = 5000U;
*
* // Handle disconnects and other network reset operations
*
* // Suspend OTA operations.
* otaErr = OTA_Suspend();
*
* if( otaErr != OtaErrNone )
* {
* // Suspend may fail due to Event queue failure,
* // or if the agent has shut down, handle the failure by
* // sending logs or retrying OTA_Suspend().
* }
* else
* {
* while( ( ( OTA_GetState() != OtaAgentStateSuspended )
* && ( suspendTimeout > 0 ) )
* {
* // Wait for OTA Library state to suspend
* portSleep( 1000U );
* suspendTimeout -= 1000U;
* }
* if( OTA_GetState() != OtaAgentStateSuspended )
* {
* // Handle Suspend failure or Retry OTA_Suspend().
* }
* }
* }
* @endcode
*/
/* @[declare_ota_suspend] */
OtaErr_t OTA_Suspend( void );
/* @[declare_ota_suspend] */
/**
* @brief Resume OTA agent operations .
*
* @return OtaErrNone if successful, otherwise an error code prefixed with 'OtaErr' from the
* list above.
*
* <b>Example</b>
* Resume the OTA agent after the network errors are resolved.
* @code{c}
* bool handleReconnect()
* {
* // OTA event message used for sending event to OTA Agent.
* OtaEventMsg_t eventMsg = { 0 };
* OtaErr_t otaErr = OtaErrUninitialized;
* bool returnStatus = establishConnection();
*
* if( returnStatus == EXIT_SUCCESS )
* {
* // Check if OTA process was suspended and resume if required.
* if( OTA_GetState() == OtaAgentStateSuspended )
* {
* // Resume OTA operations.
* otaErr = OTA_Resume();
* }
* else
* {
* // Send start event to OTA Agent.
* eventMsg.eventId = OtaAgentEventStart;
* OTA_SignalEvent( &eventMsg );
* }
*
* if( otaErr != OtaErrNone )
* returnStatus = false;
* }
*
* return returnStatus;
* }
* @endcode
*/
/* @[declare_ota_resume] */
OtaErr_t OTA_Resume( void );
/* @[declare_ota_resume] */
/**
* @brief OTA agent event processing loop.
*
* This is the main event loop to handle events for OTA update and needs to be called by
* the application task. This loop will continue to handle and execute events received for
* OTA Update until this tasks is terminated by the application.
*
* @param[in] pUnused Can be used to pass down functionality to the agent task, Unused for now.
* This can be a function pointer that executes as the first routine when the
* event loop starts.
*
* For a Posix based reference of creating a thread with this task,
* please see the [demos in AWS IoT Embedded C SDK repository](https://github.com/aws/aws-iot-device-sdk-embedded-C/tree/main/demos/ota).
*/
/* @[declare_ota_eventprocessingtask] */
void OTA_EventProcessingTask( const void * pUnused );
/* @[declare_ota_eventprocessingtask] */
/**
* @brief OTA agent event process cycler.
*
* This is the main agent event handler for OTA update and needs to be called repeatedly
* by an application task. This is functionally equivalent to @ref OTA_EventProcessingTask, except
* instead of forever looping internally, the user is responsible for periodically calling this function.
*
* @note This is NOT thread safe with @ref OTA_EventProcessingTask and the two should never be used in conjunction.
*
* @return The state of the ota agent after this single event process cycle
*
*/
/* @[declare_ota_eventprocess] */
OtaState_t OTA_EventProcess( void );
/* @[declare_ota_eventprocess] */
/**
* @brief Signal event to the OTA Agent task.
*
* This function adds the event to the back of event queue and used
* by internal OTA modules to signal agent task.
*
* @param[in] pEventMsg Event to be added to the queue
* @return true If operation is successful, false If the event can not be added
*
* <b>Example</b>
* Signal OTA agent that a new file block has been received over the http connection.
* @code{c}
* OtaHttpStatus_t handleDataFromHTTPService( const HTTPResponse_t * pResponse )
* {
* // Assume otaEventBufferGet is a user defined, thread-safe function
* // that gets an available buffer from the pool of OTA buffers.
* OtaEventData_t * pData = otaEventBufferGet();
* OtaHttpStatus_t returnValue = OtaHttpRequestFailed;
* bool result = false;
*
* // Validate pResponse for correct data.
*
* if( pData != NULL )
* {
* memcpy( pData->data, pResponse->pBody, pResponse->bodyLen );
* pData->dataLength = pResponse->bodyLen;
*
* // Send job document received event.
* eventMsg.eventId = OtaAgentEventReceivedFileBlock;
* eventMsg.pEventData = pData;
* result = OTA_SignalEvent( &eventMsg );
*
* if( result )
* {
* returnValue = OtaHttpSuccess;
* }
* }
* return returnValue;
* }
* @endcode
*/
/* @[declare_ota_signalevent] */
bool OTA_SignalEvent( const OtaEventMsg_t * const pEventMsg );
/* @[declare_ota_signalevent] */
/*---------------------------------------------------------------------------*/
/* Statistics API */
/*---------------------------------------------------------------------------*/
/**
* @brief Get the statistics of OTA message packets.
*
* Packet statistics are:
* <ul>
* <li> Received: The number of OTA packets that have been received
* but not necessarily queued for processing by the OTA agent.
* <li> Queued: The number of OTA packets that have been queued for
* processing. This implies there was a free message queue entry so
* it can be passed to the agent for processing.
* <li> Processed: The number of OTA packets that have actually been
* processed.
* <li> Dropped: The number of OTA packets that have been dropped
* because of either no queue or at shutdown cleanup.
*</ul>
* @note Calling @ref OTA_Init will reset this statistic.
*
* @return OtaErrNone if the statistics can be received successfully.
*
* <b>Example</b>
* @code{c}
* // OTA library packet statistics per job.
* OtaAgentStatistics_t otaStatistics = { 0 };
* OtaErr_t otaErr = OtaErrNone;
*
* // Get the current statistics from the agent.
* otaErr = OTA_GetStatistics( &otaStatistics );
*
* if( otaErr != OtaErrNone )
* {
* printf( " Received: %u Queued: %u Processed: %u Dropped: %u",
* otaStatistics.otaPacketsReceived,
* otaStatistics.otaPacketsQueued,
* otaStatistics.otaPacketsProcessed,
* otaStatistics.otaPacketsDropped );
* }
* @endcode
*/
/* @[declare_ota_getstatistics] */
OtaErr_t OTA_GetStatistics( OtaAgentStatistics_t * pStatistics );
/* @[declare_ota_getstatistics] */
/**
* @brief Error code to string conversion for OTA errors.
*
* @param[in] err The error to convert to a string.
*
* @return The string representation of the error.
*/
/* @[declare_ota_err_strerror] */
const char * OTA_Err_strerror( OtaErr_t err );
/* @[declare_ota_err_strerror] */
/**
* @brief Error code to string conversion for OTA Job Parsing errors.
*
* @param[in] err The error to convert to a string.
*
* @return The string representation of the error.
*/
/* @[declare_ota_jobparse_strerror] */
const char * OTA_JobParse_strerror( OtaJobParseErr_t err );
/* @[declare_ota_jobparse_strerror] */
/**
* @brief Status code to string conversion for OTA PAL status.
*
* @param[in] status The status to convert to a string.
*
* @return The string representation of the status.
*/
/* @[declare_ota_palstatus_strerror] */
const char * OTA_PalStatus_strerror( OtaPalMainStatus_t status );
/* @[declare_ota_palstatus_strerror] */
/**
* @brief Status code to string conversion for OTA OS status.
*
* @param[in] status The status to convert to a string.
*
* @return The string representation of the status.
*/
/* @[declare_ota_osstatus_strerror] */
const char * OTA_OsStatus_strerror( OtaOsStatus_t status );
/* @[declare_ota_osstatus_strerror] */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* ifndef OTA_H */

View File

@ -0,0 +1,86 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota_appversion32.h
* @brief Structure to represent the application build version.
*/
#ifndef IOT_APPVERSION32_H
#define IOT_APPVERSION32_H
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/* Standard includes. */
#include <stdint.h>
/**
* @ingroup ota_struct_types
* @brief Application version structure.
*
*/
typedef struct
{
/* MISRA Ref 19.2.1 [Unions] */
/* More details at: https://github.com/aws/ota-for-aws-iot-embedded-sdk/blob/main/MISRA.md#rule-192 */
/* coverity[misra_c_2012_rule_19_2_violation] */
union
{
#if ( defined( __BYTE_ORDER__ ) && defined( __ORDER_LITTLE_ENDIAN__ ) && ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) ) || ( __little_endian__ == 1 ) || WIN32 || ( __BYTE_ORDER == __LITTLE_ENDIAN )
struct version
{
uint16_t build; /*!< @brief Build of the firmware (Z in firmware version Z.Y.X). */
uint8_t minor; /*!< @brief Minor version number of the firmware (Y in firmware version Z.Y.X). */
uint8_t major; /*!< @brief Major version number of the firmware (X in firmware version Z.Y.X). */
} x; /*!< @brief Version number of the firmware. */
#elif ( defined( __BYTE_ORDER__ ) && defined( __ORDER_BIG_ENDIAN__ ) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ) || ( __big_endian__ == 1 ) || ( __BYTE_ORDER == __BIG_ENDIAN )
struct version
{
uint8_t major; /*!< @brief Major version number of the firmware (X in firmware version X.Y.Z). */
uint8_t minor; /*!< @brief Minor version number of the firmware (Y in firmware version X.Y.Z). */
uint16_t build; /*!< @brief Build of the firmware (Z in firmware version X.Y.Z). */
} x; /*!< @brief Version number of the firmware. */
#else /* if ( defined( __BYTE_ORDER__ ) && defined( __ORDER_LITTLE_ENDIAN__ ) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) || ( __little_endian__ == 1 ) || WIN32 || ( __BYTE_ORDER == __LITTLE_ENDIAN ) */
#error "Unable to determine byte order!"
#endif /* if ( defined( __BYTE_ORDER__ ) && defined( __ORDER_LITTLE_ENDIAN__ ) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) || ( __little_endian__ == 1 ) || WIN32 || ( __BYTE_ORDER == __LITTLE_ENDIAN ) */
uint32_t unsignedVersion32;
int32_t signedVersion32;
} u; /*!< @brief Version based on configuration in big endian or little endian. */
} AppVersion32_t;
extern const AppVersion32_t appFirmwareVersion; /*!< @brief Making the version number available globally through external linkage. */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* ifndef IOT_APPVERSION32_H */

View File

@ -0,0 +1,120 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota_base64_private.h
* @brief Function declarations and error codes for ota_base64.c.
*/
#ifndef OTA_BASE64_PRIVATE_H
#define OTA_BASE64_PRIVATE_H
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/* Standard includes. */
#include <stdint.h>
#include <stdlib.h>
/**
* ota_enum_types
* @brief The Base64 functionality return status.
*/
typedef enum Base64Status
{
/**
* @brief Base64 function success.
*/
Base64Success,
/**
* @brief Invalid symbol in the encoded data.
*/
Base64InvalidSymbol,
/**
* @brief A Base64 symbol is in an invalid location within the encoded data.
*/
Base64InvalidSymbolOrdering,
/**
* @brief Length of the encoded data is impossible to have been created with
* valid Base64 encoding.
*/
Base64InvalidInputSize,
/**
* @brief Input parameter for pointer is null.
*/
Base64NullPointerInput,
/**
* @brief Provided buffer is too small.
*/
Base64InvalidBufferSize,
/**
* @brief Padding bits inside of the encoded data are invalid because they are
* not zero.
*/
Base64NonZeroPadding,
/**
* @brief Invalid number of padding symbols.
*/
Base64InvalidPaddingSymbol
} Base64Status_t;
/**
* @brief Decode Base64 encoded data.
*
* @param[out] pDest Pointer to a buffer for storing the decoded result.
* @param[in] destLen Length of the pDest buffer.
* @param[out] pResultLen Pointer to the length of the decoded result.
* @param[in] pEncodedData Pointer to a buffer containing the Base64 encoded
* data that is intended to be decoded.
* @param[in] encodedLen Length of the pEncodedData buffer.
*
* @return One of the following:
* - #Base64Success if the Base64 encoded data was valid
* and successfully decoded.
* - An error code defined in ota_base64_private.h if the
* encoded data or input parameters are invalid.
*/
Base64Status_t base64Decode( uint8_t * pDest,
const size_t destLen,
size_t * pResultLen,
const uint8_t * pEncodedData,
const size_t encodedLen );
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* ifndef OTA_BASE64_PRIVATE_H */

View File

@ -0,0 +1,89 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota_cbor_private.h
* @brief Function declarations and field declarations for ota_cbor.c.
*/
#ifndef OTA_CBOR_H
#define OTA_CBOR_H
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/**
* Message field definitions, per the server specification. These are
* not part of the library interface but are included here for testability.
*/
#define OTA_CBOR_CLIENTTOKEN_KEY "c" /*!< Key for client id. */
#define OTA_CBOR_FILEID_KEY "f" /*!< Key for file id. */
#define OTA_CBOR_BLOCKSIZE_KEY "l" /*!< Key for file block size. */
#define OTA_CBOR_BLOCKOFFSET_KEY "o" /*!< Key for file block offset. */
#define OTA_CBOR_BLOCKBITMAP_KEY "b" /*!< Key for bitmap. */
#define OTA_CBOR_STREAMDESCRIPTION_KEY "d" /*!< Key for stream name. */
#define OTA_CBOR_STREAMFILES_KEY "r" /*!< Key for file attributes. */
#define OTA_CBOR_FILESIZE_KEY "z" /*!< Key for file size. */
#define OTA_CBOR_BLOCKID_KEY "i" /*!< Key for block id. */
#define OTA_CBOR_BLOCKPAYLOAD_KEY "p" /*!< Key for payload of a block. */
#define OTA_CBOR_NUMBEROFBLOCKS_KEY "n" /*!< Key for number of blocks. */
/**
* @brief Decode a Get Stream response message from AWS IoT OTA.
*/
bool OTA_CBOR_Decode_GetStreamResponseMessage( const uint8_t * pMessageBuffer,
size_t messageSize,
int32_t * pFileId,
int32_t * pBlockId,
int32_t * pBlockSize,
uint8_t * const * pPayload,
size_t * pPayloadSize );
/**
* @brief Create an encoded Get Stream Request message for the AWS IoT OTA
* service. The service allows block count or block bitmap to be requested,
* but not both.
*/
bool OTA_CBOR_Encode_GetStreamRequestMessage( uint8_t * pMessageBuffer,
size_t messageBufferSize,
size_t * pEncodedMessageSize,
const char * pClientToken,
int32_t fileId,
int32_t blockSize,
int32_t blockOffset,
const uint8_t * pBlockBitmap,
size_t blockBitmapSize,
int32_t numOfBlocksRequested );
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* ifndef OTA_CBOR_H */

View File

@ -0,0 +1,397 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota_config_defaults.h
* @brief This represents the default values for the configuration macros
* for the OTA library.
*
* @note This file SHOULD NOT be modified. If custom values are needed for
* any configuration macro, an ota_config.h file should be provided to
* the OTA library to override the default values defined in this file.
* To use the custom config file, the OTA_DO_NOT_USE_CUSTOM_CONFIG preprocessor
* macro SHOULD NOT be set.
*/
#ifndef OTA_CONFIG_DEFAULTS_H
#define OTA_CONFIG_DEFAULTS_H
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/* The macro definition for OTA_DO_NOT_USE_CUSTOM_CONFIG is for Doxygen
* documentation only. */
/**
* @brief Define this macro to build the OTA library without the custom config
* file ota_config.h.
*
* Without the custom config, the OTA library builds with
* default values of config macros defined in ota_config_defaults.h file.
*
* If a custom config is provided, then OTA_DO_NOT_USE_CUSTOM_CONFIG should not
* be defined.
*/
#ifdef DOXYGEN
#define OTA_DO_NOT_USE_CUSTOM_CONFIG
#endif
/**
* @brief The number of words allocated to the stack for the OTA agent.
*
* The configuration parameter specifies the size of the stack that will be allocated
* to the task being created (the size is specified in words, not bytes!). The amount
* of stack required is dependent on the application specific parameters,
* for more information [Link](https://www.freertos.org/FAQMem.html#StackSize)
*
* <b>Possible values:</b> Any positive 32 bit integer. <br>
* <b>Default value:</b> Varies by platform
*/
#ifndef otaconfigSTACK_SIZE
#define otaconfigSTACK_SIZE "Please set otaconfigSTACK_SIZE"
#endif
/**
* @brief The OTA agent task priority. Normally it runs at a low priority.
*
* For more information [Link](https://www.freertos.org/RTOS-task-priority.html).
*
* <b>Possible values:</b> 0 to ( configMAX_PRIORITIES - 1 ) <br>
* <b>Default value:</b> Varies by platform.
*/
#ifndef otaconfigAGENT_PRIORITY
#define otaconfigAGENT_PRIORITY "Please set otaconfigAGENT_PRIORITY"
#endif
/**
* @brief Log base 2 of the size of the file data block message (excluding the
* header).
*
* <b>Possible values:</b> Any unsigned 32 integer. <br>
* <b>Default value:</b> '12'
*/
#ifndef otaconfigLOG2_FILE_BLOCK_SIZE
#define otaconfigLOG2_FILE_BLOCK_SIZE 12UL
#endif
/**
* @brief Milliseconds to wait for the self test phase to succeed before we
* force reset.
*
* <b>Possible values:</b> Any unsigned 32 integer. <br>
* <b>Default value:</b> '16000'
*/
#ifndef otaconfigSELF_TEST_RESPONSE_WAIT_MS
#define otaconfigSELF_TEST_RESPONSE_WAIT_MS 16000U
#endif
/**
* @brief Milliseconds to wait before requesting data blocks from the OTA
* service if nothing is happening.
*
* @note The wait timer is reset whenever a data block is received from the OTA
* service so we will only send the request message after being idle for this
* amount of time.
*
* <b>Possible values:</b> Any unsigned 32 integer. <br>
* <b>Default value:</b> '10000'
*/
#ifndef otaconfigFILE_REQUEST_WAIT_MS
#define otaconfigFILE_REQUEST_WAIT_MS 10000U
#endif
/**
* @brief The maximum allowed length of the thing name used by the OTA agent.
*
* @note AWS IoT requires Thing names to be unique for each device that
* connects to the broker. Likewise, the OTA agent requires the developer to
* construct and pass in the Thing name when initializing the OTA agent. The
* agent uses this size to allocate static storage for the Thing name used in
* all OTA base topics. Namely $aws/things/thingName
*
* <b>Possible values:</b> Any unsigned 32 integer. <br>
* <b>Default value:</b> '64'
*/
#ifndef otaconfigMAX_THINGNAME_LEN
#define otaconfigMAX_THINGNAME_LEN 64U
#endif
/**
* @brief The maximum number of data blocks requested from OTA streaming
* service.
*
* @note This configuration parameter is sent with data requests and represents
* the maximum number of data blocks the service will send in response. The
* maximum limit for this must be calculated from the maximum data response
* limit (128 KB from service) divided by the block size. For example if block
* size is set as 1 KB then the maximum number of data blocks that we can
* request is 128/1 = 128 blocks. Configure this parameter to this maximum
* limit or lower based on how many data blocks response is expected for each
* data requests.
*
* <b>Possible values:</b> Any unsigned 32 integer value greater than 0. <br>
* <b>Default value:</b> '1'
*/
#ifndef otaconfigMAX_NUM_BLOCKS_REQUEST
#define otaconfigMAX_NUM_BLOCKS_REQUEST 1U
#endif
/**
* @brief The maximum number of requests allowed to send without a response
* before we abort.
*
* @note This configuration parameter sets the maximum number of times the
* requests are made over the selected communication channel before aborting
* and returning error.
*
* <b>Possible values:</b> Any unsigned 32 integer. <br>
* <b>Default value:</b> '32'
*/
#ifndef otaconfigMAX_NUM_REQUEST_MOMENTUM
#define otaconfigMAX_NUM_REQUEST_MOMENTUM 32U
#endif
/**
* @brief How frequently the device will report its OTA progress to the cloud.
*
* @note Device will update the job status with the number of blocks it has received every certain
* number of blocks it receives. For example, 64 means device will update job status every 64 blocks
* it receives.
*
* <b>Possible values:</b> Any unsigned 32 integer. <br>
* <b>Default value:</b> '64'
*/
#ifndef otaconfigOTA_UPDATE_STATUS_FREQUENCY
#define otaconfigOTA_UPDATE_STATUS_FREQUENCY 64U
#endif
/**
* @brief The number of data buffers reserved by the OTA agent.
*
* @note This configurations parameter sets the maximum number of static data
* buffers used by the OTA agent for job and file data blocks received.
*
* <b>Possible values:</b> Any unsigned 32 integer. <br>
* <b>Default value:</b> '1'
*/
#ifndef otaconfigMAX_NUM_OTA_DATA_BUFFERS
#define otaconfigMAX_NUM_OTA_DATA_BUFFERS 1U
#endif
/**
* @brief Data type to represent a file.
*
* It is used to represent a file received via OTA. The file is declared as
* the pointer of this type: otaconfigOTA_FILE_TYPE * pFile.
*
* <b>Possible values:</b> Any data type. <br>
* <b>Default value:</b> FILE on Windows or Linux, uint8_t on other platforms.
*/
#ifndef otaconfigOTA_FILE_TYPE
#if defined( WIN32 ) || defined( __linux__ )
#define otaconfigOTA_FILE_TYPE FILE
#else
#define otaconfigOTA_FILE_TYPE uint8_t
#endif
#endif
/**
* @brief Flag to enable booting into updates that have an identical or lower
* version than the current version.
*
* @note Set this configuration parameter to '1' to disable version checks.
* This allows updates to an identical or lower version. This is provided for
* testing purpose and it's recommended to always update to higher version and
* keep this configuration disabled.
*
* <b>Possible values:</b> Any unsigned 32 integer. <br>
* <b>Default value:</b> '0'
*/
#ifndef otaconfigAllowDowngrade
#define otaconfigAllowDowngrade 0U
#endif
/**
* @brief The file type id received in the job document.
*
* @note The file type id received in the job document that allows devices
* to identify the type of file received from the cloud. This configuration
* defines the file type id used for firmware updates. If this is changed
* then the updated value must be used while creating firmware update jobs.
*
*/
#ifndef configOTA_FIRMWARE_UPDATE_FILE_TYPE_ID
#define configOTA_FIRMWARE_UPDATE_FILE_TYPE_ID 0U
#endif
/**
* @brief The protocol selected for OTA control operations.
*
* @note This configurations parameter sets the default protocol for all the
* OTA control operations like requesting OTA job, updating the job status etc.
*
* @note Only MQTT is supported at this time for control operations.
*
* <b>Possible values:</b> OTA_CONTROL_OVER_MQTT <br>
* <b>Default value:</b> 'OTA_CONTROL_OVER_MQTT'
*/
#ifndef configENABLED_CONTROL_PROTOCOL
#define configENABLED_CONTROL_PROTOCOL ( OTA_CONTROL_OVER_MQTT )
#endif
/**
* @brief The protocol selected for OTA data operations.
*
* @note This configurations parameter sets the protocols selected for the data
* operations like requesting file blocks from the service.
*
* <b>Possible values:</b><br>
* Enable data over MQTT - ( OTA_DATA_OVER_MQTT ) <br>
* Enable data over HTTP - ( OTA_DATA_OVER_HTTP ) <br>
* Enable data over both MQTT & HTTP - ( OTA_DATA_OVER_MQTT | OTA_DATA_OVER_HTTP ) <br>
* <b>Default value:</b> 'OTA_DATA_OVER_MQTT'
*/
#ifndef configENABLED_DATA_PROTOCOLS
#define configENABLED_DATA_PROTOCOLS ( OTA_DATA_OVER_MQTT )
#endif
/**
* @brief The preferred protocol selected for OTA data operations.
*
* @note Primary data protocol will be the protocol used for downloading file
* if more than one protocol is selected while creating OTA job.
*
* <b>Possible values:</b><br>
* Data over MQTT - ( OTA_DATA_OVER_MQTT ) <br>
* Data over HTTP - ( OTA_DATA_OVER_HTTP ) <br>
* <b>Default value:</b> 'OTA_DATA_OVER_MQTT'
*/
#ifndef configOTA_PRIMARY_DATA_PROTOCOL
#define configOTA_PRIMARY_DATA_PROTOCOL ( OTA_DATA_OVER_MQTT )
#endif
/**
* @brief The polling timeout (milliseconds) to receive messages from event queue.
*
* <b>Possible values:</b> Any unsigned 32 integer. <br>
* <b>Default value:</b> '1000'
*/
#ifndef configOTA_POLLING_EVENTS_TIMEOUT_MS
#define configOTA_POLLING_EVENTS_TIMEOUT_MS ( 1000U )
#endif
/**
* @brief Macro that is called in the OTA library for logging "Error" level
* messages.
*
* To enable error level logging in the OTA library, this macro should be
* mapped to the application-specific logging implementation that supports
* error logging.
*
* @note This logging macro is called in the OTA library with parameters
* wrapped in double parentheses to be ISO C89/C90 standard compliant. For a
* reference POSIX implementation of the logging macros, refer to the ota
* default config file, and the logging-stack in demos folder of the
* [AWS IoT Embedded C SDK repository](https://github.com/aws/aws-iot-device-sdk-embedded-C/tree/main).
*
* <b>Default value</b>: Error logging is turned off, and no code is generated
* for calls to the macro in the OTA library on compilation.
*/
#ifndef LogError
#define LogError( message )
#endif
/**
* @brief Macro that is called in the OTA library for logging "Warning" level
* messages.
*
* To enable warning level logging in the OTA library, this macro should be
* mapped to the application-specific logging implementation that supports
* warning logging.
*
* @note This logging macro is called in the OTA library with parameters
* wrapped in double parentheses to be ISO C89/C90 standard compliant. For a
* reference POSIX implementation of the logging macros, refer to the ota
* default config file, and the logging-stack in demos folder of the
* [AWS IoT Embedded C SDK repository](https://github.com/aws/aws-iot-device-sdk-embedded-C/tree/main).
*
* <b>Default value</b>: Warning logging is turned off, and no code is
* generated for calls to the macro in the OTA library on compilation.
*/
#ifndef LogWarn
#define LogWarn( message )
#endif
/**
* @brief Macro that is called in the OTA library for logging "Info" level
* messages.
*
* To enable info level logging in the OTA library, this macro should be
* mapped to the application-specific logging implementation that supports
* info logging.
*
* @note This logging macro is called in the OTA library with parameters
* wrapped in double parentheses to be ISO C89/C90 standard compliant. For a
* reference POSIX implementation of the logging macros, refer to the ota
* default config file, and the logging-stack in demos folder of the
* [AWS IoT Embedded C SDK repository](https://github.com/aws/aws-iot-device-sdk-embedded-C/tree/main).
*
* <b>Default value</b>: Info logging is turned off, and no code is
* generated for calls to the macro in the OTA library on compilation.
*/
#ifndef LogInfo
#define LogInfo( message )
#endif
/**
* @brief Macro that is called in the OTA library for logging "Debug" level
* messages.
*
* To enable Debug level logging in the OTA library, this macro should be
* mapped to the application-specific logging implementation that supports
* debug logging.
*
* @note This logging macro is called in the OTA library with parameters
* wrapped in double parentheses to be ISO C89/C90 standard compliant. For a
* reference POSIX implementation of the logging macros, refer to the ota
* default config file, and the logging-stack in demos folder of the
* [AWS IoT Embedded C SDK repository](https://github.com/aws/aws-iot-device-sdk-embedded-C/tree/main).
*
* <b>Default value</b>: Debug logging is turned off, and no code is
* generated for calls to the macro in the OTA library on compilation.
*/
#ifndef LogDebug
#define LogDebug( message )
#endif
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* ifndef OTA_CONFIG_DEFAULTS_H */

View File

@ -0,0 +1,150 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota_http_interface.h
* @brief Contains OTA HTTP Statuses, function type definitions and http interface structure.
*/
#ifndef OTA_HTTP_INTERFACE_H
#define OTA_HTTP_INTERFACE_H
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/* Standard library includes. */
#include <stddef.h>
#include <stdint.h>
/**
* @otahttppage
* @brief The OTA PAL interface definition.
*
* @otahttpsectionoverview
*
* The OTA MQTT interface is a set of APIs that must be implemented by
* a library to enable the OTA library to download a file block by
* connecting to a pre-signed url and fetching data blocks.
*
* The OTA MQTT interface is defined in @ref ota_mqtt_interface.h.
* <br>
*
* The functions that must be implemented are:<br>
* - [OTA MQTT Subscribe](@ref OtaMqttSubscribe_t)
* - [OTA MQTT Unsubscribe](@ref OtaMqttSubscribe_t)
* - [OTA MQTT Publish](@ref OtaMqttSubscribe_t)
*
* These functions can be grouped into the structure `OtaHttpInterface_t`
* and passed to @ref OtaInterfaces_t to represent the MQTT interface.
* @code{c}
* OtaHttpInterface_t httpInterface;
* httpInterface.init = httpInit;
* httpInterface.request = httpRequest;
* httpInterface.deinit = httpDeinit;
*
* .....
*
* OtaInterfaces_t otaInterfaces;
* otaInterfaces.http = httpInterface
*
* .....
*
* OTA_Init( &otaBuffer,
* &otaInterfaces,
* ( CLIENT_IDENTIFIER ),
* otaAppCallback )
* @endcode
*/
/**
* @ingroup ota_enum_types
* @brief The OTA HTTP interface return status.
*/
typedef enum OtaHttpStatus
{
OtaHttpSuccess = 0, /*!< @brief OTA HTTP interface success. */
OtaHttpInitFailed = 0xc0, /*!< @brief Error initializing the HTTP connection. */
OtaHttpDeinitFailed, /*!< @brief Error deinitializing the HTTP connection. */
OtaHttpRequestFailed /*!< @brief Error sending the HTTP request. */
} OtaHttpStatus_t;
/**
* @brief Init OTA Http interface.
*
* This function parses the pre-signed url and initializes connection.
*
* @param[in] pUrl Pointer to the pre-signed url for downloading update file.
*
* @return OtaHttpSuccess if success , other error code on failure.
*/
typedef OtaHttpStatus_t ( * OtaHttpInit_t ) ( char * pUrl );
/**
* @brief Request file block over Http.
*
* This function requests file block over Http from the rangeStart and rangeEnd.
*
* @param[in] rangeStart Starting index of the file data to be requested.
*
* @param[in] rangeEnd End index of the file data to be requested.
*
* @return OtaHttpSuccess if success , other error code on failure.
*/
typedef OtaHttpStatus_t ( * OtaHttpRequest_t ) ( uint32_t rangeStart,
uint32_t rangeEnd );
/**
* @brief Deinit OTA Http interface.
*
* This function cleanups Http connection and other data used for
* requesting file blocks using the pre-signed url.
*
* @return OtaHttpSuccess if success , other error code on failure.
*/
typedef OtaHttpStatus_t ( * OtaHttpDeinit )( void );
/**
* @ingroup ota_struct_types
* @brief OTA Event Interface structure.
*
*/
typedef struct OtaHttpInterface
{
OtaHttpInit_t init; /*!< @brief Reference to HTTP initialization. */
OtaHttpRequest_t request; /*!< @brief Reference to HTTP data request. */
OtaHttpDeinit deinit; /*!< @brief Reference to HTTP deinitialize. */
} OtaHttpInterface_t;
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* ifndef OTA_HTTP_INTERFACE_H */

View File

@ -0,0 +1,124 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota_http_private.h
* @brief Contains definitions of routines for OTA download using HTTP data plane.
*/
#ifndef OTA_HTTP_H
#define OTA_HTTP_H
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/* OTA includes. */
#include "ota.h"
#include "ota_private.h"
/**
* @brief Initialize file transfer over HTTP.
*
* This function initializes the file transfer after the OTA job is parsed and accepted
* by initializing the http component with pre-signed url.
*
* @param[in] pAgentCtx The OTA agent context.
*
* @return The OTA error code. See OTA Agent error codes information in ota.h.
*/
OtaErr_t initFileTransfer_Http( const OtaAgentContext_t * pAgentCtx );
/**
* @brief Request File block over HTTP.
*
* This function is used for requesting a file block over HTTP using the
* file context.
*
* @param[in] pAgentCtx The OTA agent context.
*
* @return The OTA PAL layer error code combined with the MCU specific error code. See OTA Agent
* error codes information in ota.h.
*/
OtaErr_t requestDataBlock_Http( OtaAgentContext_t * pAgentCtx );
/**
* @brief Stub for decoding the file block.
*
* File block received over HTTP does not require decoding, only increment the number
* of blocks received.
*
* @param[in] pMessageBuffer The message to be decoded.
* @param[in] messageSize The size of the message in bytes.
* @param[out] pFileId The server file ID.
* @param[out] pBlockId The file block ID.
* @param[out] pBlockSize The file block size.
* @param[out] pPayload The payload.
* @param[out] pPayloadSize The payload size.
*
* @return The OTA PAL layer error code combined with the MCU specific error code. See OTA Agent
* error codes information in ota.h.
*/
OtaErr_t decodeFileBlock_Http( const uint8_t * pMessageBuffer,
size_t messageSize,
int32_t * pFileId,
int32_t * pBlockId,
int32_t * pBlockSize,
uint8_t * const * pPayload,
size_t * pPayloadSize );
/**
* @brief Cleanup related to OTA data plane over HTTP.
*
* This function performs cleanup by resetting the number of blocks received
* and deinit the http component.
*
* @param[in] pAgentCtx The OTA agent context.
*
* @return The OTA error code. See OTA Agent error codes information in ota.h.
*/
OtaErr_t cleanupData_Http( const OtaAgentContext_t * pAgentCtx );
/**
* @brief Status to string conversion for OTA HTTP interface status.
*
* @param[in] status The status to convert to a string.
*
* @return The string representation of the status.
*/
const char * OTA_HTTP_strerror( OtaHttpStatus_t status );
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* ifndef OTA_HTTP_H */

View File

@ -0,0 +1,125 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota_interface_private.h
* @brief Contains function definitions and structures for data and control interfaces.
*/
#ifndef OTA_INTERFACE_PRIVATE_H
#define OTA_INTERFACE_PRIVATE_H
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/* OTA includes. */
#include "ota.h"
#include "ota_private.h"
/* General Constants. */
/* OTA control protocol constants. */
#define OTA_CONTROL_OVER_MQTT 0x00000001 /*!< Specify control over mqtt. */
/* OTA data protocol constants. */
#define OTA_DATA_OVER_MQTT 0x00000001 /*!< Specify data over mqtt. */
#define OTA_DATA_OVER_HTTP 0x00000002 /*!< Specify data over http. */
#define OTA_DATA_NUM_PROTOCOLS ( 2U ) /*!< Number of protocols supported. */
/**
* @brief Represents the OTA control interface functions.
*
* The functions in this structure are used for the control operations
* during over the air updates like OTA job status updates.
*/
typedef struct
{
OtaErr_t ( * requestJob )( const OtaAgentContext_t * pAgentCtx ); /*!< Request for the next available OTA job from the job service. */
OtaErr_t ( * updateJobStatus )( const OtaAgentContext_t * pAgentCtx,
OtaJobStatus_t status,
int32_t reason,
int32_t subReason ); /*!< Updates the OTA job status with information like in progress, completion, or failure. */
OtaErr_t ( * cleanup )( const OtaAgentContext_t * pAgentCtx ); /*!< Cleanup related to OTA control plane. */
} OtaControlInterface_t;
/**
* @brief Represents the OTA data interface functions.
*
* The functions in this structure are used for the data operations
* during over the air updates like requesting file blocks.
*/
typedef struct
{
OtaErr_t ( * initFileTransfer )( const OtaAgentContext_t * pAgentCtx ); /*!< Initialize file transfer. */
OtaErr_t ( * requestFileBlock )( OtaAgentContext_t * pAgentCtx ); /*!< Request File block. */
OtaErr_t ( * decodeFileBlock )( const uint8_t * pMessageBuffer,
size_t messageSize,
int32_t * pFileId,
int32_t * pBlockId,
int32_t * pBlockSize,
uint8_t * const * pPayload,
size_t * pPayloadSize ); /*!< Decode a cbor encoded fileblock. */
OtaErr_t ( * cleanup )( const OtaAgentContext_t * pAgentCtx ); /*!< Cleanup related to OTA data plane. */
} OtaDataInterface_t;
/**
* @brief Set control interface for OTA operations.
*
* This function updates the OTA control operation functions as per the config
* options selected.
*
* @param[out] pControlInterface OTA Control interface.
*
*/
void setControlInterface( OtaControlInterface_t * pControlInterface );
/**
* @brief Set the data interface used for OTA operations.
*
* This function updates the OTA data operation based on the config options.
* The interface can be set to the MQTT interface or the HTTP interface.
*
* These interfaces can be enabled with the configENABLED_DATA_PROTOCOLS macro.
* The protocol interface that should be prioritized when both protocols are
* valid options is configured with the configOTA_PRIMARY_DATA_PROTOCOL macro.
*
* @param[out] pDataInterface OTA data interface to overwrite.
*
* @param[in] pProtocol String containing a list of protocols that may be set.
*
*/
OtaErr_t setDataInterface( OtaDataInterface_t * pDataInterface,
const uint8_t * pProtocol );
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* ifndef OTA_INTERFACE_PRIVATE_H */

View File

@ -0,0 +1,176 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota_mqtt_interface.h
* @brief Contains OTA MQTT Statuses, function type definitions and mqtt interface structure.
*/
#ifndef OTA_MQTT_INTERFACE_H
#define OTA_MQTT_INTERFACE_H
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/* Standard library includes. */
#include <stddef.h>
#include <stdint.h>
/**
* @otamqttpage
* @brief The OTA PAL interface definition.
*
* @otamqttsectionoverview
*
* The OTA MQTT interface is a set of APIs that must be implemented by
* a library to enable the OTA library to connect to AWS IoT and manage
* notification and request data. The OTA library uses MQTT PUBLISH
* messages to inform AWS IoT about the job status and receives notifications
* and datablock over `job` and `stream` topics.
*
* The OTA MQTT interface is defined in @ref ota_mqtt_interface.h.
* <br>
*
* The functions that must be implemented are:<br>
* - [OTA MQTT Subscribe](@ref OtaMqttSubscribe_t)
* - [OTA MQTT Unsubscribe](@ref OtaMqttSubscribe_t)
* - [OTA MQTT Publish](@ref OtaMqttSubscribe_t)
*
* These functions can be grouped into the structure `OtaMqttInterface_t`
* and passed to @ref OtaInterfaces_t to represent the MQTT interface.
* @code{c}
* OtaMqttInterface_t mqttInterface;
* mqttInterface.subscribe = mqttSubscribe;
* mqttInterface.unsubscribe = mqttUnsubscribe;
* mqttInterface.publish = mqttPublish;
*
* ....
*
* OtaInterfaces_t otaInterfaces;
* otaInterfaces.mqtt = mqttInterface
*
* ....
*
* OTA_Init( &otaBuffer,
* &otaInterfaces,
* ( CLIENT_IDENTIFIER ),
* otaAppCallback )
* @endcode
*/
/**
* @ingroup ota_enum_types
* @brief The OTA MQTT interface return status.
*/
typedef enum OtaMqttStatus
{
OtaMqttSuccess = 0, /*!< @brief OTA MQTT interface success. */
OtaMqttPublishFailed = 0xa0, /*!< @brief Attempt to publish a MQTT message failed. */
OtaMqttSubscribeFailed, /*!< @brief Failed to subscribe to a topic. */
OtaMqttUnsubscribeFailed /*!< @brief Failed to unsubscribe from a topic. */
} OtaMqttStatus_t;
/**
* @brief Subscribe to the Mqtt topics.
*
* This function subscribes to the Mqtt topics with the Quality of service
* received as parameter. This function also registers a callback for the
* topicfilter.
*
* @param[pTopicFilter] Mqtt topic filter.
*
* @param[topicFilterLength] Length of the topic filter.
*
* @param[ucQoS] Quality of Service
*
* @return OtaMqttSuccess if success , other error code on failure.
*/
typedef OtaMqttStatus_t ( * OtaMqttSubscribe_t ) ( const char * pTopicFilter,
uint16_t topicFilterLength,
uint8_t ucQoS );
/**
* @brief Unsubscribe to the Mqtt topics.
*
* This function unsubscribes to the Mqtt topics with the Quality of service
* received as parameter.
*
* @param[pTopicFilter] Mqtt topic filter.
*
* @param[topicFilterLength] Length of the topic filter.
*
* @param[ucQoS] Quality of Service
*
* @return OtaMqttSuccess if success , other error code on failure.
*/
typedef OtaMqttStatus_t ( * OtaMqttUnsubscribe_t ) ( const char * pTopicFilter,
uint16_t topicFilterLength,
uint8_t ucQoS );
/**
* @brief Publish message to a topic.
*
* This function publishes a message to a given topic & QoS.
*
* @param[pacTopic] Mqtt topic filter.
*
* @param[usTopicLen] Length of the topic filter.
*
* @param[pcMsg] Message to publish.
*
* @param[ulMsgSize] Message size.
*
* @param[ucQoS] Quality of Service
*
* @return OtaMqttSuccess if success , other error code on failure.
*/
typedef OtaMqttStatus_t ( * OtaMqttPublish_t )( const char * const pacTopic,
uint16_t usTopicLen,
const char * pcMsg,
uint32_t ulMsgSize,
uint8_t ucQoS );
/**
* @ingroup ota_struct_types
* @brief OTA Event Interface structure.
*/
typedef struct OtaMqttInterface
{
OtaMqttSubscribe_t subscribe; /*!< @brief Interface for subscribing to Mqtt topics. */
OtaMqttUnsubscribe_t unsubscribe; /*!< @brief interface for unsubscribing to MQTT topics. */
OtaMqttPublish_t publish; /*!< @brief Interface for publishing MQTT messages. */
} OtaMqttInterface_t;
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* ifndef OTA_MQTT_INTERFACE_H */

View File

@ -0,0 +1,171 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota_mqtt_private.h
* @brief Contains function definitions of routines for OTA download and control using MQTT data plane.
*/
#ifndef OTA_MQTT_H
#define OTA_MQTT_H
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/* OTA includes. */
#include "ota.h"
#include "ota_private.h"
/**
* @brief Check for available OTA job over MQTT.
*
* This function Request for the next available OTA job from the job service
* by publishing a "get next job" message to the job service.
*
* @param[in] pAgentCtx The OTA agent context.
*
* @return The OTA error code. See OTA Agent error codes information in ota.h.
*/
OtaErr_t requestJob_Mqtt( const OtaAgentContext_t * pAgentCtx );
/**
* @brief Initialize file transfer over MQTT.
*
* This function initializes the file transfer after the OTA job is parsed and accepted
* by subscribing to the data streaming topics.
*
* @param[in] pAgentCtx The OTA agent context.
*
* @return The OTA error code. See OTA Agent error codes information in ota.h.
*/
OtaErr_t initFileTransfer_Mqtt( const OtaAgentContext_t * pAgentCtx );
/**
* @brief Request File block over MQTT.
*
* This function is used for requesting a file block over MQTT using the
* file context.
*
* @param[in] pAgentCtx The OTA agent context.
*
* @return The OTA PAL layer error code combined with the MCU specific error code. See OTA Agent
* error codes information in ota.h.
*/
OtaErr_t requestFileBlock_Mqtt( OtaAgentContext_t * pAgentCtx );
/**
* @brief Decode a cbor encoded fileblock.
*
* This function is used for decoding a file block received over MQTT & encoded in cbor.
*
* @param[in] pMessageBuffer The message to be decoded.
* @param[in] messageSize The size of the message in bytes.
* @param[out] pFileId The server file ID.
* @param[out] pBlockId The file block ID.
* @param[out] pBlockSize The file block size.
* @param[out] pPayload The payload.
* @param[out] pPayloadSize The payload size.
*
* @return The OTA PAL layer error code combined with the MCU specific error code. See OTA Agent
* error codes information in ota.h.
*/
OtaErr_t decodeFileBlock_Mqtt( const uint8_t * pMessageBuffer,
size_t messageSize,
int32_t * pFileId,
int32_t * pBlockId,
int32_t * pBlockSize,
uint8_t * const * pPayload,
size_t * pPayloadSize );
/**
* @brief Cleanup related to OTA control plane over MQTT.
*
* This function cleanup by unsubscribing from any topics that were
* subscribed for performing OTA over MQTT.
*
* @param[in] pAgentCtx The OTA agent context.
*
* @return The OTA error code. See OTA Agent error codes information in ota.h.
*/
OtaErr_t cleanupControl_Mqtt( const OtaAgentContext_t * pAgentCtx );
/**
* @brief Cleanup related to OTA data plane over MQTT.
*
* This function performs cleanup by unsubscribing from any topics that were
* subscribed for performing OTA data over MQTT.
*
* @param[in] pAgentCtx The OTA agent context.
*
* @return The OTA error code. See OTA Agent error codes information in ota.h.
*/
OtaErr_t cleanupData_Mqtt( const OtaAgentContext_t * pAgentCtx );
/**
* @brief Update job status over MQTT.
*
* This function updates the OTA job status over MQTT with information like in progress, completion
* or failure.
*
* @param[in] pAgentCtx The OTA agent context.
*
* @param[in] status The OTA job status which should be updated. @see OtaJobStatus_t.
*
* @param[in] reason The major reason for the status update.
*
* @param[in] subReason The platform specific reason.
*
* @return The OTA error code. See OTA Agent error codes information in ota.h.
*/
OtaErr_t updateJobStatus_Mqtt( const OtaAgentContext_t * pAgentCtx,
OtaJobStatus_t status,
int32_t reason,
int32_t subReason );
/**
* @brief Status to string conversion for OTA MQTT interface status.
*
* @param[in] status The status to convert to a string.
*
* @return The string representation of the status.
*/
const char * OTA_MQTT_strerror( OtaMqttStatus_t status );
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* ifndef OTA_MQTT_H */

View File

@ -0,0 +1,320 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota_os_interface.h
* @brief Contains OTA OS Functional Interface statuses, type definitions and
* structures to store interface routines.
*/
#ifndef OTA_OS_INTERFACE_H
#define OTA_OS_INTERFACE_H
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/**
* @otaosfipage
* @brief The OTA OS Functional Interface definition.
*
* @otaosfisectionoverview
*
* The OTA OS Functional interface is a set of APIs that must be implemented
* for the device using the OTA library. The function implementations for this
* interface are provided to the OTA library in the user application. The OTA
* library calls the function implementations to perform functionalities that
* are typically provided by an operating system. This includes managing
* events, timers, and memory allocation. While these are typically provided by
* operating systems, an operating system is not required. Any implementation
* of these functionalities that meet the requirements of the interface will
* work.
*
* The OTA OS Functional Interface is defined in @ref ota_os_interface.h.
* <br>
*
* The functions that must be implemented are:<br>
* - [OTA OS Functional Interface Initialize Event Mechanism](@ref OtaInitEvent_t)
* - [OTA OS Functional Interface Send Event](@ref OtaSendEvent_t)
* - [OTA OS Functional Interface Receive Event](@ref OtaReceiveEvent_t)
* - [OTA OS Functional Interface Deinitialize Event](@ref OtaDeinitEvent_t)
* - [OTA OS Functional Interface Timer Callback](@ref OtaTimerCallback_t)
* - [OTA OS Functional Interface Start Timer](@ref OtaStartTimer_t)
* - [OTA OS Functional Interface Stop Timer](@ref OtaStopTimer_t)
* - [OTA OS Functional Interface Delete Timer](@ref OtaDeleteTimer_t)
* - [OTA OS Functional Interface Malloc](@ref OtaMalloc_t)
* - [OTA OS Functional Interface Free](@ref OtaFree_t)
*
* An example implementation for the OTA OS Functional Interface for FreeRTOS
* can be found in the files ota_os_freertos.c and ota_os_freertos.h.
*
* An example implementation for the OTA OS Functional Interface for POSIX can
* be found in the files ota_os_posix.c and ota_os_posix.h.
*/
struct OtaEventContext;
/**
* @brief Type definition for Event Context.
*/
typedef struct OtaEventContext OtaEventContext_t;
/**
* @brief Enumeration for tracking multiple timers.
*/
typedef enum
{
OtaRequestTimer = 0,
OtaSelfTestTimer,
OtaNumOfTimers
} OtaTimerId_t;
/**
* @ingroup ota_enum_types
* @brief The OTA OS interface return status.
*/
typedef enum OtaOsStatus
{
OtaOsSuccess = 0, /*!< @brief OTA OS interface success. */
OtaOsEventQueueCreateFailed = 0x80U, /*!< @brief Failed to create the event queue. */
OtaOsEventQueueSendFailed, /*!< @brief Posting event message to the event queue failed. */
OtaOsEventQueueReceiveFailed, /*!< @brief Failed to receive from the event queue. */
OtaOsEventQueueDeleteFailed, /*!< @brief Failed to delete the event queue. */
OtaOsTimerCreateFailed, /*!< @brief Failed to create the timer. */
OtaOsTimerStartFailed, /*!< @brief Failed to create the timer. */
OtaOsTimerRestartFailed, /*!< @brief Failed to restart the timer. */
OtaOsTimerStopFailed, /*!< @brief Failed to stop the timer. */
OtaOsTimerDeleteFailed /*!< @brief Failed to delete the timer. */
} OtaOsStatus_t;
/**
* @brief Initialize the OTA events.
*
* This function initializes the OTA events mechanism.
*
* @param[pEventCtx] Pointer to the OTA event context.
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
typedef OtaOsStatus_t ( * OtaInitEvent_t ) ( OtaEventContext_t * pEventCtx );
/**
* @brief Sends an OTA event.
*
* This function sends an event to OTA library event handler.
*
* @param[pEventCtx] Pointer to the OTA event context.
*
* @param[pEventMsg] Event to be sent to the OTA handler.
*
* @param[timeout] The maximum amount of time (msec) the task should block.
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
typedef OtaOsStatus_t ( * OtaSendEvent_t )( OtaEventContext_t * pEventCtx,
const void * pEventMsg,
unsigned int timeout );
/**
* @brief Receive an OTA event.
*
* This function receives next event from the pending OTA events.
*
* @param[pEventCtx] Pointer to the OTA event context.
*
* @param[pEventMsg] Pointer to store message.
*
* @param[timeout] The maximum amount of time (msec) the task should block.
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
typedef OtaOsStatus_t ( * OtaReceiveEvent_t )( OtaEventContext_t * pEventCtx,
void * pEventMsg,
uint32_t timeout );
/**
* @brief Deinitialize the OTA Events mechanism.
*
* This function deinitialize the OTA events mechanism and frees any resources
* used.
*
* @param[pEventCtx] Pointer to the OTA event context.
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
typedef OtaOsStatus_t ( * OtaDeinitEvent_t )( OtaEventContext_t * pEventCtx );
/**
* @brief Timer callback.
*
* Type definition for timer callback.
*
* @param[otaTimerId] Timer ID of type otaTimerId_t
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
typedef void ( * OtaTimerCallback_t )( OtaTimerId_t otaTimerId );
/**
* @brief Start timer.
*
* This function starts the timer or resets it if it has already started.
*
* @param[otaTimerId] Timer ID of type otaTimerId_t
*
* @param[pTimerName] Timer name.
*
* @param[timeout] Timeout for the timer in milliseconds.
*
* @param[callback] Callback to be called when timer expires.
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
typedef OtaOsStatus_t ( * OtaStartTimer_t ) ( OtaTimerId_t otaTimerId,
const char * const pTimerName,
const uint32_t timeout,
OtaTimerCallback_t callback );
/**
* @brief Stop timer.
*
* This function stops the time.
*
* @param[otaTimerId] Timer ID of type otaTimerId_t
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
typedef OtaOsStatus_t ( * OtaStopTimer_t ) ( OtaTimerId_t otaTimerId );
/**
* @brief Delete a timer.
*
* This function deletes a timer.
*
* @param[otaTimerId] Timer ID of type otaTimerId_t
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
typedef OtaOsStatus_t ( * OtaDeleteTimer_t ) ( OtaTimerId_t otaTimerId );
/**
* @brief Allocate memory.
*
* This function allocates the requested memory and returns a pointer to it.
*
* @param[size] This is the size of the memory block, in bytes..
*
* @return This function returns a pointer to the allocated memory, or NULL if
* the request fails.
*/
typedef void * ( * OtaMalloc_t ) ( size_t size );
/**
* @brief Free memory.
*
* This function deallocates the memory previously allocated by a call to allocation
* function of type OtaMalloc_t.
*
* @param[ptr] This is the pointer to a memory block previously allocated with function
* of type OtaMalloc_t. If a null pointer is passed as argument, no action occurs.
*
* @return None.
*/
typedef void ( * OtaFree_t ) ( void * ptr );
/**
* @ingroup ota_struct_types
* OTA Event Interface structure.
*/
typedef struct OtaEventInterface
{
OtaInitEvent_t init; /*!< @brief Initialization event. */
OtaSendEvent_t send; /*!< @brief Send data. */
OtaReceiveEvent_t recv; /*!< @brief Receive data. */
OtaDeinitEvent_t deinit; /*!< @brief Deinitialize event. */
OtaEventContext_t * pEventContext; /*!< @brief Event context to store event information. */
} OtaEventInterface_t;
/**
* @ingroup ota_struct_types
* @brief OTA Retry Timer Interface.
*/
typedef struct OtaTimerInterface
{
OtaStartTimer_t start; /*!< @brief Timer start state. */
OtaStopTimer_t stop; /*!< @brief Timer stop state. */
#ifndef __cplusplus
OtaDeleteTimer_t delete; /*!< @brief Delete timer. */
#else
OtaDeleteTimer_t deleteTimer; /*!< @brief Delete timer for C++ builds. */
#endif
} OtaTimerInterface_t;
/**
* @ingroup ota_struct_types
* @brief OTA memory allocation interface.
*/
typedef struct OtaMallocInterface
{
/* MISRA Ref 21.3.2 [Use of free or malloc] */
/* More details at: https://github.com/aws/ota-for-aws-iot-embedded-sdk/blob/main/MISRA.md#rule-213 */
/* coverity[misra_c_2012_rule_21_3_violation] */
OtaMalloc_t malloc; /*!< @brief OTA memory allocate interface. */
/* MISRA Ref 21.3.2 [Use of free or malloc] */
/* More details at: https://github.com/aws/ota-for-aws-iot-embedded-sdk/blob/main/MISRA.md#rule-213 */
/* coverity[misra_c_2012_rule_21_3_violation] */
OtaFree_t free; /*!< @brief OTA memory deallocate interface. */
} OtaMallocInterface_t;
/**
* @ingroup ota_struct_types
* @brief OTA OS Interface.
*/
typedef struct OtaOSInterface
{
OtaEventInterface_t event; /*!< @brief OTA Event interface. */
OtaTimerInterface_t timer; /*!< @brief OTA Timer interface. */
OtaMallocInterface_t mem; /*!< @brief OTA memory interface. */
} OtaOSInterface_t;
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* ifndef OTA_OS_INTERFACE_H */

View File

@ -0,0 +1,325 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota_platform_interface.h
* @brief Contains PAL interface statuses, type definitions and structure to store interface routines.
*/
#ifndef OTA_PLATFORM_INTERFACE
#define OTA_PLATFORM_INTERFACE
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
#include "ota_private.h"
/**
* @otapalpage
* @brief The OTA PAL interface definition.
*
* @otapalsectionoverview
*
* The OTA PAL interface is a set of APIs that must be implemented for the
* device using the OTA library. These device specific implementation for the
* OTA PAL is provided to the library in the user application. These functions
* are used by the library to store, manage, and authenticate downloads.
*
* The OTA PAL interface is defined in @ref ota_platform_interface.h.
* <br>
*
* The functions that must be implemented are:<br>
* - [OTA PAL Abort](@ref OtaPalAbort_t)
* - [OTA PAL Create File](@ref OtaPalCreateFileForRx_t)
* - [OTA PAL Close File](@ref OtaPalCloseFile_t)
* - [OTA PAL Write Block](@ref OtaPalWriteBlock_t)
* - [OTA PAL Activate New Image](@ref OtaPalActivateNewImage_t)
* - [OTA PAL Reset Device](@ref OtaPalResetDevice_t)
* - [OTA PAL Set Platform Image State](@ref OtaPalSetPlatformImageState_t)
* - [OTA PAL Get Platform Image State](@ref OtaPalGetPlatformImageState_t)
*/
/**
* @brief The OTA platform interface return status. Composed of main and sub status.
*/
typedef uint32_t OtaPalStatus_t;
/**
* @brief The OTA platform interface sub status.
*/
typedef uint32_t OtaPalSubStatus_t;
/**
* @ingroup ota_constants
* @brief The OTA platform interface main status.
*/
typedef uint32_t OtaPalMainStatus_t;
#define OtaPalSuccess 0x0U /*!< @brief OTA platform interface success. */
#define OtaPalUninitialized 0xe0U /*!< @brief Result is not yet initialized from PAL. */
#define OtaPalOutOfMemory 0xe1U /*!< @brief Out of memory. */
#define OtaPalNullFileContext 0xe2U /*!< @brief The PAL is called with a NULL file context. */
#define OtaPalSignatureCheckFailed 0xe3U /*!< @brief The signature check failed for the specified file. */
#define OtaPalRxFileCreateFailed 0xe4U /*!< @brief The PAL failed to create the OTA receive file. */
#define OtaPalRxFileTooLarge 0xe5U /*!< @brief The OTA receive file is too big for the platform to support. */
#define OtaPalBootInfoCreateFailed 0xe6U /*!< @brief The PAL failed to create the OTA boot info file. */
#define OtaPalBadSignerCert 0xe7U /*!< @brief The signer certificate was not readable or zero length. */
#define OtaPalBadImageState 0xe8U /*!< @brief The specified OTA image state was out of range. */
#define OtaPalAbortFailed 0xe9U /*!< @brief Error trying to abort the OTA. */
#define OtaPalRejectFailed 0xeaU /*!< @brief Error trying to reject the OTA image. */
#define OtaPalCommitFailed 0xebU /*!< @brief The acceptance commit of the new OTA image failed. */
#define OtaPalActivateFailed 0xecU /*!< @brief The activation of the new OTA image failed. */
#define OtaPalFileAbort 0xedU /*!< @brief Error in low level file abort. */
#define OtaPalFileClose 0xeeU /*!< @brief Error in low level file close. */
/**
* @constantspage{ota,OTA library}
*
* @section ota_constants_err_code_helpers OTA Error Code Helper constants
* @brief OTA PAL Error code helper for extracting the error code from the OTA PAL.
*
* @snippet this define_ota_err_code_helpers
*
* OTA pal error codes consist of an main code in the upper 8 bits of a 32 bit word and sometimes
* merged with a platform specific code in the lower 24 bits. You must refer to the platform PAL
* layer in use to determine the meaning of the lower 24 bits.
*/
/* @[define_ota_err_code_helpers] */
#define OTA_PAL_ERR_MASK 0xffffffUL /*!< The PAL layer uses the signed low 24 bits of the OTA error code. */
#define OTA_PAL_SUB_BITS 24U /*!< The OTA Agent error code is the highest 8 bits of the word. */
#define OTA_PAL_MAIN_ERR( err ) ( ( OtaPalMainStatus_t ) ( uint32_t ) ( ( uint32_t ) ( err ) >> ( uint32_t ) OTA_PAL_SUB_BITS ) ) /*!< Helper to get the OTA PAL main error code. */
#define OTA_PAL_SUB_ERR( err ) ( ( ( uint32_t ) ( err ) ) & ( ( uint32_t ) OTA_PAL_ERR_MASK ) ) /*!< Helper to get the OTA PAL sub error code. */
#define OTA_PAL_COMBINE_ERR( main, sub ) ( ( ( uint32_t ) ( main ) << ( uint32_t ) OTA_PAL_SUB_BITS ) | ( uint32_t ) OTA_PAL_SUB_ERR( sub ) ) /*!< Helper to combine the OTA PAL main and sub error code. */
/* @[define_ota_err_code_helpers] */
/**
* @brief Abort an OTA transfer.
*
* Aborts access to an existing open file represented by the OTA file context pFileContext. This is
* only valid for jobs that started successfully.
*
* @note The input OtaFileContext_t pFileContext is checked for NULL by the OTA agent before this
* function is called.
* This function may be called before the file is opened, so the file pointer pFileContext->fileHandle
* may be NULL when this function is called.
*
* @param[in] pFileContext OTA file context information.
*
* @return The OTA PAL layer error code combined with the MCU specific error code. See OTA Agent
* error codes information in ota.h.
*
* The file pointer will be set to NULL after this function returns.
* OtaPalSuccess is returned when aborting access to the open file was successful.
* OtaPalFileAbort is returned when aborting access to the open file context was unsuccessful.
*/
typedef OtaPalStatus_t ( * OtaPalAbort_t )( OtaFileContext_t * const pFileContext );
/**
* @brief Create a new receive file for the data chunks as they come in.
*
* @note Opens the file indicated in the OTA file context in the MCU file system.
*
* @note The previous image may be present in the designated image download partition or file, so the
* partition or file must be completely erased or overwritten in this routine.
*
* @note The input OtaFileContext_t pFileContext is checked for NULL by the OTA agent before this
* function is called.
* The device file path is a required field in the OTA job document, so pFileContext->pFilePath is
* checked for NULL by the OTA agent before this function is called.
*
* @param[in] pFileContext OTA file context information.
*
* @return The OTA PAL layer error code combined with the MCU specific error code. See OTA Agent
* error codes information in ota.h.
*
* OtaPalSuccess is returned when file creation is successful.
* OtaPalRxFileTooLarge is returned if the file to be created exceeds the device's non-volatile memory size constraints.
* OtaPalBootInfoCreateFailed is returned if the bootloader information file creation fails.
* OtaPalRxFileCreateFailed is returned for other errors creating the file in the device's non-volatile memory.
*/
typedef OtaPalStatus_t (* OtaPalCreateFileForRx_t)( OtaFileContext_t * const pFileContext );
/**
* @brief Authenticate and close the underlying receive file in the specified OTA context.
*
* @note The input OtaFileContext_t pFileContext is checked for NULL by the OTA agent before this
* function is called. This function is called only at the end of block ingestion.
* prvPAL_CreateFileForRx() must succeed before this function is reached, so
* pFileContext->fileHandle(or pFileContext->pFile) is never NULL.
* The certificate path on the device is a required job document field in the OTA Agent,
* so pFileContext->pCertFilepath is never NULL.
* The file signature key is required job document field in the OTA Agent, so pFileContext->pSignature will
* never be NULL.
*
* If the signature verification fails, file close should still be attempted.
*
* @param[in] pFileContext OTA file context information.
*
* @return The OTA PAL layer error code combined with the MCU specific error code. See OTA Agent
* error codes information in ota.h.
*
* OtaPalSuccess is returned on success.
* OtaPalSignatureCheckFailed is returned when cryptographic signature verification fails.
* OtaPalBadSignerCert is returned for errors in the certificate itself.
* OtaPalFileClose is returned when closing the file fails.
*/
typedef OtaPalStatus_t ( * OtaPalCloseFile_t )( OtaFileContext_t * const pFileContext );
/**
* @brief Write a block of data to the specified file at the given offset.
*
* @note This function must always write a complete file block before returning. So the number of
* bytes written will be equal to the size of the file block. Exception only in case of last block
* where the number of bytes written will be equal or less than the size of the file block.
*
* @note The input OtaFileContext_t pFileContext is checked for NULL by the OTA agent before this
* function is called.
* The file pointer/handle pFileContext->pFile, is checked for NULL by the OTA agent before this
* function is called.
* pData is checked for NULL by the OTA agent before this function is called.
* blockSize is validated for range by the OTA agent before this function is called.
* offset is validated by the OTA agent before this function is called.
*
* @param[in] pFileContext OTA file context information.
* @param[in] offset Byte offset to write to from the beginning of the file.
* @param[in] pData Pointer to the byte array of data to write.
* @param[in] blockSize The number of bytes to write.
*
* @return The number of bytes written on a success, or a negative error code from the platform
* abstraction layer.
*/
typedef int16_t ( * OtaPalWriteBlock_t ) ( OtaFileContext_t * const pFileContext,
uint32_t offset,
uint8_t * const pData,
uint32_t blockSize );
/**
* @brief Activate the newest MCU image received via OTA.
*
* This function shall do whatever is necessary to activate the newest MCU
* firmware received via OTA. It is typically just a reset of the device.
*
* @note This function SHOULD not return. If it does, the platform does not support
* an automatic reset or an error occurred.
*
* @return The OTA PAL layer error code combined with the MCU specific error code. See OTA Agent
* error codes information in ota.h.
*/
typedef OtaPalStatus_t ( * OtaPalActivateNewImage_t )( OtaFileContext_t * const pFileContext );
/**
* @brief Reset the device.
*
* This function shall reset the MCU and cause a reboot of the system.
*
* @note This function SHOULD not return. If it does, the platform does not support
* an automatic reset or an error occurred.
*
* @return The OTA PAL layer error code combined with the MCU specific error code. See OTA Agent
* error codes information in ota.h.
*/
typedef OtaPalStatus_t ( * OtaPalResetDevice_t ) ( OtaFileContext_t * const pFileContext );
/**
* @brief Attempt to set the state of the OTA update image.
*
* Do whatever is required by the platform to Accept/Reject the OTA update image (or bundle).
* Refer to the PAL implementation to determine what happens on your platform.
*
* @param[in] pFileContext File context of type OtaFileContext_t.
*
* @param[in] eState The desired state of the OTA update image.
*
* @return The OtaPalStatus_t error code combined with the MCU specific error code. See ota.h for
* OTA major error codes and your specific PAL implementation for the sub error code.
*
* Major error codes returned are:
*
* OtaPalSuccess on success.
* OtaPalBadImageState: if you specify an invalid OtaImageState_t. No sub error code.
* OtaPalAbortFailed: failed to roll back the update image as requested by OtaImageStateAborted.
* OtaPalRejectFailed: failed to roll back the update image as requested by OtaImageStateRejected.
* OtaPalCommitFailed: failed to make the update image permanent as requested by OtaImageStateAccepted.
*/
typedef OtaPalStatus_t ( * OtaPalSetPlatformImageState_t )( OtaFileContext_t * const pFileContext,
OtaImageState_t eState );
/**
* @brief Get the state of the OTA update image.
*
* We read this at OTA_Init time and when the latest OTA job reports itself in self
* test. If the update image is in the "pending commit" state, we start a self test
* timer to assure that we can successfully connect to the OTA services and accept
* the OTA update image within a reasonable amount of time (user configurable). If
* we don't satisfy that requirement, we assume there is something wrong with the
* firmware and automatically reset the device, causing it to roll back to the
* previously known working code.
*
* If the update image state is not in "pending commit," the self test timer is
* not started.
*
* @param[in] pFileContext File context of type OtaFileContext_t.
*
* @return An OtaPalImageState_t. One of the following:
* OtaPalImageStatePendingCommit (the new firmware image is in the self test phase)
* OtaPalImageStateValid (the new firmware image is already committed)
* OtaPalImageStateInvalid (the new firmware image is invalid or non-existent)
*
* NOTE: OtaPalImageStateUnknown should NEVER be returned and indicates an implementation error.
*/
typedef OtaPalImageState_t ( * OtaPalGetPlatformImageState_t ) ( OtaFileContext_t * const pFileContext );
/**
* @ingroup ota_struct_types
* @brief OTA pal Interface structure.
*/
typedef struct OtaPalInterface
{
/* MISRA rule 21.8 prohibits the use of abort from stdlib.h. However, this is merely one of the
* OTA platform abstraction layer interfaces, which is used to abort an OTA update. So it's a
* false positive. */
/* MISRA Ref 21.8.1 [Standard library includes] */
/* More details at: https://github.com/aws/ota-for-aws-iot-embedded-sdk/blob/main/MISRA.md#rule-101 */
/* coverity[misra_c_2012_rule_21_8_violation] */
OtaPalAbort_t abort; /*!< @brief Abort an OTA transfer. */
OtaPalCreateFileForRx_t createFile; /*!< @brief Create a new receive file. */
OtaPalCloseFile_t closeFile; /*!< @brief Authenticate and close the receive file. */
OtaPalWriteBlock_t writeBlock; /*!< @brief Write a block of data to the specified file at the given offset. */
OtaPalActivateNewImage_t activate; /*!< @brief Activate the file received over-the-air. */
OtaPalResetDevice_t reset; /*!< @brief Reset the device. */
OtaPalSetPlatformImageState_t setPlatformImageState; /*!< @brief Set the state of the OTA update image. */
OtaPalGetPlatformImageState_t getPlatformImageState; /*!< @brief Get the state of the OTA update image. */
} OtaPalInterface_t;
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* ifndef OTA_PLATFORM_INTERFACE */

View File

@ -0,0 +1,443 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota_private.h
* @brief Macros, enums, variables, and definitions internal to the OTA Agent module and
* shared by other OTA modules and testing files.
*/
#ifndef OTA_PRIVATE_H
#define OTA_PRIVATE_H
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/* Standard includes. */
/* For FILE type in OtaFileContext_t.*/
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
/* OTA_DO_NOT_USE_CUSTOM_CONFIG allows building the OTA library
* without a custom config. If a custom config is provided, the
* OTA_DO_NOT_USE_CUSTOM_CONFIG macro should not be defined. */
#ifndef OTA_DO_NOT_USE_CUSTOM_CONFIG
#include "ota_config.h"
#endif
/* Include config defaults header to get default values of configs not defined
* in ota_config.h file. */
#include "ota_config_defaults.h"
/**
* @addtogroup ota_constants
* @{
*/
/* General constants. */
#define LOG2_BITS_PER_BYTE 3U /*!< @brief Log base 2 of bits per byte. */
#define BITS_PER_BYTE ( ( uint32_t ) 1U << LOG2_BITS_PER_BYTE ) /*!< @brief Number of bits in a byte. This is used by the block bitmap implementation. */
#define OTA_FILE_BLOCK_SIZE ( ( uint32_t ) 1U << otaconfigLOG2_FILE_BLOCK_SIZE ) /*!< @brief Data section size of the file data block message (excludes the header). */
#define OTA_MAX_FILES 1U /*!< @brief [MUST REMAIN 1! Future support.] Maximum number of concurrent OTA files. */
#define OTA_MAX_BLOCK_BITMAP_SIZE 128U /*!< @brief Max allowed number of bytes to track all blocks of an OTA file. Adjust block size if more range is needed. */
#define OTA_REQUEST_MSG_MAX_SIZE ( 3U * OTA_MAX_BLOCK_BITMAP_SIZE ) /*!< @brief Maximum size of the message */
#define OTA_REQUEST_URL_MAX_SIZE ( 1500 ) /*!< @brief Maximum size of the S3 presigned URL */
#define OTA_ERASED_BLOCKS_VAL 0xffU /*!< @brief The starting state of a group of erased blocks in the Rx block bitmap. */
#define OTA_MAX_FILE_SIZE UINT32_MAX - OTA_FILE_BLOCK_SIZE + 1U /*!< @brief The maximum file size supported by the library. */
/** @} */
/**
* @addtogroup ota_constants
* @{
*/
/* Job document parser constants. */
#define OTA_MAX_JSON_TOKENS 64U /*!< @brief Number of JSON tokens supported in a single parser call. */
#define OTA_MAX_JSON_STR_LEN 256U /*!< @brief Limit our JSON string compares to something small to avoid going into the weeds. */
#define OTA_DOC_MODEL_MAX_PARAMS 32U /*!< @brief The parameter list is backed by a 32 bit longword bitmap by design. */
#define OTA_JOB_PARAM_REQUIRED ( bool ) true /*!< @brief Used to denote a required document model parameter. */
#define OTA_JOB_PARAM_OPTIONAL ( bool ) false /*!< @brief Used to denote an optional document model parameter. */
#define OTA_DONT_STORE_PARAM 0xffff /*!< @brief If destOffset in the model is 0xffffffff, do not store the value. */
#define OTA_STORE_NESTED_JSON 0x1fffU /*!< @brief Store the reference to a nested JSON in a separate pointer */
#define OTA_DATA_BLOCK_SIZE ( ( 1U << otaconfigLOG2_FILE_BLOCK_SIZE ) + OTA_REQUEST_URL_MAX_SIZE + 30 ) /*!< @brief Header is 19 bytes.*/
/** @} */
/**
* @addtogroup ota_constants
* @{
*/
/* OTA Agent task event flags. */
#define OTA_EVT_MASK_JOB_MSG_READY 0x00000001UL /*!< Event flag for OTA Job message ready. */
#define OTA_EVT_MASK_DATA_MSG_READY 0x00000002UL /*!< Event flag for OTA Data message ready. */
#define OTA_EVT_MASK_SHUTDOWN 0x00000004UL /*!< Event flag to request OTA shutdown. */
#define OTA_EVT_MASK_REQ_TIMEOUT 0x00000008UL /*!< Event flag indicating the request timer has timed out. */
#define OTA_EVT_MASK_USER_ABORT 0x000000016UL /*!< Event flag to indicate user initiated OTA abort. */
#define OTA_EVT_MASK_ALL_EVENTS ( OTA_EVT_MASK_JOB_MSG_READY | OTA_EVT_MASK_DATA_MSG_READY | OTA_EVT_MASK_SHUTDOWN | OTA_EVT_MASK_REQ_TIMEOUT | OTA_EVT_MASK_USER_ABORT ) /*!< Event flag to mask indicate all events.*/
/** @} */
/**
* @brief Number of parameters in the job document.
*
*/
#define OTA_NUM_JOB_PARAMS ( 21 )
/**
* @brief Maximum size of the Job ID.
*
*/
#define OTA_JOB_ID_MAX_SIZE ( 72UL + 1UL )
/**
* @brief Size of the buffer used to store the protocol field of the job document.
*
*/
#define OTA_PROTOCOL_BUFFER_SIZE 20U
/**
* @ingroup ota_constants
* @brief A composite cryptographic signature structure able to hold our largest supported signature.
*/
#define kOTA_MaxSignatureSize 384 /* Max bytes supported for a file signature (3072 bit RSA is 384 bytes). */
/**
*
* @brief Keys in OTA job doc.
*
* The OTA job document contains parameters that are required for us to build the
* stream request message and manage the OTA process. Including info like file name,
* size, attributes, etc. The following value specifies the number of parameters
* that are included in the job document model although some may be optional.
* @addtogroup ota_constants
* @{
*/
#define OTA_JSON_SEPARATOR "." /*!< @brief Separator used to define nested keys. */
#define OTA_JSON_CLIENT_TOKEN_KEY "clientToken" /*!< @brief Client token. */
#define OTA_JSON_TIMESTAMP_KEY "timestamp" /*!< @brief Used to calculate timeout and time spent on the operation. */
#define OTA_JSON_EXECUTION_KEY "execution" /*!< @brief Contains job execution parameters . */
#define OTA_JSON_JOB_ID_KEY OTA_JSON_EXECUTION_KEY OTA_JSON_SEPARATOR "jobId" /*!< @brief Name of the job. */
#define OTA_JSON_STATUS_DETAILS_KEY OTA_JSON_EXECUTION_KEY OTA_JSON_SEPARATOR "statusDetails" /*!< @brief Current status of the job. */
#define OTA_JSON_SELF_TEST_KEY OTA_JSON_STATUS_DETAILS_KEY OTA_JSON_SEPARATOR "self_test" /*!< @brief Specifies if the platform and service is is selftest. */
#define OTA_JSON_UPDATED_BY_KEY OTA_JSON_STATUS_DETAILS_KEY OTA_JSON_SEPARATOR "updatedBy" /*!< @brief Parameter to specify update status. */
#define OTA_JSON_UPDATED_BY_KEY_ONLY "updatedBy" /*!< @brief Specifies if the platform and service is is selftest. Not searched in sub fields. */
#define OTA_JSON_SELF_TEST_KEY_ONLY "self_test" /*!< @brief Parameter to specify update status. Not searched in sub fields. */
#define OTA_JSON_JOB_DOC_KEY OTA_JSON_EXECUTION_KEY OTA_JSON_SEPARATOR "jobDocument" /*!< @brief Parameters that specify the nature of the job. */
#define OTA_JSON_OTA_UNIT_KEY OTA_JSON_JOB_DOC_KEY OTA_JSON_SEPARATOR "afr_ota" /*!< @brief afr-ota. */
#define OTA_JSON_PROTOCOLS_KEY OTA_JSON_OTA_UNIT_KEY OTA_JSON_SEPARATOR "protocols" /*!< @brief Protocols over which the download can take place. */
#define OTA_JSON_FILE_GROUP_KEY OTA_JSON_OTA_UNIT_KEY OTA_JSON_SEPARATOR "files" /*!< @brief Parameters for specifying file configurations. */
#define OTA_JSON_STREAM_NAME_KEY OTA_JSON_OTA_UNIT_KEY OTA_JSON_SEPARATOR "streamname" /*!< @brief Name of the stream used for download. */
#define OTA_JSON_FILE_PATH_KEY "filepath" /*!< @brief Path to store the image on the device. */
#define OTA_JSON_FILE_SIZE_KEY "filesize" /*!< @brief Size of the file to be downloaded. */
#define OTA_JSON_FILE_ID_KEY "fileid" /*!< @brief Used to identify the file in case of multiple file downloads. */
#define OTA_JSON_FILE_ATTRIBUTE_KEY "attr" /*!< @brief Additional file attributes. */
#define OTA_JSON_FILE_CERT_NAME_KEY "certfile" /*!< @brief Location of the certificate on the device to find code signing. */
#define OTA_JSON_UPDATE_DATA_URL_KEY "update_data_url" /*!< @brief S3 bucket presigned url to fetch the image from . */
#define OTA_JSON_AUTH_SCHEME_KEY "auth_scheme" /*!< @brief Authentication scheme for downloading a the image over HTTP. */
#define OTA_JSON_FILETYPE_KEY "fileType" /*!< @brief Used to identify the file in case of multi file type support. */
/** @} */
/**
* @ingroup ota_private_enum_types
* @brief Data ingest results.
*
* The negative error codes represent actual error in ingesting the data block whereas the positive error codes
* represent success and other conditions that are not ingest errors like duplicate block is received.
*/
typedef enum
{
IngestResultFileComplete = -1, /*!< The file transfer is complete and the signature check passed. */
IngestResultSigCheckFail = -2, /*!< The file transfer is complete but the signature check failed. */
IngestResultFileCloseFail = -3, /*!< There was a problem trying to close the receive file. */
IngestResultNullInput = -4, /*!< One of the input pointers is NULL. */
IngestResultBadFileHandle = -5, /*!< The receive file pointer is invalid. */
IngestResultUnexpectedBlock = -6, /*!< We were asked to ingest a block but were not expecting one. */
IngestResultBlockOutOfRange = -7, /*!< The received block is out of the expected range. */
IngestResultBadData = -8, /*!< The data block from the server was malformed. */
IngestResultWriteBlockFailed = -9, /*!< The PAL layer failed to write the file block. */
IngestResultNoDecodeMemory = -10, /*!< Memory could not be allocated for decoding . */
IngestResultUninitialized = -127, /*!< Software BUG: We forgot to set the result code. */
IngestResultAccepted_Continue = 0, /*!< The block was accepted and we're expecting more. */
IngestResultDuplicate_Continue = 1 /*!< The block was a duplicate but that's OK. Continue. */
} IngestResult_t;
/**
* @ingroup ota_private_enum_types
* @brief Generic JSON document parser errors.
*
*/
typedef enum
{
DocParseErrUnknown = -1, /*!< The error code has not yet been set by a logic path. */
DocParseErrNone = 0, /*!< No error in parsing the document. */
DocParseErrOutOfMemory, /*!< We failed to allocate enough dynamic memory for a field. */
DocParseErrUserBufferInsuffcient, /*!< The supplied user buffer is insufficient for a field. */
DocParseErrFieldTypeMismatch, /*!< The field type parsed does not match the document model. */
DocParseErrBase64Decode, /*!< There was an error decoding the base64 data. */
DocParseErrInvalidNumChar, /*!< There was an invalid character in a numeric value field. */
DocParseErrDuplicatesNotAllowed, /*!< A duplicate parameter was found in the job document. */
DocParseErrMalformedDoc, /*!< The document didn't fulfill the model requirements. */
DocParseErr_InvalidJSONBuffer, /*!< When the JSON is malformed and not parsed correctly. */
DocParseErrNullModelPointer, /*!< The pointer to the document model was NULL. */
DocParseErrNullBodyPointer, /*!< The document model's internal body pointer was NULL. */
DocParseErrNullDocPointer, /*!< The pointer to the JSON document was NULL. */
DocParseErrTooManyParams, /*!< The document model has more parameters than we can handle. */
DocParseErrParamKeyNotInModel, /*!< The document model does not include the specified parameter key. */
DocParseErrInvalidModelParamType, /*!< The document model specified an invalid parameter type. */
DocParseErrInvalidToken /*!< The Jasmine token was invalid, producing a NULL pointer. */
} DocParseErr_t;
/**
* @ingroup ota_private_enum_types
* @brief Document model parameter types used by the JSON document parser.
*
*/
typedef enum
{
ModelParamTypeStringCopy,
ModelParamTypeStringInDoc, /* Only use this type if you can process before freeing the document memory. */
ModelParamTypeObject,
ModelParamTypeArray,
ModelParamTypeUInt32,
ModelParamTypeSigBase64,
ModelParamTypeIdent,
ModelParamTypeArrayCopy
} ModelParamType_t;
/**
* @ingroup ota_private_enum_types
* @brief Gives the reason to set for job parsing operation.
*
*/
typedef enum
{
JobReasonReceiving = 0, /* Update progress status. */
JobReasonSigCheckPassed, /* Set status details to Self Test Ready. */
JobReasonSelfTestActive, /* Set status details to Self Test Active. */
JobReasonAccepted, /* Set job state to Succeeded. */
JobReasonRejected, /* Set job state to Failed. */
JobReasonAborted, /* Set job state to Failed. */
NumJobReasons
} OtaJobReason_t;
/**
* @ingroup ota_private_struct_types
* @brief JSON document parameter to store the details of keys and where to store them.
*
* This is a document parameter structure used by the document model. It determines
* the type of parameter specified by the key name and where to store the parameter
* locally when it is extracted from the JSON document. It also contains the
* expected Jasmine type of the value field for validation.
*
* @note The destOffset field is an offset into the models context structure.
*/
typedef struct
{
const char * pSrcKey; /*!< Expected key name. */
const bool required; /*!< If true, this parameter must exist in the document. */
uint16_t pDestOffset; /*!< Offset to where we will store the value, if not ~0. */
uint16_t pDestSizeOffset; /*!< Offset to where we will store the value, if not ~0. */
const ModelParamType_t modelParamType; /*!< We extract the value, if found, based on this type. */
} JsonDocParam_t;
/**
* @ingroup ota_private_struct_types
* @brief JSON document model to store the details of parameters expected in the job document.
*
* The document model is currently limited to 32 parameters per the implementation,
* although it may be easily expanded to more in the future by simply expanding
* the parameter bitmap.
*
* The document model is used to control what JSON parameters are expected from a
* document and where to store the parameters, if desired, in a destination context.
* We currently only store parameters into an OtaFileContext_t but it could be used
* for any structure since we don't use a type pointer.
*/
typedef struct
{
void * contextBase; /*!< The base address of the destination OTA context structure. */
uint32_t contextSize; /*!< The size, in bytes, of the destination context structure. */
const JsonDocParam_t * pBodyDef; /*!< Pointer to the document model body definition. */
uint16_t numModelParams; /*!< The number of entries in the document model (limited to 32). */
uint32_t paramsReceivedBitmap; /*!< Bitmap of the parameters received based on the model. */
uint32_t paramsRequiredBitmap; /*!< Bitmap of the parameters required from the model. */
} JsonDocModel_t;
/**
* @ingroup ota_private_struct_types
* @brief This is the OTA statistics structure to hold useful info.
*/
typedef struct OtaAgentStatistics
{
uint32_t otaPacketsReceived; /*!< Number of OTA packets received by the MQTT callback. */
uint32_t otaPacketsQueued; /*!< Number of OTA packets queued by the MQTT callback. */
uint32_t otaPacketsProcessed; /*!< Number of OTA packets processed by the OTA task. */
uint32_t otaPacketsDropped; /*!< Number of OTA packets dropped due to congestion. */
} OtaAgentStatistics_t;
/**
* @ingroup ota_enum_types
* @brief OTA Image states.
*
* After an OTA update image is received and authenticated, it is logically moved to
* the Self Test state by the OTA agent pending final acceptance. After the image is
* activated and tested by your user code, you should put it into either the Accepted
* or Rejected state by calling @ref OTA_SetImageState ( OtaImageStateAccepted ) or
* @ref OTA_SetImageState ( OtaImageStateRejected ). If the image is accepted, it becomes
* the main firmware image to be booted from then on. If it is rejected, the image is
* no longer valid and shall not be used, reverting to the last known good image.
*
* If you want to abort an active OTA transfer, you may do so by calling the API
* @ref OTA_SetImageState ( OtaImageStateAborted ).
*/
typedef enum OtaImageState
{
OtaImageStateUnknown = 0, /*!< @brief The initial state of the OTA MCU Image. */
OtaImageStateTesting = 1, /*!< @brief The state of the OTA MCU Image post successful download and reboot. */
OtaImageStateAccepted = 2, /*!< @brief The state of the OTA MCU Image post successful download and successful self_test. */
OtaImageStateRejected = 3, /*!< @brief The state of the OTA MCU Image when the job has been rejected. */
OtaImageStateAborted = 4, /*!< @brief The state of the OTA MCU Image after a timeout publish to the stream request fails.
* Also if the OTA MCU image is aborted in the middle of a stream. */
OtaLastImageState = OtaImageStateAborted
} OtaImageState_t;
/**
* @ingroup ota_enum_types
* @brief OTA Platform Image State.
*
* The image state set by platform implementation.
*/
typedef enum OtaPalImageState
{
OtaPalImageStateUnknown = 0, /*!< @brief The initial state of the OTA PAL Image. */
OtaPalImageStatePendingCommit, /*!< @brief OTA PAL Image awaiting update. */
OtaPalImageStateValid, /*!< @brief OTA PAL Image is valid. */
OtaPalImageStateInvalid /*!< @brief OTA PAL Image is invalid. */
} OtaPalImageState_t;
/**
* @ingroup ota_enum_types
* @brief OTA Agent Events.
*
* The events sent to OTA agent.
*/
typedef enum OtaEvent
{
OtaAgentEventStart = 0, /*!< @brief Start the OTA state machine */
OtaAgentEventStartSelfTest, /*!< @brief Event to trigger self test. */
OtaAgentEventRequestJobDocument, /*!< @brief Event for requesting job document. */
OtaAgentEventReceivedJobDocument, /*!< @brief Event when job document is received. */
OtaAgentEventCreateFile, /*!< @brief Event to create a file. */
OtaAgentEventRequestFileBlock, /*!< @brief Event to request file blocks. */
OtaAgentEventReceivedFileBlock, /*!< @brief Event to trigger when file block is received. */
OtaAgentEventRequestTimer, /*!< @brief Event to request event timer. */
OtaAgentEventCloseFile, /*!< @brief Event to trigger closing file. */
OtaAgentEventSuspend, /*!< @brief Event to suspend ota task */
OtaAgentEventResume, /*!< @brief Event to resume suspended task */
OtaAgentEventUserAbort, /*!< @brief Event triggered by user to stop agent. */
OtaAgentEventShutdown, /*!< @brief Event to trigger ota shutdown */
OtaAgentEventMax /*!< @brief Last event specifier */
} OtaEvent_t;
/**
* @ingroup ota_struct_types
* @brief OTA File Signature info.
*
* File key signature information to verify the authenticity of the incoming file
*/
typedef struct
{
uint16_t size; /*!< @brief Size, in bytes, of the signature. */
uint8_t data[ kOTA_MaxSignatureSize ]; /*!< @brief The binary signature data. */
} Sig_t;
/**
* @ingroup ota_struct_types
* @brief OTA File Context Information.
*
* Information about an OTA Update file that is to be streamed. This structure is filled in from a
* job notification MQTT message. Currently only one file context can be streamed at time.
*/
typedef struct OtaFileContext
{
uint8_t * pFilePath; /*!< @brief Update file pathname. */
uint16_t filePathMaxSize; /*!< @brief Maximum size of the update file path */
otaconfigOTA_FILE_TYPE * pFile; /*!< @brief File type after file is open for write. */
uint32_t fileSize; /*!< @brief The size of the file in bytes. */
uint32_t blocksRemaining; /*!< @brief How many blocks remain to be received (a code optimization). */
uint32_t fileAttributes; /*!< @brief Flags specific to the file being received (e.g. secure, bundle, archive). */
uint32_t serverFileID; /*!< @brief The file is referenced by this numeric ID in the OTA job. */
uint8_t * pJobName; /*!< @brief The job name associated with this file from the job service. */
uint16_t jobNameMaxSize; /*!< @brief Maximum size of the job name. */
uint8_t * pStreamName; /*!< @brief The stream associated with this file from the OTA service. */
uint16_t streamNameMaxSize; /*!< @brief Maximum size of the stream name. */
uint8_t * pRxBlockBitmap; /*!< @brief Bitmap of blocks received (for deduplicating and missing block request). */
uint16_t blockBitmapMaxSize; /*!< @brief Maximum size of the block bitmap. */
uint8_t * pCertFilepath; /*!< @brief Pathname of the certificate file used to validate the receive file. */
uint16_t certFilePathMaxSize; /*!< @brief Maximum certificate path size. */
uint8_t * pUpdateUrlPath; /*!< @brief Url for the file. */
uint16_t updateUrlMaxSize; /*!< @brief Maximum size of the url. */
uint8_t * pAuthScheme; /*!< @brief Authorization scheme. */
uint16_t authSchemeMaxSize; /*!< @brief Maximum size of the auth scheme. */
uint32_t updaterVersion; /*!< @brief Used by OTA self-test detection, the version of Firmware that did the update. */
bool isInSelfTest; /*!< @brief True if the job is in self test mode. */
uint8_t * pProtocols; /*!< @brief Authorization scheme. */
uint16_t protocolMaxSize; /*!< @brief Maximum size of the supported protocols string. */
uint8_t * pDecodeMem; /*!< @brief Decode memory. */
uint32_t decodeMemMaxSize; /*!< @brief Maximum size of the decode memory. */
uint32_t fileType; /*!< @brief The file type id set when creating the OTA job. */
Sig_t * pSignature; /*!< @brief Pointer to the file's signature structure. */
} OtaFileContext_t;
/**
* @ingroup ota_private_struct_types
* @brief The OTA Agent event and data structures.
*/
typedef struct OtaEventData
{
uint8_t data[ OTA_DATA_BLOCK_SIZE ]; /*!< Buffer for storing event information. */
uint32_t dataLength; /*!< Total space required for the event. */
bool bufferUsed; /*!< Flag set when buffer is used otherwise cleared. */
} OtaEventData_t;
/**
* @ingroup ota_private_struct_types
* @brief Stores information about the event message.
*
*/
typedef struct OtaEventMsg
{
OtaEventData_t * pEventData; /*!< Event status message. */
OtaEvent_t eventId; /*!< Identifier for the event. */
} OtaEventMsg_t;
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* ifndef OTA_PRIVATE_H */

View File

@ -0,0 +1,30 @@
#ifndef _STDBOOL_H
#define _STDBOOL_H
/*******************************************************************************
* This file contains the definitions specified in stdbool.h. It is provided to
* allow OTA to be built using compilers that do not provide their own
* stdbool.h defintion.
*
* To use this file:
*
* 1) Copy this file into a directory that is in your compiler's include path.
* The directory must be part of the include path for system header files,
* for example passed using gcc's "-I" or "-isystem" options.
*
* 2) Rename the copied file stdbool.h.
*
*/
#ifndef __cplusplus
/* _Bool was introduced in C99. */
#define bool int
#define false 0
#define true 1
#endif
#define __bool_true_false_are_defined 1
#endif /* _STDBOOL_H */

View File

@ -0,0 +1,37 @@
#ifndef _STDINT_H
#define _STDINT_H
/*******************************************************************************
* THIS IS NOT A FULL stdint.h IMPLEMENTATION - It only contains the definitions
* necessary to build the OTA code. It is provided to allow OTA to be
* built using compilers that do not provide their own stdint.h definition.
*
* To use this file:
*
* 1) Copy this file into a directory that is in your compiler's include path.
* The directory must be part of the include path for system header file,
* for example passed using gcc's "-I" or "-isystem" options.
*
* 2) Rename the copied file stdint.h.
*
*/
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef long int32_t;
typedef unsigned long uint32_t;
typedef long long int64_t;
typedef unsigned long long uint64_t;
#define INT8_MAX ( ( signed char ) 127 )
#define UINT8_MAX ( ( unsigned char ) ) 255
#define INT16_MAX ( ( short ) 32767 )
#define UINT16_MAX ( ( unsigned short ) 65535 )
#define INT32_MAX 2147483647L
#define UINT32_MAX 4294967295UL
#define INT64_MAX 9223372036854775807LL
#define UINT64_MAX 18446744073709551615ULL
#endif /* _STDINT_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,518 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota_base64.c
* @brief Implements a Base64 decoding routine.
*/
#include "ota_base64_private.h"
#include <assert.h>
/**
* @brief Number to represent both line feed and carriage return symbols in the
* pBase64SymbolToIndexMap table.
*/
#define NEWLINE 64U
/**
* @brief Number to represent the whitespace character in the pBase64SymbolToIndexMap table.
*/
#define WHITESPACE 65U
/**
* @brief Number to represent the Base64 padding symbol in the pBase64SymbolToIndexMap table.
*/
#define PADDING_SYMBOL 66U
/**
* @brief Number to represent values that are invalid in the pBase64SymbolToIndexMap table.
*/
#define NON_BASE64_INDEX 67U
/**
* @brief Maximum value for a Base64 index that represents a valid, non-formatting Base64 symbol.
*/
#define VALID_BASE64_SYMBOL_INDEX_RANGE_MAX 63U
/**
* @brief Number of bits in a sextet.
*/
#define SEXTET_SIZE 6
/**
* @brief Maximum number of Base64 symbols to store in a buffer before decoding them.
*/
#define MAX_NUM_BASE64_DATA 4U
/**
* @brief Maximum number of padding symbols in a string of encoded data that is considered valid.
*/
#define MAX_EXPECTED_NUM_PADDING 2
/**
* @brief Smallest amount of data that can be Base64 encoded is a byte. Encoding a single byte of
* data results in 2 bytes of encoded data. Therefore if the encoded data is smaller than 2
* bytes, there is an error with the data.
*/
#define MIN_VALID_ENCODED_DATA_SIZE 2U
/**
* @brief The number of bits in a single octet.
*/
#define SIZE_OF_ONE_OCTET 8U
/**
* @brief The number of bits in two octets.
*/
#define SIZE_OF_TWO_OCTETS 16U
/**
* @brief The number of padding bits that are present when there are two sextets of encoded data.
*/
#define SIZE_OF_PADDING_WITH_TWO_SEXTETS 4
/**
* @brief The number of padding bits that are present when there are three sextets of encoded data.
*/
#define SIZE_OF_PADDING_WITH_THREE_SEXTETS 2
/**
* @brief Inclusive upper bound for valid values that can be contained in pBase64SymbolToIndexMap.
*/
#define SYMBOL_TO_INDEX_MAP_VALUE_UPPER_BOUND 67U
/**
* @brief Inclusive upper bound for the range of valid Base64 index values.
*/
#define BASE64_INDEX_VALUE_UPPER_BOUND 63U
/**
* @brief This table takes is indexed by an Ascii character and returns the respective Base64 index.
* The Ascii character used to index into this table is assumed to represent a symbol in a
* string of Base64 encoded data. There are three kinds of possible ascii characters:
* 1) Base64 Symbols. These are the digits of a Base 64 number system.
* 2) Formatting characters. These are newline, whitespace, and padding.
* 3) Symbols that are impossible to have inside of correctly Base64 encoded data.
*
* This table assumes that the padding symbol is the Ascii character '='
*
* Valid Base64 symbols will have an index ranging from 0-63. The Base64 digits being used
* are "ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxyz0123456789+/" where 'A' is the
* 0th index of the Base64 symbols and '/' is the 63rd index.
*
* Outside of the numbers 0-63, there are magic numbers in this table:
* - The 11th entry in this table has the number 64. This is to identify the ascii character
* '\n' as a newline character.
* - The 14th entry in this table has the number 64. This is to identify the ascii character
* '\\r' as a newline character.
* - The 33rd entry in this table has the number 65. This is to identify the ascii character
* ' ' as a whitespace character.
* - The 62nd entry in this table has the number 66. This is to identify the ascii character
* '=' as the padding character.
* - All positions in the ascii table that are invalid symbols are identified with the
* number 67 (other than '\n','\\r',' ','=').
*/
static const uint8_t pBase64SymbolToIndexMap[] =
{
67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
64, 67, 67, 64, 67, 67, 67, 67, 67, 67,
67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
67, 67, 65, 67, 67, 67, 67, 67, 67, 67,
67, 67, 67, 62, 67, 67, 67, 63, 52, 53,
54, 55, 56, 57, 58, 59, 60, 61, 67, 67,
67, 66, 67, 67, 67, 0, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 67, 67, 67, 67, 67, 67, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 67, 67, 67, 67, 67, 67, 67,
67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
67, 67, 67, 67, 67, 67
};
/**
* @brief Validates the input Base64 index based on the context of what
* has been decoded so far and the value of the index. Updates
* the input counters that are used to keep track of the number
* of whitespace and padding symbols that have been parsed so
* far.
*
* @param[in] base64Index Base64 index that can have on of the values
* listed in pBase64SymbolToIndexMap. This index represents the
* value of a valid Base64 symbol, a number to identify it as a
* formatting symbol, or a number to identify it as an invalid
* symbol.
* @param[in,out] pNumPadding Pointer to the number of padding symbols that are
* present before the input Base64 index in the encoded data.
* This number is incremented if the input symbol is a padding
* symbol.
* @param[in,out] pNumWhitespace Pointer to the number of whitespace symbols
* that are present before the input Base64 index in the encoded
* data. This number is incremented if the input symbol is a
* whitespace symbol.
*
* @return One of the following:
* - #Base64Success if the Base64 encoded data was valid
* and successfully decoded.
* - An error code defined in ota_base64_private.h if the
* encoded data or input parameters are invalid.
*/
static Base64Status_t preprocessBase64Index( uint8_t base64Index,
int64_t * pNumPadding,
int64_t * pNumWhitespace )
{
Base64Status_t returnVal = Base64Success;
int64_t numPadding;
int64_t numWhitespace;
assert( pNumPadding != NULL );
assert( pNumWhitespace != NULL );
numPadding = *pNumPadding;
numWhitespace = *pNumWhitespace;
/* Validate that the Base64 index is valid and in an appropriate place. */
if( base64Index == NON_BASE64_INDEX )
{
returnVal = Base64InvalidSymbol;
}
else if( base64Index == PADDING_SYMBOL )
{
if( numWhitespace != 0 )
{
returnVal = Base64InvalidSymbolOrdering;
}
else if( ++numPadding > MAX_EXPECTED_NUM_PADDING )
{
returnVal = Base64InvalidPaddingSymbol;
}
else
{
/* No action required. */
}
}
else if( base64Index == WHITESPACE )
{
++numWhitespace;
}
else if( base64Index == NEWLINE )
{
/* No action required. */
}
/* In this case, the input is valid because the value of its index is inclusively between 0
* and 63. Check that there was not a whitespace or padding symbol before this valid index. */
else
{
assert( base64Index <= BASE64_INDEX_VALUE_UPPER_BOUND );
if( ( numWhitespace != 0 ) || ( numPadding != 0 ) )
{
returnVal = Base64InvalidSymbolOrdering;
}
}
*pNumWhitespace = numWhitespace;
*pNumPadding = numPadding;
return returnVal;
}
/**
* @brief Add a Base64 index to a Base64 index buffer. The buffer will
* only be updated if the index represents a Base64 digit.
*
* @param[in] base64Index Base64 index that can have one of the values
* listed in pBase64SymbolToIndexMap.
* @param[in,out] pBase64IndexBuffer Pointer to a 32 bit variable that contains
* Base64 indexes that will be decoded.
* @param[in,out] pNumDataInBuffer Pointer to the number of sextets that are
* stored in pBase64IndexBuffer. This will be incremented if
* base64Index is stored in pBase64IndexBuffer.
*/
static void updateBase64DecodingBuffer( const uint8_t base64Index,
uint32_t * pBase64IndexBuffer,
uint32_t * pNumDataInBuffer )
{
uint32_t base64IndexBuffer;
uint32_t numDataInBuffer;
assert( pBase64IndexBuffer != NULL );
assert( pNumDataInBuffer != NULL );
assert( base64Index <= SYMBOL_TO_INDEX_MAP_VALUE_UPPER_BOUND );
base64IndexBuffer = *pBase64IndexBuffer;
numDataInBuffer = *pNumDataInBuffer;
/* Only update the buffer if the Base64 index is representing a Base64 digit. Base64 digits
* have a Base64 index that is inclusively between 0 and 63. */
if( base64Index <= VALID_BASE64_SYMBOL_INDEX_RANGE_MAX )
{
/* Shift the previously stored data over to make room for the next Base64 sextet and
* store the current Base64 index that is represented by the 6 least significant bits.
* Six is the number of bits you need to represent a character in Base64 (log2(64) = 6).
* The remaining two most significant bits will always be 0 since the only valid range of
* input data is between 0 and 63. */
base64IndexBuffer = ( base64IndexBuffer << SEXTET_SIZE ) | base64Index;
++numDataInBuffer;
}
*pBase64IndexBuffer = base64IndexBuffer;
*pNumDataInBuffer = numDataInBuffer;
}
/**
* @brief Decode a buffer containing two, three, or four Base64
* indices.
*
* @param[in,out] pBase64IndexBuffer Pointer to a 32 bit variable that contains
* Base64 indexes that will be decoded. Each index is
* represented by a sextet in the buffer.
* @param[in,out] pNumDataInBuffer Pointer to the number of sextets (indexes)
* that are concatenated and stored in pBase64IndexBuffer. This
* will be set to zero before this function returns.
* @param[out] pDest Pointer to a buffer used for storing the decoded data.
* @param[in] destLen Length of the pDest buffer.
* @param[in,out] pOutputLen Pointer to the index of pDest where the output
* should be written.
*
* @return One of the following:
* - #Base64Success if the Base64 encoded data was valid
* and successfully decoded.
* - An error code defined in ota_base64_private.h if the
* encoded data or input parameters are invalid.
*/
static Base64Status_t decodeBase64IndexBuffer( uint32_t * pBase64IndexBuffer,
uint32_t * pNumDataInBuffer,
uint8_t * pDest,
const size_t destLen,
size_t * pOutputLen )
{
Base64Status_t returnVal = Base64Success;
size_t outputLen;
uint32_t base64IndexBuffer;
uint32_t numDataInBuffer;
uint32_t numDataToWrite;
assert( pBase64IndexBuffer != NULL );
assert( pNumDataInBuffer != NULL );
assert( ( *pNumDataInBuffer == 2U ) ||
( *pNumDataInBuffer == 3U ) ||
( *pNumDataInBuffer == 4U ) );
assert( pDest != NULL );
assert( pOutputLen != NULL );
outputLen = *pOutputLen;
base64IndexBuffer = *pBase64IndexBuffer;
numDataInBuffer = *pNumDataInBuffer;
numDataToWrite = ( numDataInBuffer * 3U ) / 4U;
if( destLen < ( outputLen + numDataToWrite ) )
{
returnVal = Base64InvalidBufferSize;
}
else
{
/* If the buffer is full, convert the 4 sextets of encoded data into
* three sequential octets of decoded data starting from the most
* significant bits and ending at the least significant bits. */
if( numDataInBuffer == MAX_NUM_BASE64_DATA )
{
pDest[ outputLen ] = ( uint8_t ) ( ( base64IndexBuffer >> SIZE_OF_TWO_OCTETS ) & 0xFFU );
pDest[ outputLen + 1U ] = ( uint8_t ) ( ( base64IndexBuffer >> SIZE_OF_ONE_OCTET ) & 0xFFU );
pDest[ outputLen + 2U ] = ( uint8_t ) ( base64IndexBuffer & 0xFFU );
outputLen += 3U;
}
if( numDataInBuffer == 3U )
{
/* When there are only three sextets of data remaining at the end of the encoded data,
* it is assumed that these three sextets should be decoded into two octets of data. In
* this case, the two least significant bits are ignored and the following sixteen
* least significant bits are converted into two octets of data. */
if( ( base64IndexBuffer & 0x3U ) != 0U )
{
returnVal = Base64NonZeroPadding;
}
if( returnVal == Base64Success )
{
base64IndexBuffer = base64IndexBuffer >> SIZE_OF_PADDING_WITH_THREE_SEXTETS;
pDest[ outputLen ] = ( uint8_t ) ( ( base64IndexBuffer >> SIZE_OF_ONE_OCTET ) & 0xFFU );
pDest[ outputLen + 1U ] = ( uint8_t ) ( base64IndexBuffer & 0xFFU );
outputLen += 2U;
}
}
if( numDataInBuffer == 2U )
{
/* When there are only two sextets of data remaining at the end of the encoded data, it
* is assumed that these two sextets should be decoded into one octet of data. In this
* case, the four least significant bits are ignored and the following eight least
* significant bits are converted into one octet of data. */
if( ( base64IndexBuffer & 0xFU ) != 0U )
{
returnVal = Base64NonZeroPadding;
}
if( returnVal == Base64Success )
{
base64IndexBuffer = base64IndexBuffer >> SIZE_OF_PADDING_WITH_TWO_SEXTETS;
pDest[ outputLen ] = ( uint8_t ) ( base64IndexBuffer & 0xFFU );
outputLen += 1U;
}
}
}
*pNumDataInBuffer = 0;
*pOutputLen = outputLen;
*pBase64IndexBuffer = 0;
return returnVal;
}
/**
* @brief Decode Base64 encoded data.
*
* @param[out] pDest Pointer to a buffer for storing the decoded result.
* @param[in] destLen Length of the pDest buffer.
* @param[out] pResultLen Pointer to the length of the decoded result.
* @param[in] pEncodedData Pointer to a buffer containing the Base64 encoded
* data that is intended to be decoded.
* @param[in] encodedLen Length of the pEncodedData buffer.
*
* @return One of the following:
* - #Base64Success if the Base64 encoded data was valid
* and successfully decoded.
* - An error code defined in ota_base64_private.h if the
* encoded data or input parameters are invalid.
*/
Base64Status_t base64Decode( uint8_t * pDest,
const size_t destLen,
size_t * pResultLen,
const uint8_t * pEncodedData,
const size_t encodedLen )
{
uint32_t base64IndexBuffer = 0;
uint32_t numDataInBuffer = 0;
const uint8_t * pCurrBase64Symbol = pEncodedData;
size_t outputLen = 0;
int64_t numPadding = 0;
int64_t numWhitespace = 0;
Base64Status_t returnVal = Base64Success;
if( ( pEncodedData == NULL ) || ( pDest == NULL ) || ( pResultLen == NULL ) )
{
returnVal = Base64NullPointerInput;
}
if( encodedLen < MIN_VALID_ENCODED_DATA_SIZE )
{
returnVal = Base64InvalidInputSize;
}
/* This loop will decode the first (encodedLen - (encodedLen % 4)) amount of data. */
while( ( returnVal == Base64Success ) &&
( pCurrBase64Symbol < ( pEncodedData + encodedLen ) ) )
{
uint8_t base64Index = 0;
/* Read in the next Ascii character that represents the current Base64 symbol. */
uint8_t base64AsciiSymbol = *pCurrBase64Symbol++;
/* Get the Base64 index that represents the Base64 symbol. */
base64Index = pBase64SymbolToIndexMap[ base64AsciiSymbol ];
/* Validate the input and update counters for padding and whitespace. */
returnVal = preprocessBase64Index( base64Index,
&numPadding,
&numWhitespace );
if( returnVal != Base64Success )
{
break;
}
/* Add the current Base64 index to a buffer. */
updateBase64DecodingBuffer( base64Index,
&base64IndexBuffer,
&numDataInBuffer );
/* Decode the buffer when it's full and store the result. */
if( numDataInBuffer == MAX_NUM_BASE64_DATA )
{
returnVal = decodeBase64IndexBuffer( &base64IndexBuffer,
&numDataInBuffer,
pDest,
destLen,
&outputLen );
}
}
if( returnVal == Base64Success )
{
/* This scenario is only possible when the number of encoded symbols ( excluding newlines
* and padding ) being decoded mod four is equal to one. There is no valid scenario where
* data can be encoded to create a result of this size. Therefore if this size is
* encountered, it's assumed that the incoming Base64 data is not encoded correctly. */
if( numDataInBuffer == 1U )
{
returnVal = Base64InvalidInputSize;
}
}
if( returnVal == Base64Success )
{
/* Handle the scenarios where there is padding at the end of the encoded data.
*
* Note: This implementation assumes that non-zero padding bits are an error. This prevents
* having multiple non-matching encoded data strings map to identical decoded strings. */
if( ( numDataInBuffer == 2U ) || ( numDataInBuffer == 3U ) )
{
returnVal = decodeBase64IndexBuffer( &base64IndexBuffer,
&numDataInBuffer,
pDest,
destLen,
&outputLen );
}
}
if( returnVal == Base64Success )
{
*pResultLen = outputLen;
}
return returnVal;
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,366 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota_cbor.c
* @brief CBOR encode/decode routines for AWS IoT Over-the-Air updates.
*/
#include <stdlib.h>
#include "cbor.h"
#include "ota_cbor_private.h"
/**
* @brief Number of keys in cbor get stream request message.
*/
#define OTA_CBOR_GETSTREAMREQUEST_ITEM_COUNT 6
/* ========================================================================== */
/**
* @brief Helper function to verify the data type of the value in map.
*
* @param[in] expectedType Data type expected.
* @param[in] cborValue Value to check.
* @return CborError
*/
static CborError checkDataType( CborType expectedType,
const CborValue * cborValue )
{
CborError cborResult = CborNoError;
CborType actualType = cbor_value_get_type( cborValue );
if( actualType != expectedType )
{
cborResult = CborErrorIllegalType;
}
return cborResult;
}
/**
* @brief Decode a Get Stream response message from AWS IoT OTA.
*
* @param[in] pMessageBuffer message to decode.
* @param[in] messageSize size of the message to decode.
* @param[out] pFileId Decoded file id value.
* @param[out] pBlockId Decoded block id value.
* @param[out] pBlockSize Decoded block size value.
* @param[out] pPayload Buffer for the decoded payload.
* @param[in,out] pPayloadSize maximum size of the buffer as in and actual
* payload size for the decoded payload as out.
*
* @return TRUE when success, otherwise FALSE.
*/
bool OTA_CBOR_Decode_GetStreamResponseMessage( const uint8_t * pMessageBuffer,
size_t messageSize,
int32_t * pFileId,
int32_t * pBlockId,
int32_t * pBlockSize,
uint8_t * const * pPayload,
size_t * pPayloadSize )
{
CborError cborResult = CborNoError;
CborParser cborParser;
CborValue cborValue, cborMap;
size_t payloadSizeReceived = 0;
if( ( pFileId == NULL ) ||
( pBlockId == NULL ) ||
( pBlockSize == NULL ) ||
( pPayload == NULL ) ||
( pPayloadSize == NULL ) ||
( pMessageBuffer == NULL ) )
{
cborResult = CborUnknownError;
}
/* Initialize the parser. */
if( CborNoError == cborResult )
{
cborResult = cbor_parser_init( pMessageBuffer,
messageSize,
0,
&cborParser,
&cborMap );
}
/* Get the outer element and confirm that it's a "map," i.e., a set of
* CBOR key/value pairs. */
if( CborNoError == cborResult )
{
if( false == cbor_value_is_map( &cborMap ) )
{
cborResult = CborErrorIllegalType;
}
}
/* Find the file ID. */
if( CborNoError == cborResult )
{
cborResult = cbor_value_map_find_value( &cborMap,
OTA_CBOR_FILEID_KEY,
&cborValue );
}
if( CborNoError == cborResult )
{
cborResult = checkDataType( CborIntegerType, &cborValue );
}
if( CborNoError == cborResult )
{
cborResult = cbor_value_get_int( &cborValue,
( int32_t * ) pFileId );
}
/* Find the block ID. */
if( CborNoError == cborResult )
{
cborResult = cbor_value_map_find_value( &cborMap,
OTA_CBOR_BLOCKID_KEY,
&cborValue );
}
if( CborNoError == cborResult )
{
cborResult = checkDataType( CborIntegerType, &cborValue );
}
if( CborNoError == cborResult )
{
cborResult = cbor_value_get_int( &cborValue,
( int32_t * ) pBlockId );
}
/* Find the block size. */
if( CborNoError == cborResult )
{
cborResult = cbor_value_map_find_value( &cborMap,
OTA_CBOR_BLOCKSIZE_KEY,
&cborValue );
}
if( CborNoError == cborResult )
{
cborResult = checkDataType( CborIntegerType, &cborValue );
}
if( CborNoError == cborResult )
{
cborResult = cbor_value_get_int( &cborValue,
( int32_t * ) pBlockSize );
}
/* Find the payload bytes. */
if( CborNoError == cborResult )
{
cborResult = cbor_value_map_find_value( &cborMap,
OTA_CBOR_BLOCKPAYLOAD_KEY,
&cborValue );
}
if( CborNoError == cborResult )
{
cborResult = checkDataType( CborByteStringType, &cborValue );
}
/* Calculate the size we need to malloc for the payload. */
if( CborNoError == cborResult )
{
cborResult = cbor_value_calculate_string_length( &cborValue,
&payloadSizeReceived );
}
if( CborNoError == cborResult )
{
/* Check if the received payload size is less than or equal to buffer size. */
if( payloadSizeReceived <= ( *pPayloadSize ) )
{
*pPayloadSize = payloadSizeReceived;
}
else
{
cborResult = CborErrorOutOfMemory;
}
}
if( CborNoError == cborResult )
{
cborResult = cbor_value_copy_byte_string( &cborValue,
*pPayload,
pPayloadSize,
NULL );
}
return CborNoError == cborResult;
}
/**
* @brief Create an encoded Get Stream Request message for the AWS IoT OTA
* service. The service allows block count or block bitmap to be requested,
* but not both.
*
* @param[in,out] pMessageBuffer Buffer to store the encoded message.
* @param[in] messageBufferSize Size of the buffer to store the encoded message.
* @param[out] pEncodedMessageSize Size of the final encoded message.
* @param[in] pClientToken Client token in the encoded message.
* @param[in] fileId Value of file id in the encoded message.
* @param[in] blockSize Value of block size in the encoded message.
* @param[in] blockOffset Value of block offset in the encoded message.
* @param[in] pBlockBitmap bitmap in the encoded message.
* @param[in] blockBitmapSize Size of the provided bitmap buffer.
* @param[in] numOfBlocksRequested number of blocks to request in the encoded message.
*
* @return TRUE when success, otherwise FALSE.
*/
bool OTA_CBOR_Encode_GetStreamRequestMessage( uint8_t * pMessageBuffer,
size_t messageBufferSize,
size_t * pEncodedMessageSize,
const char * pClientToken,
int32_t fileId,
int32_t blockSize,
int32_t blockOffset,
const uint8_t * pBlockBitmap,
size_t blockBitmapSize,
int32_t numOfBlocksRequested )
{
CborError cborResult = CborNoError;
CborEncoder cborEncoder, cborMapEncoder;
if( ( pMessageBuffer == NULL ) ||
( pEncodedMessageSize == NULL ) ||
( pClientToken == NULL ) ||
( pBlockBitmap == NULL ) )
{
cborResult = CborUnknownError;
}
/* Initialize the CBOR encoder. */
if( CborNoError == cborResult )
{
cbor_encoder_init( &cborEncoder,
pMessageBuffer,
messageBufferSize,
0 );
cborResult = cbor_encoder_create_map( &cborEncoder,
&cborMapEncoder,
OTA_CBOR_GETSTREAMREQUEST_ITEM_COUNT );
}
/* Encode the client token key and value. */
if( CborNoError == cborResult )
{
cborResult = cbor_encode_text_stringz( &cborMapEncoder,
OTA_CBOR_CLIENTTOKEN_KEY );
}
if( CborNoError == cborResult )
{
cborResult = cbor_encode_text_stringz( &cborMapEncoder,
pClientToken );
}
/* Encode the file ID key and value. */
if( CborNoError == cborResult )
{
cborResult = cbor_encode_text_stringz( &cborMapEncoder,
OTA_CBOR_FILEID_KEY );
}
if( CborNoError == cborResult )
{
cborResult = cbor_encode_int( &cborMapEncoder,
fileId );
}
/* Encode the block size key and value. */
if( CborNoError == cborResult )
{
cborResult = cbor_encode_text_stringz( &cborMapEncoder,
OTA_CBOR_BLOCKSIZE_KEY );
}
if( CborNoError == cborResult )
{
cborResult = cbor_encode_int( &cborMapEncoder,
blockSize );
}
/* Encode the block offset key and value. */
if( CborNoError == cborResult )
{
cborResult = cbor_encode_text_stringz( &cborMapEncoder,
OTA_CBOR_BLOCKOFFSET_KEY );
}
if( CborNoError == cborResult )
{
cborResult = cbor_encode_int( &cborMapEncoder,
blockOffset );
}
/* Encode the block bitmap key and value. */
if( CborNoError == cborResult )
{
cborResult = cbor_encode_text_stringz( &cborMapEncoder,
OTA_CBOR_BLOCKBITMAP_KEY );
}
if( CborNoError == cborResult )
{
cborResult = cbor_encode_byte_string( &cborMapEncoder,
pBlockBitmap,
blockBitmapSize );
}
/* Encode the number of blocks requested key and value. */
if( CborNoError == cborResult )
{
cborResult = cbor_encode_text_stringz( &cborMapEncoder,
OTA_CBOR_NUMBEROFBLOCKS_KEY );
}
if( CborNoError == cborResult )
{
cborResult = cbor_encode_int( &cborMapEncoder,
numOfBlocksRequested );
}
/* Close the encoder. */
if( CborNoError == cborResult )
{
cborResult = cbor_encoder_close_container_checked( &cborEncoder,
&cborMapEncoder );
}
/* Get the encoded size. */
if( CborNoError == cborResult )
{
*pEncodedMessageSize = cbor_encoder_get_buffer_size( &cborEncoder,
pMessageBuffer );
}
return CborNoError == cborResult;
}

View File

@ -0,0 +1,209 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota_http.c
* @brief Data transfer over HTTP routines.
*/
/* Standard library include. */
#include <string.h>
#include <stdio.h>
#include <assert.h>
/* OTA includes. */
#include "ota.h"
#include "ota_private.h"
#include "ota_http_private.h"
/**
* @brief Track the current block for HTTP requests
*
*/
static uint32_t currBlock;
/*
* Init file transfer by initializing the http module with the pre-signed url.
*/
OtaErr_t initFileTransfer_Http( const OtaAgentContext_t * pAgentCtx )
{
OtaHttpStatus_t httpStatus = OtaHttpSuccess;
char * pURL = NULL;
const OtaFileContext_t * fileContext = NULL;
LogDebug( ( "Invoking initFileTransfer_Http" ) );
assert( ( pAgentCtx != NULL ) && ( pAgentCtx->pOtaInterface != NULL ) && ( pAgentCtx->pOtaInterface->http.init != NULL ) );
/* File context from OTA agent. */
fileContext = &( pAgentCtx->fileContext );
/* Get pre-signed URL from pAgentCtx. */
pURL = ( char * ) fileContext->pUpdateUrlPath;
/* Connect to the HTTP server and initialize download information. */
httpStatus = pAgentCtx->pOtaInterface->http.init( pURL );
if( httpStatus != OtaHttpSuccess )
{
LogError( ( "Error occured while initializing http:"
"OtaHttpStatus_t=%s"
, OTA_HTTP_strerror( httpStatus ) ) );
}
return ( httpStatus == OtaHttpSuccess ) ? OtaErrNone : OtaErrInitFileTransferFailed;
}
/*
* Check for next available OTA job from the job service.
*/
/* MISRA Ref 8.13.1 [Const qualified types] */
/* More details at: https://github.com/aws/ota-for-aws-iot-embedded-sdk/blob/main/MISRA.md#rule-813 */
/* coverity[misra_c_2012_rule_8_13_violation] */
OtaErr_t requestDataBlock_Http( OtaAgentContext_t * pAgentCtx )
{
OtaHttpStatus_t httpStatus = OtaHttpSuccess;
/* Values for the "Range" field in HTTP header. */
uint32_t rangeStart = 0;
uint32_t rangeEnd = 0;
const OtaFileContext_t * fileContext;
assert( ( pAgentCtx != NULL ) && ( pAgentCtx->pOtaInterface != NULL ) && ( pAgentCtx->pOtaInterface->http.request != NULL ) );
fileContext = &( pAgentCtx->fileContext );
LogDebug( ( "Invoking requestDataBlock_Http" ) );
/* fileContext */
/* Calculate ranges. */
rangeStart = currBlock * OTA_FILE_BLOCK_SIZE;
if( fileContext->blocksRemaining == 1U )
{
rangeEnd = fileContext->fileSize - 1U;
}
else
{
rangeEnd = rangeStart + OTA_FILE_BLOCK_SIZE - 1U;
}
/* Request file data over HTTP using the rangeStart and rangeEnd. */
httpStatus = pAgentCtx->pOtaInterface->http.request( rangeStart, rangeEnd );
if( httpStatus != OtaHttpSuccess )
{
LogError( ( "Error occured while requesting data block:"
"OtaHttpStatus_t=%s"
, OTA_HTTP_strerror( httpStatus ) ) );
}
return ( httpStatus == OtaHttpSuccess ) ? OtaErrNone : OtaErrRequestFileBlockFailed;
}
/*
* HTTP file block does not need to decode the block, only increment
* number of blocks received.
*/
OtaErr_t decodeFileBlock_Http( const uint8_t * pMessageBuffer,
size_t messageSize,
int32_t * pFileId,
int32_t * pBlockId,
int32_t * pBlockSize,
uint8_t * const * pPayload,
size_t * pPayloadSize )
{
OtaErr_t err = OtaErrNone;
assert( ( pMessageBuffer != NULL ) && ( pFileId != NULL ) && ( pBlockId != NULL ) &&
( pBlockSize != NULL ) && ( pPayload != NULL ) && ( pPayloadSize != NULL ) );
if( messageSize > OTA_FILE_BLOCK_SIZE )
{
LogError( ( "Incoming file block size %d larger than block size %d.",
( int ) messageSize, ( int ) OTA_FILE_BLOCK_SIZE ) );
err = OtaErrInvalidArg;
}
else
{
*pFileId = 0;
*pBlockId = ( int32_t ) currBlock;
*pBlockSize = ( int32_t ) messageSize;
/* The data received over HTTP does not require any decoding. */
( void ) memcpy( *pPayload, pMessageBuffer, messageSize );
*pPayloadSize = messageSize;
/* Current block is processed, set the file block to next. */
currBlock++;
}
return err;
}
/*
* Perform any cleanup operations required for data plane.
*/
OtaErr_t cleanupData_Http( const OtaAgentContext_t * pAgentCtx )
{
OtaHttpStatus_t httpStatus = OtaHttpSuccess;
assert( ( pAgentCtx != NULL ) && ( pAgentCtx->pOtaInterface != NULL ) && ( pAgentCtx->pOtaInterface->http.deinit != NULL ) );
httpStatus = pAgentCtx->pOtaInterface->http.deinit();
/* Reset currBlock. */
currBlock = 0;
return ( httpStatus == OtaHttpSuccess ) ? OtaErrNone : OtaErrCleanupDataFailed;
}
const char * OTA_HTTP_strerror( OtaHttpStatus_t status )
{
const char * str = NULL;
switch( status )
{
case OtaHttpSuccess:
str = "OtaHttpSuccess";
break;
case OtaHttpInitFailed:
str = "OtaHttpInitFailed";
break;
case OtaHttpDeinitFailed:
str = "OtaHttpDeinitFailed";
break;
case OtaHttpRequestFailed:
str = "OtaHttpRequestFailed";
break;
default:
str = "InvalidErrorCode";
break;
}
return str;
}

View File

@ -0,0 +1,149 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota_interface.c
* @brief Internal interface for setting the data and control planes.
*/
/* Standard library includes. */
#include <string.h>
#include <assert.h>
/* OTA interface includes. */
#include "ota_interface_private.h"
/* OTA transport interface includes. */
#if ( configENABLED_DATA_PROTOCOLS & OTA_DATA_OVER_MQTT ) || ( configENABLED_CONTROL_PROTOCOL & OTA_CONTROL_OVER_MQTT )
#include "ota_mqtt_private.h"
#endif
#if ( configENABLED_DATA_PROTOCOLS & OTA_DATA_OVER_HTTP )
#include "ota_http_private.h"
#endif
/* Check for invalid data interface configurations. */
#if !( configENABLED_DATA_PROTOCOLS & configOTA_PRIMARY_DATA_PROTOCOL )
#error "Primary data protocol must be enabled in the OTA configuration file."
#endif
#if !( ( configENABLED_DATA_PROTOCOLS & OTA_DATA_OVER_MQTT ) | ( configENABLED_DATA_PROTOCOLS & OTA_DATA_OVER_HTTP ) )
#error "One or more of the data protocols must be set with configENABLED_DATA_PROTOCOLS."
#endif
#if !( ( configOTA_PRIMARY_DATA_PROTOCOL & OTA_DATA_OVER_MQTT ) | ( configOTA_PRIMARY_DATA_PROTOCOL & OTA_DATA_OVER_HTTP ) )
#error "configOTA_PRIMARY_DATA_PROTOCOL must be set to OTA_DATA_OVER_MQTT or OTA_DATA_OVER_HTTP."
#endif
#if ( configOTA_PRIMARY_DATA_PROTOCOL >= ( OTA_DATA_OVER_MQTT | OTA_DATA_OVER_HTTP ) )
#error "Invalid value for configOTA_PRIMARY_DATA_PROTOCOL: Value is expected to be OTA_DATA_OVER_MQTT or OTA_DATA_OVER_HTTP."
#endif
void setControlInterface( OtaControlInterface_t * pControlInterface )
{
assert( pControlInterface != NULL );
#if ( configENABLED_CONTROL_PROTOCOL == OTA_CONTROL_OVER_MQTT )
pControlInterface->requestJob = requestJob_Mqtt;
pControlInterface->updateJobStatus = updateJobStatus_Mqtt;
pControlInterface->cleanup = cleanupControl_Mqtt;
#else
#error "Enable MQTT control as control operations are only supported over MQTT."
#endif
}
OtaErr_t setDataInterface( OtaDataInterface_t * pDataInterface,
const uint8_t * pProtocol )
{
OtaErr_t err = OtaErrInvalidDataProtocol;
bool httpInJobDoc;
bool mqttInJobDoc;
httpInJobDoc = ( strstr( ( const char * ) pProtocol, "\"HTTP\"" ) != NULL ) ? true : false;
mqttInJobDoc = ( strstr( ( const char * ) pProtocol, "\"MQTT\"" ) != NULL ) ? true : false;
#if ( ( configENABLED_DATA_PROTOCOLS & OTA_DATA_OVER_MQTT ) && !( configENABLED_DATA_PROTOCOLS & OTA_DATA_OVER_HTTP ) )
( void ) httpInJobDoc;
if( mqttInJobDoc == true )
{
pDataInterface->initFileTransfer = initFileTransfer_Mqtt;
pDataInterface->requestFileBlock = requestFileBlock_Mqtt;
pDataInterface->decodeFileBlock = decodeFileBlock_Mqtt;
pDataInterface->cleanup = cleanupData_Mqtt;
err = OtaErrNone;
}
#elif ( ( configENABLED_DATA_PROTOCOLS & OTA_DATA_OVER_HTTP ) && !( configENABLED_DATA_PROTOCOLS & OTA_DATA_OVER_MQTT ) )
( void ) mqttInJobDoc;
if( httpInJobDoc == true )
{
pDataInterface->initFileTransfer = initFileTransfer_Http;
pDataInterface->requestFileBlock = requestDataBlock_Http;
pDataInterface->decodeFileBlock = decodeFileBlock_Http;
pDataInterface->cleanup = cleanupData_Http;
err = OtaErrNone;
}
#else /* if ( ( configENABLED_DATA_PROTOCOLS & OTA_DATA_OVER_MQTT ) && !( configENABLED_DATA_PROTOCOLS & OTA_DATA_OVER_HTTP ) ) */
#if ( configOTA_PRIMARY_DATA_PROTOCOL == OTA_DATA_OVER_MQTT )
if( mqttInJobDoc == true )
{
pDataInterface->initFileTransfer = initFileTransfer_Mqtt;
pDataInterface->requestFileBlock = requestFileBlock_Mqtt;
pDataInterface->decodeFileBlock = decodeFileBlock_Mqtt;
pDataInterface->cleanup = cleanupData_Mqtt;
err = OtaErrNone;
}
else if( httpInJobDoc == true )
{
pDataInterface->initFileTransfer = initFileTransfer_Http;
pDataInterface->requestFileBlock = requestDataBlock_Http;
pDataInterface->decodeFileBlock = decodeFileBlock_Http;
pDataInterface->cleanup = cleanupData_Http;
err = OtaErrNone;
}
#elif ( configOTA_PRIMARY_DATA_PROTOCOL == OTA_DATA_OVER_HTTP )
if( httpInJobDoc == true )
{
pDataInterface->initFileTransfer = initFileTransfer_Http;
pDataInterface->requestFileBlock = requestDataBlock_Http;
pDataInterface->decodeFileBlock = decodeFileBlock_Http;
pDataInterface->cleanup = cleanupData_Http;
err = OtaErrNone;
}
else if( mqttInJobDoc == true )
{
pDataInterface->initFileTransfer = initFileTransfer_Mqtt;
pDataInterface->requestFileBlock = requestFileBlock_Mqtt;
pDataInterface->decodeFileBlock = decodeFileBlock_Mqtt;
pDataInterface->cleanup = cleanupData_Mqtt;
err = OtaErrNone;
}
#endif /* if ( configOTA_PRIMARY_DATA_PROTOCOL == OTA_DATA_OVER_MQTT ) */
#endif /* if ( ( configENABLED_DATA_PROTOCOLS & OTA_DATA_OVER_MQTT ) && !( configENABLED_DATA_PROTOCOLS & OTA_DATA_OVER_HTTP ) ) */
return err;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,360 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota_os_freertos.c
* @brief Example implementation of the OTA OS Functional Interface for
* FreeRTOS.
*/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "timers.h"
#include "queue.h"
/* OTA OS POSIX Interface Includes.*/
#include "ota_os_freertos.h"
/* OTA Library include. */
#include "ota.h"
#include "ota_private.h"
/* OTA Event queue attributes.*/
#define MAX_MESSAGES 20
#define MAX_MSG_SIZE sizeof( OtaEventMsg_t )
/* Array containing pointer to the OTA event structures used to send events to the OTA task. */
static OtaEventMsg_t queueData[ MAX_MESSAGES * MAX_MSG_SIZE ];
/* The queue control structure. .*/
static StaticQueue_t staticQueue;
/* The queue control handle. .*/
static QueueHandle_t otaEventQueue;
/* OTA App Timer callback.*/
static OtaTimerCallback_t otaTimerCallbackPtr;
/* OTA Timer handles.*/
static TimerHandle_t otaTimer[ OtaNumOfTimers ];
/* OTA Timer callbacks.*/
static void requestTimerCallback( TimerHandle_t T );
static void selfTestTimerCallback( TimerHandle_t T );
void ( * timerCallback[ OtaNumOfTimers ] )( TimerHandle_t T ) = { requestTimerCallback, selfTestTimerCallback };
OtaOsStatus_t OtaInitEvent_FreeRTOS( OtaEventContext_t * pEventCtx )
{
OtaOsStatus_t otaOsStatus = OtaOsSuccess;
( void ) pEventCtx;
otaEventQueue = xQueueCreateStatic( ( UBaseType_t ) MAX_MESSAGES,
( UBaseType_t ) MAX_MSG_SIZE,
( uint8_t * ) queueData,
&staticQueue );
if( otaEventQueue == NULL )
{
otaOsStatus = OtaOsEventQueueCreateFailed;
LogError( ( "Failed to create OTA Event Queue: "
"xQueueCreateStatic returned error: "
"OtaOsStatus_t=%i ",
otaOsStatus ) );
}
else
{
LogDebug( ( "OTA Event Queue created." ) );
}
return otaOsStatus;
}
OtaOsStatus_t OtaSendEvent_FreeRTOS( OtaEventContext_t * pEventCtx,
const void * pEventMsg,
unsigned int timeout )
{
OtaOsStatus_t otaOsStatus = OtaOsSuccess;
BaseType_t retVal = pdFALSE;
( void ) pEventCtx;
( void ) timeout;
/* Send the event to OTA event queue.*/
retVal = xQueueSendToBack( otaEventQueue, pEventMsg, ( TickType_t ) 0 );
if( retVal == pdTRUE )
{
LogDebug( ( "OTA Event Sent." ) );
}
else
{
otaOsStatus = OtaOsEventQueueSendFailed;
LogError( ( "Failed to send event to OTA Event Queue: "
"xQueueSendToBack returned error: "
"OtaOsStatus_t=%i ",
otaOsStatus ) );
}
return otaOsStatus;
}
OtaOsStatus_t OtaReceiveEvent_FreeRTOS( OtaEventContext_t * pEventCtx,
void * pEventMsg,
uint32_t timeout )
{
OtaOsStatus_t otaOsStatus = OtaOsSuccess;
BaseType_t retVal = pdFALSE;
/* Temp buffer.*/
uint8_t buff[ sizeof( OtaEventMsg_t ) ];
( void ) pEventCtx;
retVal = xQueueReceive( otaEventQueue, &buff, pdMS_TO_TICKS( timeout ) );
if( retVal == pdTRUE )
{
/* copy the data from local buffer.*/
memcpy( pEventMsg, buff, MAX_MSG_SIZE );
LogDebug( ( "OTA Event received" ) );
}
else
{
otaOsStatus = OtaOsEventQueueReceiveFailed;
LogDebug( ( "Failed to receive event or timeout from OTA Event Queue: "
"xQueueReceive returned error: "
"OtaOsStatus_t=%i ",
otaOsStatus ) );
}
return otaOsStatus;
}
OtaOsStatus_t OtaDeinitEvent_FreeRTOS( OtaEventContext_t * pEventCtx )
{
OtaOsStatus_t otaOsStatus = OtaOsSuccess;
( void ) pEventCtx;
/* Remove the event queue.*/
if( otaEventQueue != NULL )
{
vQueueDelete( otaEventQueue );
LogDebug( ( "OTA Event Queue Deleted." ) );
}
return otaOsStatus;
}
static void selfTestTimerCallback( TimerHandle_t T )
{
( void ) T;
LogDebug( ( "Self-test expired within %ums\r\n",
otaconfigSELF_TEST_RESPONSE_WAIT_MS ) );
if( otaTimerCallbackPtr != NULL )
{
otaTimerCallbackPtr( OtaSelfTestTimer );
}
else
{
LogWarn( ( "Self-test timer event unhandled.\r\n" ) );
}
}
static void requestTimerCallback( TimerHandle_t T )
{
( void ) T;
LogDebug( ( "Request timer expired in %ums \r\n",
otaconfigFILE_REQUEST_WAIT_MS ) );
if( otaTimerCallbackPtr != NULL )
{
otaTimerCallbackPtr( OtaRequestTimer );
}
else
{
LogWarn( ( "Request timer event unhandled.\r\n" ) );
}
}
OtaOsStatus_t OtaStartTimer_FreeRTOS( OtaTimerId_t otaTimerId,
const char * const pTimerName,
const uint32_t timeout,
OtaTimerCallback_t callback )
{
OtaOsStatus_t otaOsStatus = OtaOsSuccess;
BaseType_t retVal = pdFALSE;
configASSERT( callback != NULL );
configASSERT( pTimerName != NULL );
/* Set OTA lib callback. */
otaTimerCallbackPtr = callback;
/* If timer is not created.*/
if( otaTimer[ otaTimerId ] == NULL )
{
/* Create the timer. */
otaTimer[ otaTimerId ] = xTimerCreate( pTimerName,
pdMS_TO_TICKS( timeout ),
pdFALSE,
NULL,
timerCallback[ otaTimerId ] );
if( otaTimer[ otaTimerId ] == NULL )
{
otaOsStatus = OtaOsTimerCreateFailed;
LogError( ( "Failed to create OTA timer: "
"timerCreate returned NULL "
"OtaOsStatus_t=%i ",
otaOsStatus ) );
}
else
{
LogDebug( ( "OTA Timer created." ) );
/* Start the timer. */
retVal = xTimerStart( otaTimer[ otaTimerId ], portMAX_DELAY );
if( retVal == pdTRUE )
{
LogDebug( ( "OTA Timer started." ) );
}
else
{
otaOsStatus = OtaOsTimerStartFailed;
LogError( ( "Failed to start OTA timer: "
"timerStart returned error." ) );
}
}
}
else
{
/* Reset the timer. */
retVal = xTimerReset( otaTimer[ otaTimerId ], portMAX_DELAY );
if( retVal == pdTRUE )
{
LogDebug( ( "OTA Timer restarted." ) );
}
else
{
otaOsStatus = OtaOsTimerRestartFailed;
LogError( ( "Failed to set OTA timer timeout: "
"timer_settime returned error: "
"OtaOsStatus_t=%i ",
otaOsStatus ) );
}
}
return otaOsStatus;
}
OtaOsStatus_t OtaStopTimer_FreeRTOS( OtaTimerId_t otaTimerId )
{
OtaOsStatus_t otaOsStatus = OtaOsSuccess;
BaseType_t retVal = pdFALSE;
if( otaTimer[ otaTimerId ] != NULL )
{
/* Stop the timer. */
retVal = xTimerStop( otaTimer[ otaTimerId ], portMAX_DELAY );
if( retVal == pdTRUE )
{
LogDebug( ( "OTA Timer Stopped for Timerid=%i.", otaTimerId ) );
}
else
{
LogError( ( "Failed to stop OTA timer: "
"timer_settime returned error: "
"OtaOsStatus_t=%i ",
otaOsStatus ) );
otaOsStatus = OtaOsTimerStopFailed;
}
}
else
{
LogWarn( ( "OTA Timer handle NULL for Timerid=%i, can't stop.", otaTimerId ) );
}
return otaOsStatus;
}
OtaOsStatus_t OtaDeleteTimer_FreeRTOS( OtaTimerId_t otaTimerId )
{
OtaOsStatus_t otaOsStatus = OtaOsSuccess;
BaseType_t retVal = pdFALSE;
if( otaTimer[ otaTimerId ] != NULL )
{
/* Delete the timer. */
retVal = xTimerDelete( otaTimer[ otaTimerId ], portMAX_DELAY );
if( retVal == pdTRUE )
{
otaTimer[ otaTimerId ] = NULL;
LogDebug( ( "OTA Timer deleted." ) );
}
else
{
otaOsStatus = OtaOsTimerDeleteFailed;
LogError( ( "Failed to delete OTA timer: "
"timer_delete returned error: "
"OtaOsStatus_t=%i ",
otaOsStatus ) );
}
}
else
{
otaOsStatus = OtaOsTimerDeleteFailed;
LogWarn( ( "OTA Timer handle NULL for Timerid=%i, can't delete.", otaTimerId ) );
}
return otaOsStatus;
}
void * Malloc_FreeRTOS( size_t size )
{
return pvPortMalloc( size );
}
void Free_FreeRTOS( void * ptr )
{
vPortFree( ptr );
}

View File

@ -0,0 +1,168 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota_os_freertos.h
* @brief Function declarations for the example OTA OS Functional interface for
* FreeRTOS.
*/
#ifndef _OTA_OS_FREERTOS_H_
#define _OTA_OS_FREERTOS_H_
/* Standard library include. */
#include <stdint.h>
#include <string.h>
/* OTA library interface include. */
#include "ota_os_interface.h"
/**
* @brief Initialize the OTA events.
*
* This function initializes the OTA events mechanism for freeRTOS platforms.
*
* @param[pEventCtx] Pointer to the OTA event context.
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
OtaOsStatus_t OtaInitEvent_FreeRTOS( OtaEventContext_t * pEventCtx );
/**
* @brief Sends an OTA event.
*
* This function sends an event to OTA library event handler on FreeRTOS platforms.
*
* @param[pEventCtx] Pointer to the OTA event context.
*
* @param[pEventMsg] Event to be sent to the OTA handler.
*
* @param[timeout] The maximum amount of time (msec) the task should block.
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
OtaOsStatus_t OtaSendEvent_FreeRTOS( OtaEventContext_t * pEventCtx,
const void * pEventMsg,
unsigned int timeout );
/**
* @brief Receive an OTA event.
*
* This function receives next event from the pending OTA events on FreeRTOS platforms.
*
* @param[pEventCtx] Pointer to the OTA event context.
*
* @param[pEventMsg] Pointer to store message.
*
* @param[timeout] The maximum amount of time the task should block.
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
OtaOsStatus_t OtaReceiveEvent_FreeRTOS( OtaEventContext_t * pEventCtx,
void * pEventMsg,
uint32_t timeout );
/**
* @brief Deinitialize the OTA Events mechanism.
*
* This function deinitialize the OTA events mechanism and frees any resources
* used on FreeRTOS platforms.
*
* @param[pEventCtx] Pointer to the OTA event context.
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
OtaOsStatus_t OtaDeinitEvent_FreeRTOS( OtaEventContext_t * pEventCtx );
/**
* @brief Start timer.
*
* This function starts the timer or resets it if it is already started on FreeRTOS platforms.
*
* @param[otaTimerId] Timer ID of type otaTimerId_t.
*
* @param[pTimerName] Timer name.
*
* @param[timeout] Timeout for the timer.
*
* @param[callback] Callback to be called when timer expires.
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
OtaOsStatus_t OtaStartTimer_FreeRTOS( OtaTimerId_t otaTimerId,
const char * const pTimerName,
const uint32_t timeout,
OtaTimerCallback_t callback );
/**
* @brief Stop timer.
*
* This function stops the timer on FreeRTOS platforms.
*
* @param[otaTimerId] Timer ID of type otaTimerId_t.
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
OtaOsStatus_t OtaStopTimer_FreeRTOS( OtaTimerId_t otaTimerId );
/**
* @brief Delete a timer.
*
* This function deletes a timer for POSIX platforms.
*
* @param[otaTimerId] Timer ID of type otaTimerId_t.
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
OtaOsStatus_t OtaDeleteTimer_FreeRTOS( OtaTimerId_t otaTimerId );
/**
* @brief Allocate memory.
*
* This function allocates the requested memory and returns a pointer to it on FreeRTOS platforms.
*
* @param[size] This is the size of the memory block, in bytes..
*
* @return This function returns a pointer to the allocated memory, or NULL if
* the request fails.
*/
void * Malloc_FreeRTOS( size_t size );
/**
* @brief Free memory.
*
* This function deallocates the memory previously allocated by a call to allocation
* function of type OtaMalloc_t on FreeRTOS platforms.
*
* @param[size] This is the pointer to a memory block previously allocated with function
* of type OtaMalloc_t. If a null pointer is passed as an argument, no action occurs.
*
* @return None.
*/
void Free_FreeRTOS( void * ptr );
#endif /* ifndef _OTA_OS_FREERTOS_H_ */

View File

@ -0,0 +1,612 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota_os_posix.c
* @brief Example implementation of the OTA OS Functional Interface for POSIX.
*/
/* Standard Includes.*/
#include <stdlib.h>
#include <string.h>
/* MISRA Ref 21.10.1 [Date and Time] */
/* More details at: https://github.com/aws/ota-for-aws-iot-embedded-sdk/blob/main/MISRA.md#rule-2110 */
/* coverity[misra_c_2012_rule_21_10_violation] */
#include <time.h>
/* MISRA Ref 21.5.1 [Signal] */
/* More details at: https://github.com/aws/ota-for-aws-iot-embedded-sdk/blob/main/MISRA.md#rule-215 */
/* coverity[misra_c_2012_rule_21_5_violation] */
#include <signal.h>
#include <errno.h>
/* Posix includes. */
#include <sys/types.h>
#include <sys/stat.h>
#include <mqueue.h>
#include <poll.h>
#include <limits.h> /* For INT_MAX. */
/* OTA OS POSIX Interface Includes.*/
#include "ota_os_posix.h"
/* OTA Library include. */
#include "ota_private.h"
/* OTA Event queue attributes.*/
#define OTA_QUEUE_NAME "/otaqueue"
#define MAX_MESSAGES 10
#define MAX_MSG_SIZE sizeof( OtaEventMsg_t )
static void requestTimerCallback( union sigval arg );
static void selfTestTimerCallback( union sigval arg );
static OtaTimerCallback_t otaTimerCallbackPtr;
/* OTA Event queue attributes.*/
static mqd_t otaEventQueue;
/* OTA Timer handles.*/
static timer_t otaTimers[ OtaNumOfTimers ];
static timer_t * pOtaTimers[ OtaNumOfTimers ] = { 0 };
/* OTA Timer callbacks.*/
static void ( * timerCallback[ OtaNumOfTimers ] )( union sigval arg ) = { requestTimerCallback, selfTestTimerCallback };
/* Time difference calculation with timespec structure. */
static inline int lMsSinceTs( struct timespec * pxEntryTime );
/* Internal function to poll and send event message. */
static OtaOsStatus_t pollAndSend( const void * buff,
int len,
int timeout );
/* Internal function to poll and receive event message. */
static OtaOsStatus_t pollAndReceive( char * buff,
int size,
int timeout );
OtaOsStatus_t Posix_OtaInitEvent( OtaEventContext_t * pEventCtx )
{
OtaOsStatus_t otaOsStatus = OtaOsSuccess;
struct mq_attr attr;
( void ) pEventCtx;
/* Unlink the event queue.*/
( void ) mq_unlink( OTA_QUEUE_NAME );
/* Initialize queue attributes.*/
attr.mq_flags = 0;
attr.mq_maxmsg = MAX_MESSAGES;
attr.mq_msgsize = ( long ) MAX_MSG_SIZE;
attr.mq_curmsgs = 0;
/* Open the event queue.*/
errno = 0;
/* MISRA Ref 10.1.1 [Essential operand type] */
/* More details at: https://github.com/aws/ota-for-aws-iot-embedded-sdk/blob/main/MISRA.md#rule-101 */
/* coverity[misra_c_2012_rule_10_1_violation] */
otaEventQueue = mq_open( OTA_QUEUE_NAME, O_CREAT | O_RDWR | O_NONBLOCK, S_IRWXU, &attr );
if( otaEventQueue == -1 )
{
otaOsStatus = OtaOsEventQueueCreateFailed;
LogError( ( "Failed to create OTA Event Queue: "
"mq_open returned error: "
"OtaOsStatus_t=%i "
",errno=%s",
otaOsStatus,
strerror( errno ) ) );
}
else
{
LogDebug( ( "OTA Event Queue created." ) );
}
return otaOsStatus;
}
OtaOsStatus_t Posix_OtaSendEvent( OtaEventContext_t * pEventCtx,
const void * pEventMsg,
unsigned int timeout )
{
OtaOsStatus_t otaOsStatus = OtaOsSuccess;
struct timespec xEntryTime = { 0 };
int remainingTimeMs = 0;
( void ) pEventCtx;
if( timeout > INT_MAX )
{
otaOsStatus = OtaOsEventQueueSendFailed;
LogError( ( "Invalid input, Posix_OtaSendEvent supports timeout < INT_MAX, "
"timeout = %u",
timeout ) );
}
if( otaOsStatus == OtaOsSuccess )
{
errno = 0;
if( clock_gettime( CLOCK_MONOTONIC, &xEntryTime ) != 0 )
{
/* Handle clock_gettime error */
otaOsStatus = OtaOsEventQueueSendFailed;
LogError( ( "Failed to get entry time: "
"Posix_OtaSendEvent returned error: "
"OtaOsStatus_t=%i "
",errno=%s ",
otaOsStatus,
strerror( errno ) ) );
}
}
if( otaOsStatus == OtaOsSuccess )
{
remainingTimeMs = ( int ) timeout - lMsSinceTs( &xEntryTime );
do
{
otaOsStatus = pollAndSend( pEventMsg, MAX_MSG_SIZE, remainingTimeMs );
if( otaOsStatus == OtaOsSuccess )
{
break;
}
remainingTimeMs = ( int ) timeout - lMsSinceTs( &xEntryTime );
} while( remainingTimeMs > 0 );
}
return otaOsStatus;
}
OtaOsStatus_t Posix_OtaReceiveEvent( OtaEventContext_t * pEventCtx,
void * pEventMsg,
uint32_t timeout )
{
OtaOsStatus_t otaOsStatus = OtaOsSuccess;
char * pDst = pEventMsg;
char buff[ MAX_MSG_SIZE ];
struct timespec xEntryTime = { 0 };
int remainingTimeMs = 0;
( void ) pEventCtx;
/* Check timeout. */
if( timeout > INT_MAX )
{
otaOsStatus = OtaOsEventQueueReceiveFailed;
LogError( ( "Invalid input, Posix_OtaReceiveEvent supports timeout < INT_MAX, "
"timeout = %u",
timeout ) );
}
if( otaOsStatus == OtaOsSuccess )
{
errno = 0;
if( clock_gettime( CLOCK_MONOTONIC, &xEntryTime ) != 0 )
{
/* Handle clock_gettime error */
otaOsStatus = OtaOsEventQueueReceiveFailed;
LogError( ( "Failed to get entry time: "
"Posix_OtaReceiveEvent returned error: "
"OtaOsStatus_t=%i "
",errno=%s ",
otaOsStatus,
strerror( errno ) ) );
}
}
if( otaOsStatus == OtaOsSuccess )
{
remainingTimeMs = ( int ) timeout - lMsSinceTs( &xEntryTime );
do
{
otaOsStatus = pollAndReceive( buff, sizeof( buff ), remainingTimeMs );
if( otaOsStatus == OtaOsSuccess )
{
/* copy the data from local buffer.*/
( void ) memcpy( pDst, buff, MAX_MSG_SIZE );
break;
}
remainingTimeMs = ( int ) timeout - lMsSinceTs( &xEntryTime );
} while( remainingTimeMs > 0 );
}
return otaOsStatus;
}
OtaOsStatus_t Posix_OtaDeinitEvent( OtaEventContext_t * pEventCtx )
{
OtaOsStatus_t otaOsStatus = OtaOsSuccess;
( void ) pEventCtx;
/* Remove the event queue.*/
errno = 0;
if( mq_unlink( OTA_QUEUE_NAME ) == -1 )
{
otaOsStatus = OtaOsEventQueueDeleteFailed;
LogError( ( "Failed to delete OTA Event queue: "
"mq_unlink returned error: "
"OtaOsStatus_t=%i "
",errno=%s",
otaOsStatus,
strerror( errno ) ) );
}
else
{
LogDebug( ( "OTA Event queue deleted." ) );
}
return otaOsStatus;
}
static void selfTestTimerCallback( union sigval arg )
{
( void ) arg;
LogDebug( ( "Self-test expired within %ums\r\n",
otaconfigSELF_TEST_RESPONSE_WAIT_MS ) );
if( otaTimerCallbackPtr != NULL )
{
otaTimerCallbackPtr( OtaSelfTestTimer );
}
else
{
LogWarn( ( "Self-test timer event unhandled.\r\n" ) );
}
}
static void requestTimerCallback( union sigval arg )
{
( void ) arg;
LogDebug( ( "Request timer expired in %ums \r\n",
otaconfigFILE_REQUEST_WAIT_MS ) );
if( otaTimerCallbackPtr != NULL )
{
otaTimerCallbackPtr( OtaRequestTimer );
}
else
{
LogWarn( ( "Request timer event unhandled.\r\n" ) );
}
}
static inline int lMsSinceTs( struct timespec * pxEntryTime )
{
struct timespec xNow;
double diffNsToMs = 0;
double diffSecToMs = 0;
double retMs = INT_MAX;
if( pxEntryTime == NULL )
{
LogError( ( "lMsSinceTs: Invalid input - NULL pointer." ) );
}
else
{
if( clock_gettime( CLOCK_MONOTONIC, &xNow ) == 0 )
{
diffNsToMs = ( double ) ( xNow.tv_nsec - pxEntryTime->tv_nsec ) / 1000000;
diffSecToMs = ( double ) ( xNow.tv_sec - pxEntryTime->tv_sec ) * 1000;
if( diffSecToMs + diffNsToMs > INT_MAX )
{
retMs = INT_MAX;
}
else if( diffNsToMs + diffSecToMs < 0 )
{
retMs = 0;
}
else
{
retMs = diffSecToMs + diffNsToMs;
}
}
}
return retMs > 0 ? ( int ) retMs : 0;
}
static OtaOsStatus_t pollAndSend( const void * buff,
int len,
int timeout )
{
OtaOsStatus_t otaOsStatus = OtaOsEventQueueSendFailed;
struct pollfd fds = { 0 };
int pollResult = 0;
fds.fd = otaEventQueue;
fds.events = POLLOUT;
pollResult = poll( &fds, 1, timeout );
if( ( pollResult != 0 ) && ( fds.revents & POLLOUT ) )
{
if( mq_send( otaEventQueue, buff, ( size_t ) len, 0 ) == 0 )
{
otaOsStatus = OtaOsSuccess;
LogDebug( ( "OTA Event Sent." ) );
}
}
if( otaOsStatus != OtaOsSuccess )
{
LogError( ( "Failed to send event to OTA Event Queue: "
"mq_send timeout: "
"OtaOsStatus_t=%i"
", errno=%s"
", revents=%x",
otaOsStatus,
strerror( errno ),
fds.revents ) );
}
return otaOsStatus;
}
static OtaOsStatus_t pollAndReceive( char * buff,
int size,
int timeout )
{
OtaOsStatus_t otaOsStatus = OtaOsEventQueueReceiveFailed;
struct pollfd fds = { 0 };
int pollResult = 0;
fds.fd = otaEventQueue;
fds.events = POLLIN;
pollResult = poll( &fds, 1, timeout );
if( ( pollResult != 0 ) && ( fds.revents & POLLIN ) )
{
if( mq_receive( otaEventQueue, buff, ( size_t ) size, NULL ) != -1 )
{
otaOsStatus = OtaOsSuccess;
LogDebug( ( "OTA Event received." ) );
}
}
if( ( otaOsStatus != OtaOsSuccess ) && ( pollResult == 0 ) )
{
LogDebug( ( "Failed to receive OTA Event before timeout" ) );
}
else if( otaOsStatus != OtaOsSuccess )
{
LogError( ( "Failed to receive event to OTA Event Queue: "
"mq_receive timeout: "
"OtaOsStatus_t=%i"
", errno=%s"
", revents=%x",
otaOsStatus,
strerror( errno ),
fds.revents ) );
}
else
{
/* Do nothing in success case. */
}
return otaOsStatus;
}
OtaOsStatus_t Posix_OtaStartTimer( OtaTimerId_t otaTimerId,
const char * const pTimerName,
const uint32_t timeout,
OtaTimerCallback_t callback )
{
OtaOsStatus_t otaOsStatus = OtaOsSuccess;
/* Create the timer structures. */
struct sigevent sgEvent;
struct itimerspec timerAttr;
( void ) pTimerName;
/* clear everything in the structures. */
( void ) memset( &sgEvent, 0, sizeof( struct sigevent ) );
( void ) memset( &timerAttr, 0, sizeof( struct itimerspec ) );
/* Set attributes. */
sgEvent.sigev_notify = SIGEV_THREAD;
sgEvent.sigev_value.sival_ptr = ( void * ) otaTimers[ otaTimerId ];
sgEvent.sigev_notify_function = timerCallback[ otaTimerId ];
/* Set OTA lib callback. */
otaTimerCallbackPtr = callback;
/* Set timeout attributes.*/
timerAttr.it_value.tv_sec = ( time_t ) timeout / 1000;
/* Create timer if required.*/
if( pOtaTimers[ otaTimerId ] == NULL )
{
errno = 0;
if( timer_create( CLOCK_REALTIME, &sgEvent, &otaTimers[ otaTimerId ] ) == -1 )
{
otaOsStatus = OtaOsTimerCreateFailed;
LogError( ( "Failed to create OTA timer: "
"timer_create returned error: "
"OtaOsStatus_t=%i "
",errno=%s",
otaOsStatus,
strerror( errno ) ) );
}
else
{
pOtaTimers[ otaTimerId ] = &otaTimers[ otaTimerId ];
}
}
/* Set timeout.*/
if( pOtaTimers[ otaTimerId ] != NULL )
{
errno = 0;
if( timer_settime( otaTimers[ otaTimerId ], 0, &timerAttr, NULL ) == -1 )
{
otaOsStatus = OtaOsTimerStartFailed;
LogError( ( "Failed to set OTA timer timeout: "
"timer_settime returned error: "
"OtaOsStatus_t=%i "
",errno=%s",
otaOsStatus,
strerror( errno ) ) );
}
else
{
LogDebug( ( "OTA Timer started." ) );
}
}
return otaOsStatus;
}
OtaOsStatus_t Posix_OtaStopTimer( OtaTimerId_t otaTimerId )
{
OtaOsStatus_t otaOsStatus = OtaOsSuccess;
/* Create the timer structures. */
struct itimerspec timerAttr;
/* clear everything in the structures. */
( void ) memset( &timerAttr, 0, sizeof( struct itimerspec ) );
/* Clear the timeout. */
timerAttr.it_value.tv_sec = 0;
if( pOtaTimers[ otaTimerId ] != NULL )
{
/* Stop the timer*/
errno = 0;
if( timer_settime( otaTimers[ otaTimerId ], 0, &timerAttr, NULL ) == -1 )
{
otaOsStatus = OtaOsTimerStopFailed;
LogError( ( "Failed to stop OTA timer: "
"timer_settime returned error: "
"OtaOsStatus_t=%i "
",errno=%s",
otaOsStatus,
strerror( errno ) ) );
}
else
{
LogDebug( ( "OTA Timer Stopped for Timerid=%i.", otaTimerId ) );
}
}
else
{
LogDebug( ( "OTA Timer handle NULL for Timerid=%i, can't stop.", otaTimerId ) );
otaOsStatus = OtaOsTimerStopFailed;
}
return otaOsStatus;
}
OtaOsStatus_t Posix_OtaDeleteTimer( OtaTimerId_t otaTimerId )
{
OtaOsStatus_t otaOsStatus = OtaOsSuccess;
if( pOtaTimers[ otaTimerId ] != NULL )
{
/* Delete the timer*/
errno = 0;
if( timer_delete( otaTimers[ otaTimerId ] ) == -1 )
{
otaOsStatus = OtaOsTimerDeleteFailed;
LogError( ( "Failed to delete OTA timer: "
"timer_delete returned error: "
"OtaOsStatus_t=%i "
",errno=%s",
otaOsStatus,
strerror( errno ) ) );
}
else
{
LogDebug( ( "OTA Timer deleted." ) );
pOtaTimers[ otaTimerId ] = NULL;
}
}
else
{
LogWarn( ( "OTA Timer handle NULL for Timerid=%i, can't delete.", otaTimerId ) );
otaOsStatus = OtaOsTimerDeleteFailed;
}
return otaOsStatus;
}
void * STDC_Malloc( size_t size )
{
/* Use standard C malloc.*/
/* MISRA Ref 21.3.1 [Memory Allocation] */
/* More details at: https://github.com/aws/ota-for-aws-iot-embedded-sdk/blob/main/MISRA.md#rule-213 */
/* coverity[misra_c_2012_rule_21_3_violation]. */
return malloc( size );
}
void STDC_Free( void * ptr )
{
/* Use standard C free.*/
/* MISRA Ref 21.3.1 [Memory Allocation] */
/* More details at: https://github.com/aws/ota-for-aws-iot-embedded-sdk/blob/main/MISRA.md#rule-213 */
/* coverity[misra_c_2012_rule_21_3_violation]. */
free( ptr );
}

View File

@ -0,0 +1,175 @@
/*
* AWS IoT Over-the-air Update v3.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file ota_os_posix.h
* @brief Function declarations for the example OTA OS Functional interface for
* POSIX.
*/
#ifndef _OTA_OS_POSIX_H_
#define _OTA_OS_POSIX_H_
/* Standard library include. */
#include <stdint.h>
#include <time.h>
/* OTA library interface include. */
#include "ota_os_interface.h"
struct OtaTimerContext
{
timer_t timer;
OtaTimerId_t timerId;
};
/**
* @brief Initialize the OTA events.
*
* This function initializes the OTA events mechanism for POSIX platforms.
*
* @param[pEventCtx] Pointer to the OTA event context.
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
OtaOsStatus_t Posix_OtaInitEvent( OtaEventContext_t * pEventCtx );
/**
* @brief Sends an OTA event.
*
* This function sends an event to OTA library event handler for POSIX platforms.
*
* @param[pEventCtx] Pointer to the OTA event context.
*
* @param[pEventMsg] Event to be sent to the OTA handler.
*
* @param[timeout] The maximum amount of time (msec) the task should block.
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
OtaOsStatus_t Posix_OtaSendEvent( OtaEventContext_t * pEventCtx,
const void * pEventMsg,
unsigned int timeout );
/**
* @brief Receive an OTA event.
*
* This function receives next event from the pending OTA events for POSIX platforms.
*
* @param[pEventCtx] Pointer to the OTA event context.
*
* @param[pEventMsg] Pointer to store message.
*
* @param[timeout] The maximum amount of time the task should block.
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
OtaOsStatus_t Posix_OtaReceiveEvent( OtaEventContext_t * pEventCtx,
void * pEventMsg,
uint32_t timeout );
/**
* @brief Deinitialize the OTA Events mechanism.
*
* This function deinitialize the OTA events mechanism and frees any resources
* used on POSIX platforms.
*
* @param[pEventCtx] Pointer to the OTA event context.
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
OtaOsStatus_t Posix_OtaDeinitEvent( OtaEventContext_t * pEventCtx );
/**
* @brief Start timer.
*
* This function starts the timer or resets it if it is already started for POSIX platforms.
*
* @param[otaTimerId] Timer ID of type otaTimerId_t.
*
* @param[pTimerName] Timer name.
*
* @param[timeout] Timeout for the timer.
*
* @param[callback] Callback to be called when timer expires.
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
OtaOsStatus_t Posix_OtaStartTimer( OtaTimerId_t otaTimerId,
const char * const pTimerName,
const uint32_t timeout,
OtaTimerCallback_t callback );
/**
* @brief Stop timer.
*
* This function stops the timer fro POSIX platforms.
*
* @param[otaTimerId] Timer ID of type otaTimerId_t.
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
OtaOsStatus_t Posix_OtaStopTimer( OtaTimerId_t otaTimerId );
/**
* @brief Delete a timer.
*
* This function deletes a timer for POSIX platforms.
*
* @param[otaTimerId] Timer ID of type otaTimerId_t.
*
* @return OtaOsStatus_t, OtaOsSuccess if success , other error code on failure.
*/
OtaOsStatus_t Posix_OtaDeleteTimer( OtaTimerId_t otaTimerId );
/**
* @brief Allocate memory.
*
* This function allocates the requested memory and returns a pointer to it using standard
* C library malloc.
*
* @param[size] This is the size of the memory block, in bytes..
*
* @return This function returns a pointer to the allocated memory, or NULL if
* the request fails.
*/
void * STDC_Malloc( size_t size );
/**
* @brief Free memory.
*
* This function deallocates the memory previously allocated by a call to allocation
* function of type OtaMalloc_t and uses standard C library free.
*
* @param[ptr] This is the pointer to a memory block previously allocated with function
* of type OtaMalloc_t. If a null pointer is passed as argument, no action occurs.
*
* @return None.
*/
void STDC_Free( void * ptr );
#endif /* ifndef _OTA_OS_POSIX_H_ */