テスト用です。

Dependencies:   mbed

Committer:
jksoft
Date:
Tue Oct 11 11:09:42 2016 +0000
Revision:
0:8468a4403fea
SB??ver;

Who changed what in which revision?

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