bsp_btn_ble.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /**
  2. * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #include "bsp_btn_ble.h"
  41. #include "nrf_sdh_ble.h"
  42. #include "bsp.h"
  43. #define BTN_ID_WAKEUP 0 /**< ID of button used to wake up the application. */
  44. #define BTN_ID_SLEEP 0 /**< ID of button used to put the application into sleep mode. */
  45. #define BTN_ID_DISCONNECT 0 /**< ID of button used to gracefully terminate a connection on long press. */
  46. #define BTN_ID_WAKEUP_BOND_DELETE 1 /**< ID of button used to wake up the application and delete all bonding information. */
  47. #define BTN_ID_WHITELIST_OFF 1 /**< ID of button used to turn off usage of the whitelist. */
  48. #define BTN_ACTION_SLEEP BSP_BUTTON_ACTION_RELEASE /**< Button action used to put the application into sleep mode. */
  49. #define BTN_ACTION_DISCONNECT BSP_BUTTON_ACTION_LONG_PUSH /**< Button action used to gracefully terminate a connection on long press. */
  50. #define BTN_ACTION_WHITELIST_OFF BSP_BUTTON_ACTION_LONG_PUSH /**< Button action used to turn off usage of the whitelist. */
  51. /**@brief This macro will return from the current function if err_code
  52. * is not NRF_SUCCESS or NRF_ERROR_INVALID_PARAM.
  53. */
  54. #define RETURN_ON_ERROR_NOT_INVALID_PARAM(err_code) \
  55. do \
  56. { \
  57. if (((err_code) != NRF_SUCCESS) && ((err_code) != NRF_ERROR_INVALID_PARAM)) \
  58. { \
  59. return err_code; \
  60. } \
  61. } \
  62. while (0)
  63. /**@brief This macro will return from the current function if err_code
  64. * is not NRF_SUCCESS or NRF_ERROR_NOT_SUPPORTED.
  65. */
  66. #define RETURN_ON_ERROR_NOT_NOT_SUPPORTED(err_code) \
  67. do \
  68. { \
  69. if (((err_code) != NRF_SUCCESS) && ((err_code) != NRF_ERROR_NOT_SUPPORTED)) \
  70. { \
  71. return err_code; \
  72. } \
  73. } \
  74. while (0)
  75. /**@brief This macro will call the registered error handler if err_code
  76. * is not NRF_SUCCESS and the error handler is not NULL.
  77. */
  78. #define CALL_HANDLER_ON_ERROR(err_code) \
  79. do \
  80. { \
  81. if (((err_code) != NRF_SUCCESS) && (m_error_handler != NULL)) \
  82. { \
  83. m_error_handler(err_code); \
  84. } \
  85. } \
  86. while (0)
  87. static bsp_btn_ble_error_handler_t m_error_handler = NULL; /**< Error handler registered by the user. */
  88. static uint32_t m_num_connections = 0; /**< Number of connections the device is currently in. */
  89. /**@brief Function for configuring the buttons for connection.
  90. *
  91. * @retval NRF_SUCCESS Configured successfully.
  92. * @return A propagated error code.
  93. */
  94. static uint32_t connection_buttons_configure()
  95. {
  96. uint32_t err_code;
  97. err_code = bsp_event_to_button_action_assign(BTN_ID_SLEEP,
  98. BTN_ACTION_SLEEP,
  99. BSP_EVENT_DEFAULT);
  100. RETURN_ON_ERROR_NOT_INVALID_PARAM(err_code);
  101. err_code = bsp_event_to_button_action_assign(BTN_ID_WHITELIST_OFF,
  102. BTN_ACTION_WHITELIST_OFF,
  103. BSP_EVENT_WHITELIST_OFF);
  104. RETURN_ON_ERROR_NOT_INVALID_PARAM(err_code);
  105. err_code = bsp_event_to_button_action_assign(BTN_ID_DISCONNECT,
  106. BTN_ACTION_DISCONNECT,
  107. BSP_EVENT_DISCONNECT);
  108. RETURN_ON_ERROR_NOT_INVALID_PARAM(err_code);
  109. return NRF_SUCCESS;
  110. }
  111. /**@brief Function for configuring the buttons for advertisement.
  112. *
  113. * @retval NRF_SUCCESS Configured successfully.
  114. * @return A propagated error code.
  115. */
  116. static uint32_t advertising_buttons_configure()
  117. {
  118. uint32_t err_code;
  119. err_code = bsp_event_to_button_action_assign(BTN_ID_DISCONNECT,
  120. BTN_ACTION_DISCONNECT,
  121. BSP_EVENT_DEFAULT);
  122. RETURN_ON_ERROR_NOT_INVALID_PARAM(err_code);
  123. err_code = bsp_event_to_button_action_assign(BTN_ID_WHITELIST_OFF,
  124. BTN_ACTION_WHITELIST_OFF,
  125. BSP_EVENT_WHITELIST_OFF);
  126. RETURN_ON_ERROR_NOT_INVALID_PARAM(err_code);
  127. err_code = bsp_event_to_button_action_assign(BTN_ID_SLEEP,
  128. BTN_ACTION_SLEEP,
  129. BSP_EVENT_SLEEP);
  130. RETURN_ON_ERROR_NOT_INVALID_PARAM(err_code);
  131. return NRF_SUCCESS;
  132. }
  133. /**@brief Function for extracting the BSP event valid at startup.
  134. *
  135. * @details When a button was used to wake up the device, the button press will not generate an
  136. * interrupt. This function reads which button was pressed at startup, and returns the
  137. * appropriate BSP event.
  138. *
  139. * @param[out] p_startup_event Where to put the extracted BSP event.
  140. */
  141. static void startup_event_extract(bsp_event_t * p_startup_event)
  142. {
  143. // React to button states
  144. if (bsp_button_is_pressed(BTN_ID_WAKEUP_BOND_DELETE))
  145. {
  146. *p_startup_event = BSP_EVENT_CLEAR_BONDING_DATA;
  147. }
  148. else if (bsp_button_is_pressed(BTN_ID_WAKEUP))
  149. {
  150. *p_startup_event = BSP_EVENT_WAKEUP;
  151. }
  152. else
  153. {
  154. *p_startup_event = BSP_EVENT_NOTHING;
  155. }
  156. }
  157. uint32_t bsp_btn_ble_sleep_mode_prepare(void)
  158. {
  159. uint32_t err_code;
  160. err_code = bsp_wakeup_button_enable(BTN_ID_WAKEUP);
  161. RETURN_ON_ERROR_NOT_NOT_SUPPORTED(err_code);
  162. err_code = bsp_wakeup_button_enable(BTN_ID_WAKEUP_BOND_DELETE);
  163. RETURN_ON_ERROR_NOT_NOT_SUPPORTED(err_code);
  164. return NRF_SUCCESS;
  165. }
  166. /**
  167. * @brief Function for handling BLE events.
  168. *
  169. * @param[in] p_ble_evt Event received from the BLE stack.
  170. * @param[in] p_context Context.
  171. */
  172. static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
  173. {
  174. uint32_t err_code;
  175. switch (p_ble_evt->header.evt_id)
  176. {
  177. case BLE_GAP_EVT_CONNECTED:
  178. if (m_num_connections == 0)
  179. {
  180. err_code = connection_buttons_configure();
  181. CALL_HANDLER_ON_ERROR(err_code);
  182. }
  183. m_num_connections++;
  184. break;
  185. case BLE_GAP_EVT_DISCONNECTED:
  186. m_num_connections--;
  187. if (m_num_connections == 0)
  188. {
  189. err_code = advertising_buttons_configure();
  190. CALL_HANDLER_ON_ERROR(err_code);
  191. }
  192. break;
  193. default:
  194. break;
  195. }
  196. }
  197. NRF_SDH_BLE_OBSERVER(m_ble_observer, BSP_BTN_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
  198. uint32_t bsp_btn_ble_init(bsp_btn_ble_error_handler_t error_handler, bsp_event_t * p_startup_bsp_evt)
  199. {
  200. uint32_t err_code = NRF_SUCCESS;
  201. m_error_handler = error_handler;
  202. if (p_startup_bsp_evt != NULL)
  203. {
  204. startup_event_extract(p_startup_bsp_evt);
  205. }
  206. if (m_num_connections == 0)
  207. {
  208. err_code = advertising_buttons_configure();
  209. }
  210. return err_code;
  211. }