diff options
Diffstat (limited to 'utilities/fsl_notifier.c')
-rw-r--r-- | utilities/fsl_notifier.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/utilities/fsl_notifier.c b/utilities/fsl_notifier.c new file mode 100644 index 0000000..3e2744f --- /dev/null +++ b/utilities/fsl_notifier.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "fsl_notifier.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/******************************************************************************* + * Variables + ******************************************************************************/ + +/******************************************************************************* + * Code + ******************************************************************************/ + +status_t NOTIFIER_CreateHandle(notifier_handle_t *notifierHandle, + notifier_user_config_t **configs, + uint8_t configsNumber, + notifier_callback_config_t *callbacks, + uint8_t callbacksNumber, + notifier_user_function_t userFunction, + void *userData) +{ + /* Check input parameter - at least one configuration is required and userFunction must exist */ + if ((configs == NULL) || (configsNumber == 0U) || (userFunction == NULL)) + { + return kStatus_Fail; + } + /* Initialize handle structure */ + memset(notifierHandle, 0, sizeof(notifier_handle_t)); + /* Store references to user-defined configurations */ + notifierHandle->configsTable = configs; + notifierHandle->configsNumber = configsNumber; + /* Store references to user-defined callback configurations */ + if (callbacks != NULL) + { + notifierHandle->callbacksTable = callbacks; + notifierHandle->callbacksNumber = callbacksNumber; + /* If all callbacks return success, then the errorCallbackIndex is callbacksNumber */ + notifierHandle->errorCallbackIndex = callbacksNumber; + } + notifierHandle->userFunction = userFunction; + notifierHandle->userData = userData; + + return kStatus_Success; +} + +status_t NOTIFIER_SwitchConfig(notifier_handle_t *notifierHandle, uint8_t configIndex, notifier_policy_t policy) +{ + uint8_t currentStaticCallback = 0U; /* Index to array of statically registered call-backs */ + status_t returnCode = kStatus_Success; /* Function return */ + + notifier_notification_block_t notifyBlock; /* Callback notification block */ + notifier_callback_config_t *callbackConfig; /* Pointer to callback configuration */ + + /* Set errorcallbackindex as callbacksNumber, which means no callback error now */ + notifierHandle->errorCallbackIndex = notifierHandle->callbacksNumber; + + /* Requested configuration availability check */ + if (configIndex >= notifierHandle->configsNumber) + { + return kStatus_OutOfRange; + } + + /* Initialization of local variables from the Notifier handle structure */ + + notifyBlock.policy = policy; + notifyBlock.targetConfig = notifierHandle->configsTable[configIndex]; + notifyBlock.notifyType = kNOTIFIER_NotifyBefore; + + /* From all statically registered call-backs... */ + for (currentStaticCallback = 0U; currentStaticCallback < notifierHandle->callbacksNumber; currentStaticCallback++) + { + callbackConfig = &(notifierHandle->callbacksTable[currentStaticCallback]); + /* ...notify only those which asked to be called before the configuration switch */ + if (((uint32_t)callbackConfig->callbackType) & kNOTIFIER_CallbackBefore) + { + /* In case that call-back returned error code mark it, store the call-back handle and eventually cancel + * the configuration switch */ + if (callbackConfig->callback(¬ifyBlock, callbackConfig->callbackData) != kStatus_Success) + { + returnCode = kStatus_NOTIFIER_ErrorNotificationBefore; + notifierHandle->errorCallbackIndex = currentStaticCallback; + /* If not forcing configuration switch, call all already notified call-backs to revert their state + * as the switch is canceled */ + if (policy != kNOTIFIER_PolicyForcible) + { + break; + } + } + } + } + + /* Set configuration */ + + /* In case that any call-back returned error code and policy doesn't force the configuration set, go to after + * switch call-backs */ + if ((policy == kNOTIFIER_PolicyForcible) || (returnCode == kStatus_Success)) + { + returnCode = notifierHandle->userFunction(notifierHandle->configsTable[configIndex], notifierHandle->userData); + if (returnCode != kStatus_Success) + { + return returnCode; + } + /* Update current configuration index */ + notifierHandle->currentConfigIndex = configIndex; + notifyBlock.notifyType = kNOTIFIER_NotifyAfter; + /* From all statically registered call-backs... */ + for (currentStaticCallback = 0U; currentStaticCallback < notifierHandle->callbacksNumber; + currentStaticCallback++) + { + callbackConfig = &(notifierHandle->callbacksTable[currentStaticCallback]); + /* ...notify only those which asked to be called after the configruation switch */ + if (((uint32_t)callbackConfig->callbackType) & kNOTIFIER_CallbackAfter) + { + /* In case that call-back returned error code mark it and store the call-back handle */ + if (callbackConfig->callback(¬ifyBlock, callbackConfig->callbackData) != kStatus_Success) + { + returnCode = kStatus_NOTIFIER_ErrorNotificationAfter; + notifierHandle->errorCallbackIndex = currentStaticCallback; + if (policy != kNOTIFIER_PolicyForcible) + { + break; + } + } + } + } + } + else + { + /* End of unsuccessful switch */ + notifyBlock.notifyType = kNOTIFIER_NotifyRecover; + while (currentStaticCallback--) + { + callbackConfig = &(notifierHandle->callbacksTable[currentStaticCallback]); + if (((uint32_t)callbackConfig->callbackType) & kNOTIFIER_CallbackBefore) + { + callbackConfig->callback(¬ifyBlock, callbackConfig->callbackData); + } + } + } + + return returnCode; +} + +uint8_t NOTIFIER_GetErrorCallbackIndex(notifier_handle_t *notifierHandle) +{ + return notifierHandle->errorCallbackIndex; +} |