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