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