project for nrf51822 qfab

Dependencies:   eddystone_URL mbed

Fork of eddystone_URL by vo dung

Committer:
tridung141196
Date:
Thu Nov 23 15:38:48 2017 +0000
Revision:
5:267bdacf5508
Parent:
0:76dfa9657d9d
ibeacon

Who changed what in which revision?

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