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