R1 code for micro:bit based train controller code, requires second micro:bit running rx code to operate - see https://meanderingpi.wordpress.com/ for more information

Fork of nrf51-sdk by Lancaster University

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ble_conn_params.cpp Source File

ble_conn_params.cpp

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_params.h "
00034 #include <stdlib.h>
00035 #include "nordic_common.h"
00036 #include "ble_hci.h"
00037 #include "ble_srv_common.h "
00038 #include "app_util.h "
00039 
00040 #ifdef USE_APP_TIMER
00041 #include "app_timer.h "
00042 #else
00043     #ifdef YOTTA_CFG_MBED_OS
00044         #include "mbed-drivers/mbed.h"
00045     #else
00046         #include "mbed.h"
00047     #endif
00048 #endif
00049 
00050 static ble_conn_params_init_t m_conn_params_config;     /**< Configuration as specified by the application. */
00051 static ble_gap_conn_params_t  m_preferred_conn_params;  /**< Connection parameters preferred by the application. */
00052 static uint8_t                m_update_count;           /**< Number of Connection Parameter Update messages that has currently been sent. */
00053 static uint16_t               m_conn_handle;            /**< Current connection handle. */
00054 static ble_gap_conn_params_t  m_current_conn_params;    /**< Connection parameters received in the most recent Connect event. */
00055 #ifdef USE_APP_TIMER
00056 static app_timer_id_t         m_conn_params_timer_id;   /**< Connection parameters timer. */
00057 #else
00058 static Ticker                 m_conn_params_timer;
00059 #endif
00060 
00061 static bool m_change_param = false;
00062 
00063 static bool is_conn_params_ok(ble_gap_conn_params_t * p_conn_params)
00064 {
00065     // Check if interval is within the acceptable range.
00066     // NOTE: Using max_conn_interval in the received event data because this contains
00067     //       the client's connection interval.
00068     if (
00069         (p_conn_params->max_conn_interval >= m_preferred_conn_params.min_conn_interval)
00070         && 
00071         (p_conn_params->max_conn_interval <= m_preferred_conn_params.max_conn_interval)
00072        )
00073     {
00074         return true;
00075     }
00076     else
00077     {
00078         return false;
00079     }
00080 }
00081 
00082 
00083 #ifdef USE_APP_TIMER
00084 static void update_timeout_handler(void * p_context)
00085 {
00086     UNUSED_PARAMETER(p_context);
00087 
00088 #else /* #if !USE_APP_TIMER */
00089 static void update_timeout_handler(void)
00090 {
00091     m_conn_params_timer.detach(); /* this is supposed to be a single-shot timer callback */
00092 #endif /* #if !USE_APP_TIMER */
00093     if (m_conn_handle != BLE_CONN_HANDLE_INVALID)
00094     {
00095         // Check if we have reached the maximum number of attempts
00096         m_update_count++;
00097         if (m_update_count <= m_conn_params_config.max_conn_params_update_count)
00098         {
00099             uint32_t err_code;
00100 
00101             // Parameters are not ok, send connection parameters update request.
00102             err_code = sd_ble_gap_conn_param_update(m_conn_handle, &m_preferred_conn_params);
00103             if ((err_code != NRF_SUCCESS) && (m_conn_params_config.error_handler != NULL))
00104             {
00105                 m_conn_params_config.error_handler(err_code);
00106             }
00107         }
00108         else
00109         {
00110             m_update_count = 0;
00111 
00112             // Negotiation failed, disconnect automatically if this has been configured
00113             if (m_conn_params_config.disconnect_on_fail)
00114             {
00115                 uint32_t err_code;
00116 
00117                 err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
00118                 if ((err_code != NRF_SUCCESS) && (m_conn_params_config.error_handler != NULL))
00119                 {
00120                     m_conn_params_config.error_handler(err_code);
00121                 }
00122             }
00123 
00124             // Notify the application that the procedure has failed
00125             if (m_conn_params_config.evt_handler != NULL)
00126             {
00127                 ble_conn_params_evt_t evt;
00128 
00129                 evt.evt_type = BLE_CONN_PARAMS_EVT_FAILED;
00130                 m_conn_params_config.evt_handler(&evt);
00131             }
00132         }
00133     }
00134 }
00135 
00136 
00137 uint32_t ble_conn_params_init(const ble_conn_params_init_t * p_init)
00138 {
00139     uint32_t err_code;
00140 
00141     m_conn_params_config = *p_init;
00142     m_change_param = false;
00143     if (p_init->p_conn_params != NULL)
00144     {
00145         m_preferred_conn_params = *p_init->p_conn_params;
00146 
00147         // Set the connection params in stack
00148         err_code = sd_ble_gap_ppcp_set(&m_preferred_conn_params);
00149         if (err_code != NRF_SUCCESS)
00150         {
00151             return err_code;
00152         }
00153     }
00154     else
00155     {
00156         // Fetch the connection params from stack
00157         err_code = sd_ble_gap_ppcp_get(&m_preferred_conn_params);
00158         if (err_code != NRF_SUCCESS)
00159         {
00160             return err_code;
00161         }
00162     }
00163 
00164     m_conn_handle  = BLE_CONN_HANDLE_INVALID;
00165     m_update_count = 0;
00166 
00167 #ifdef USE_APP_TIMER
00168     return app_timer_create(&m_conn_params_timer_id,
00169                             APP_TIMER_MODE_SINGLE_SHOT,
00170                             update_timeout_handler);
00171 #else
00172     return NRF_SUCCESS;
00173 #endif
00174 }
00175 
00176 
00177 uint32_t ble_conn_params_stop(void)
00178 {
00179 #ifdef USE_APP_TIMER
00180     return app_timer_stop(m_conn_params_timer_id);
00181 #else /* #if !USE_APP_TIMER */
00182     m_conn_params_timer.detach();
00183     return NRF_SUCCESS;
00184 #endif /* #if !USE_APP_TIMER */
00185 }
00186 
00187 
00188 static void conn_params_negotiation(void)
00189 {
00190     // Start negotiation if the received connection parameters are not acceptable
00191     if (!is_conn_params_ok(&m_current_conn_params))
00192     {
00193 #ifdef USE_APP_TIMER
00194         uint32_t err_code;
00195 #endif
00196         uint32_t timeout_ticks;
00197 
00198         if (m_change_param)
00199         {
00200             // Notify the application that the procedure has failed
00201             if (m_conn_params_config.evt_handler != NULL)
00202             {
00203                 ble_conn_params_evt_t evt;
00204 
00205                 evt.evt_type = BLE_CONN_PARAMS_EVT_FAILED;
00206                 m_conn_params_config.evt_handler(&evt);
00207             }
00208         }
00209         else
00210         {
00211             if (m_update_count == 0)
00212             {
00213                 // First connection parameter update
00214                 timeout_ticks = m_conn_params_config.first_conn_params_update_delay;
00215             }
00216             else
00217             {
00218                 timeout_ticks = m_conn_params_config.next_conn_params_update_delay;
00219             }
00220 
00221 #ifdef USE_APP_TIMER
00222             err_code = app_timer_start(m_conn_params_timer_id, timeout_ticks, NULL);
00223             if ((err_code != NRF_SUCCESS) && (m_conn_params_config.error_handler != NULL))
00224             {
00225                 m_conn_params_config.error_handler(err_code);
00226             }
00227 #else
00228             m_conn_params_timer.attach(update_timeout_handler, timeout_ticks / 32768);
00229 #endif
00230         }
00231     }
00232     else
00233     {
00234         // Notify the application that the procedure has succeded
00235         if (m_conn_params_config.evt_handler != NULL)
00236         {
00237             ble_conn_params_evt_t evt;
00238 
00239             evt.evt_type = BLE_CONN_PARAMS_EVT_SUCCEEDED;
00240             m_conn_params_config.evt_handler(&evt);
00241         }
00242     }
00243     m_change_param = false;
00244 }
00245 
00246 
00247 static void on_connect(ble_evt_t * p_ble_evt)
00248 {
00249     // Save connection parameters
00250     m_conn_handle         = p_ble_evt->evt.gap_evt.conn_handle;
00251     m_current_conn_params = p_ble_evt->evt.gap_evt.params.connected.conn_params;
00252     m_update_count        = 0;  // Connection parameter negotiation should re-start every connection
00253 
00254     // Check if we shall handle negotiation on connect
00255     if (m_conn_params_config.start_on_notify_cccd_handle == BLE_GATT_HANDLE_INVALID)
00256     {
00257         conn_params_negotiation();
00258     }
00259 }
00260 
00261 
00262 static void on_disconnect(ble_evt_t * p_ble_evt)
00263 {
00264 #ifdef USE_APP_TIMER
00265     uint32_t err_code;
00266 #endif
00267 
00268     m_conn_handle = BLE_CONN_HANDLE_INVALID;
00269 
00270     // Stop timer if running
00271     m_update_count = 0; // Connection parameters updates should happen during every connection
00272 
00273 #ifdef USE_APP_TIMER
00274     err_code = app_timer_stop(m_conn_params_timer_id);
00275     if ((err_code != NRF_SUCCESS) && (m_conn_params_config.error_handler != NULL))
00276     {
00277         m_conn_params_config.error_handler(err_code);
00278     }
00279 #else
00280     m_conn_params_timer.detach();
00281 #endif
00282 }
00283 
00284 
00285 static void on_write(ble_evt_t * p_ble_evt)
00286 {
00287     ble_gatts_evt_write_t * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
00288 
00289     // Check if this the correct CCCD
00290     if (
00291         (p_evt_write->handle == m_conn_params_config.start_on_notify_cccd_handle)
00292         &&
00293         (p_evt_write->len == 2)
00294        )
00295     {
00296         // Check if this is a 'start notification'
00297         if (ble_srv_is_notification_enabled(p_evt_write->data))
00298         {
00299             // Do connection parameter negotiation if necessary
00300             conn_params_negotiation();
00301         }
00302         else
00303         {
00304 #ifdef USE_APP_TIMER
00305             uint32_t err_code;
00306 
00307             // Stop timer if running
00308             err_code = app_timer_stop(m_conn_params_timer_id);
00309             if ((err_code != NRF_SUCCESS) && (m_conn_params_config.error_handler != NULL))
00310             {
00311                 m_conn_params_config.error_handler(err_code);
00312             }
00313 #else /* #if !USE_APP_TIMER */
00314             m_conn_params_timer.detach();
00315 #endif /* #if !USE_APP_TIMER */
00316         }
00317     }
00318 }
00319 
00320 
00321 static void on_conn_params_update(ble_evt_t * p_ble_evt)
00322 {
00323     // Copy the parameters
00324     m_current_conn_params = p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params;
00325 
00326     conn_params_negotiation();
00327 }
00328 
00329 
00330 void ble_conn_params_on_ble_evt(ble_evt_t * p_ble_evt)
00331 {
00332     switch (p_ble_evt->header.evt_id)
00333     {
00334         case BLE_GAP_EVT_CONNECTED:
00335             on_connect(p_ble_evt);
00336             break;
00337 
00338         case BLE_GAP_EVT_DISCONNECTED:
00339             on_disconnect(p_ble_evt);
00340             break;
00341 
00342         case BLE_GATTS_EVT_WRITE:
00343             on_write(p_ble_evt);
00344             break;
00345 
00346         case BLE_GAP_EVT_CONN_PARAM_UPDATE:
00347             on_conn_params_update(p_ble_evt);
00348             break;
00349 
00350         default:
00351             // No implementation needed.
00352             break;
00353     }
00354 }
00355 
00356 
00357 uint32_t ble_conn_params_change_conn_params(ble_gap_conn_params_t * new_params)
00358 {
00359     uint32_t err_code;
00360 
00361     m_preferred_conn_params = *new_params;
00362     // Set the connection params in stack
00363     err_code = sd_ble_gap_ppcp_set(&m_preferred_conn_params);
00364     if (err_code == NRF_SUCCESS)
00365     {
00366         if (!is_conn_params_ok(&m_current_conn_params))
00367         {
00368             m_change_param = true;
00369             err_code = sd_ble_gap_conn_param_update(m_conn_handle, &m_preferred_conn_params);
00370             m_update_count = 1;
00371         }
00372         else
00373         {
00374             // Notify the application that the procedure has succeded
00375             if (m_conn_params_config.evt_handler != NULL)
00376             {
00377                 ble_conn_params_evt_t evt;
00378 
00379                 evt.evt_type = BLE_CONN_PARAMS_EVT_SUCCEEDED;
00380                 m_conn_params_config.evt_handler(&evt);
00381             }
00382             err_code = NRF_SUCCESS;
00383         }
00384     }
00385     return err_code;
00386 }