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