Cefn Hoile / nRF51822

Dependencies:   nrf51-sdk

Dependents:   microbit-dal

Fork of nRF51822 by Lancaster University

Committer:
rgrover1
Date:
Thu Jul 02 09:08:44 2015 +0100
Revision:
361:d2405f5a4853
Parent:
346:14b090482fd2
Child:
362:6fa0d4d555f6
Synchronized with git rev 9f72c4ba
Author: Rohit Grover
Release 0.3.7
=============

This is a minor set of enhancements mostly around reduce our global static
memory footprint.

Enhancements
~~~~~~~~~~~~

* Reduce the maximum number of CHARACTERISTICS and DESCRIPTORS that can be
handled. This has memory implications for static global memory. It should
be possible to re-architect our solution for add_characteristic() to not
require these limits; hopefully we'll get there soon.

* Move nRF51GattServer::getInstance() into a .cpp file; same for nRF51Gap::getInstance().

* Reduce max bonds to managed by device-manager to 4; this has memory implications for static global memory.

* Reduce pStorage command queue size to 2; this has memory implications for static global memory.

* Replace uses of deprecated Gap::addr_type_t with Gap::AddressType_t.

* Some UUID-related types have moved into UUID class. Minor changes were needed to work around build errors.

Bugfixes
~~~~~~~~

* None.

Who changed what in which revision?

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