Committer:
jinu
Date:
Thu Feb 09 06:08:17 2017 +0000
Revision:
0:6ba9b94b8997
NRF51 serialization libraries for mDot

Who changed what in which revision?

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