/* * 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; }