mediCAL's first BLE project

Dependents:   BLE_mediCAL

Fork of nRF51822 by Nordic Semiconductor

Committer:
bogdanm
Date:
Wed Mar 26 14:38:17 2014 +0000
Revision:
0:eff01767de02
Child:
65:98215c4f3a25
Initial import of the nRF51822 code

Who changed what in which revision?

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