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 nRF51822 by
ble_advdata.c
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 tx_power_level_encode(int8_t tx_power_level, 00126 uint8_t * p_encoded_data, 00127 uint8_t * p_len) 00128 { 00129 // Check for buffer overflow. 00130 if ((*p_len) + 3 > BLE_GAP_ADV_MAX_SIZE) 00131 { 00132 return NRF_ERROR_DATA_SIZE; 00133 } 00134 00135 // Encode TX Power Level. 00136 p_encoded_data[(*p_len)++] = 2; 00137 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_TX_POWER_LEVEL; 00138 p_encoded_data[(*p_len)++] = (uint8_t)tx_power_level; 00139 00140 return NRF_SUCCESS; 00141 } 00142 00143 00144 static uint32_t uuid_list_sized_encode(const ble_advdata_uuid_list_t * p_uuid_list, 00145 uint8_t adv_type, 00146 uint8_t uuid_size, 00147 uint8_t * p_encoded_data, 00148 uint8_t * p_len) 00149 { 00150 int i; 00151 bool is_heading_written = false; 00152 uint8_t start_pos = *p_len; 00153 00154 for (i = 0; i < p_uuid_list->uuid_cnt; i++) 00155 { 00156 uint32_t err_code; 00157 uint8_t encoded_size; 00158 ble_uuid_t uuid = p_uuid_list->p_uuids[i]; 00159 00160 // Find encoded uuid size. 00161 err_code = sd_ble_uuid_encode(&uuid, &encoded_size, NULL); 00162 if (err_code != NRF_SUCCESS) 00163 { 00164 return err_code; 00165 } 00166 00167 // Check size. 00168 if (encoded_size == uuid_size) 00169 { 00170 uint8_t heading_bytes = (is_heading_written) ? 0 : 2; 00171 00172 // Check for buffer overflow 00173 if (*p_len + encoded_size + heading_bytes > BLE_GAP_ADV_MAX_SIZE) 00174 { 00175 return NRF_ERROR_DATA_SIZE; 00176 } 00177 00178 if (!is_heading_written) 00179 { 00180 // Write AD structure heading. 00181 (*p_len)++; 00182 p_encoded_data[(*p_len)++] = adv_type; 00183 is_heading_written = true; 00184 } 00185 00186 // Write UUID. 00187 err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &p_encoded_data[*p_len]); 00188 if (err_code != NRF_SUCCESS) 00189 { 00190 return err_code; 00191 } 00192 (*p_len) += encoded_size; 00193 } 00194 } 00195 00196 if (is_heading_written) 00197 { 00198 // Write length. 00199 p_encoded_data[start_pos] = (*p_len) - (start_pos + 1); 00200 } 00201 00202 return NRF_SUCCESS; 00203 } 00204 00205 00206 static uint32_t uuid_list_encode(const ble_advdata_uuid_list_t * p_uuid_list, 00207 uint8_t adv_type_16, 00208 uint8_t adv_type_128, 00209 uint8_t * p_encoded_data, 00210 uint8_t * p_len) 00211 { 00212 uint32_t err_code; 00213 00214 // Encode 16 bit UUIDs. 00215 err_code = uuid_list_sized_encode(p_uuid_list, 00216 adv_type_16, 00217 sizeof(uint16_le_t), 00218 p_encoded_data, 00219 p_len); 00220 if (err_code != NRF_SUCCESS) 00221 { 00222 return err_code; 00223 } 00224 00225 // Encode 128 bit UUIDs. 00226 err_code = uuid_list_sized_encode(p_uuid_list, 00227 adv_type_128, 00228 sizeof(ble_uuid128_t), 00229 p_encoded_data, 00230 p_len); 00231 if (err_code != NRF_SUCCESS) 00232 { 00233 return err_code; 00234 } 00235 00236 return NRF_SUCCESS; 00237 } 00238 00239 00240 static uint32_t conn_int_check(const ble_advdata_conn_int_t *p_conn_int) 00241 { 00242 // Check Minimum Connection Interval. 00243 if ((p_conn_int->min_conn_interval < 0x0006) || 00244 ( 00245 (p_conn_int->min_conn_interval > 0x0c80) && 00246 (p_conn_int->min_conn_interval != 0xffff) 00247 ) 00248 ) 00249 { 00250 return NRF_ERROR_INVALID_PARAM; 00251 } 00252 00253 // Check Maximum Connection Interval. 00254 if ((p_conn_int->max_conn_interval < 0x0006) || 00255 ( 00256 (p_conn_int->max_conn_interval > 0x0c80) && 00257 (p_conn_int->max_conn_interval != 0xffff) 00258 ) 00259 ) 00260 { 00261 return NRF_ERROR_INVALID_PARAM; 00262 } 00263 00264 // Make sure Minimum Connection Interval is not bigger than Maximum Connection Interval. 00265 if ((p_conn_int->min_conn_interval != 0xffff) && 00266 (p_conn_int->max_conn_interval != 0xffff) && 00267 (p_conn_int->min_conn_interval > p_conn_int->max_conn_interval) 00268 ) 00269 { 00270 return NRF_ERROR_INVALID_PARAM; 00271 } 00272 00273 return NRF_SUCCESS; 00274 } 00275 00276 00277 static uint32_t conn_int_encode(const ble_advdata_conn_int_t * p_conn_int, 00278 uint8_t * p_encoded_data, 00279 uint8_t * p_len) 00280 { 00281 uint32_t err_code; 00282 00283 // Check for buffer overflow. 00284 if ((*p_len) + ADV_DATA_OFFSET + 2 * sizeof(uint16_le_t) > BLE_GAP_ADV_MAX_SIZE) 00285 { 00286 return NRF_ERROR_DATA_SIZE; 00287 } 00288 00289 // Check parameters. 00290 err_code = conn_int_check(p_conn_int); 00291 if (err_code != NRF_SUCCESS) 00292 { 00293 return err_code; 00294 } 00295 00296 // Encode Length and AD Type. 00297 p_encoded_data[(*p_len)++] = 1 + 2 * sizeof(uint16_le_t); 00298 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE; 00299 00300 // Encode Minimum and Maximum Connection Intervals. 00301 (*p_len) += uint16_encode(p_conn_int->min_conn_interval, &p_encoded_data[*p_len]); 00302 (*p_len) += uint16_encode(p_conn_int->max_conn_interval, &p_encoded_data[*p_len]); 00303 00304 return NRF_SUCCESS; 00305 } 00306 00307 00308 static uint32_t manuf_specific_data_encode(const ble_advdata_manuf_data_t * p_manuf_sp_data, 00309 uint8_t * p_encoded_data, 00310 uint8_t * p_len) 00311 { 00312 uint8_t data_size = sizeof(uint16_le_t) + p_manuf_sp_data->data.size; 00313 00314 // Check for buffer overflow. 00315 if ((*p_len) + ADV_DATA_OFFSET + data_size > BLE_GAP_ADV_MAX_SIZE) 00316 { 00317 return NRF_ERROR_DATA_SIZE; 00318 } 00319 00320 // Encode Length and AD Type. 00321 p_encoded_data[(*p_len)++] = 1 + data_size; 00322 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA; 00323 00324 // Encode Company Identifier. 00325 (*p_len) += uint16_encode(p_manuf_sp_data->company_identifier, &p_encoded_data[*p_len]); 00326 00327 // Encode additional manufacturer specific data. 00328 if (p_manuf_sp_data->data.size > 0) 00329 { 00330 if (p_manuf_sp_data->data.p_data == NULL) 00331 { 00332 return NRF_ERROR_INVALID_PARAM; 00333 } 00334 memcpy(&p_encoded_data[*p_len], p_manuf_sp_data->data.p_data, p_manuf_sp_data->data.size); 00335 (*p_len) += p_manuf_sp_data->data.size; 00336 } 00337 00338 return NRF_SUCCESS; 00339 } 00340 00341 00342 static uint32_t service_data_encode(const ble_advdata_t * p_advdata, 00343 uint8_t * p_encoded_data, 00344 uint8_t * p_len) 00345 { 00346 uint8_t i; 00347 00348 // Check parameter consistency. 00349 if (p_advdata->p_service_data_array == NULL) 00350 { 00351 return NRF_ERROR_INVALID_PARAM; 00352 } 00353 00354 for (i = 0; i < p_advdata->service_data_count; i++) 00355 { 00356 ble_advdata_service_data_t * p_service_data; 00357 uint8_t data_size; 00358 00359 p_service_data = &p_advdata->p_service_data_array[i]; 00360 data_size = sizeof(uint16_le_t) + p_service_data->data.size; 00361 00362 // Encode Length and AD Type. 00363 p_encoded_data[(*p_len)++] = 1 + data_size; 00364 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_SERVICE_DATA; 00365 00366 // Encode service UUID. 00367 (*p_len) += uint16_encode(p_service_data->service_uuid, &p_encoded_data[*p_len]); 00368 00369 // Encode additional service data. 00370 if (p_service_data->data.size > 0) 00371 { 00372 if (p_service_data->data.p_data == NULL) 00373 { 00374 return NRF_ERROR_INVALID_PARAM; 00375 } 00376 memcpy(&p_encoded_data[*p_len], p_service_data->data.p_data, p_service_data->data.size); 00377 (*p_len) += p_service_data->data.size; 00378 } 00379 } 00380 00381 return NRF_SUCCESS; 00382 } 00383 00384 00385 static uint32_t adv_data_encode(const ble_advdata_t * p_advdata, 00386 uint8_t * p_encoded_data, 00387 uint8_t * p_len) 00388 { 00389 uint32_t err_code = NRF_SUCCESS; 00390 00391 *p_len = 0; 00392 00393 // Encode name. 00394 if (p_advdata->name_type != BLE_ADVDATA_NO_NAME) 00395 { 00396 err_code = name_encode(p_advdata, p_encoded_data, p_len); 00397 if (err_code != NRF_SUCCESS) 00398 { 00399 return err_code; 00400 } 00401 } 00402 00403 // Encode appearance. 00404 if (p_advdata->include_appearance) 00405 { 00406 err_code = appearance_encode(p_encoded_data, p_len); 00407 if (err_code != NRF_SUCCESS) 00408 { 00409 return err_code; 00410 } 00411 } 00412 00413 if(p_advdata->flags != 0 ) 00414 { 00415 // Encode flags. 00416 p_encoded_data[(*p_len)++] = 1 + sizeof(uint8_t); 00417 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_FLAGS; 00418 p_encoded_data[(*p_len)++] = p_advdata->flags; 00419 } 00420 00421 // Encode TX power level. 00422 if (p_advdata->p_tx_power_level != NULL) 00423 { 00424 err_code = tx_power_level_encode(*p_advdata->p_tx_power_level, p_encoded_data, p_len); 00425 if (err_code != NRF_SUCCESS) 00426 { 00427 return err_code; 00428 } 00429 } 00430 00431 // Encode 'more available' uuid list. 00432 if (p_advdata->uuids_more_available.uuid_cnt > 0) 00433 { 00434 err_code = uuid_list_encode(&p_advdata->uuids_more_available, 00435 BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE, 00436 BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE, 00437 p_encoded_data, 00438 p_len); 00439 if (err_code != NRF_SUCCESS) 00440 { 00441 return err_code; 00442 } 00443 } 00444 00445 // Encode 'complete' uuid list. 00446 if (p_advdata->uuids_complete.uuid_cnt > 0) 00447 { 00448 err_code = uuid_list_encode(&p_advdata->uuids_complete, 00449 BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE, 00450 BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE, 00451 p_encoded_data, 00452 p_len); 00453 if (err_code != NRF_SUCCESS) 00454 { 00455 return err_code; 00456 } 00457 } 00458 00459 // Encode 'solicited service' uuid list. 00460 if (p_advdata->uuids_solicited.uuid_cnt > 0) 00461 { 00462 err_code = uuid_list_encode(&p_advdata->uuids_solicited, 00463 BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT, 00464 BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT, 00465 p_encoded_data, 00466 p_len); 00467 if (err_code != NRF_SUCCESS) 00468 { 00469 return err_code; 00470 } 00471 } 00472 00473 // Encode Slave Connection Interval Range. 00474 if (p_advdata->p_slave_conn_int != NULL) 00475 { 00476 err_code = conn_int_encode(p_advdata->p_slave_conn_int, p_encoded_data, p_len); 00477 if (err_code != NRF_SUCCESS) 00478 { 00479 return err_code; 00480 } 00481 } 00482 00483 // Encode Manufacturer Specific Data. 00484 if (p_advdata->p_manuf_specific_data != NULL) 00485 { 00486 err_code = manuf_specific_data_encode(p_advdata->p_manuf_specific_data, 00487 p_encoded_data, 00488 p_len); 00489 if (err_code != NRF_SUCCESS) 00490 { 00491 return err_code; 00492 } 00493 } 00494 00495 // Encode Service Data. 00496 if (p_advdata->service_data_count > 0) 00497 { 00498 err_code = service_data_encode(p_advdata, p_encoded_data, p_len); 00499 if (err_code != NRF_SUCCESS) 00500 { 00501 return err_code; 00502 } 00503 } 00504 00505 return err_code; 00506 } 00507 00508 00509 static uint32_t advdata_check(const ble_advdata_t * p_advdata) 00510 { 00511 // Flags must be included in advertising data, and the BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED flag must be set. 00512 if ( 00513 ((p_advdata->flags & BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) == 0) 00514 ) 00515 { 00516 return NRF_ERROR_INVALID_PARAM; 00517 } 00518 00519 return NRF_SUCCESS; 00520 } 00521 00522 00523 static uint32_t srdata_check(const ble_advdata_t * p_srdata) 00524 { 00525 // Flags shall not be included in the scan response data. 00526 if (p_srdata->flags) 00527 { 00528 return NRF_ERROR_INVALID_PARAM; 00529 } 00530 00531 return NRF_SUCCESS; 00532 } 00533 00534 00535 uint32_t ble_advdata_set(const ble_advdata_t * p_advdata, const ble_advdata_t * p_srdata) 00536 { 00537 uint32_t err_code; 00538 uint8_t len_advdata = 0; 00539 uint8_t len_srdata = 0; 00540 uint8_t encoded_advdata[BLE_GAP_ADV_MAX_SIZE]; 00541 uint8_t encoded_srdata[BLE_GAP_ADV_MAX_SIZE]; 00542 uint8_t * p_encoded_advdata; 00543 uint8_t * p_encoded_srdata; 00544 00545 // Encode advertising data (if supplied). 00546 if (p_advdata != NULL) 00547 { 00548 err_code = advdata_check(p_advdata); 00549 if (err_code != NRF_SUCCESS) 00550 { 00551 return err_code; 00552 } 00553 00554 err_code = adv_data_encode(p_advdata, encoded_advdata, &len_advdata); 00555 if (err_code != NRF_SUCCESS) 00556 { 00557 return err_code; 00558 } 00559 p_encoded_advdata = encoded_advdata; 00560 } 00561 else 00562 { 00563 p_encoded_advdata = NULL; 00564 } 00565 00566 // Encode scan response data (if supplied). 00567 if (p_srdata != NULL) 00568 { 00569 err_code = srdata_check(p_srdata); 00570 if (err_code != NRF_SUCCESS) 00571 { 00572 return err_code; 00573 } 00574 00575 err_code = adv_data_encode(p_srdata, encoded_srdata, &len_srdata); 00576 if (err_code != NRF_SUCCESS) 00577 { 00578 return err_code; 00579 } 00580 p_encoded_srdata = encoded_srdata; 00581 } 00582 else 00583 { 00584 p_encoded_srdata = NULL; 00585 } 00586 00587 // Pass encoded advertising data and/or scan response data to the stack. 00588 return sd_ble_gap_adv_data_set(p_encoded_advdata, len_advdata, p_encoded_srdata, len_srdata); 00589 }
Generated on Tue Jul 12 2022 19:22:46 by
1.7.2
