test
Fork of nRF51822 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 #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 1.7.2