project for nrf51822 qfab

Dependencies:   eddystone_URL mbed

Fork of eddystone_URL by vo dung

Committer:
jksoft
Date:
Wed Nov 12 02:40:34 2014 +0000
Revision:
0:76dfa9657d9d
????????

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jksoft 0:76dfa9657d9d 1 /* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
jksoft 0:76dfa9657d9d 2 *
jksoft 0:76dfa9657d9d 3 * The information contained herein is property of Nordic Semiconductor ASA.
jksoft 0:76dfa9657d9d 4 * Terms and conditions of usage are described in detail in NORDIC
jksoft 0:76dfa9657d9d 5 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
jksoft 0:76dfa9657d9d 6 *
jksoft 0:76dfa9657d9d 7 * Licensees are granted free, non-transferable use of the information. NO
jksoft 0:76dfa9657d9d 8 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
jksoft 0:76dfa9657d9d 9 * the file.
jksoft 0:76dfa9657d9d 10 *
jksoft 0:76dfa9657d9d 11 */
jksoft 0:76dfa9657d9d 12
jksoft 0:76dfa9657d9d 13 #include "ble_conn_params.h"
jksoft 0:76dfa9657d9d 14 #include <stdlib.h>
jksoft 0:76dfa9657d9d 15 #include "nordic_common.h"
jksoft 0:76dfa9657d9d 16 #include "ble_hci.h"
jksoft 0:76dfa9657d9d 17 #include "app_timer.h"
jksoft 0:76dfa9657d9d 18 #include "ble_srv_common.h"
jksoft 0:76dfa9657d9d 19 #include "app_util.h"
jksoft 0:76dfa9657d9d 20
jksoft 0:76dfa9657d9d 21
jksoft 0:76dfa9657d9d 22 static ble_conn_params_init_t m_conn_params_config; /**< Configuration as specified by the application. */
jksoft 0:76dfa9657d9d 23 static ble_gap_conn_params_t m_preferred_conn_params; /**< Connection parameters preferred by the application. */
jksoft 0:76dfa9657d9d 24 static uint8_t m_update_count; /**< Number of Connection Parameter Update messages that has currently been sent. */
jksoft 0:76dfa9657d9d 25 static uint16_t m_conn_handle; /**< Current connection handle. */
jksoft 0:76dfa9657d9d 26 static ble_gap_conn_params_t m_current_conn_params; /**< Connection parameters received in the most recent Connect event. */
jksoft 0:76dfa9657d9d 27 static app_timer_id_t m_conn_params_timer_id; /**< Connection parameters timer. */
jksoft 0:76dfa9657d9d 28
jksoft 0:76dfa9657d9d 29 static bool m_change_param = false;
jksoft 0:76dfa9657d9d 30
jksoft 0:76dfa9657d9d 31 static bool is_conn_params_ok(ble_gap_conn_params_t * p_conn_params)
jksoft 0:76dfa9657d9d 32 {
jksoft 0:76dfa9657d9d 33 // Check if interval is within the acceptable range.
jksoft 0:76dfa9657d9d 34 // NOTE: Using max_conn_interval in the received event data because this contains
jksoft 0:76dfa9657d9d 35 // the client's connection interval.
jksoft 0:76dfa9657d9d 36 if ((p_conn_params->max_conn_interval >= m_preferred_conn_params.min_conn_interval) &&
jksoft 0:76dfa9657d9d 37 (p_conn_params->max_conn_interval <= m_preferred_conn_params.max_conn_interval)) {
jksoft 0:76dfa9657d9d 38 return true;
jksoft 0:76dfa9657d9d 39 } else {
jksoft 0:76dfa9657d9d 40 return false;
jksoft 0:76dfa9657d9d 41 }
jksoft 0:76dfa9657d9d 42 }
jksoft 0:76dfa9657d9d 43
jksoft 0:76dfa9657d9d 44
jksoft 0:76dfa9657d9d 45 static void update_timeout_handler(void * p_context)
jksoft 0:76dfa9657d9d 46 {
jksoft 0:76dfa9657d9d 47 UNUSED_PARAMETER(p_context);
jksoft 0:76dfa9657d9d 48
jksoft 0:76dfa9657d9d 49 if (m_conn_handle != BLE_CONN_HANDLE_INVALID)
jksoft 0:76dfa9657d9d 50 {
jksoft 0:76dfa9657d9d 51 // Check if we have reached the maximum number of attempts
jksoft 0:76dfa9657d9d 52 m_update_count++;
jksoft 0:76dfa9657d9d 53 if (m_update_count <= m_conn_params_config.max_conn_params_update_count)
jksoft 0:76dfa9657d9d 54 {
jksoft 0:76dfa9657d9d 55 uint32_t err_code;
jksoft 0:76dfa9657d9d 56
jksoft 0:76dfa9657d9d 57 // Parameters are not ok, send connection parameters update request.
jksoft 0:76dfa9657d9d 58 err_code = sd_ble_gap_conn_param_update(m_conn_handle, &m_preferred_conn_params);
jksoft 0:76dfa9657d9d 59 if ((err_code != NRF_SUCCESS) && (m_conn_params_config.error_handler != NULL))
jksoft 0:76dfa9657d9d 60 {
jksoft 0:76dfa9657d9d 61 m_conn_params_config.error_handler(err_code);
jksoft 0:76dfa9657d9d 62 }
jksoft 0:76dfa9657d9d 63 }
jksoft 0:76dfa9657d9d 64 else
jksoft 0:76dfa9657d9d 65 {
jksoft 0:76dfa9657d9d 66 m_update_count = 0;
jksoft 0:76dfa9657d9d 67
jksoft 0:76dfa9657d9d 68 // Negotiation failed, disconnect automatically if this has been configured
jksoft 0:76dfa9657d9d 69 if (m_conn_params_config.disconnect_on_fail)
jksoft 0:76dfa9657d9d 70 {
jksoft 0:76dfa9657d9d 71 uint32_t err_code;
jksoft 0:76dfa9657d9d 72
jksoft 0:76dfa9657d9d 73 err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
jksoft 0:76dfa9657d9d 74 if ((err_code != NRF_SUCCESS) && (m_conn_params_config.error_handler != NULL))
jksoft 0:76dfa9657d9d 75 {
jksoft 0:76dfa9657d9d 76 m_conn_params_config.error_handler(err_code);
jksoft 0:76dfa9657d9d 77 }
jksoft 0:76dfa9657d9d 78 }
jksoft 0:76dfa9657d9d 79
jksoft 0:76dfa9657d9d 80 // Notify the application that the procedure has failed
jksoft 0:76dfa9657d9d 81 if (m_conn_params_config.evt_handler != NULL)
jksoft 0:76dfa9657d9d 82 {
jksoft 0:76dfa9657d9d 83 ble_conn_params_evt_t evt;
jksoft 0:76dfa9657d9d 84
jksoft 0:76dfa9657d9d 85 evt.evt_type = BLE_CONN_PARAMS_EVT_FAILED;
jksoft 0:76dfa9657d9d 86 m_conn_params_config.evt_handler(&evt);
jksoft 0:76dfa9657d9d 87 }
jksoft 0:76dfa9657d9d 88 }
jksoft 0:76dfa9657d9d 89 }
jksoft 0:76dfa9657d9d 90 }
jksoft 0:76dfa9657d9d 91
jksoft 0:76dfa9657d9d 92
jksoft 0:76dfa9657d9d 93 uint32_t ble_conn_params_init(const ble_conn_params_init_t * p_init)
jksoft 0:76dfa9657d9d 94 {
jksoft 0:76dfa9657d9d 95 uint32_t err_code;
jksoft 0:76dfa9657d9d 96
jksoft 0:76dfa9657d9d 97 m_conn_params_config = *p_init;
jksoft 0:76dfa9657d9d 98 m_change_param = false;
jksoft 0:76dfa9657d9d 99 if (p_init->p_conn_params != NULL)
jksoft 0:76dfa9657d9d 100 {
jksoft 0:76dfa9657d9d 101 m_preferred_conn_params = *p_init->p_conn_params;
jksoft 0:76dfa9657d9d 102
jksoft 0:76dfa9657d9d 103 // Set the connection params in stack
jksoft 0:76dfa9657d9d 104 err_code = sd_ble_gap_ppcp_set(&m_preferred_conn_params);
jksoft 0:76dfa9657d9d 105 if (err_code != NRF_SUCCESS)
jksoft 0:76dfa9657d9d 106 {
jksoft 0:76dfa9657d9d 107 return err_code;
jksoft 0:76dfa9657d9d 108 }
jksoft 0:76dfa9657d9d 109 }
jksoft 0:76dfa9657d9d 110 else
jksoft 0:76dfa9657d9d 111 {
jksoft 0:76dfa9657d9d 112 // Fetch the connection params from stack
jksoft 0:76dfa9657d9d 113 err_code = sd_ble_gap_ppcp_get(&m_preferred_conn_params);
jksoft 0:76dfa9657d9d 114 if (err_code != NRF_SUCCESS)
jksoft 0:76dfa9657d9d 115 {
jksoft 0:76dfa9657d9d 116 return err_code;
jksoft 0:76dfa9657d9d 117 }
jksoft 0:76dfa9657d9d 118 }
jksoft 0:76dfa9657d9d 119
jksoft 0:76dfa9657d9d 120 m_conn_handle = BLE_CONN_HANDLE_INVALID;
jksoft 0:76dfa9657d9d 121 m_update_count = 0;
jksoft 0:76dfa9657d9d 122
jksoft 0:76dfa9657d9d 123 return app_timer_create(&m_conn_params_timer_id,
jksoft 0:76dfa9657d9d 124 APP_TIMER_MODE_SINGLE_SHOT,
jksoft 0:76dfa9657d9d 125 update_timeout_handler);
jksoft 0:76dfa9657d9d 126 }
jksoft 0:76dfa9657d9d 127
jksoft 0:76dfa9657d9d 128
jksoft 0:76dfa9657d9d 129 uint32_t ble_conn_params_stop(void)
jksoft 0:76dfa9657d9d 130 {
jksoft 0:76dfa9657d9d 131 return app_timer_stop(m_conn_params_timer_id);
jksoft 0:76dfa9657d9d 132 }
jksoft 0:76dfa9657d9d 133
jksoft 0:76dfa9657d9d 134
jksoft 0:76dfa9657d9d 135 static void conn_params_negotiation(void)
jksoft 0:76dfa9657d9d 136 {
jksoft 0:76dfa9657d9d 137 // Start negotiation if the received connection parameters are not acceptable
jksoft 0:76dfa9657d9d 138 if (!is_conn_params_ok(&m_current_conn_params))
jksoft 0:76dfa9657d9d 139 {
jksoft 0:76dfa9657d9d 140 uint32_t err_code;
jksoft 0:76dfa9657d9d 141 uint32_t timeout_ticks;
jksoft 0:76dfa9657d9d 142
jksoft 0:76dfa9657d9d 143 if (m_change_param)
jksoft 0:76dfa9657d9d 144 {
jksoft 0:76dfa9657d9d 145 // Notify the application that the procedure has failed
jksoft 0:76dfa9657d9d 146 if (m_conn_params_config.evt_handler != NULL)
jksoft 0:76dfa9657d9d 147 {
jksoft 0:76dfa9657d9d 148 ble_conn_params_evt_t evt;
jksoft 0:76dfa9657d9d 149
jksoft 0:76dfa9657d9d 150 evt.evt_type = BLE_CONN_PARAMS_EVT_FAILED;
jksoft 0:76dfa9657d9d 151 m_conn_params_config.evt_handler(&evt);
jksoft 0:76dfa9657d9d 152 }
jksoft 0:76dfa9657d9d 153 }
jksoft 0:76dfa9657d9d 154 else
jksoft 0:76dfa9657d9d 155 {
jksoft 0:76dfa9657d9d 156 if (m_update_count == 0)
jksoft 0:76dfa9657d9d 157 {
jksoft 0:76dfa9657d9d 158 // First connection parameter update
jksoft 0:76dfa9657d9d 159 timeout_ticks = m_conn_params_config.first_conn_params_update_delay;
jksoft 0:76dfa9657d9d 160 }
jksoft 0:76dfa9657d9d 161 else
jksoft 0:76dfa9657d9d 162 {
jksoft 0:76dfa9657d9d 163 timeout_ticks = m_conn_params_config.next_conn_params_update_delay;
jksoft 0:76dfa9657d9d 164 }
jksoft 0:76dfa9657d9d 165
jksoft 0:76dfa9657d9d 166 err_code = app_timer_start(m_conn_params_timer_id, timeout_ticks, NULL);
jksoft 0:76dfa9657d9d 167 if ((err_code != NRF_SUCCESS) && (m_conn_params_config.error_handler != NULL))
jksoft 0:76dfa9657d9d 168 {
jksoft 0:76dfa9657d9d 169 m_conn_params_config.error_handler(err_code);
jksoft 0:76dfa9657d9d 170 }
jksoft 0:76dfa9657d9d 171 }
jksoft 0:76dfa9657d9d 172 }
jksoft 0:76dfa9657d9d 173 else
jksoft 0:76dfa9657d9d 174 {
jksoft 0:76dfa9657d9d 175 // Notify the application that the procedure has succeded
jksoft 0:76dfa9657d9d 176 if (m_conn_params_config.evt_handler != NULL)
jksoft 0:76dfa9657d9d 177 {
jksoft 0:76dfa9657d9d 178 ble_conn_params_evt_t evt;
jksoft 0:76dfa9657d9d 179
jksoft 0:76dfa9657d9d 180 evt.evt_type = BLE_CONN_PARAMS_EVT_SUCCEEDED;
jksoft 0:76dfa9657d9d 181 m_conn_params_config.evt_handler(&evt);
jksoft 0:76dfa9657d9d 182 }
jksoft 0:76dfa9657d9d 183 }
jksoft 0:76dfa9657d9d 184 m_change_param = false;
jksoft 0:76dfa9657d9d 185 }
jksoft 0:76dfa9657d9d 186
jksoft 0:76dfa9657d9d 187
jksoft 0:76dfa9657d9d 188 static void on_connect(ble_evt_t * p_ble_evt)
jksoft 0:76dfa9657d9d 189 {
jksoft 0:76dfa9657d9d 190 // Save connection parameters
jksoft 0:76dfa9657d9d 191 m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
jksoft 0:76dfa9657d9d 192 m_current_conn_params = p_ble_evt->evt.gap_evt.params.connected.conn_params;
jksoft 0:76dfa9657d9d 193 m_update_count = 0; // Connection parameter negotiation should re-start every connection
jksoft 0:76dfa9657d9d 194
jksoft 0:76dfa9657d9d 195 // Check if we shall handle negotiation on connect
jksoft 0:76dfa9657d9d 196 if (m_conn_params_config.start_on_notify_cccd_handle == BLE_GATT_HANDLE_INVALID)
jksoft 0:76dfa9657d9d 197 {
jksoft 0:76dfa9657d9d 198 conn_params_negotiation();
jksoft 0:76dfa9657d9d 199 }
jksoft 0:76dfa9657d9d 200 }
jksoft 0:76dfa9657d9d 201
jksoft 0:76dfa9657d9d 202
jksoft 0:76dfa9657d9d 203 static void on_disconnect(ble_evt_t * p_ble_evt)
jksoft 0:76dfa9657d9d 204 {
jksoft 0:76dfa9657d9d 205 uint32_t err_code;
jksoft 0:76dfa9657d9d 206
jksoft 0:76dfa9657d9d 207 m_conn_handle = BLE_CONN_HANDLE_INVALID;
jksoft 0:76dfa9657d9d 208
jksoft 0:76dfa9657d9d 209 // Stop timer if running
jksoft 0:76dfa9657d9d 210 m_update_count = 0; // Connection parameters updates should happen during every connection
jksoft 0:76dfa9657d9d 211
jksoft 0:76dfa9657d9d 212 err_code = app_timer_stop(m_conn_params_timer_id);
jksoft 0:76dfa9657d9d 213 if ((err_code != NRF_SUCCESS) && (m_conn_params_config.error_handler != NULL))
jksoft 0:76dfa9657d9d 214 {
jksoft 0:76dfa9657d9d 215 m_conn_params_config.error_handler(err_code);
jksoft 0:76dfa9657d9d 216 }
jksoft 0:76dfa9657d9d 217 }
jksoft 0:76dfa9657d9d 218
jksoft 0:76dfa9657d9d 219
jksoft 0:76dfa9657d9d 220 static void on_write(ble_evt_t * p_ble_evt)
jksoft 0:76dfa9657d9d 221 {
jksoft 0:76dfa9657d9d 222 ble_gatts_evt_write_t * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
jksoft 0:76dfa9657d9d 223
jksoft 0:76dfa9657d9d 224 // Check if this the correct CCCD
jksoft 0:76dfa9657d9d 225 if (
jksoft 0:76dfa9657d9d 226 (p_evt_write->handle == m_conn_params_config.start_on_notify_cccd_handle)
jksoft 0:76dfa9657d9d 227 &&
jksoft 0:76dfa9657d9d 228 (p_evt_write->len == 2)
jksoft 0:76dfa9657d9d 229 )
jksoft 0:76dfa9657d9d 230 {
jksoft 0:76dfa9657d9d 231 // Check if this is a 'start notification'
jksoft 0:76dfa9657d9d 232 if (ble_srv_is_notification_enabled(p_evt_write->data))
jksoft 0:76dfa9657d9d 233 {
jksoft 0:76dfa9657d9d 234 // Do connection parameter negotiation if necessary
jksoft 0:76dfa9657d9d 235 conn_params_negotiation();
jksoft 0:76dfa9657d9d 236 }
jksoft 0:76dfa9657d9d 237 else
jksoft 0:76dfa9657d9d 238 {
jksoft 0:76dfa9657d9d 239 uint32_t err_code;
jksoft 0:76dfa9657d9d 240
jksoft 0:76dfa9657d9d 241 // Stop timer if running
jksoft 0:76dfa9657d9d 242 err_code = app_timer_stop(m_conn_params_timer_id);
jksoft 0:76dfa9657d9d 243 if ((err_code != NRF_SUCCESS) && (m_conn_params_config.error_handler != NULL))
jksoft 0:76dfa9657d9d 244 {
jksoft 0:76dfa9657d9d 245 m_conn_params_config.error_handler(err_code);
jksoft 0:76dfa9657d9d 246 }
jksoft 0:76dfa9657d9d 247 }
jksoft 0:76dfa9657d9d 248 }
jksoft 0:76dfa9657d9d 249 }
jksoft 0:76dfa9657d9d 250
jksoft 0:76dfa9657d9d 251
jksoft 0:76dfa9657d9d 252 static void on_conn_params_update(ble_evt_t * p_ble_evt)
jksoft 0:76dfa9657d9d 253 {
jksoft 0:76dfa9657d9d 254 // Copy the parameters
jksoft 0:76dfa9657d9d 255 m_current_conn_params = p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params;
jksoft 0:76dfa9657d9d 256
jksoft 0:76dfa9657d9d 257 conn_params_negotiation();
jksoft 0:76dfa9657d9d 258 }
jksoft 0:76dfa9657d9d 259
jksoft 0:76dfa9657d9d 260
jksoft 0:76dfa9657d9d 261 void ble_conn_params_on_ble_evt(ble_evt_t * p_ble_evt)
jksoft 0:76dfa9657d9d 262 {
jksoft 0:76dfa9657d9d 263 switch (p_ble_evt->header.evt_id)
jksoft 0:76dfa9657d9d 264 {
jksoft 0:76dfa9657d9d 265 case BLE_GAP_EVT_CONNECTED:
jksoft 0:76dfa9657d9d 266 on_connect(p_ble_evt);
jksoft 0:76dfa9657d9d 267 break;
jksoft 0:76dfa9657d9d 268
jksoft 0:76dfa9657d9d 269 case BLE_GAP_EVT_DISCONNECTED:
jksoft 0:76dfa9657d9d 270 on_disconnect(p_ble_evt);
jksoft 0:76dfa9657d9d 271 break;
jksoft 0:76dfa9657d9d 272
jksoft 0:76dfa9657d9d 273 case BLE_GATTS_EVT_WRITE:
jksoft 0:76dfa9657d9d 274 on_write(p_ble_evt);
jksoft 0:76dfa9657d9d 275 break;
jksoft 0:76dfa9657d9d 276
jksoft 0:76dfa9657d9d 277 case BLE_GAP_EVT_CONN_PARAM_UPDATE:
jksoft 0:76dfa9657d9d 278 on_conn_params_update(p_ble_evt);
jksoft 0:76dfa9657d9d 279 break;
jksoft 0:76dfa9657d9d 280
jksoft 0:76dfa9657d9d 281 default:
jksoft 0:76dfa9657d9d 282 // No implementation needed.
jksoft 0:76dfa9657d9d 283 break;
jksoft 0:76dfa9657d9d 284 }
jksoft 0:76dfa9657d9d 285 }
jksoft 0:76dfa9657d9d 286
jksoft 0:76dfa9657d9d 287 uint32_t ble_conn_params_change_conn_params(ble_gap_conn_params_t *new_params)
jksoft 0:76dfa9657d9d 288 {
jksoft 0:76dfa9657d9d 289 uint32_t err_code;
jksoft 0:76dfa9657d9d 290
jksoft 0:76dfa9657d9d 291 m_preferred_conn_params = *new_params;
jksoft 0:76dfa9657d9d 292 // Set the connection params in stack
jksoft 0:76dfa9657d9d 293 err_code = sd_ble_gap_ppcp_set(&m_preferred_conn_params);
jksoft 0:76dfa9657d9d 294 if (err_code == NRF_SUCCESS)
jksoft 0:76dfa9657d9d 295 {
jksoft 0:76dfa9657d9d 296 if (!is_conn_params_ok(&m_current_conn_params))
jksoft 0:76dfa9657d9d 297 {
jksoft 0:76dfa9657d9d 298 m_change_param = true;
jksoft 0:76dfa9657d9d 299 err_code = sd_ble_gap_conn_param_update(m_conn_handle, &m_preferred_conn_params);
jksoft 0:76dfa9657d9d 300 m_update_count = 1;
jksoft 0:76dfa9657d9d 301 }
jksoft 0:76dfa9657d9d 302 else
jksoft 0:76dfa9657d9d 303 {
jksoft 0:76dfa9657d9d 304 // Notify the application that the procedure has succeded
jksoft 0:76dfa9657d9d 305 if (m_conn_params_config.evt_handler != NULL)
jksoft 0:76dfa9657d9d 306 {
jksoft 0:76dfa9657d9d 307 ble_conn_params_evt_t evt;
jksoft 0:76dfa9657d9d 308
jksoft 0:76dfa9657d9d 309 evt.evt_type = BLE_CONN_PARAMS_EVT_SUCCEEDED;
jksoft 0:76dfa9657d9d 310 m_conn_params_config.evt_handler(&evt);
jksoft 0:76dfa9657d9d 311 }
jksoft 0:76dfa9657d9d 312 err_code = NRF_SUCCESS;
jksoft 0:76dfa9657d9d 313 }
jksoft 0:76dfa9657d9d 314 }
jksoft 0:76dfa9657d9d 315 return err_code;
jksoft 0:76dfa9657d9d 316 }