Lancaster University fork of the Nordic nrf51-SDK repository, which actually lives on github: https://github.com/lancaster-university/nrf51-sdk

Dependents:   nRF51822

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ble_conn_state.c Source File

ble_conn_state.c

00001 /*
00002  * Copyright (c) Nordic Semiconductor ASA
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without modification,
00006  * are permitted provided that the following conditions are met:
00007  *
00008  *   1. Redistributions of source code must retain the above copyright notice, this
00009  *   list of conditions and the following disclaimer.
00010  *
00011  *   2. Redistributions in binary form must reproduce the above copyright notice, this
00012  *   list of conditions and the following disclaimer in the documentation and/or
00013  *   other materials provided with the distribution.
00014  *
00015  *   3. Neither the name of Nordic Semiconductor ASA nor the names of other
00016  *   contributors to this software may be used to endorse or promote products
00017  *   derived from this software without specific prior written permission.
00018  *
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00021  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00022  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00023  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00024  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00025  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00026  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00027  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00028  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00029  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030  *
00031  */
00032 
00033 #include "ble_conn_state.h "
00034 #include <stdbool.h>
00035 #include <stdint.h>
00036 #include <string.h>
00037 #include "ble.h"
00038 #include "sdk_mapped_flags.h "
00039 #include "app_error.h "
00040 
00041 
00042 #if defined(__CC_ARM)
00043   #pragma push
00044   #pragma anon_unions
00045 #elif defined(__ICCARM__)
00046   #pragma language=extended
00047 #elif defined(__GNUC__)
00048   /* anonymous unions are enabled by default */
00049 #endif
00050 
00051 
00052 #define BLE_CONN_STATE_N_DEFAULT_FLAGS 5                                                       /**< The number of flags kept for each connection, excluding user flags. */
00053 #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. */
00054 
00055 
00056 /**@brief Structure containing all the flag collections maintained by the Connection State module.
00057  */
00058 typedef struct
00059 {
00060     sdk_mapped_flags_t valid_flags;                                 /**< Flags indicating which connection handles are valid. */
00061     sdk_mapped_flags_t connected_flags;                             /**< Flags indicating which connections are connected, since disconnected connection handles will not immediately be invalidated. */
00062     sdk_mapped_flags_t central_flags;                               /**< Flags indicating in which connections the local device is the central. */
00063     sdk_mapped_flags_t encrypted_flags;                             /**< Flags indicating which connections are encrypted. */
00064     sdk_mapped_flags_t mitm_protected_flags;                        /**< Flags indicating which connections have encryption with protection from man-in-the-middle attacks. */
00065     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. */
00066 } ble_conn_state_flag_collections_t;
00067 
00068 
00069 /**@brief Structure containing the internal state of the Connection State module.
00070  */
00071 typedef struct
00072 {
00073     uint16_t           acquired_flags;                              /**< Bitmap for keeping track of which user flags have been acquired. */
00074     uint16_t           valid_conn_handles[SDK_MAPPED_FLAGS_N_KEYS]; /**< List of connection handles used as keys for the sdk_mapped_flags module. */
00075     union
00076     {
00077         ble_conn_state_flag_collections_t flags;                              /**< Flag collections kept by the Connection State module. */
00078         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. */
00079     };
00080 } ble_conn_state_t;
00081 
00082 
00083 #if defined(__CC_ARM)
00084   #pragma pop
00085 #elif defined(__ICCARM__)
00086   /* leave anonymous unions enabled */
00087 #elif defined(__GNUC__)
00088   /* anonymous unions are enabled by default */
00089 #endif
00090 
00091 
00092 static ble_conn_state_t m_bcs = {0}; /**< Instantiation of the internal state. */
00093 
00094 
00095 /**@brief Function for resetting all internal memory to the values it had at initialization.
00096  */
00097 void bcs_internal_state_reset(void)
00098 {
00099     memset( &m_bcs, 0, sizeof(ble_conn_state_t) );
00100 }
00101 
00102 
00103 /**@brief Function for activating a connection record.
00104  *
00105  * @param p_record     The record to activate.
00106  * @param conn_handle  The connection handle to copy into the record.
00107  * @param role         The role of the connection.
00108  *
00109  * @return whether the record was activated successfully.
00110  */
00111 static bool record_activate(uint16_t conn_handle)
00112 {
00113     uint16_t available_index = sdk_mapped_flags_first_key_index_get(~m_bcs.flags.valid_flags);
00114 
00115     if (available_index != SDK_MAPPED_FLAGS_INVALID_INDEX)
00116     {
00117         m_bcs.valid_conn_handles[available_index] = conn_handle;
00118         sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles,
00119                                       &m_bcs.flags.connected_flags,
00120                                        conn_handle,
00121                                        1);
00122         sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles,
00123                                       &m_bcs.flags.valid_flags,
00124                                        conn_handle,
00125                                        1);
00126 
00127         return true;
00128     }
00129 
00130     return false;
00131 }
00132 
00133 
00134 /**@brief Function for marking a connection record as invalid and resetting the values.
00135  *
00136  * @param p_record  The record to invalidate.
00137  */
00138 static void record_invalidate(uint16_t conn_handle)
00139 {
00140     sdk_mapped_flags_bulk_update_by_key(m_bcs.valid_conn_handles,
00141                                         m_bcs.flag_array,
00142                                         BLE_CONN_STATE_N_FLAGS,
00143                                         conn_handle,
00144                                         0);
00145 }
00146 
00147 
00148 /**@brief Function for marking a connection as disconnected. See @ref BLE_CONN_STATUS_DISCONNECTED.
00149  *
00150  * @param p_record   The record of the connection to set as disconnected.
00151  */
00152 static void record_set_disconnected(uint16_t conn_handle)
00153 {
00154     sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles,
00155                                   &m_bcs.flags.connected_flags,
00156                                    conn_handle,
00157                                    0);
00158 }
00159 
00160 
00161 /**@brief Function for invalidating records with a @ref BLE_CONN_STATUS_DISCONNECTED
00162  *        connection status
00163  */
00164 static void record_purge_disconnected()
00165 {
00166     sdk_mapped_flags_key_list_t disconnected_list;
00167 
00168     disconnected_list = sdk_mapped_flags_key_list_get(
00169                                    m_bcs.valid_conn_handles,
00170                                  (~m_bcs.flags.connected_flags) & (m_bcs.flags.valid_flags));
00171 
00172     for (int i = 0; i < disconnected_list.len; i++)
00173     {
00174         record_invalidate(disconnected_list.flag_keys[i]);
00175     }
00176 }
00177 
00178 
00179 /**@brief Function for checking if a user flag has been acquired.
00180  *
00181  * @param[in]  flag_id  Which flag to check.
00182  *
00183  * @return  Whether the flag has been acquired.
00184  */
00185 static bool user_flag_is_acquired(ble_conn_state_user_flag_id_t flag_id)
00186 {
00187     return ((m_bcs.acquired_flags & (1 << flag_id)) != 0);
00188 }
00189 
00190 
00191 /**@brief Function for marking a user flag as acquired.
00192  *
00193  * @param[in]  flag_id  Which flag to mark.
00194  */
00195 static void user_flag_acquire(ble_conn_state_user_flag_id_t flag_id)
00196 {
00197     m_bcs.acquired_flags |= (1 << flag_id);
00198 }
00199 
00200 
00201 void ble_conn_state_init(void)
00202 {
00203     bcs_internal_state_reset();
00204 }
00205 
00206 
00207 void ble_conn_state_on_ble_evt(ble_evt_t * p_ble_evt)
00208 {
00209     switch (p_ble_evt->header.evt_id)
00210     {
00211         case BLE_GAP_EVT_CONNECTED:
00212             record_purge_disconnected();
00213 
00214             if ( !record_activate(p_ble_evt->evt.gap_evt.conn_handle) )
00215             {
00216                 // No more records available. Should not happen.
00217                 APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
00218             }
00219             else
00220             {
00221 #if defined(TARGET_MCU_NRF51_16K_S110) || defined(TARGET_MCU_NRF51_32K_S110)
00222                 bool is_central = false;
00223 #elif defined(TARGET_MCU_NRF51_16K_S120) || defined(TARGET_MCU_NRF51_32K_S120)
00224                 bool is_central = true;
00225 #else
00226                 bool is_central =
00227                         (p_ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_CENTRAL);
00228 #endif
00229 
00230                 sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles,
00231                                               &m_bcs.flags.central_flags,
00232                                                p_ble_evt->evt.gap_evt.conn_handle,
00233                                                is_central);
00234             }
00235 
00236             break;
00237 
00238         case BLE_GAP_EVT_DISCONNECTED:
00239             record_set_disconnected(p_ble_evt->evt.gap_evt.conn_handle);
00240             break;
00241 
00242         case BLE_GAP_EVT_CONN_SEC_UPDATE:
00243             sdk_mapped_flags_update_by_key(
00244                           m_bcs.valid_conn_handles,
00245                          &m_bcs.flags.encrypted_flags,
00246                           p_ble_evt->evt.gap_evt.conn_handle,
00247                          (p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv > 1));
00248             sdk_mapped_flags_update_by_key(
00249                           m_bcs.valid_conn_handles,
00250                          &m_bcs.flags.mitm_protected_flags,
00251                           p_ble_evt->evt.gap_evt.conn_handle,
00252                          (p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv > 2));
00253             break;
00254     }
00255 }
00256 
00257 
00258 bool ble_conn_state_valid(uint16_t conn_handle)
00259 {
00260     return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
00261                                        m_bcs.flags.valid_flags,
00262                                        conn_handle);
00263 }
00264 
00265 
00266 uint8_t ble_conn_state_role(uint16_t conn_handle)
00267 {
00268     uint8_t role = BLE_GAP_ROLE_INVALID;
00269 
00270     if ( sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, m_bcs.flags.valid_flags, conn_handle) )
00271     {
00272         bool central = sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
00273                                                    m_bcs.flags.central_flags,
00274                                                    conn_handle);
00275 
00276         role = central ? BLE_GAP_ROLE_CENTRAL : BLE_GAP_ROLE_PERIPH;
00277     }
00278 
00279     return role;
00280 }
00281 
00282 
00283 ble_conn_state_status_t ble_conn_state_status(uint16_t conn_handle)
00284 {
00285     ble_conn_state_status_t conn_status = BLE_CONN_STATUS_INVALID;
00286     bool valid = sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
00287                                              m_bcs.flags.valid_flags,
00288                                              conn_handle);
00289 
00290     if (valid)
00291     {
00292         bool connected = sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
00293                                                      m_bcs.flags.connected_flags,
00294                                                      conn_handle);
00295 
00296         conn_status = connected ? BLE_CONN_STATUS_CONNECTED : BLE_CONN_STATUS_DISCONNECTED;
00297     }
00298 
00299     return conn_status;
00300 }
00301 
00302 
00303 bool ble_conn_state_encrypted(uint16_t conn_handle)
00304 {
00305     return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
00306                                        m_bcs.flags.encrypted_flags,
00307                                        conn_handle);
00308 }
00309 
00310 
00311 bool ble_conn_state_mitm_protected(uint16_t conn_handle)
00312 {
00313     return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
00314                                        m_bcs.flags.mitm_protected_flags,
00315                                        conn_handle);
00316 }
00317 
00318 
00319 uint32_t ble_conn_state_n_connections(void)
00320 {
00321     return sdk_mapped_flags_n_flags_set(m_bcs.flags.connected_flags);
00322 }
00323 
00324 
00325 uint32_t ble_conn_state_n_centrals(void)
00326 {
00327     return sdk_mapped_flags_n_flags_set((m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags));
00328 }
00329 
00330 
00331 uint32_t ble_conn_state_n_peripherals(void)
00332 {
00333     return sdk_mapped_flags_n_flags_set((~m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags));
00334 }
00335 
00336 
00337 sdk_mapped_flags_key_list_t ble_conn_state_conn_handles(void)
00338 {
00339     return sdk_mapped_flags_key_list_get(m_bcs.valid_conn_handles, m_bcs.flags.valid_flags);
00340 }
00341 
00342 
00343 sdk_mapped_flags_key_list_t ble_conn_state_central_handles(void)
00344 {
00345     return sdk_mapped_flags_key_list_get(m_bcs.valid_conn_handles,
00346                                         (m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags));
00347 }
00348 
00349 
00350 sdk_mapped_flags_key_list_t ble_conn_state_periph_handles(void)
00351 {
00352     return sdk_mapped_flags_key_list_get(m_bcs.valid_conn_handles,
00353                                         (~m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags));
00354 }
00355 
00356 
00357 ble_conn_state_user_flag_id_t ble_conn_state_user_flag_acquire(void)
00358 {
00359     for (ble_conn_state_user_flag_id_t i = BLE_CONN_STATE_USER_FLAG0;
00360                                        i < BLE_CONN_STATE_N_USER_FLAGS;
00361                                        i++)
00362     {
00363         if ( !user_flag_is_acquired(i) )
00364         {
00365             user_flag_acquire(i);
00366             return i;
00367         }
00368     }
00369 
00370     return BLE_CONN_STATE_USER_FLAG_INVALID;
00371 }
00372 
00373 
00374 bool ble_conn_state_user_flag_get(uint16_t conn_handle, ble_conn_state_user_flag_id_t flag_id)
00375 {
00376     if (user_flag_is_acquired(flag_id))
00377     {
00378         return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
00379                                            m_bcs.flags.user_flags[flag_id],
00380                                            conn_handle);
00381     }
00382     else
00383     {
00384         return false;
00385     }
00386 }
00387 
00388 
00389 void ble_conn_state_user_flag_set(uint16_t                      conn_handle,
00390                                   ble_conn_state_user_flag_id_t flag_id,
00391                                   bool                          value)
00392 {
00393     if (user_flag_is_acquired(flag_id))
00394     {
00395         sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles,
00396                                       &m_bcs.flags.user_flags[flag_id],
00397                                        conn_handle,
00398                                        value);
00399     }
00400 }
00401 
00402 
00403 sdk_mapped_flags_t ble_conn_state_user_flag_collection(ble_conn_state_user_flag_id_t flag_id)
00404 {
00405     if ( user_flag_is_acquired(flag_id) )
00406     {
00407         return m_bcs.flags.user_flags[flag_id];
00408     }
00409     else
00410     {
00411         return 0;
00412     }
00413 }
00414