Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of LinkNode-Test by
ble_advdata.c
00001 /* 00002 * Copyright (c) Nordic Semiconductor ASA 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without modification, 00006 * are permitted provided that the following conditions are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright notice, this 00009 * list of conditions and the following disclaimer. 00010 * 00011 * 2. Redistributions in binary form must reproduce the above copyright notice, this 00012 * list of conditions and the following disclaimer in the documentation and/or 00013 * other materials provided with the distribution. 00014 * 00015 * 3. Neither the name of Nordic Semiconductor ASA nor the names of other 00016 * contributors to this software may be used to endorse or promote products 00017 * derived from this software without specific prior written permission. 00018 * 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00021 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00022 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00023 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00024 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00025 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00026 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 00027 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00029 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00030 * 00031 */ 00032 00033 #include "ble_advdata.h " 00034 #include "nordic_common.h" 00035 #include "nrf_error.h" 00036 #include "ble_gap.h" 00037 #include "ble_srv_common.h " 00038 #include "app_util.h" 00039 00040 00041 // Offset from where advertisement data other than flags information can start. 00042 #define ADV_FLAG_OFFSET 2 00043 00044 // Offset for Advertising Data. 00045 // Offset is 2 as each Advertising Data contain 1 octet of Adveritising Data Type and 00046 // one octet Advertising Data Length. 00047 #define ADV_DATA_OFFSET 2 00048 00049 // NOTE: For now, Security Manager TK Value and Security Manager Out of Band Flags (OOB) are omitted 00050 // from the advertising data. 00051 00052 00053 static uint32_t name_encode(const ble_advdata_t * p_advdata, 00054 uint8_t * p_encoded_data, 00055 uint8_t * p_len) 00056 { 00057 uint32_t err_code; 00058 uint16_t rem_adv_data_len; 00059 uint16_t actual_length; 00060 uint8_t adv_data_format; 00061 uint8_t adv_offset; 00062 00063 adv_offset = *p_len; 00064 00065 00066 // Check for buffer overflow. 00067 if ((adv_offset + ADV_DATA_OFFSET > BLE_GAP_ADV_MAX_SIZE) || 00068 ((p_advdata->short_name_len + ADV_DATA_OFFSET) > BLE_GAP_ADV_MAX_SIZE)) 00069 { 00070 return NRF_ERROR_DATA_SIZE; 00071 } 00072 actual_length = rem_adv_data_len = (BLE_GAP_ADV_MAX_SIZE - adv_offset - ADV_FLAG_OFFSET); 00073 00074 // Get GAP device name and length 00075 err_code = sd_ble_gap_device_name_get(&p_encoded_data[adv_offset + ADV_DATA_OFFSET], 00076 &actual_length); 00077 if (err_code != NRF_SUCCESS) 00078 { 00079 return err_code; 00080 } 00081 00082 // Check if device internd to use short name and it can fit available data size. 00083 if ((p_advdata->name_type == BLE_ADVDATA_FULL_NAME) && (actual_length <= rem_adv_data_len)) 00084 { 00085 // Complete device name can fit, setting Complete Name in Adv Data. 00086 adv_data_format = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME; 00087 rem_adv_data_len = actual_length; 00088 } 00089 else 00090 { 00091 // Else short name needs to be used. Or application has requested use of short name. 00092 adv_data_format = BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME; 00093 00094 // If application has set a preference on the short name size, it needs to be considered, 00095 // else fit what can be fit. 00096 if ((p_advdata->short_name_len != 0) && (p_advdata->short_name_len <= rem_adv_data_len)) 00097 { 00098 // Short name fits available size. 00099 rem_adv_data_len = p_advdata->short_name_len; 00100 } 00101 // Else whatever can fit the data buffer will be packed. 00102 else 00103 { 00104 rem_adv_data_len = actual_length; 00105 } 00106 } 00107 00108 // Complete name field in encoded data. 00109 p_encoded_data[adv_offset++] = rem_adv_data_len + 1; 00110 p_encoded_data[adv_offset++] = adv_data_format; 00111 (*p_len) += (rem_adv_data_len + ADV_DATA_OFFSET); 00112 00113 return NRF_SUCCESS; 00114 } 00115 00116 00117 static uint32_t appearance_encode(uint8_t * p_encoded_data, uint8_t * p_len) 00118 { 00119 uint32_t err_code; 00120 uint16_t appearance; 00121 00122 // Check for buffer overflow. 00123 if ((*p_len) + 4 > BLE_GAP_ADV_MAX_SIZE) 00124 { 00125 return NRF_ERROR_DATA_SIZE; 00126 } 00127 00128 // Get GAP appearance field. 00129 err_code = sd_ble_gap_appearance_get(&appearance); 00130 if (err_code != NRF_SUCCESS) 00131 { 00132 return err_code; 00133 } 00134 00135 // Encode Length, AD Type and Appearance. 00136 p_encoded_data[(*p_len)++] = 3; 00137 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_APPEARANCE; 00138 00139 (*p_len) += uint16_encode(appearance, &p_encoded_data[*p_len]); 00140 00141 return NRF_SUCCESS; 00142 } 00143 00144 00145 static uint32_t tx_power_level_encode(int8_t tx_power_level, 00146 uint8_t * p_encoded_data, 00147 uint8_t * p_len) 00148 { 00149 // Check for buffer overflow. 00150 if ((*p_len) + 3 > BLE_GAP_ADV_MAX_SIZE) 00151 { 00152 return NRF_ERROR_DATA_SIZE; 00153 } 00154 00155 // Encode TX Power Level. 00156 p_encoded_data[(*p_len)++] = 2; 00157 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_TX_POWER_LEVEL; 00158 p_encoded_data[(*p_len)++] = (uint8_t)tx_power_level; 00159 00160 return NRF_SUCCESS; 00161 } 00162 00163 00164 static uint32_t uuid_list_sized_encode(const ble_advdata_uuid_list_t * p_uuid_list, 00165 uint8_t adv_type, 00166 uint8_t uuid_size, 00167 uint8_t * p_encoded_data, 00168 uint8_t * p_len) 00169 { 00170 int i; 00171 bool is_heading_written = false; 00172 uint8_t start_pos = *p_len; 00173 00174 for (i = 0; i < p_uuid_list->uuid_cnt; i++) 00175 { 00176 uint32_t err_code; 00177 uint8_t encoded_size; 00178 ble_uuid_t uuid = p_uuid_list->p_uuids[i]; 00179 00180 // Find encoded uuid size. 00181 err_code = sd_ble_uuid_encode(&uuid, &encoded_size, NULL); 00182 if (err_code != NRF_SUCCESS) 00183 { 00184 return err_code; 00185 } 00186 00187 // Check size. 00188 if (encoded_size == uuid_size) 00189 { 00190 uint8_t heading_bytes = (is_heading_written) ? 0 : 2; 00191 00192 // Check for buffer overflow 00193 if (*p_len + encoded_size + heading_bytes > BLE_GAP_ADV_MAX_SIZE) 00194 { 00195 return NRF_ERROR_DATA_SIZE; 00196 } 00197 00198 if (!is_heading_written) 00199 { 00200 // Write AD structure heading. 00201 (*p_len)++; 00202 p_encoded_data[(*p_len)++] = adv_type; 00203 is_heading_written = true; 00204 } 00205 00206 // Write UUID. 00207 err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &p_encoded_data[*p_len]); 00208 if (err_code != NRF_SUCCESS) 00209 { 00210 return err_code; 00211 } 00212 (*p_len) += encoded_size; 00213 } 00214 } 00215 00216 if (is_heading_written) 00217 { 00218 // Write length. 00219 p_encoded_data[start_pos] = (*p_len) - (start_pos + 1); 00220 } 00221 00222 return NRF_SUCCESS; 00223 } 00224 00225 00226 static uint32_t uuid_list_encode(const ble_advdata_uuid_list_t * p_uuid_list, 00227 uint8_t adv_type_16, 00228 uint8_t adv_type_128, 00229 uint8_t * p_encoded_data, 00230 uint8_t * p_len) 00231 { 00232 uint32_t err_code; 00233 00234 // Encode 16 bit UUIDs. 00235 err_code = uuid_list_sized_encode(p_uuid_list, 00236 adv_type_16, 00237 sizeof(uint16_le_t), 00238 p_encoded_data, 00239 p_len); 00240 if (err_code != NRF_SUCCESS) 00241 { 00242 return err_code; 00243 } 00244 00245 // Encode 128 bit UUIDs. 00246 err_code = uuid_list_sized_encode(p_uuid_list, 00247 adv_type_128, 00248 sizeof(ble_uuid128_t), 00249 p_encoded_data, 00250 p_len); 00251 if (err_code != NRF_SUCCESS) 00252 { 00253 return err_code; 00254 } 00255 00256 return NRF_SUCCESS; 00257 } 00258 00259 00260 static uint32_t conn_int_check(const ble_advdata_conn_int_t *p_conn_int) 00261 { 00262 // Check Minimum Connection Interval. 00263 if ((p_conn_int->min_conn_interval < 0x0006) || 00264 ( 00265 (p_conn_int->min_conn_interval > 0x0c80) && 00266 (p_conn_int->min_conn_interval != 0xffff) 00267 ) 00268 ) 00269 { 00270 return NRF_ERROR_INVALID_PARAM; 00271 } 00272 00273 // Check Maximum Connection Interval. 00274 if ((p_conn_int->max_conn_interval < 0x0006) || 00275 ( 00276 (p_conn_int->max_conn_interval > 0x0c80) && 00277 (p_conn_int->max_conn_interval != 0xffff) 00278 ) 00279 ) 00280 { 00281 return NRF_ERROR_INVALID_PARAM; 00282 } 00283 00284 // Make sure Minimum Connection Interval is not bigger than Maximum Connection Interval. 00285 if ((p_conn_int->min_conn_interval != 0xffff) && 00286 (p_conn_int->max_conn_interval != 0xffff) && 00287 (p_conn_int->min_conn_interval > p_conn_int->max_conn_interval) 00288 ) 00289 { 00290 return NRF_ERROR_INVALID_PARAM; 00291 } 00292 00293 return NRF_SUCCESS; 00294 } 00295 00296 00297 static uint32_t conn_int_encode(const ble_advdata_conn_int_t * p_conn_int, 00298 uint8_t * p_encoded_data, 00299 uint8_t * p_len) 00300 { 00301 uint32_t err_code; 00302 00303 // Check for buffer overflow. 00304 if ((*p_len) + ADV_DATA_OFFSET + 2 * sizeof(uint16_le_t) > BLE_GAP_ADV_MAX_SIZE) 00305 { 00306 return NRF_ERROR_DATA_SIZE; 00307 } 00308 00309 // Check parameters. 00310 err_code = conn_int_check(p_conn_int); 00311 if (err_code != NRF_SUCCESS) 00312 { 00313 return err_code; 00314 } 00315 00316 // Encode Length and AD Type. 00317 p_encoded_data[(*p_len)++] = 1 + 2 * sizeof(uint16_le_t); 00318 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE; 00319 00320 // Encode Minimum and Maximum Connection Intervals. 00321 (*p_len) += uint16_encode(p_conn_int->min_conn_interval, &p_encoded_data[*p_len]); 00322 (*p_len) += uint16_encode(p_conn_int->max_conn_interval, &p_encoded_data[*p_len]); 00323 00324 return NRF_SUCCESS; 00325 } 00326 00327 00328 static uint32_t manuf_specific_data_encode(const ble_advdata_manuf_data_t * p_manuf_sp_data, 00329 uint8_t * p_encoded_data, 00330 uint8_t * p_len) 00331 { 00332 uint8_t data_size = sizeof(uint16_le_t) + p_manuf_sp_data->data.size; 00333 00334 // Check for buffer overflow. 00335 if ((*p_len) + ADV_DATA_OFFSET + data_size > BLE_GAP_ADV_MAX_SIZE) 00336 { 00337 return NRF_ERROR_DATA_SIZE; 00338 } 00339 00340 // Encode Length and AD Type. 00341 p_encoded_data[(*p_len)++] = 1 + data_size; 00342 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA; 00343 00344 // Encode Company Identifier. 00345 (*p_len) += uint16_encode(p_manuf_sp_data->company_identifier, &p_encoded_data[*p_len]); 00346 00347 // Encode additional manufacturer specific data. 00348 if (p_manuf_sp_data->data.size > 0) 00349 { 00350 if (p_manuf_sp_data->data.p_data == NULL) 00351 { 00352 return NRF_ERROR_INVALID_PARAM; 00353 } 00354 memcpy(&p_encoded_data[*p_len], p_manuf_sp_data->data.p_data, p_manuf_sp_data->data.size); 00355 (*p_len) += p_manuf_sp_data->data.size; 00356 } 00357 00358 return NRF_SUCCESS; 00359 } 00360 00361 00362 static uint32_t service_data_encode(const ble_advdata_t * p_advdata, 00363 uint8_t * p_encoded_data, 00364 uint8_t * p_len) 00365 { 00366 uint8_t i; 00367 00368 // Check parameter consistency. 00369 if (p_advdata->p_service_data_array == NULL) 00370 { 00371 return NRF_ERROR_INVALID_PARAM; 00372 } 00373 00374 for (i = 0; i < p_advdata->service_data_count; i++) 00375 { 00376 ble_advdata_service_data_t * p_service_data; 00377 uint8_t data_size; 00378 00379 p_service_data = &p_advdata->p_service_data_array[i]; 00380 data_size = sizeof(uint16_le_t) + p_service_data->data.size; 00381 00382 // Encode Length and AD Type. 00383 p_encoded_data[(*p_len)++] = 1 + data_size; 00384 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_SERVICE_DATA; 00385 00386 // Encode service UUID. 00387 (*p_len) += uint16_encode(p_service_data->service_uuid, &p_encoded_data[*p_len]); 00388 00389 // Encode additional service data. 00390 if (p_service_data->data.size > 0) 00391 { 00392 if (p_service_data->data.p_data == NULL) 00393 { 00394 return NRF_ERROR_INVALID_PARAM; 00395 } 00396 memcpy(&p_encoded_data[*p_len], p_service_data->data.p_data, p_service_data->data.size); 00397 (*p_len) += p_service_data->data.size; 00398 } 00399 } 00400 00401 return NRF_SUCCESS; 00402 } 00403 00404 00405 static uint32_t adv_data_encode(const ble_advdata_t * p_advdata, 00406 uint8_t * p_encoded_data, 00407 uint8_t * p_len) 00408 { 00409 uint32_t err_code = NRF_SUCCESS; 00410 00411 *p_len = 0; 00412 00413 // Encode name. 00414 if (p_advdata->name_type != BLE_ADVDATA_NO_NAME) 00415 { 00416 err_code = name_encode(p_advdata, p_encoded_data, p_len); 00417 if (err_code != NRF_SUCCESS) 00418 { 00419 return err_code; 00420 } 00421 } 00422 00423 // Encode appearance. 00424 if (p_advdata->include_appearance) 00425 { 00426 err_code = appearance_encode(p_encoded_data, p_len); 00427 if (err_code != NRF_SUCCESS) 00428 { 00429 return err_code; 00430 } 00431 } 00432 00433 if(p_advdata->flags != 0 ) 00434 { 00435 // Encode flags. 00436 p_encoded_data[(*p_len)++] = 1 + sizeof(uint8_t); 00437 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_FLAGS; 00438 p_encoded_data[(*p_len)++] = p_advdata->flags; 00439 } 00440 00441 // Encode TX power level. 00442 if (p_advdata->p_tx_power_level != NULL) 00443 { 00444 err_code = tx_power_level_encode(*p_advdata->p_tx_power_level, p_encoded_data, p_len); 00445 if (err_code != NRF_SUCCESS) 00446 { 00447 return err_code; 00448 } 00449 } 00450 00451 // Encode 'more available' uuid list. 00452 if (p_advdata->uuids_more_available.uuid_cnt > 0) 00453 { 00454 err_code = uuid_list_encode(&p_advdata->uuids_more_available, 00455 BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE, 00456 BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE, 00457 p_encoded_data, 00458 p_len); 00459 if (err_code != NRF_SUCCESS) 00460 { 00461 return err_code; 00462 } 00463 } 00464 00465 // Encode 'complete' uuid list. 00466 if (p_advdata->uuids_complete.uuid_cnt > 0) 00467 { 00468 err_code = uuid_list_encode(&p_advdata->uuids_complete, 00469 BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE, 00470 BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE, 00471 p_encoded_data, 00472 p_len); 00473 if (err_code != NRF_SUCCESS) 00474 { 00475 return err_code; 00476 } 00477 } 00478 00479 // Encode 'solicited service' uuid list. 00480 if (p_advdata->uuids_solicited.uuid_cnt > 0) 00481 { 00482 err_code = uuid_list_encode(&p_advdata->uuids_solicited, 00483 BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT, 00484 BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT, 00485 p_encoded_data, 00486 p_len); 00487 if (err_code != NRF_SUCCESS) 00488 { 00489 return err_code; 00490 } 00491 } 00492 00493 // Encode Slave Connection Interval Range. 00494 if (p_advdata->p_slave_conn_int != NULL) 00495 { 00496 err_code = conn_int_encode(p_advdata->p_slave_conn_int, p_encoded_data, p_len); 00497 if (err_code != NRF_SUCCESS) 00498 { 00499 return err_code; 00500 } 00501 } 00502 00503 // Encode Manufacturer Specific Data. 00504 if (p_advdata->p_manuf_specific_data != NULL) 00505 { 00506 err_code = manuf_specific_data_encode(p_advdata->p_manuf_specific_data, 00507 p_encoded_data, 00508 p_len); 00509 if (err_code != NRF_SUCCESS) 00510 { 00511 return err_code; 00512 } 00513 } 00514 00515 // Encode Service Data. 00516 if (p_advdata->service_data_count > 0) 00517 { 00518 err_code = service_data_encode(p_advdata, p_encoded_data, p_len); 00519 if (err_code != NRF_SUCCESS) 00520 { 00521 return err_code; 00522 } 00523 } 00524 00525 return err_code; 00526 } 00527 00528 00529 static uint32_t advdata_check(const ble_advdata_t * p_advdata) 00530 { 00531 // Flags must be included in advertising data, and the BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED flag must be set. 00532 if ( 00533 ((p_advdata->flags & BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) == 0) 00534 ) 00535 { 00536 return NRF_ERROR_INVALID_PARAM; 00537 } 00538 00539 return NRF_SUCCESS; 00540 } 00541 00542 00543 static uint32_t srdata_check(const ble_advdata_t * p_srdata) 00544 { 00545 // Flags shall not be included in the scan response data. 00546 if (p_srdata->flags) 00547 { 00548 return NRF_ERROR_INVALID_PARAM; 00549 } 00550 00551 return NRF_SUCCESS; 00552 } 00553 00554 00555 uint32_t ble_advdata_set(const ble_advdata_t * p_advdata, const ble_advdata_t * p_srdata) 00556 { 00557 uint32_t err_code; 00558 uint8_t len_advdata = 0; 00559 uint8_t len_srdata = 0; 00560 uint8_t encoded_advdata[BLE_GAP_ADV_MAX_SIZE]; 00561 uint8_t encoded_srdata[BLE_GAP_ADV_MAX_SIZE]; 00562 uint8_t * p_encoded_advdata; 00563 uint8_t * p_encoded_srdata; 00564 00565 // Encode advertising data (if supplied). 00566 if (p_advdata != NULL) 00567 { 00568 err_code = advdata_check(p_advdata); 00569 if (err_code != NRF_SUCCESS) 00570 { 00571 return err_code; 00572 } 00573 00574 err_code = adv_data_encode(p_advdata, encoded_advdata, &len_advdata); 00575 if (err_code != NRF_SUCCESS) 00576 { 00577 return err_code; 00578 } 00579 p_encoded_advdata = encoded_advdata; 00580 } 00581 else 00582 { 00583 p_encoded_advdata = NULL; 00584 } 00585 00586 // Encode scan response data (if supplied). 00587 if (p_srdata != NULL) 00588 { 00589 err_code = srdata_check(p_srdata); 00590 if (err_code != NRF_SUCCESS) 00591 { 00592 return err_code; 00593 } 00594 00595 err_code = adv_data_encode(p_srdata, encoded_srdata, &len_srdata); 00596 if (err_code != NRF_SUCCESS) 00597 { 00598 return err_code; 00599 } 00600 p_encoded_srdata = encoded_srdata; 00601 } 00602 else 00603 { 00604 p_encoded_srdata = NULL; 00605 } 00606 00607 // Pass encoded advertising data and/or scan response data to the stack. 00608 return sd_ble_gap_adv_data_set(p_encoded_advdata, len_advdata, p_encoded_srdata, len_srdata); 00609 }
Generated on Tue Jul 12 2022 16:00:19 by
