ble_conn_state.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. /* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
  2. *
  3. * The information contained herein is property of Nordic Semiconductor ASA.
  4. * Terms and conditions of usage are described in detail in NORDIC
  5. * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
  6. *
  7. * Licensees are granted free, non-transferable use of the information. NO
  8. * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
  9. * the file.
  10. *
  11. */
  12. #include "ble_conn_state.h"
  13. #include <stdbool.h>
  14. #include <stdint.h>
  15. #include <string.h>
  16. #include "ble.h"
  17. #include "sdk_mapped_flags.h"
  18. #include "app_error.h"
  19. #if defined(__CC_ARM)
  20. #pragma push
  21. #pragma anon_unions
  22. #elif defined(__ICCARM__)
  23. #pragma language=extended
  24. #elif defined(__GNUC__)
  25. /* anonymous unions are enabled by default */
  26. #endif
  27. #define BLE_CONN_STATE_N_DEFAULT_FLAGS 5 /**< The number of flags kept for each connection, excluding user flags. */
  28. #define BLE_CONN_STATE_N_FLAGS (BLE_CONN_STATE_N_DEFAULT_FLAGS + BLE_CONN_STATE_N_USER_FLAGS) /**< The number of flags kept for each connection, including user flags. */
  29. /**@brief Structure containing all the flag collections maintained by the Connection State module.
  30. */
  31. typedef struct
  32. {
  33. sdk_mapped_flags_t valid_flags; /**< Flags indicating which connection handles are valid. */
  34. sdk_mapped_flags_t connected_flags; /**< Flags indicating which connections are connected, since disconnected connection handles will not immediately be invalidated. */
  35. sdk_mapped_flags_t central_flags; /**< Flags indicating in which connections the local device is the central. */
  36. sdk_mapped_flags_t encrypted_flags; /**< Flags indicating which connections are encrypted. */
  37. sdk_mapped_flags_t mitm_protected_flags; /**< Flags indicating which connections have encryption with protection from man-in-the-middle attacks. */
  38. sdk_mapped_flags_t user_flags[BLE_CONN_STATE_N_USER_FLAGS]; /**< Flags that can be reserved by the user. The flags will be cleared when a connection is invalidated, otherwise, the user is wholly responsible for the flag states. */
  39. } ble_conn_state_flag_collections_t;
  40. /**@brief Structure containing the internal state of the Connection State module.
  41. */
  42. typedef struct
  43. {
  44. uint32_t acquired_flags; /**< Bitmap for keeping track of which user flags have been acquired. */
  45. uint16_t valid_conn_handles[SDK_MAPPED_FLAGS_N_KEYS]; /**< List of connection handles used as keys for the sdk_mapped_flags module. */
  46. union
  47. {
  48. ble_conn_state_flag_collections_t flags; /**< Flag collections kept by the Connection State module. */
  49. sdk_mapped_flags_t flag_array[BLE_CONN_STATE_N_FLAGS]; /**< Flag collections as array to allow use of @ref sdk_mapped_flags_bulk_update_by_key() when setting all flags. */
  50. };
  51. } ble_conn_state_t;
  52. #if defined(__CC_ARM)
  53. #pragma pop
  54. #elif defined(__ICCARM__)
  55. /* leave anonymous unions enabled */
  56. #elif defined(__GNUC__)
  57. /* anonymous unions are enabled by default */
  58. #endif
  59. static ble_conn_state_t m_bcs = {0}; /**< Instantiation of the internal state. */
  60. /**@brief Function for resetting all internal memory to the values it had at initialization.
  61. */
  62. void bcs_internal_state_reset(void)
  63. {
  64. memset( &m_bcs, 0, sizeof(ble_conn_state_t) );
  65. }
  66. /**@brief Function for activating a connection record.
  67. *
  68. * @param p_record The record to activate.
  69. * @param conn_handle The connection handle to copy into the record.
  70. * @param role The role of the connection.
  71. *
  72. * @return whether the record was activated successfully.
  73. */
  74. static bool record_activate(uint16_t conn_handle)
  75. {
  76. uint16_t available_index = sdk_mapped_flags_first_key_index_get(~m_bcs.flags.valid_flags);
  77. if (available_index != SDK_MAPPED_FLAGS_INVALID_INDEX)
  78. {
  79. m_bcs.valid_conn_handles[available_index] = conn_handle;
  80. sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles,
  81. &m_bcs.flags.connected_flags,
  82. conn_handle,
  83. 1);
  84. sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles,
  85. &m_bcs.flags.valid_flags,
  86. conn_handle,
  87. 1);
  88. return true;
  89. }
  90. return false;
  91. }
  92. /**@brief Function for marking a connection record as invalid and resetting the values.
  93. *
  94. * @param p_record The record to invalidate.
  95. */
  96. static void record_invalidate(uint16_t conn_handle)
  97. {
  98. sdk_mapped_flags_bulk_update_by_key(m_bcs.valid_conn_handles,
  99. m_bcs.flag_array,
  100. BLE_CONN_STATE_N_FLAGS,
  101. conn_handle,
  102. 0);
  103. }
  104. /**@brief Function for marking a connection as disconnected. See @ref BLE_CONN_STATUS_DISCONNECTED.
  105. *
  106. * @param p_record The record of the connection to set as disconnected.
  107. */
  108. static void record_set_disconnected(uint16_t conn_handle)
  109. {
  110. sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles,
  111. &m_bcs.flags.connected_flags,
  112. conn_handle,
  113. 0);
  114. }
  115. /**@brief Function for invalidating records with a @ref BLE_CONN_STATUS_DISCONNECTED
  116. * connection status
  117. */
  118. static void record_purge_disconnected()
  119. {
  120. sdk_mapped_flags_key_list_t disconnected_list;
  121. disconnected_list = sdk_mapped_flags_key_list_get(
  122. m_bcs.valid_conn_handles,
  123. (~m_bcs.flags.connected_flags) & (m_bcs.flags.valid_flags));
  124. for (uint32_t i = 0; i < disconnected_list.len; i++)
  125. {
  126. record_invalidate(disconnected_list.flag_keys[i]);
  127. }
  128. }
  129. /**@brief Function for checking if a user flag has been acquired.
  130. *
  131. * @param[in] flag_id Which flag to check.
  132. *
  133. * @return Whether the flag has been acquired.
  134. */
  135. static bool user_flag_is_acquired(ble_conn_state_user_flag_id_t flag_id)
  136. {
  137. return ((m_bcs.acquired_flags & (1 << flag_id)) != 0);
  138. }
  139. /**@brief Function for marking a user flag as acquired.
  140. *
  141. * @param[in] flag_id Which flag to mark.
  142. */
  143. static void user_flag_acquire(ble_conn_state_user_flag_id_t flag_id)
  144. {
  145. m_bcs.acquired_flags |= (1 << flag_id);
  146. }
  147. void ble_conn_state_init(void)
  148. {
  149. bcs_internal_state_reset();
  150. }
  151. void ble_conn_state_on_ble_evt(ble_evt_t * p_ble_evt)
  152. {
  153. switch (p_ble_evt->header.evt_id)
  154. {
  155. case BLE_GAP_EVT_CONNECTED:
  156. record_purge_disconnected();
  157. if ( !record_activate(p_ble_evt->evt.gap_evt.conn_handle) )
  158. {
  159. // No more records available. Should not happen.
  160. APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
  161. }
  162. else
  163. {
  164. bool is_central =
  165. (p_ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_CENTRAL);
  166. sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles,
  167. &m_bcs.flags.central_flags,
  168. p_ble_evt->evt.gap_evt.conn_handle,
  169. is_central);
  170. }
  171. break;
  172. case BLE_GAP_EVT_DISCONNECTED:
  173. record_set_disconnected(p_ble_evt->evt.gap_evt.conn_handle);
  174. break;
  175. case BLE_GAP_EVT_CONN_SEC_UPDATE:
  176. sdk_mapped_flags_update_by_key(
  177. m_bcs.valid_conn_handles,
  178. &m_bcs.flags.encrypted_flags,
  179. p_ble_evt->evt.gap_evt.conn_handle,
  180. (p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv > 1));
  181. sdk_mapped_flags_update_by_key(
  182. m_bcs.valid_conn_handles,
  183. &m_bcs.flags.mitm_protected_flags,
  184. p_ble_evt->evt.gap_evt.conn_handle,
  185. (p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv > 2));
  186. break;
  187. }
  188. }
  189. bool ble_conn_state_valid(uint16_t conn_handle)
  190. {
  191. return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
  192. m_bcs.flags.valid_flags,
  193. conn_handle);
  194. }
  195. uint8_t ble_conn_state_role(uint16_t conn_handle)
  196. {
  197. uint8_t role = BLE_GAP_ROLE_INVALID;
  198. if ( sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, m_bcs.flags.valid_flags, conn_handle) )
  199. {
  200. bool central = sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
  201. m_bcs.flags.central_flags,
  202. conn_handle);
  203. role = central ? BLE_GAP_ROLE_CENTRAL : BLE_GAP_ROLE_PERIPH;
  204. }
  205. return role;
  206. }
  207. ble_conn_state_status_t ble_conn_state_status(uint16_t conn_handle)
  208. {
  209. ble_conn_state_status_t conn_status = BLE_CONN_STATUS_INVALID;
  210. bool valid = sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
  211. m_bcs.flags.valid_flags,
  212. conn_handle);
  213. if (valid)
  214. {
  215. bool connected = sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
  216. m_bcs.flags.connected_flags,
  217. conn_handle);
  218. conn_status = connected ? BLE_CONN_STATUS_CONNECTED : BLE_CONN_STATUS_DISCONNECTED;
  219. }
  220. return conn_status;
  221. }
  222. bool ble_conn_state_encrypted(uint16_t conn_handle)
  223. {
  224. return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
  225. m_bcs.flags.encrypted_flags,
  226. conn_handle);
  227. }
  228. bool ble_conn_state_mitm_protected(uint16_t conn_handle)
  229. {
  230. return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
  231. m_bcs.flags.mitm_protected_flags,
  232. conn_handle);
  233. }
  234. uint32_t ble_conn_state_n_connections(void)
  235. {
  236. return sdk_mapped_flags_n_flags_set(m_bcs.flags.connected_flags);
  237. }
  238. uint32_t ble_conn_state_n_centrals(void)
  239. {
  240. return sdk_mapped_flags_n_flags_set((m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags));
  241. }
  242. uint32_t ble_conn_state_n_peripherals(void)
  243. {
  244. return sdk_mapped_flags_n_flags_set((~m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags));
  245. }
  246. sdk_mapped_flags_key_list_t ble_conn_state_conn_handles(void)
  247. {
  248. return sdk_mapped_flags_key_list_get(m_bcs.valid_conn_handles, m_bcs.flags.valid_flags);
  249. }
  250. sdk_mapped_flags_key_list_t ble_conn_state_central_handles(void)
  251. {
  252. return sdk_mapped_flags_key_list_get(m_bcs.valid_conn_handles,
  253. (m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags));
  254. }
  255. sdk_mapped_flags_key_list_t ble_conn_state_periph_handles(void)
  256. {
  257. return sdk_mapped_flags_key_list_get(m_bcs.valid_conn_handles,
  258. (~m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags));
  259. }
  260. ble_conn_state_user_flag_id_t ble_conn_state_user_flag_acquire(void)
  261. {
  262. for (ble_conn_state_user_flag_id_t i = BLE_CONN_STATE_USER_FLAG0;
  263. i < BLE_CONN_STATE_N_USER_FLAGS;
  264. i++)
  265. {
  266. if ( !user_flag_is_acquired(i) )
  267. {
  268. user_flag_acquire(i);
  269. return i;
  270. }
  271. }
  272. return BLE_CONN_STATE_USER_FLAG_INVALID;
  273. }
  274. bool ble_conn_state_user_flag_get(uint16_t conn_handle, ble_conn_state_user_flag_id_t flag_id)
  275. {
  276. if (user_flag_is_acquired(flag_id))
  277. {
  278. return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
  279. m_bcs.flags.user_flags[flag_id],
  280. conn_handle);
  281. }
  282. else
  283. {
  284. return false;
  285. }
  286. }
  287. void ble_conn_state_user_flag_set(uint16_t conn_handle,
  288. ble_conn_state_user_flag_id_t flag_id,
  289. bool value)
  290. {
  291. if (user_flag_is_acquired(flag_id))
  292. {
  293. sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles,
  294. &m_bcs.flags.user_flags[flag_id],
  295. conn_handle,
  296. value);
  297. }
  298. }
  299. sdk_mapped_flags_t ble_conn_state_user_flag_collection(ble_conn_state_user_flag_id_t flag_id)
  300. {
  301. if ( user_flag_is_acquired(flag_id) )
  302. {
  303. return m_bcs.flags.user_flags[flag_id];
  304. }
  305. else
  306. {
  307. return 0;
  308. }
  309. }