bugfix for duplicate symbol

Fork of nRF51822 by Nordic Semiconductor

Committer:
rgrover1
Date:
Wed Apr 15 08:59:11 2015 +0100
Revision:
103:138bdc859cc9
Child:
112:737b08b3b995
Synchronized with git rev fa183c40
Author: Rohit Grover
updating to v7.1 of the Nordic SDK.
Re-organized file layout to match that from the SDK.

Who changed what in which revision?

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