Is it possible to send additional data in eddystone protocol ?
If yes please do share a snap of code with me.
Is it possible to send additional data in eddystone protocol ?
If yes please do share a snap of code with me.
Hi,
What do you mean by additional data? There is quite a lot of flexibility in the Eddystone protocol allready, and the Eddystone example in the nRF5 SDK implements everything in the protocol.
Note that Google discontinued Edystone in 2018, so depending on you ruse case it might not be the most suitable choice going forward.
additional data means like manufacturing data or scan response data i.e. if i want to advertise some more data
Hi,
Manufacturer specific data and scan response data is allready used in the Eddystone implementation, but it is for Eddystone specific things. If you modify this you would break Eddystone compatibility.
Is the thing here that you really want another type of custom beacon (not Eddystone at all)? If you don't really want an Eddystone beacon the you can do whatever you want with your advertisement packets. If you want an Eddystone beacon and something else, then perhaps it would be better to alternate between sending Eddystone beaconpacekts and some other advertisement packets that you have full control over (and if so, it could be that another Eddystone sample would be a better starting point, depending on which Eddystone features you need).
That is what i wanted to implement but i don't know how to built my own packet and then advertising it.
Which of the alternatives I outlined is it you want to implement?
basically i want to advertise customized data packet for that i need to form a packet which contains the data i want to advertise and then advertise it
How to do that
I see. Then I suggest you refer to the Beacon Transmitter Sample Application. This essentially shows you how to make a simple advertising packet using manufacturer specific data (you can remove all the iBeacon related stuff).
If you want you can also add a scan response packet, which is generated in the same way as the advertising packet, and in that case set the scan_rsp_data fields in the ble_gap_adv_data_t instead off leaving it NULL.
I see. Then I suggest you refer to the Beacon Transmitter Sample Application. This essentially shows you how to make a simple advertising packet using manufacturer specific data (you can remove all the iBeacon related stuff).
If you want you can also add a scan response packet, which is generated in the same way as the advertising packet, and in that case set the scan_rsp_data fields in the ble_gap_adv_data_t instead off leaving it NULL.
I am doing the same sending manufacturing data and scan response data in eddystone template but its not showing while advertising that is why i got stuck can you please share the code or steps if how you had done this
The BLE app uart example in nRF5 SDK demonstrates using scan response data (search for srdata in examples/ble_peripheral/ble_app_uart/main.c).
Perhaps you can show what you have done and how you have tested and debugged, and then I may be able to spot the issue.
I am attaching Snap of my code how i had tried implementing to advertise scan response and manufacturing specific data in eddystone but it's not showing this data while advertising 

It is not easy to spot the issue with snippets in screenshots. Can you post your full code as text as well as a description on how you have tested and debugged, and what you have found? Please explain if it does advertise at all, but with wrong data? And if not, what happens? Any error checks being hit? Other behavior? Please elaborate.
Below written is my code it's not showing any error it simply advertising in the same way as it advertise without adding any scan response and manufacturing data
#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;
ble_advertising_init_t init;
if ((p_init == NULL) || (p_advertising == NULL))
{
return NRF_ERROR_NULL;
}
if (!config_is_valid(&p_init->config))
{
return NRF_ERROR_INVALID_PARAM;
}
// manufacturing data
p_advertising->d = 's' ; // Extra
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));
// Manufacturing Specific data
ble_advdata_manuf_data_t manuf_data; //Variable to hold manufacturer specific data
uint8_t data[] = "SomeData!"; //Our data to advertise
manuf_data.company_identifier = 0x0059; //Nordics company ID
manuf_data.data.p_data = data;
manuf_data.data.size = sizeof(data);
init.advdata.p_manuf_specific_data = &manuf_data;
// Scan response data
ble_advdata_manuf_data_t manuf_data_response;
uint8_t data_response[] = "Many_bytes_of_data";
manuf_data_response.company_identifier = 0x0059;
manuf_data_response.data.p_data = data_response;
manuf_data_response.data.size = sizeof(data_response);
init.srdata.name_type = BLE_ADVDATA_NO_NAME;
init.srdata.p_manuf_specific_data = &manuf_data_response;
// 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)