Cefn Hoile / nRF51822

Dependencies:   nrf51-sdk

Dependents:   microbit-dal

Fork of nRF51822 by Lancaster University

Committer:
rgrover1
Date:
Fri Jun 19 15:55:35 2015 +0100
Revision:
345:dfde56236c36
Parent:
343:6675661fa600
Child:
346:14b090482fd2
Synchronized with git rev fbfc6d16
Author: Andrew Fernandes
Fix various GCC compilation issues.

Who changed what in which revision?

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