test
Fork of nrf51-sdk by
Embed:
(wiki syntax)
Show/hide line numbers
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 15:51:25 by 1.7.2