shunpei kataoka / nRF51822

Fork of nRF51822 by Shuta Nakamae

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