/** * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form, except as embedded into a Nordic * Semiconductor ASA integrated circuit in a product or a software update for * such product, must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. Neither the name of Nordic Semiconductor ASA nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 4. This software, with or without modification, must only be used with a * Nordic Semiconductor ASA integrated circuit. * * 5. Any software provided in binary form under this license must not be reverse * engineered, decompiled, modified and/or disassembled. * * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "sdk_common.h" #if NRF_MODULE_ENABLED(BLE_ADVERTISING) #include "ble_advdata.h" #include "ble_advertising.h" #include "nrf_soc.h" #include "nrf_log.h" #include "sdk_errors.h" #include "nrf_sdh_ble.h" #define BLE_ADV_MODES (5) /**< Total number of possible advertising modes. */ /**@brief Function for checking if the whitelist is in use. * * @param[in] p_advertising Advertising module instance. */ static bool whitelist_has_entries(ble_advertising_t * const p_advertising) { return p_advertising->whitelist_in_use; } /**@brief Function for checking if an address is valid. * * @param[in] p_addr Pointer to a bluetooth address. */ static bool addr_is_valid(uint8_t const * const p_addr) { for (uint32_t i = 0; i < BLE_GAP_ADDR_LEN; i++) { if (p_addr[i] != 0) { return true; } } return false; } /**@brief Function for checking the next advertising mode. * * @param[in] adv_mode Current advertising mode. */ static ble_adv_mode_t adv_mode_next_get(ble_adv_mode_t adv_mode) { return (ble_adv_mode_t)((adv_mode + 1) % BLE_ADV_MODES); } /**@brief Function for handling the Connected event. * * @param[in] p_ble_evt Event received from the BLE stack. */ static void on_connected(ble_advertising_t * const p_advertising, ble_evt_t const * p_ble_evt) { if (p_ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_PERIPH) { p_advertising->current_slave_link_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; } } /**@brief Function for handling the Disconnected event. * * @param[in] p_advertising Advertising module instance. * @param[in] p_ble_evt Event received from the BLE stack. */ static void on_disconnected(ble_advertising_t * const p_advertising, ble_evt_t const * p_ble_evt) { uint32_t ret; p_advertising->whitelist_temporarily_disabled = false; if (p_ble_evt->evt.gap_evt.conn_handle == p_advertising->current_slave_link_conn_handle && p_advertising->adv_modes_config.ble_adv_on_disconnect_disabled == false) { ret = ble_advertising_start(p_advertising, BLE_ADV_MODE_DIRECTED_HIGH_DUTY); if ((ret != NRF_SUCCESS) && (p_advertising->error_handler != NULL)) { p_advertising->error_handler(ret); } } } /**@brief Function for handling the Timeout event. * * @param[in] p_advertising Advertising module instance. * @param[in] p_ble_evt Event received from the BLE stack. */ static void on_terminated(ble_advertising_t * const p_advertising, ble_evt_t const * p_ble_evt) { ret_code_t ret; if (p_ble_evt->header.evt_id != BLE_GAP_EVT_ADV_SET_TERMINATED) { // Nothing to do. return; } if ( p_ble_evt->evt.gap_evt.params.adv_set_terminated.reason == BLE_GAP_EVT_ADV_SET_TERMINATED_REASON_TIMEOUT ||p_ble_evt->evt.gap_evt.params.adv_set_terminated.reason == BLE_GAP_EVT_ADV_SET_TERMINATED_REASON_LIMIT_REACHED) { // Start advertising in the next mode. ret = ble_advertising_start(p_advertising, adv_mode_next_get(p_advertising->adv_mode_current)); if ((ret != NRF_SUCCESS) && (p_advertising->error_handler != NULL)) { p_advertising->error_handler(ret); } } } /**@brief Get the next available advertising mode. * * @param[in] p_advertising Advertising module instance. * @param[in] adv_mode Requested advertising mode. * * @returns adv_mode if possible, or the best available mode if not. */ static ble_adv_mode_t adv_mode_next_avail_get(ble_advertising_t * const p_advertising, ble_adv_mode_t adv_mode) { bool peer_addr_is_valid = addr_is_valid(p_advertising->peer_address.addr); // If a mode is disabled, continue to the next mode. switch (adv_mode) { case BLE_ADV_MODE_DIRECTED_HIGH_DUTY: if ( (p_advertising->adv_modes_config.ble_adv_directed_high_duty_enabled) && (!p_advertising->adv_modes_config.ble_adv_extended_enabled) && (peer_addr_is_valid)) { return BLE_ADV_MODE_DIRECTED_HIGH_DUTY; } // Fallthrough. case BLE_ADV_MODE_DIRECTED: if ((p_advertising->adv_modes_config.ble_adv_directed_enabled) && peer_addr_is_valid) { return BLE_ADV_MODE_DIRECTED; } // Fallthrough. case BLE_ADV_MODE_FAST: if (p_advertising->adv_modes_config.ble_adv_fast_enabled) { return BLE_ADV_MODE_FAST; } // Fallthrough. case BLE_ADV_MODE_SLOW: if (p_advertising->adv_modes_config.ble_adv_slow_enabled) { return BLE_ADV_MODE_SLOW; } // Fallthrough. default: return BLE_ADV_MODE_IDLE; } } /**@brief Function for starting high duty directed advertising. * * @param[in] p_advertising Advertising instance. * @param[out] p_adv_params Advertising parameters. * * @return NRF_SUCCESS */ static ret_code_t set_adv_mode_directed_high_duty(ble_advertising_t * const p_advertising, ble_gap_adv_params_t * p_adv_params) { p_advertising->adv_evt = BLE_ADV_EVT_DIRECTED_HIGH_DUTY; p_advertising->p_adv_data = NULL; p_adv_params->p_peer_addr = &(p_advertising->peer_address); p_adv_params->interval = 0; p_adv_params->properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_NONSCANNABLE_DIRECTED_HIGH_DUTY_CYCLE; p_adv_params->duration = BLE_GAP_ADV_TIMEOUT_HIGH_DUTY_MAX; return NRF_SUCCESS; } /**@brief Function for starting directed slow advertising. * * @param[in] p_advertising Advertising module instance. * @param[out] p_adv_params Advertising parameters. * * @return NRF_SUCCESS */ static ret_code_t set_adv_mode_directed(ble_advertising_t * const p_advertising, ble_gap_adv_params_t * p_adv_params) { p_advertising->adv_evt = BLE_ADV_EVT_DIRECTED; #if !defined (S112) && !defined(S312) && !defined(S113) if (p_advertising->adv_modes_config.ble_adv_extended_enabled) { p_adv_params->properties.type = BLE_GAP_ADV_TYPE_EXTENDED_CONNECTABLE_NONSCANNABLE_DIRECTED; } else { #endif // !defined (S112) && !defined(S312) p_adv_params->properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_NONSCANNABLE_DIRECTED; #if !defined (S112) && !defined(S312) && !defined(S113) } #endif // !defined (S112) && !defined(S312) && !defined(S113) p_adv_params->duration = p_advertising->adv_modes_config.ble_adv_directed_timeout; p_advertising->p_adv_data = NULL; p_adv_params->p_peer_addr = &p_advertising->peer_address; p_adv_params->interval = p_advertising->adv_modes_config.ble_adv_directed_interval; return NRF_SUCCESS; } /**@brief Function for indicating whether to use whitelist for advertising. * * @param[in] p_advertising Advertising module instance. * * @return Whether to use whitelist. */ static bool use_whitelist(ble_advertising_t * const p_advertising) { return((p_advertising->adv_modes_config.ble_adv_whitelist_enabled) && (!p_advertising->whitelist_temporarily_disabled) && (whitelist_has_entries(p_advertising))); } /**@brief Function for setting new advertising flags in the advertising parameters. * * @param[in] p_advertising Advertising module instance. * @param[in] flags New flags. * * @return Any error from @ref sd_ble_gap_adv_set_configure. */ static ret_code_t flags_set(ble_advertising_t * const p_advertising, uint8_t flags) { uint8_t * p_flags = ble_advdata_parse(p_advertising->adv_data.adv_data.p_data, p_advertising->adv_data.adv_data.len, BLE_GAP_AD_TYPE_FLAGS); if (p_flags != NULL) { *p_flags = flags; } return sd_ble_gap_adv_set_configure(&p_advertising->adv_handle, &p_advertising->adv_data, &p_advertising->adv_params); } /**@brief Function for starting fast advertising. * * @param[in] p_advertising Advertising module instance. * @param[out] p_adv_params Advertising parameters. * * @return NRF_SUCCESS or an error from @ref flags_set(). */ static ret_code_t set_adv_mode_fast(ble_advertising_t * const p_advertising, ble_gap_adv_params_t * p_adv_params) { ret_code_t ret; p_adv_params->interval = p_advertising->adv_modes_config.ble_adv_fast_interval; p_adv_params->duration = p_advertising->adv_modes_config.ble_adv_fast_timeout; #if !defined (S112) && !defined(S312) && !defined(S113) if (p_advertising->adv_modes_config.ble_adv_extended_enabled) { p_advertising->adv_params.properties.type = BLE_GAP_ADV_TYPE_EXTENDED_CONNECTABLE_NONSCANNABLE_UNDIRECTED; } else { #endif // !defined (S112) && !defined(S312) && !defined(S113) p_advertising->adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED; #if !defined (S112) && !defined(S312) && !defined(S113) } #endif // !defined (S112) && !defined(S312) && !defined(S113) if (use_whitelist(p_advertising)) { p_adv_params->filter_policy = BLE_GAP_ADV_FP_FILTER_CONNREQ; // Set correct flags. ret = flags_set(p_advertising, BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED); VERIFY_SUCCESS(ret); p_advertising->adv_evt = BLE_ADV_EVT_FAST_WHITELIST; } else { p_advertising->adv_evt = BLE_ADV_EVT_FAST; } p_advertising->p_adv_data = &(p_advertising->adv_data); return NRF_SUCCESS; } /**@brief Function for starting slow advertising. * * @param[in] p_advertising Advertising module instance. * @param[out] p_adv_params Advertising parameters. * * @return NRF_SUCCESS or an error from @ref flags_set(). */ static ret_code_t set_adv_mode_slow(ble_advertising_t * const p_advertising, ble_gap_adv_params_t * p_adv_params) { ret_code_t ret; p_adv_params->interval = p_advertising->adv_modes_config.ble_adv_slow_interval; p_adv_params->duration = p_advertising->adv_modes_config.ble_adv_slow_timeout; #if !defined (S112) && !defined(S312) && !defined(S113) if (p_advertising->adv_modes_config.ble_adv_extended_enabled) { p_advertising->adv_params.properties.type = BLE_GAP_ADV_TYPE_EXTENDED_CONNECTABLE_NONSCANNABLE_UNDIRECTED; } else { #endif // !defined (S112) && !defined(S312) && !defined(S113) p_advertising->adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED; #if !defined (S112) && !defined(S312) && !defined(S113) } #endif // !defined (S112) && !defined(S312) && !defined(S113) if (use_whitelist(p_advertising)) { p_adv_params->filter_policy = BLE_GAP_ADV_FP_FILTER_CONNREQ; // Set correct flags. ret = flags_set(p_advertising, BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED); VERIFY_SUCCESS(ret); p_advertising->adv_evt = BLE_ADV_EVT_SLOW_WHITELIST; } else { p_advertising->adv_evt = BLE_ADV_EVT_SLOW; } p_advertising->p_adv_data = &(p_advertising->adv_data); return NRF_SUCCESS; } /**@brief Function for checking if an advertising module configuration is legal. * * @details Advertising module can not be initialized if high duty directed advertising is used * together with extended advertising. * * @param[in] p_config Pointer to the configuration. * * @return True If the configuration is valid. * @return False If the configuration is invalid. */ static bool config_is_valid(ble_adv_modes_config_t const * const p_config) { if ((p_config->ble_adv_directed_high_duty_enabled == true) && (p_config->ble_adv_extended_enabled == true)) { return false; } #if !defined (S140) else if ( p_config->ble_adv_primary_phy == BLE_GAP_PHY_CODED || p_config->ble_adv_secondary_phy == BLE_GAP_PHY_CODED) { return false; } #endif // !defined (S140) else { return true; } } /**@brief Function for getting the maximum size of the advertising data buffer. * * @param[in] p_advertising Advertising module instance. * * @returns The maximum size of the advertising data buffer. */ static uint16_t adv_set_data_size_max_get(ble_advertising_t const * const p_advertising) { uint16_t adv_set_data_size_max; if (p_advertising->adv_modes_config.ble_adv_extended_enabled == true) { #ifdef BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_CONNECTABLE_MAX_SUPPORTED adv_set_data_size_max = BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_CONNECTABLE_MAX_SUPPORTED; #else adv_set_data_size_max = BLE_GAP_ADV_SET_DATA_SIZE_MAX; #endif // BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_CONNECTABLE_MAX_SUPPORTED } else { adv_set_data_size_max = BLE_GAP_ADV_SET_DATA_SIZE_MAX; } return adv_set_data_size_max; } void ble_advertising_conn_cfg_tag_set(ble_advertising_t * const p_advertising, uint8_t ble_cfg_tag) { p_advertising->conn_cfg_tag = ble_cfg_tag; } uint32_t ble_advertising_init(ble_advertising_t * const p_advertising, ble_advertising_init_t const * const p_init) { uint32_t ret; if ((p_init == NULL) || (p_advertising == NULL)) { return NRF_ERROR_NULL; } if (!config_is_valid(&p_init->config)) { return NRF_ERROR_INVALID_PARAM; } p_advertising->adv_mode_current = BLE_ADV_MODE_IDLE; p_advertising->adv_modes_config = p_init->config; p_advertising->conn_cfg_tag = BLE_CONN_CFG_TAG_DEFAULT; p_advertising->evt_handler = p_init->evt_handler; p_advertising->error_handler = p_init->error_handler; p_advertising->current_slave_link_conn_handle = BLE_CONN_HANDLE_INVALID; p_advertising->p_adv_data = &p_advertising->adv_data; memset(&p_advertising->peer_address, 0, sizeof(p_advertising->peer_address)); // Copy advertising data. if (!p_advertising->initialized) { p_advertising->adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; } p_advertising->adv_data.adv_data.p_data = p_advertising->enc_advdata[0]; p_advertising->adv_data.adv_data.len = adv_set_data_size_max_get(p_advertising); ret = ble_advdata_encode(&p_init->advdata, p_advertising->enc_advdata[0], &p_advertising->adv_data.adv_data.len); VERIFY_SUCCESS(ret); p_advertising->adv_data.scan_rsp_data.p_data = p_advertising->enc_scan_rsp_data[0]; p_advertising->adv_data.scan_rsp_data.len = adv_set_data_size_max_get(p_advertising); ret = ble_advdata_encode(&p_init->srdata, p_advertising->adv_data.scan_rsp_data.p_data, &p_advertising->adv_data.scan_rsp_data.len); VERIFY_SUCCESS(ret); // Configure a initial advertising configuration. The advertising data and and advertising // parameters will be changed later when we call @ref ble_advertising_start, but must be set // to legal values here to define an advertising handle. p_advertising->adv_params.primary_phy = BLE_GAP_PHY_1MBPS; p_advertising->adv_params.duration = p_advertising->adv_modes_config.ble_adv_fast_timeout; p_advertising->adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED; p_advertising->adv_params.p_peer_addr = NULL; p_advertising->adv_params.filter_policy = BLE_GAP_ADV_FP_ANY; p_advertising->adv_params.interval = p_advertising->adv_modes_config.ble_adv_fast_interval; ret = sd_ble_gap_adv_set_configure(&p_advertising->adv_handle, NULL, &p_advertising->adv_params); VERIFY_SUCCESS(ret); p_advertising->initialized = true; return ret; } /**@brief Function for checking that a phy define value matches one of the valid phys from the SD. * * @param[in] PHY to be validated. * * @retval true If the PHY value is valid (1mbit, 2mbit, coded). * @retval false If the PHY value is invalid. */ static bool phy_is_valid(uint32_t const * const p_phy) { if ((*p_phy) == BLE_GAP_PHY_1MBPS || (*p_phy) == BLE_GAP_PHY_2MBPS #if defined (S140) || (*p_phy) == BLE_GAP_PHY_CODED #endif // !defined (S140) ) { return true; } else { return false; } } uint32_t ble_advertising_start(ble_advertising_t * const p_advertising, ble_adv_mode_t advertising_mode) { uint32_t ret; if (p_advertising->initialized == false) { return NRF_ERROR_INVALID_STATE; } p_advertising->adv_mode_current = advertising_mode; memset(&p_advertising->peer_address, 0, sizeof(p_advertising->peer_address)); if ( ((p_advertising->adv_modes_config.ble_adv_directed_high_duty_enabled) && (p_advertising->adv_mode_current == BLE_ADV_MODE_DIRECTED_HIGH_DUTY)) ||((p_advertising->adv_modes_config.ble_adv_directed_enabled) && (p_advertising->adv_mode_current == BLE_ADV_MODE_DIRECTED_HIGH_DUTY)) ||((p_advertising->adv_modes_config.ble_adv_directed_enabled) && (p_advertising->adv_mode_current == BLE_ADV_MODE_DIRECTED)) ) { if (p_advertising->evt_handler != NULL) { p_advertising->peer_addr_reply_expected = true; p_advertising->evt_handler(BLE_ADV_EVT_PEER_ADDR_REQUEST); } else { p_advertising->peer_addr_reply_expected = false; } } p_advertising->adv_mode_current = adv_mode_next_avail_get(p_advertising, advertising_mode); // Fetch the whitelist. if ((p_advertising->evt_handler != NULL) && (p_advertising->adv_mode_current == BLE_ADV_MODE_FAST || p_advertising->adv_mode_current == BLE_ADV_MODE_SLOW) && (p_advertising->adv_modes_config.ble_adv_whitelist_enabled) && (!p_advertising->whitelist_temporarily_disabled)) { p_advertising->whitelist_in_use = false; p_advertising->whitelist_reply_expected = true; p_advertising->evt_handler(BLE_ADV_EVT_WHITELIST_REQUEST); } else { p_advertising->whitelist_reply_expected = false; } // Initialize advertising parameters with default values. memset(&p_advertising->adv_params, 0, sizeof(p_advertising->adv_params)); p_advertising->adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED; // Use 1MBIT as primary phy if no phy was selected. if (phy_is_valid(&p_advertising->adv_modes_config.ble_adv_primary_phy)) { p_advertising->adv_params.primary_phy = p_advertising->adv_modes_config.ble_adv_primary_phy; } else { p_advertising->adv_params.primary_phy = BLE_GAP_PHY_1MBPS; } if (p_advertising->adv_modes_config.ble_adv_extended_enabled) { // Use 1MBIT as secondary phy if no phy was selected. if (phy_is_valid(&p_advertising->adv_modes_config.ble_adv_secondary_phy)) { p_advertising->adv_params.secondary_phy = p_advertising->adv_modes_config.ble_adv_secondary_phy; } else { p_advertising->adv_params.secondary_phy = BLE_GAP_PHY_1MBPS; } } p_advertising->adv_params.filter_policy = BLE_GAP_ADV_FP_ANY; // Set advertising parameters and events according to selected advertising mode. switch (p_advertising->adv_mode_current) { case BLE_ADV_MODE_DIRECTED_HIGH_DUTY: ret = set_adv_mode_directed_high_duty(p_advertising, &p_advertising->adv_params); break; case BLE_ADV_MODE_DIRECTED: ret = set_adv_mode_directed(p_advertising, &p_advertising->adv_params); break; case BLE_ADV_MODE_FAST: ret = set_adv_mode_fast(p_advertising, &p_advertising->adv_params); break; case BLE_ADV_MODE_SLOW: ret = set_adv_mode_slow(p_advertising, &p_advertising->adv_params); break; case BLE_ADV_MODE_IDLE: p_advertising->adv_evt = BLE_ADV_EVT_IDLE; break; default: break; } if (p_advertising->adv_mode_current != BLE_ADV_MODE_IDLE) { ret = sd_ble_gap_adv_set_configure(&p_advertising->adv_handle, p_advertising->p_adv_data, &p_advertising->adv_params); if (ret != NRF_SUCCESS) { return ret; } ret = sd_ble_gap_adv_start(p_advertising->adv_handle, p_advertising->conn_cfg_tag); if (ret != NRF_SUCCESS) { return ret; } } if (p_advertising->evt_handler != NULL) { p_advertising->evt_handler(p_advertising->adv_evt); } return NRF_SUCCESS; } void ble_advertising_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) { ble_advertising_t * p_advertising = (ble_advertising_t *)p_context; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: on_connected(p_advertising, p_ble_evt); break; // Upon disconnection, whitelist will be activated and direct advertising is started. case BLE_GAP_EVT_DISCONNECTED: on_disconnected(p_advertising, p_ble_evt); break; // Upon terminated advertising (time-out), the next advertising mode is started. case BLE_GAP_EVT_ADV_SET_TERMINATED: on_terminated(p_advertising, p_ble_evt); break; default: break; } } uint32_t ble_advertising_peer_addr_reply(ble_advertising_t * const p_advertising, ble_gap_addr_t * p_peer_address) { if (!p_advertising->peer_addr_reply_expected) { return NRF_ERROR_INVALID_STATE; } p_advertising->peer_addr_reply_expected = false; memcpy(&p_advertising->peer_address, p_peer_address, sizeof(p_advertising->peer_address)); return NRF_SUCCESS; } uint32_t ble_advertising_whitelist_reply(ble_advertising_t * const p_advertising, ble_gap_addr_t const * p_gap_addrs, uint32_t addr_cnt, ble_gap_irk_t const * p_gap_irks, uint32_t irk_cnt) { if (!p_advertising->whitelist_reply_expected) { return NRF_ERROR_INVALID_STATE; } p_advertising->whitelist_reply_expected = false; p_advertising->whitelist_in_use = ((addr_cnt > 0) || (irk_cnt > 0)); return NRF_SUCCESS; } uint32_t ble_advertising_restart_without_whitelist(ble_advertising_t * const p_advertising) { ret_code_t ret; (void) sd_ble_gap_adv_stop(p_advertising->adv_handle); p_advertising->whitelist_temporarily_disabled = true; p_advertising->whitelist_in_use = false; p_advertising->adv_params.filter_policy = BLE_GAP_ADV_FP_ANY; // Set correct flags. ret = flags_set(p_advertising, BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE); VERIFY_SUCCESS(ret); ret = ble_advertising_start(p_advertising, p_advertising->adv_mode_current); if ((ret != NRF_SUCCESS) && (p_advertising->error_handler != NULL)) { p_advertising->error_handler(ret); } return NRF_SUCCESS; } void ble_advertising_modes_config_set(ble_advertising_t * const p_advertising, ble_adv_modes_config_t const * const p_adv_modes_config) { p_advertising->adv_modes_config = *p_adv_modes_config; } ret_code_t ble_advertising_advdata_update(ble_advertising_t * const p_advertising, ble_advdata_t const * const p_advdata, ble_advdata_t const * const p_srdata) { VERIFY_PARAM_NOT_NULL(p_advertising); if (p_advertising->initialized == false) { return NRF_ERROR_INVALID_STATE; } if ((p_advdata == NULL) && (p_srdata == NULL)) { return NRF_ERROR_NULL; } ble_gap_adv_data_t new_adv_data; memset(&new_adv_data, 0, sizeof(new_adv_data)); if (p_advdata != NULL) { new_adv_data.adv_data.p_data = (p_advertising->p_adv_data->adv_data.p_data != p_advertising->enc_advdata[0]) ? p_advertising->enc_advdata[0] : p_advertising->enc_advdata[1]; new_adv_data.adv_data.len = adv_set_data_size_max_get(p_advertising); ret_code_t ret = ble_advdata_encode(p_advdata, new_adv_data.adv_data.p_data, &new_adv_data.adv_data.len); VERIFY_SUCCESS(ret); } if (p_srdata != NULL) { new_adv_data.scan_rsp_data.p_data = (p_advertising->p_adv_data->scan_rsp_data.p_data != p_advertising->enc_scan_rsp_data[0]) ? p_advertising->enc_scan_rsp_data[0] : p_advertising->enc_scan_rsp_data[1]; new_adv_data.scan_rsp_data.len = adv_set_data_size_max_get(p_advertising); ret_code_t ret = ble_advdata_encode(p_srdata, new_adv_data.scan_rsp_data.p_data, &new_adv_data.scan_rsp_data.len); VERIFY_SUCCESS(ret); } memcpy(&p_advertising->adv_data, &new_adv_data, sizeof(p_advertising->adv_data)); p_advertising->p_adv_data = &p_advertising->adv_data; return sd_ble_gap_adv_set_configure(&p_advertising->adv_handle, p_advertising->p_adv_data, NULL); } #endif // NRF_MODULE_ENABLED(BLE_ADVERTISING)