BLE FOTA APP

Dependencies:   BLE_API mbed

It doesn't work with the default FOTA bootloader. It use NVIC_SystemReset() to enter a bootloader.

Committer:
yihui
Date:
Fri Oct 10 03:36:28 2014 +0000
Revision:
1:a607cd9655d7
use NVIC_SystemReset() to run bootloader

Who changed what in which revision?

UserRevisionLine numberNew contents of line
yihui 1:a607cd9655d7 1 /* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
yihui 1:a607cd9655d7 2 *
yihui 1:a607cd9655d7 3 * The information contained herein is property of Nordic Semiconductor ASA.
yihui 1:a607cd9655d7 4 * Terms and conditions of usage are described in detail in NORDIC
yihui 1:a607cd9655d7 5 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
yihui 1:a607cd9655d7 6 *
yihui 1:a607cd9655d7 7 * Licensees are granted free, non-transferable use of the information. NO
yihui 1:a607cd9655d7 8 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
yihui 1:a607cd9655d7 9 * the file.
yihui 1:a607cd9655d7 10 *
yihui 1:a607cd9655d7 11 */
yihui 1:a607cd9655d7 12
yihui 1:a607cd9655d7 13 #include "ble_advdata.h"
yihui 1:a607cd9655d7 14 #include "nordic_common.h"
yihui 1:a607cd9655d7 15 #include "nrf_error.h"
yihui 1:a607cd9655d7 16 #include "ble_gap.h"
yihui 1:a607cd9655d7 17 #include "ble_srv_common.h"
yihui 1:a607cd9655d7 18 #include "app_util.h"
yihui 1:a607cd9655d7 19
yihui 1:a607cd9655d7 20
yihui 1:a607cd9655d7 21 // Offset from where advertisement data other than flags information can start.
yihui 1:a607cd9655d7 22 #define ADV_FLAG_OFFSET 2
yihui 1:a607cd9655d7 23
yihui 1:a607cd9655d7 24 // Offset for Advertising Data.
yihui 1:a607cd9655d7 25 // Offset is 2 as each Advertising Data contain 1 octet of Adveritising Data Type and
yihui 1:a607cd9655d7 26 // one octet Advertising Data Length.
yihui 1:a607cd9655d7 27 #define ADV_DATA_OFFSET 2
yihui 1:a607cd9655d7 28
yihui 1:a607cd9655d7 29 // NOTE: For now, Security Manager TK Value and Security Manager Out of Band Flags (OOB) are omitted
yihui 1:a607cd9655d7 30 // from the advertising data.
yihui 1:a607cd9655d7 31
yihui 1:a607cd9655d7 32
yihui 1:a607cd9655d7 33 static uint32_t name_encode(const ble_advdata_t * p_advdata,
yihui 1:a607cd9655d7 34 uint8_t * p_encoded_data,
yihui 1:a607cd9655d7 35 uint8_t * p_len)
yihui 1:a607cd9655d7 36 {
yihui 1:a607cd9655d7 37 uint32_t err_code;
yihui 1:a607cd9655d7 38 uint16_t rem_adv_data_len;
yihui 1:a607cd9655d7 39 uint16_t actual_length;
yihui 1:a607cd9655d7 40 uint8_t adv_data_format;
yihui 1:a607cd9655d7 41 uint8_t adv_offset;
yihui 1:a607cd9655d7 42
yihui 1:a607cd9655d7 43 adv_offset = *p_len;
yihui 1:a607cd9655d7 44
yihui 1:a607cd9655d7 45
yihui 1:a607cd9655d7 46 // Check for buffer overflow.
yihui 1:a607cd9655d7 47 if ((adv_offset + ADV_DATA_OFFSET > BLE_GAP_ADV_MAX_SIZE) ||
yihui 1:a607cd9655d7 48 ((p_advdata->short_name_len + ADV_DATA_OFFSET) > BLE_GAP_ADV_MAX_SIZE))
yihui 1:a607cd9655d7 49 {
yihui 1:a607cd9655d7 50 return NRF_ERROR_DATA_SIZE;
yihui 1:a607cd9655d7 51 }
yihui 1:a607cd9655d7 52 actual_length = rem_adv_data_len = (BLE_GAP_ADV_MAX_SIZE - adv_offset - ADV_FLAG_OFFSET);
yihui 1:a607cd9655d7 53
yihui 1:a607cd9655d7 54 // Get GAP device name and length
yihui 1:a607cd9655d7 55 err_code = sd_ble_gap_device_name_get(&p_encoded_data[adv_offset + ADV_DATA_OFFSET],
yihui 1:a607cd9655d7 56 &actual_length);
yihui 1:a607cd9655d7 57 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 58 {
yihui 1:a607cd9655d7 59 return err_code;
yihui 1:a607cd9655d7 60 }
yihui 1:a607cd9655d7 61
yihui 1:a607cd9655d7 62 // Check if device internd to use short name and it can fit available data size.
yihui 1:a607cd9655d7 63 if ((p_advdata->name_type == BLE_ADVDATA_FULL_NAME) && (actual_length <= rem_adv_data_len))
yihui 1:a607cd9655d7 64 {
yihui 1:a607cd9655d7 65 // Complete device name can fit, setting Complete Name in Adv Data.
yihui 1:a607cd9655d7 66 adv_data_format = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME;
yihui 1:a607cd9655d7 67 rem_adv_data_len = actual_length;
yihui 1:a607cd9655d7 68 }
yihui 1:a607cd9655d7 69 else
yihui 1:a607cd9655d7 70 {
yihui 1:a607cd9655d7 71 // Else short name needs to be used. Or application has requested use of short name.
yihui 1:a607cd9655d7 72 adv_data_format = BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME;
yihui 1:a607cd9655d7 73
yihui 1:a607cd9655d7 74 // If application has set a preference on the short name size, it needs to be considered,
yihui 1:a607cd9655d7 75 // else fit what can be fit.
yihui 1:a607cd9655d7 76 if ((p_advdata->short_name_len != 0) && (p_advdata->short_name_len <= rem_adv_data_len))
yihui 1:a607cd9655d7 77 {
yihui 1:a607cd9655d7 78 // Short name fits available size.
yihui 1:a607cd9655d7 79 rem_adv_data_len = p_advdata->short_name_len;
yihui 1:a607cd9655d7 80 }
yihui 1:a607cd9655d7 81 // Else whatever can fit the data buffer will be packed.
yihui 1:a607cd9655d7 82 else
yihui 1:a607cd9655d7 83 {
yihui 1:a607cd9655d7 84 rem_adv_data_len = actual_length;
yihui 1:a607cd9655d7 85 }
yihui 1:a607cd9655d7 86 }
yihui 1:a607cd9655d7 87
yihui 1:a607cd9655d7 88 // Complete name field in encoded data.
yihui 1:a607cd9655d7 89 p_encoded_data[adv_offset++] = rem_adv_data_len + 1;
yihui 1:a607cd9655d7 90 p_encoded_data[adv_offset++] = adv_data_format;
yihui 1:a607cd9655d7 91 (*p_len) += (rem_adv_data_len + ADV_DATA_OFFSET);
yihui 1:a607cd9655d7 92
yihui 1:a607cd9655d7 93 return NRF_SUCCESS;
yihui 1:a607cd9655d7 94 }
yihui 1:a607cd9655d7 95
yihui 1:a607cd9655d7 96
yihui 1:a607cd9655d7 97 static uint32_t appearance_encode(uint8_t * p_encoded_data, uint8_t * p_len)
yihui 1:a607cd9655d7 98 {
yihui 1:a607cd9655d7 99 uint32_t err_code;
yihui 1:a607cd9655d7 100 uint16_t appearance;
yihui 1:a607cd9655d7 101
yihui 1:a607cd9655d7 102 // Check for buffer overflow.
yihui 1:a607cd9655d7 103 if ((*p_len) + 4 > BLE_GAP_ADV_MAX_SIZE)
yihui 1:a607cd9655d7 104 {
yihui 1:a607cd9655d7 105 return NRF_ERROR_DATA_SIZE;
yihui 1:a607cd9655d7 106 }
yihui 1:a607cd9655d7 107
yihui 1:a607cd9655d7 108 // Get GAP appearance field.
yihui 1:a607cd9655d7 109 err_code = sd_ble_gap_appearance_get(&appearance);
yihui 1:a607cd9655d7 110 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 111 {
yihui 1:a607cd9655d7 112 return err_code;
yihui 1:a607cd9655d7 113 }
yihui 1:a607cd9655d7 114
yihui 1:a607cd9655d7 115 // Encode Length, AD Type and Appearance.
yihui 1:a607cd9655d7 116 p_encoded_data[(*p_len)++] = 3;
yihui 1:a607cd9655d7 117 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_APPEARANCE;
yihui 1:a607cd9655d7 118
yihui 1:a607cd9655d7 119 (*p_len) += uint16_encode(appearance, &p_encoded_data[*p_len]);
yihui 1:a607cd9655d7 120
yihui 1:a607cd9655d7 121 return NRF_SUCCESS;
yihui 1:a607cd9655d7 122 }
yihui 1:a607cd9655d7 123
yihui 1:a607cd9655d7 124
yihui 1:a607cd9655d7 125 static uint32_t uint8_array_encode(const uint8_array_t * p_uint8_array,
yihui 1:a607cd9655d7 126 uint8_t adv_type,
yihui 1:a607cd9655d7 127 uint8_t * p_encoded_data,
yihui 1:a607cd9655d7 128 uint8_t * p_len)
yihui 1:a607cd9655d7 129 {
yihui 1:a607cd9655d7 130 // Check parameter consistency.
yihui 1:a607cd9655d7 131 if (p_uint8_array->p_data == NULL)
yihui 1:a607cd9655d7 132 {
yihui 1:a607cd9655d7 133 return NRF_ERROR_INVALID_PARAM;
yihui 1:a607cd9655d7 134 }
yihui 1:a607cd9655d7 135
yihui 1:a607cd9655d7 136 // Check for buffer overflow.
yihui 1:a607cd9655d7 137 if ((*p_len) + ADV_DATA_OFFSET + p_uint8_array->size > BLE_GAP_ADV_MAX_SIZE)
yihui 1:a607cd9655d7 138 {
yihui 1:a607cd9655d7 139 return NRF_ERROR_DATA_SIZE;
yihui 1:a607cd9655d7 140 }
yihui 1:a607cd9655d7 141
yihui 1:a607cd9655d7 142 // Encode Length and AD Type.
yihui 1:a607cd9655d7 143 p_encoded_data[(*p_len)++] = 1 + p_uint8_array->size;
yihui 1:a607cd9655d7 144 p_encoded_data[(*p_len)++] = adv_type;
yihui 1:a607cd9655d7 145
yihui 1:a607cd9655d7 146 // Encode array.
yihui 1:a607cd9655d7 147 memcpy(&p_encoded_data[*p_len], p_uint8_array->p_data, p_uint8_array->size);
yihui 1:a607cd9655d7 148 (*p_len) += p_uint8_array->size;
yihui 1:a607cd9655d7 149
yihui 1:a607cd9655d7 150 return NRF_SUCCESS;
yihui 1:a607cd9655d7 151 }
yihui 1:a607cd9655d7 152
yihui 1:a607cd9655d7 153
yihui 1:a607cd9655d7 154 static uint32_t tx_power_level_encode(int8_t tx_power_level,
yihui 1:a607cd9655d7 155 uint8_t * p_encoded_data,
yihui 1:a607cd9655d7 156 uint8_t * p_len)
yihui 1:a607cd9655d7 157 {
yihui 1:a607cd9655d7 158 // Check for buffer overflow.
yihui 1:a607cd9655d7 159 if ((*p_len) + 3 > BLE_GAP_ADV_MAX_SIZE)
yihui 1:a607cd9655d7 160 {
yihui 1:a607cd9655d7 161 return NRF_ERROR_DATA_SIZE;
yihui 1:a607cd9655d7 162 }
yihui 1:a607cd9655d7 163
yihui 1:a607cd9655d7 164 // Encode TX Power Level.
yihui 1:a607cd9655d7 165 p_encoded_data[(*p_len)++] = 2;
yihui 1:a607cd9655d7 166 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_TX_POWER_LEVEL;
yihui 1:a607cd9655d7 167 p_encoded_data[(*p_len)++] = (uint8_t)tx_power_level;
yihui 1:a607cd9655d7 168
yihui 1:a607cd9655d7 169 return NRF_SUCCESS;
yihui 1:a607cd9655d7 170 }
yihui 1:a607cd9655d7 171
yihui 1:a607cd9655d7 172
yihui 1:a607cd9655d7 173 static uint32_t uuid_list_sized_encode(const ble_advdata_uuid_list_t * p_uuid_list,
yihui 1:a607cd9655d7 174 uint8_t adv_type,
yihui 1:a607cd9655d7 175 uint8_t uuid_size,
yihui 1:a607cd9655d7 176 uint8_t * p_encoded_data,
yihui 1:a607cd9655d7 177 uint8_t * p_len)
yihui 1:a607cd9655d7 178 {
yihui 1:a607cd9655d7 179 int i;
yihui 1:a607cd9655d7 180 bool is_heading_written = false;
yihui 1:a607cd9655d7 181 uint8_t start_pos = *p_len;
yihui 1:a607cd9655d7 182
yihui 1:a607cd9655d7 183 for (i = 0; i < p_uuid_list->uuid_cnt; i++)
yihui 1:a607cd9655d7 184 {
yihui 1:a607cd9655d7 185 uint32_t err_code;
yihui 1:a607cd9655d7 186 uint8_t encoded_size;
yihui 1:a607cd9655d7 187 ble_uuid_t uuid = p_uuid_list->p_uuids[i];
yihui 1:a607cd9655d7 188
yihui 1:a607cd9655d7 189 // Find encoded uuid size.
yihui 1:a607cd9655d7 190 err_code = sd_ble_uuid_encode(&uuid, &encoded_size, NULL);
yihui 1:a607cd9655d7 191 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 192 {
yihui 1:a607cd9655d7 193 return err_code;
yihui 1:a607cd9655d7 194 }
yihui 1:a607cd9655d7 195
yihui 1:a607cd9655d7 196 // Check size.
yihui 1:a607cd9655d7 197 if (encoded_size == uuid_size)
yihui 1:a607cd9655d7 198 {
yihui 1:a607cd9655d7 199 uint8_t heading_bytes = (is_heading_written) ? 0 : 2;
yihui 1:a607cd9655d7 200
yihui 1:a607cd9655d7 201 // Check for buffer overflow
yihui 1:a607cd9655d7 202 if (*p_len + encoded_size + heading_bytes > BLE_GAP_ADV_MAX_SIZE)
yihui 1:a607cd9655d7 203 {
yihui 1:a607cd9655d7 204 return NRF_ERROR_DATA_SIZE;
yihui 1:a607cd9655d7 205 }
yihui 1:a607cd9655d7 206
yihui 1:a607cd9655d7 207 if (!is_heading_written)
yihui 1:a607cd9655d7 208 {
yihui 1:a607cd9655d7 209 // Write AD structure heading.
yihui 1:a607cd9655d7 210 (*p_len)++;
yihui 1:a607cd9655d7 211 p_encoded_data[(*p_len)++] = adv_type;
yihui 1:a607cd9655d7 212 is_heading_written = true;
yihui 1:a607cd9655d7 213 }
yihui 1:a607cd9655d7 214
yihui 1:a607cd9655d7 215 // Write UUID.
yihui 1:a607cd9655d7 216 err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &p_encoded_data[*p_len]);
yihui 1:a607cd9655d7 217 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 218 {
yihui 1:a607cd9655d7 219 return err_code;
yihui 1:a607cd9655d7 220 }
yihui 1:a607cd9655d7 221 (*p_len) += encoded_size;
yihui 1:a607cd9655d7 222 }
yihui 1:a607cd9655d7 223 }
yihui 1:a607cd9655d7 224
yihui 1:a607cd9655d7 225 if (is_heading_written)
yihui 1:a607cd9655d7 226 {
yihui 1:a607cd9655d7 227 // Write length.
yihui 1:a607cd9655d7 228 p_encoded_data[start_pos] = (*p_len) - (start_pos + 1);
yihui 1:a607cd9655d7 229 }
yihui 1:a607cd9655d7 230
yihui 1:a607cd9655d7 231 return NRF_SUCCESS;
yihui 1:a607cd9655d7 232 }
yihui 1:a607cd9655d7 233
yihui 1:a607cd9655d7 234
yihui 1:a607cd9655d7 235 static uint32_t uuid_list_encode(const ble_advdata_uuid_list_t * p_uuid_list,
yihui 1:a607cd9655d7 236 uint8_t adv_type_16,
yihui 1:a607cd9655d7 237 uint8_t adv_type_128,
yihui 1:a607cd9655d7 238 uint8_t * p_encoded_data,
yihui 1:a607cd9655d7 239 uint8_t * p_len)
yihui 1:a607cd9655d7 240 {
yihui 1:a607cd9655d7 241 uint32_t err_code;
yihui 1:a607cd9655d7 242
yihui 1:a607cd9655d7 243 // Encode 16 bit UUIDs.
yihui 1:a607cd9655d7 244 err_code = uuid_list_sized_encode(p_uuid_list,
yihui 1:a607cd9655d7 245 adv_type_16,
yihui 1:a607cd9655d7 246 sizeof(uint16_le_t),
yihui 1:a607cd9655d7 247 p_encoded_data,
yihui 1:a607cd9655d7 248 p_len);
yihui 1:a607cd9655d7 249 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 250 {
yihui 1:a607cd9655d7 251 return err_code;
yihui 1:a607cd9655d7 252 }
yihui 1:a607cd9655d7 253
yihui 1:a607cd9655d7 254 // Encode 128 bit UUIDs.
yihui 1:a607cd9655d7 255 err_code = uuid_list_sized_encode(p_uuid_list,
yihui 1:a607cd9655d7 256 adv_type_128,
yihui 1:a607cd9655d7 257 sizeof(ble_uuid128_t),
yihui 1:a607cd9655d7 258 p_encoded_data,
yihui 1:a607cd9655d7 259 p_len);
yihui 1:a607cd9655d7 260 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 261 {
yihui 1:a607cd9655d7 262 return err_code;
yihui 1:a607cd9655d7 263 }
yihui 1:a607cd9655d7 264
yihui 1:a607cd9655d7 265 return NRF_SUCCESS;
yihui 1:a607cd9655d7 266 }
yihui 1:a607cd9655d7 267
yihui 1:a607cd9655d7 268
yihui 1:a607cd9655d7 269 static uint32_t conn_int_check(const ble_advdata_conn_int_t *p_conn_int)
yihui 1:a607cd9655d7 270 {
yihui 1:a607cd9655d7 271 // Check Minimum Connection Interval.
yihui 1:a607cd9655d7 272 if ((p_conn_int->min_conn_interval < 0x0006) ||
yihui 1:a607cd9655d7 273 (
yihui 1:a607cd9655d7 274 (p_conn_int->min_conn_interval > 0x0c80) &&
yihui 1:a607cd9655d7 275 (p_conn_int->min_conn_interval != 0xffff)
yihui 1:a607cd9655d7 276 )
yihui 1:a607cd9655d7 277 )
yihui 1:a607cd9655d7 278 {
yihui 1:a607cd9655d7 279 return NRF_ERROR_INVALID_PARAM;
yihui 1:a607cd9655d7 280 }
yihui 1:a607cd9655d7 281
yihui 1:a607cd9655d7 282 // Check Maximum Connection Interval.
yihui 1:a607cd9655d7 283 if ((p_conn_int->max_conn_interval < 0x0006) ||
yihui 1:a607cd9655d7 284 (
yihui 1:a607cd9655d7 285 (p_conn_int->max_conn_interval > 0x0c80) &&
yihui 1:a607cd9655d7 286 (p_conn_int->max_conn_interval != 0xffff)
yihui 1:a607cd9655d7 287 )
yihui 1:a607cd9655d7 288 )
yihui 1:a607cd9655d7 289 {
yihui 1:a607cd9655d7 290 return NRF_ERROR_INVALID_PARAM;
yihui 1:a607cd9655d7 291 }
yihui 1:a607cd9655d7 292
yihui 1:a607cd9655d7 293 // Make sure Minimum Connection Interval is not bigger than Maximum Connection Interval.
yihui 1:a607cd9655d7 294 if ((p_conn_int->min_conn_interval != 0xffff) &&
yihui 1:a607cd9655d7 295 (p_conn_int->max_conn_interval != 0xffff) &&
yihui 1:a607cd9655d7 296 (p_conn_int->min_conn_interval > p_conn_int->max_conn_interval)
yihui 1:a607cd9655d7 297 )
yihui 1:a607cd9655d7 298 {
yihui 1:a607cd9655d7 299 return NRF_ERROR_INVALID_PARAM;
yihui 1:a607cd9655d7 300 }
yihui 1:a607cd9655d7 301
yihui 1:a607cd9655d7 302 return NRF_SUCCESS;
yihui 1:a607cd9655d7 303 }
yihui 1:a607cd9655d7 304
yihui 1:a607cd9655d7 305
yihui 1:a607cd9655d7 306 static uint32_t conn_int_encode(const ble_advdata_conn_int_t * p_conn_int,
yihui 1:a607cd9655d7 307 uint8_t * p_encoded_data,
yihui 1:a607cd9655d7 308 uint8_t * p_len)
yihui 1:a607cd9655d7 309 {
yihui 1:a607cd9655d7 310 uint32_t err_code;
yihui 1:a607cd9655d7 311
yihui 1:a607cd9655d7 312 // Check for buffer overflow.
yihui 1:a607cd9655d7 313 if ((*p_len) + ADV_DATA_OFFSET + 2 * sizeof(uint16_le_t) > BLE_GAP_ADV_MAX_SIZE)
yihui 1:a607cd9655d7 314 {
yihui 1:a607cd9655d7 315 return NRF_ERROR_DATA_SIZE;
yihui 1:a607cd9655d7 316 }
yihui 1:a607cd9655d7 317
yihui 1:a607cd9655d7 318 // Check parameters.
yihui 1:a607cd9655d7 319 err_code = conn_int_check(p_conn_int);
yihui 1:a607cd9655d7 320 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 321 {
yihui 1:a607cd9655d7 322 return err_code;
yihui 1:a607cd9655d7 323 }
yihui 1:a607cd9655d7 324
yihui 1:a607cd9655d7 325 // Encode Length and AD Type.
yihui 1:a607cd9655d7 326 p_encoded_data[(*p_len)++] = 1 + 2 * sizeof(uint16_le_t);
yihui 1:a607cd9655d7 327 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE;
yihui 1:a607cd9655d7 328
yihui 1:a607cd9655d7 329 // Encode Minimum and Maximum Connection Intervals.
yihui 1:a607cd9655d7 330 (*p_len) += uint16_encode(p_conn_int->min_conn_interval, &p_encoded_data[*p_len]);
yihui 1:a607cd9655d7 331 (*p_len) += uint16_encode(p_conn_int->max_conn_interval, &p_encoded_data[*p_len]);
yihui 1:a607cd9655d7 332
yihui 1:a607cd9655d7 333 return NRF_SUCCESS;
yihui 1:a607cd9655d7 334 }
yihui 1:a607cd9655d7 335
yihui 1:a607cd9655d7 336
yihui 1:a607cd9655d7 337 static uint32_t manuf_specific_data_encode(const ble_advdata_manuf_data_t * p_manuf_sp_data,
yihui 1:a607cd9655d7 338 uint8_t * p_encoded_data,
yihui 1:a607cd9655d7 339 uint8_t * p_len)
yihui 1:a607cd9655d7 340 {
yihui 1:a607cd9655d7 341 uint8_t data_size = sizeof(uint16_le_t) + p_manuf_sp_data->data.size;
yihui 1:a607cd9655d7 342
yihui 1:a607cd9655d7 343 // Check for buffer overflow.
yihui 1:a607cd9655d7 344 if ((*p_len) + ADV_DATA_OFFSET + data_size > BLE_GAP_ADV_MAX_SIZE)
yihui 1:a607cd9655d7 345 {
yihui 1:a607cd9655d7 346 return NRF_ERROR_DATA_SIZE;
yihui 1:a607cd9655d7 347 }
yihui 1:a607cd9655d7 348
yihui 1:a607cd9655d7 349 // Encode Length and AD Type.
yihui 1:a607cd9655d7 350 p_encoded_data[(*p_len)++] = 1 + data_size;
yihui 1:a607cd9655d7 351 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA;
yihui 1:a607cd9655d7 352
yihui 1:a607cd9655d7 353 // Encode Company Identifier.
yihui 1:a607cd9655d7 354 (*p_len) += uint16_encode(p_manuf_sp_data->company_identifier, &p_encoded_data[*p_len]);
yihui 1:a607cd9655d7 355
yihui 1:a607cd9655d7 356 // Encode additional manufacturer specific data.
yihui 1:a607cd9655d7 357 if (p_manuf_sp_data->data.size > 0)
yihui 1:a607cd9655d7 358 {
yihui 1:a607cd9655d7 359 if (p_manuf_sp_data->data.p_data == NULL)
yihui 1:a607cd9655d7 360 {
yihui 1:a607cd9655d7 361 return NRF_ERROR_INVALID_PARAM;
yihui 1:a607cd9655d7 362 }
yihui 1:a607cd9655d7 363 memcpy(&p_encoded_data[*p_len], p_manuf_sp_data->data.p_data, p_manuf_sp_data->data.size);
yihui 1:a607cd9655d7 364 (*p_len) += p_manuf_sp_data->data.size;
yihui 1:a607cd9655d7 365 }
yihui 1:a607cd9655d7 366
yihui 1:a607cd9655d7 367 return NRF_SUCCESS;
yihui 1:a607cd9655d7 368 }
yihui 1:a607cd9655d7 369
yihui 1:a607cd9655d7 370
yihui 1:a607cd9655d7 371 static uint32_t service_data_encode(const ble_advdata_t * p_advdata,
yihui 1:a607cd9655d7 372 uint8_t * p_encoded_data,
yihui 1:a607cd9655d7 373 uint8_t * p_len)
yihui 1:a607cd9655d7 374 {
yihui 1:a607cd9655d7 375 uint8_t i;
yihui 1:a607cd9655d7 376
yihui 1:a607cd9655d7 377 // Check parameter consistency.
yihui 1:a607cd9655d7 378 if (p_advdata->p_service_data_array == NULL)
yihui 1:a607cd9655d7 379 {
yihui 1:a607cd9655d7 380 return NRF_ERROR_INVALID_PARAM;
yihui 1:a607cd9655d7 381 }
yihui 1:a607cd9655d7 382
yihui 1:a607cd9655d7 383 for (i = 0; i < p_advdata->service_data_count; i++)
yihui 1:a607cd9655d7 384 {
yihui 1:a607cd9655d7 385 ble_advdata_service_data_t * p_service_data;
yihui 1:a607cd9655d7 386 uint8_t data_size;
yihui 1:a607cd9655d7 387
yihui 1:a607cd9655d7 388 p_service_data = &p_advdata->p_service_data_array[i];
yihui 1:a607cd9655d7 389 data_size = sizeof(uint16_le_t) + p_service_data->data.size;
yihui 1:a607cd9655d7 390
yihui 1:a607cd9655d7 391 // Encode Length and AD Type.
yihui 1:a607cd9655d7 392 p_encoded_data[(*p_len)++] = 1 + data_size;
yihui 1:a607cd9655d7 393 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_SERVICE_DATA;
yihui 1:a607cd9655d7 394
yihui 1:a607cd9655d7 395 // Encode service UUID.
yihui 1:a607cd9655d7 396 (*p_len) += uint16_encode(p_service_data->service_uuid, &p_encoded_data[*p_len]);
yihui 1:a607cd9655d7 397
yihui 1:a607cd9655d7 398 // Encode additional service data.
yihui 1:a607cd9655d7 399 if (p_service_data->data.size > 0)
yihui 1:a607cd9655d7 400 {
yihui 1:a607cd9655d7 401 if (p_service_data->data.p_data == NULL)
yihui 1:a607cd9655d7 402 {
yihui 1:a607cd9655d7 403 return NRF_ERROR_INVALID_PARAM;
yihui 1:a607cd9655d7 404 }
yihui 1:a607cd9655d7 405 memcpy(&p_encoded_data[*p_len], p_service_data->data.p_data, p_service_data->data.size);
yihui 1:a607cd9655d7 406 (*p_len) += p_service_data->data.size;
yihui 1:a607cd9655d7 407 }
yihui 1:a607cd9655d7 408 }
yihui 1:a607cd9655d7 409
yihui 1:a607cd9655d7 410 return NRF_SUCCESS;
yihui 1:a607cd9655d7 411 }
yihui 1:a607cd9655d7 412
yihui 1:a607cd9655d7 413
yihui 1:a607cd9655d7 414 static uint32_t adv_data_encode(const ble_advdata_t * p_advdata,
yihui 1:a607cd9655d7 415 uint8_t * p_encoded_data,
yihui 1:a607cd9655d7 416 uint8_t * p_len)
yihui 1:a607cd9655d7 417 {
yihui 1:a607cd9655d7 418 uint32_t err_code = NRF_SUCCESS;
yihui 1:a607cd9655d7 419
yihui 1:a607cd9655d7 420 *p_len = 0;
yihui 1:a607cd9655d7 421
yihui 1:a607cd9655d7 422 // Encode name.
yihui 1:a607cd9655d7 423 if (p_advdata->name_type != BLE_ADVDATA_NO_NAME)
yihui 1:a607cd9655d7 424 {
yihui 1:a607cd9655d7 425 err_code = name_encode(p_advdata, p_encoded_data, p_len);
yihui 1:a607cd9655d7 426 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 427 {
yihui 1:a607cd9655d7 428 return err_code;
yihui 1:a607cd9655d7 429 }
yihui 1:a607cd9655d7 430 }
yihui 1:a607cd9655d7 431
yihui 1:a607cd9655d7 432 // Encode appearance.
yihui 1:a607cd9655d7 433 if (p_advdata->include_appearance)
yihui 1:a607cd9655d7 434 {
yihui 1:a607cd9655d7 435 err_code = appearance_encode(p_encoded_data, p_len);
yihui 1:a607cd9655d7 436 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 437 {
yihui 1:a607cd9655d7 438 return err_code;
yihui 1:a607cd9655d7 439 }
yihui 1:a607cd9655d7 440 }
yihui 1:a607cd9655d7 441
yihui 1:a607cd9655d7 442 // Encode flags.
yihui 1:a607cd9655d7 443 if (p_advdata->flags.size > 0)
yihui 1:a607cd9655d7 444 {
yihui 1:a607cd9655d7 445 err_code = uint8_array_encode(&p_advdata->flags,
yihui 1:a607cd9655d7 446 BLE_GAP_AD_TYPE_FLAGS,
yihui 1:a607cd9655d7 447 p_encoded_data,
yihui 1:a607cd9655d7 448 p_len);
yihui 1:a607cd9655d7 449 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 450 {
yihui 1:a607cd9655d7 451 return err_code;
yihui 1:a607cd9655d7 452 }
yihui 1:a607cd9655d7 453 }
yihui 1:a607cd9655d7 454
yihui 1:a607cd9655d7 455 // Encode TX power level.
yihui 1:a607cd9655d7 456 if (p_advdata->p_tx_power_level != NULL)
yihui 1:a607cd9655d7 457 {
yihui 1:a607cd9655d7 458 err_code = tx_power_level_encode(*p_advdata->p_tx_power_level, p_encoded_data, p_len);
yihui 1:a607cd9655d7 459 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 460 {
yihui 1:a607cd9655d7 461 return err_code;
yihui 1:a607cd9655d7 462 }
yihui 1:a607cd9655d7 463 }
yihui 1:a607cd9655d7 464
yihui 1:a607cd9655d7 465 // Encode 'more available' uuid list.
yihui 1:a607cd9655d7 466 if (p_advdata->uuids_more_available.uuid_cnt > 0)
yihui 1:a607cd9655d7 467 {
yihui 1:a607cd9655d7 468 err_code = uuid_list_encode(&p_advdata->uuids_more_available,
yihui 1:a607cd9655d7 469 BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE,
yihui 1:a607cd9655d7 470 BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE,
yihui 1:a607cd9655d7 471 p_encoded_data,
yihui 1:a607cd9655d7 472 p_len);
yihui 1:a607cd9655d7 473 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 474 {
yihui 1:a607cd9655d7 475 return err_code;
yihui 1:a607cd9655d7 476 }
yihui 1:a607cd9655d7 477 }
yihui 1:a607cd9655d7 478
yihui 1:a607cd9655d7 479 // Encode 'complete' uuid list.
yihui 1:a607cd9655d7 480 if (p_advdata->uuids_complete.uuid_cnt > 0)
yihui 1:a607cd9655d7 481 {
yihui 1:a607cd9655d7 482 err_code = uuid_list_encode(&p_advdata->uuids_complete,
yihui 1:a607cd9655d7 483 BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE,
yihui 1:a607cd9655d7 484 BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE,
yihui 1:a607cd9655d7 485 p_encoded_data,
yihui 1:a607cd9655d7 486 p_len);
yihui 1:a607cd9655d7 487 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 488 {
yihui 1:a607cd9655d7 489 return err_code;
yihui 1:a607cd9655d7 490 }
yihui 1:a607cd9655d7 491 }
yihui 1:a607cd9655d7 492
yihui 1:a607cd9655d7 493 // Encode 'solicited service' uuid list.
yihui 1:a607cd9655d7 494 if (p_advdata->uuids_solicited.uuid_cnt > 0)
yihui 1:a607cd9655d7 495 {
yihui 1:a607cd9655d7 496 err_code = uuid_list_encode(&p_advdata->uuids_solicited,
yihui 1:a607cd9655d7 497 BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT,
yihui 1:a607cd9655d7 498 BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT,
yihui 1:a607cd9655d7 499 p_encoded_data,
yihui 1:a607cd9655d7 500 p_len);
yihui 1:a607cd9655d7 501 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 502 {
yihui 1:a607cd9655d7 503 return err_code;
yihui 1:a607cd9655d7 504 }
yihui 1:a607cd9655d7 505 }
yihui 1:a607cd9655d7 506
yihui 1:a607cd9655d7 507 // Encode Slave Connection Interval Range.
yihui 1:a607cd9655d7 508 if (p_advdata->p_slave_conn_int != NULL)
yihui 1:a607cd9655d7 509 {
yihui 1:a607cd9655d7 510 err_code = conn_int_encode(p_advdata->p_slave_conn_int, p_encoded_data, p_len);
yihui 1:a607cd9655d7 511 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 512 {
yihui 1:a607cd9655d7 513 return err_code;
yihui 1:a607cd9655d7 514 }
yihui 1:a607cd9655d7 515 }
yihui 1:a607cd9655d7 516
yihui 1:a607cd9655d7 517 // Encode Manufacturer Specific Data.
yihui 1:a607cd9655d7 518 if (p_advdata->p_manuf_specific_data != NULL)
yihui 1:a607cd9655d7 519 {
yihui 1:a607cd9655d7 520 err_code = manuf_specific_data_encode(p_advdata->p_manuf_specific_data,
yihui 1:a607cd9655d7 521 p_encoded_data,
yihui 1:a607cd9655d7 522 p_len);
yihui 1:a607cd9655d7 523 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 524 {
yihui 1:a607cd9655d7 525 return err_code;
yihui 1:a607cd9655d7 526 }
yihui 1:a607cd9655d7 527 }
yihui 1:a607cd9655d7 528
yihui 1:a607cd9655d7 529 // Encode Service Data.
yihui 1:a607cd9655d7 530 if (p_advdata->service_data_count > 0)
yihui 1:a607cd9655d7 531 {
yihui 1:a607cd9655d7 532 err_code = service_data_encode(p_advdata, p_encoded_data, p_len);
yihui 1:a607cd9655d7 533 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 534 {
yihui 1:a607cd9655d7 535 return err_code;
yihui 1:a607cd9655d7 536 }
yihui 1:a607cd9655d7 537 }
yihui 1:a607cd9655d7 538
yihui 1:a607cd9655d7 539 return err_code;
yihui 1:a607cd9655d7 540 }
yihui 1:a607cd9655d7 541
yihui 1:a607cd9655d7 542
yihui 1:a607cd9655d7 543 static uint32_t advdata_check(const ble_advdata_t * p_advdata)
yihui 1:a607cd9655d7 544 {
yihui 1:a607cd9655d7 545 // Flags must be included in advertising data, and the BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED flag must be set.
yihui 1:a607cd9655d7 546 if ((p_advdata->flags.size == 0) ||
yihui 1:a607cd9655d7 547 (p_advdata->flags.p_data == NULL) ||
yihui 1:a607cd9655d7 548 ((p_advdata->flags.p_data[0] & BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) == 0)
yihui 1:a607cd9655d7 549 )
yihui 1:a607cd9655d7 550 {
yihui 1:a607cd9655d7 551 return NRF_ERROR_INVALID_PARAM;
yihui 1:a607cd9655d7 552 }
yihui 1:a607cd9655d7 553
yihui 1:a607cd9655d7 554 return NRF_SUCCESS;
yihui 1:a607cd9655d7 555 }
yihui 1:a607cd9655d7 556
yihui 1:a607cd9655d7 557
yihui 1:a607cd9655d7 558 static uint32_t srdata_check(const ble_advdata_t * p_srdata)
yihui 1:a607cd9655d7 559 {
yihui 1:a607cd9655d7 560 // Flags shall not be included in the scan response data.
yihui 1:a607cd9655d7 561 if (p_srdata->flags.size > 0)
yihui 1:a607cd9655d7 562 {
yihui 1:a607cd9655d7 563 return NRF_ERROR_INVALID_PARAM;
yihui 1:a607cd9655d7 564 }
yihui 1:a607cd9655d7 565
yihui 1:a607cd9655d7 566 return NRF_SUCCESS;
yihui 1:a607cd9655d7 567 }
yihui 1:a607cd9655d7 568
yihui 1:a607cd9655d7 569
yihui 1:a607cd9655d7 570 uint32_t ble_advdata_set(const ble_advdata_t * p_advdata, const ble_advdata_t * p_srdata)
yihui 1:a607cd9655d7 571 {
yihui 1:a607cd9655d7 572 uint32_t err_code;
yihui 1:a607cd9655d7 573 uint8_t len_advdata = 0;
yihui 1:a607cd9655d7 574 uint8_t len_srdata = 0;
yihui 1:a607cd9655d7 575 uint8_t encoded_advdata[BLE_GAP_ADV_MAX_SIZE];
yihui 1:a607cd9655d7 576 uint8_t encoded_srdata[BLE_GAP_ADV_MAX_SIZE];
yihui 1:a607cd9655d7 577 uint8_t * p_encoded_advdata;
yihui 1:a607cd9655d7 578 uint8_t * p_encoded_srdata;
yihui 1:a607cd9655d7 579
yihui 1:a607cd9655d7 580 // Encode advertising data (if supplied).
yihui 1:a607cd9655d7 581 if (p_advdata != NULL)
yihui 1:a607cd9655d7 582 {
yihui 1:a607cd9655d7 583 err_code = advdata_check(p_advdata);
yihui 1:a607cd9655d7 584 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 585 {
yihui 1:a607cd9655d7 586 return err_code;
yihui 1:a607cd9655d7 587 }
yihui 1:a607cd9655d7 588
yihui 1:a607cd9655d7 589 err_code = adv_data_encode(p_advdata, encoded_advdata, &len_advdata);
yihui 1:a607cd9655d7 590 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 591 {
yihui 1:a607cd9655d7 592 return err_code;
yihui 1:a607cd9655d7 593 }
yihui 1:a607cd9655d7 594 p_encoded_advdata = encoded_advdata;
yihui 1:a607cd9655d7 595 }
yihui 1:a607cd9655d7 596 else
yihui 1:a607cd9655d7 597 {
yihui 1:a607cd9655d7 598 p_encoded_advdata = NULL;
yihui 1:a607cd9655d7 599 }
yihui 1:a607cd9655d7 600
yihui 1:a607cd9655d7 601 // Encode scan response data (if supplied).
yihui 1:a607cd9655d7 602 if (p_srdata != NULL)
yihui 1:a607cd9655d7 603 {
yihui 1:a607cd9655d7 604 err_code = srdata_check(p_srdata);
yihui 1:a607cd9655d7 605 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 606 {
yihui 1:a607cd9655d7 607 return err_code;
yihui 1:a607cd9655d7 608 }
yihui 1:a607cd9655d7 609
yihui 1:a607cd9655d7 610 err_code = adv_data_encode(p_srdata, encoded_srdata, &len_srdata);
yihui 1:a607cd9655d7 611 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 612 {
yihui 1:a607cd9655d7 613 return err_code;
yihui 1:a607cd9655d7 614 }
yihui 1:a607cd9655d7 615 p_encoded_srdata = encoded_srdata;
yihui 1:a607cd9655d7 616 }
yihui 1:a607cd9655d7 617 else
yihui 1:a607cd9655d7 618 {
yihui 1:a607cd9655d7 619 p_encoded_srdata = NULL;
yihui 1:a607cd9655d7 620 }
yihui 1:a607cd9655d7 621
yihui 1:a607cd9655d7 622 // Pass encoded advertising data and/or scan response data to the stack.
yihui 1:a607cd9655d7 623 return sd_ble_gap_adv_data_set(p_encoded_advdata, len_advdata, p_encoded_srdata, len_srdata);
yihui 1:a607cd9655d7 624 }