Cefn Hoile / nRF51822

Dependencies:   nrf51-sdk

Dependents:   microbit-dal

Fork of nRF51822 by Lancaster University

Committer:
rgrover1
Date:
Mon Jul 06 10:13:27 2015 +0100
Revision:
371:8f7d2137727a
Parent:
370:295f76db798e
Synchronized with git rev 2716309c
Author: Rohit Grover
Release 0.4.0
=============

This is a major release which introduces the GATT Client functionality. It
aligns with release 0.4.0 of BLE_API.

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

* Introduce GattClient. This includes functionality for service-discovery,
connections, and attribute-reads and writes. You'll find a demo program for
LEDBlinker on the mbed.org Bluetooth team page to use the new APIs. Some of
the GATT client functionality hasn't been implemented yet, but the APIs have
been added.

* We've added an implementation for the abstract base class for
SecurityManager. All security related APIs have been moved into that.

* There has been a major cleanup of APIs under BLE. APIs have now been
categorized as belonging to Gap, GattServer, GattClient, or SecurityManager.
There are accessors to get references for Gap, GattServer, GattClient, and
SecurityManager. A former call to ble.setAddress(...) is now expected to be
achieved with ble.gap().setAddress(...).

* We've cleaned up our APIs, and this has resulted in dropping some APIs like
BLE::reset().

* We've also dropped GattServer::initializeGattDatabase(). THis was added at
some point to support controllers where a commit point was needed to
indicate when the application had finished constructing the GATT database.
This API would get called internally before Gap::startAdvertising(). We now
expect the underlying port to do the equivalent of initializeGattDatabase()
implicitly upon Gap::startAdvertising().

* We've added a version of Gap::disconnect() which takes a connection handle.
The previous API (which did not take a connection handle) has been
deprecated; it will still work for situations where there's only a single
active connection. We hold on to that API to allow existing code to migrate
to the new API.

Bugfixes
~~~~~~~~

* None.

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 }