fsl_notifier.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * Copyright (c) 2015, Freescale Semiconductor, Inc.
  3. * Copyright 2016-2017 NXP
  4. * All rights reserved.
  5. *
  6. * SPDX-License-Identifier: BSD-3-Clause
  7. */
  8. #include "fsl_notifier.h"
  9. /*******************************************************************************
  10. * Definitions
  11. ******************************************************************************/
  12. /*******************************************************************************
  13. * Prototypes
  14. ******************************************************************************/
  15. /*******************************************************************************
  16. * Variables
  17. ******************************************************************************/
  18. /*******************************************************************************
  19. * Code
  20. ******************************************************************************/
  21. /*!
  22. * brief Creates a Notifier handle.
  23. *
  24. * param notifierHandle A pointer to the notifier handle.
  25. * param configs A pointer to an array with references to all configurations which is handled by the Notifier.
  26. * param configsNumber Number of configurations. Size of the configuration array.
  27. * param callbacks A pointer to an array of callback configurations.
  28. * If there are no callbacks to register during Notifier initialization, use NULL value.
  29. * param callbacksNumber Number of registered callbacks. Size of the callbacks array.
  30. * param userFunction User function.
  31. * param userData User data passed to user function.
  32. * return An error Code or kStatus_Success.
  33. */
  34. status_t NOTIFIER_CreateHandle(notifier_handle_t *notifierHandle,
  35. notifier_user_config_t **configs,
  36. uint8_t configsNumber,
  37. notifier_callback_config_t *callbacks,
  38. uint8_t callbacksNumber,
  39. notifier_user_function_t userFunction,
  40. void *userData)
  41. {
  42. /* Check input parameter - at least one configuration is required and userFunction must exist */
  43. if ((configs == NULL) || (configsNumber == 0U) || (userFunction == NULL))
  44. {
  45. return kStatus_Fail;
  46. }
  47. /* Initialize handle structure */
  48. (void)memset(notifierHandle, 0, sizeof(notifier_handle_t));
  49. /* Store references to user-defined configurations */
  50. notifierHandle->configsTable = configs;
  51. notifierHandle->configsNumber = configsNumber;
  52. /* Store references to user-defined callback configurations */
  53. if (callbacks != NULL)
  54. {
  55. notifierHandle->callbacksTable = callbacks;
  56. notifierHandle->callbacksNumber = callbacksNumber;
  57. /* If all callbacks return success, then the errorCallbackIndex is callbacksNumber */
  58. notifierHandle->errorCallbackIndex = callbacksNumber;
  59. }
  60. notifierHandle->userFunction = userFunction;
  61. notifierHandle->userData = userData;
  62. return kStatus_Success;
  63. }
  64. /*!
  65. * brief Switches the configuration according to a pre-defined structure.
  66. *
  67. * This function sets the system to the target configuration. Before transition,
  68. * the Notifier sends notifications to all callbacks registered to the callback table.
  69. * Callbacks are invoked in the following order: All registered callbacks are notified
  70. * ordered by index in the callbacks array. The same order is used for before and after switch notifications.
  71. * The notifications before the configuration switch can be used to obtain confirmation about
  72. * the change from registered callbacks. If any registered callback denies the
  73. * configuration change, further execution of this function depends on the notifier policy: the
  74. * configuration change is either forced (kNOTIFIER_PolicyForcible) or exited (kNOTIFIER_PolicyAgreement).
  75. * When configuration change is forced, the result of the before switch notifications are ignored. If an
  76. * agreement is required, if any callback returns an error code, further notifications
  77. * before switch notifications are cancelled and all already notified callbacks are re-invoked.
  78. * The index of the callback which returned error code during pre-switch notifications is stored
  79. * (any error codes during callbacks re-invocation are ignored) and NOTIFIER_GetErrorCallback() can be used to get it.
  80. * Regardless of the policies, if any callback returns an error code, an error code indicating in which phase
  81. * the error occurred is returned when NOTIFIER_SwitchConfig() exits.
  82. * param notifierHandle pointer to notifier handle
  83. * param configIndex Index of the target configuration.
  84. * param policy Transaction policy, kNOTIFIER_PolicyAgreement or kNOTIFIER_PolicyForcible.
  85. *
  86. * return An error code or kStatus_Success.
  87. *
  88. */
  89. status_t NOTIFIER_SwitchConfig(notifier_handle_t *notifierHandle, uint8_t configIndex, notifier_policy_t policy)
  90. {
  91. uint8_t currentStaticCallback = 0U; /* Index to array of statically registered call-backs */
  92. status_t returnCode = kStatus_Success; /* Function return */
  93. notifier_notification_block_t notifyBlock; /* Callback notification block */
  94. notifier_callback_config_t *callbackConfig; /* Pointer to callback configuration */
  95. /* Set errorcallbackindex as callbacksNumber, which means no callback error now */
  96. notifierHandle->errorCallbackIndex = notifierHandle->callbacksNumber;
  97. /* Requested configuration availability check */
  98. if (configIndex >= notifierHandle->configsNumber)
  99. {
  100. return kStatus_OutOfRange;
  101. }
  102. /* Initialization of local variables from the Notifier handle structure */
  103. notifyBlock.policy = policy;
  104. notifyBlock.targetConfig = notifierHandle->configsTable[configIndex];
  105. notifyBlock.notifyType = kNOTIFIER_NotifyBefore;
  106. /* From all statically registered call-backs... */
  107. for (currentStaticCallback = 0U; currentStaticCallback < notifierHandle->callbacksNumber; currentStaticCallback++)
  108. {
  109. callbackConfig = &(notifierHandle->callbacksTable[currentStaticCallback]);
  110. /* ...notify only those which asked to be called before the configuration switch */
  111. if (((uint32_t)callbackConfig->callbackType & (uint32_t)kNOTIFIER_CallbackBefore) != 0U)
  112. {
  113. /* In case that call-back returned error code mark it, store the call-back handle and eventually cancel
  114. * the configuration switch */
  115. if (callbackConfig->callback(&notifyBlock, callbackConfig->callbackData) != kStatus_Success)
  116. {
  117. returnCode = (status_t)kStatus_NOTIFIER_ErrorNotificationBefore;
  118. notifierHandle->errorCallbackIndex = currentStaticCallback;
  119. /* If not forcing configuration switch, call all already notified call-backs to revert their state
  120. * as the switch is canceled */
  121. if (policy != kNOTIFIER_PolicyForcible)
  122. {
  123. break;
  124. }
  125. }
  126. }
  127. }
  128. /* Set configuration */
  129. /* In case that any call-back returned error code and policy doesn't force the configuration set, go to after
  130. * switch call-backs */
  131. if ((policy == kNOTIFIER_PolicyForcible) || (returnCode == kStatus_Success))
  132. {
  133. returnCode = notifierHandle->userFunction(notifierHandle->configsTable[configIndex], notifierHandle->userData);
  134. if (returnCode != kStatus_Success)
  135. {
  136. return returnCode;
  137. }
  138. /* Update current configuration index */
  139. notifierHandle->currentConfigIndex = configIndex;
  140. notifyBlock.notifyType = kNOTIFIER_NotifyAfter;
  141. /* From all statically registered call-backs... */
  142. for (currentStaticCallback = 0U; currentStaticCallback < notifierHandle->callbacksNumber;
  143. currentStaticCallback++)
  144. {
  145. callbackConfig = &(notifierHandle->callbacksTable[currentStaticCallback]);
  146. /* ...notify only those which asked to be called after the configuration switch */
  147. if (((uint32_t)callbackConfig->callbackType & (uint32_t)kNOTIFIER_CallbackAfter) != 0U)
  148. {
  149. /* In case that call-back returned error code mark it and store the call-back handle */
  150. if (callbackConfig->callback(&notifyBlock, callbackConfig->callbackData) != kStatus_Success)
  151. {
  152. returnCode = (status_t)kStatus_NOTIFIER_ErrorNotificationAfter;
  153. notifierHandle->errorCallbackIndex = currentStaticCallback;
  154. if (policy != kNOTIFIER_PolicyForcible)
  155. {
  156. break;
  157. }
  158. }
  159. }
  160. }
  161. }
  162. else
  163. {
  164. /* End of unsuccessful switch */
  165. notifyBlock.notifyType = kNOTIFIER_NotifyRecover;
  166. while (currentStaticCallback-- > 0U)
  167. {
  168. callbackConfig = &(notifierHandle->callbacksTable[currentStaticCallback]);
  169. if (((uint32_t)callbackConfig->callbackType & (uint32_t)kNOTIFIER_CallbackBefore) != 0U)
  170. {
  171. (void)callbackConfig->callback(&notifyBlock, callbackConfig->callbackData);
  172. }
  173. }
  174. }
  175. return returnCode;
  176. }
  177. /*!
  178. * brief This function returns the last failed notification callback.
  179. *
  180. * This function returns an index of the last callback that failed during the configuration switch while
  181. * the last NOTIFIER_SwitchConfig() was called. If the last NOTIFIER_SwitchConfig() call ended successfully
  182. * value equal to callbacks number is returned. The returned value represents an index in the array of
  183. * static call-backs.
  184. *
  185. * param notifierHandle Pointer to the notifier handle
  186. * return Callback Index of the last failed callback or value equal to callbacks count.
  187. */
  188. uint8_t NOTIFIER_GetErrorCallbackIndex(notifier_handle_t *notifierHandle)
  189. {
  190. return notifierHandle->errorCallbackIndex;
  191. }