Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of nrf51-sdk by
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 }
Generated on Tue Jul 12 2022 14:11:18 by
