test

Fork of nRF51822 by Nordic Semiconductor

Committer:
GlimwormBeacons
Date:
Sat Oct 10 09:19:50 2015 +0000
Revision:
448:b71e96a821de
Parent:
387:b13ab9a7ddb9
test

Who changed what in which revision?

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