uint32_t ble_advertising_start(ble_adv_mode_t advertising_mode) { uint32_t err_code; ble_gap_adv_params_t adv_params; m_adv_mode_current = advertising_mode; uint32_t count = 0; // Verify if there are any pending flash operations. If so, delay starting advertising until // the flash operations are complete. err_code = pstorage_access_status_get(&count); if (err_code == NRF_ERROR_INVALID_STATE) { // Pstorage is not initialized, i.e. not in use. count = 0; } else if (err_code != NRF_SUCCESS) { return err_code; } if (count != 0) { m_advertising_start_pending = true; return NRF_SUCCESS; } // Fetch the peer address. ble_advertising_peer_address_clear(); if ( ((m_adv_modes_config.ble_adv_directed_enabled) && m_adv_mode_current == BLE_ADV_MODE_DIRECTED) ||((m_adv_modes_config.ble_adv_directed_slow_enabled) && m_adv_mode_current == BLE_ADV_MODE_DIRECTED_SLOW)) { if (m_evt_handler != NULL) { m_peer_addr_reply_expected = true; m_evt_handler(BLE_ADV_EVT_PEER_ADDR_REQUEST); } else { m_peer_addr_reply_expected = false; } } // If a mode is disabled, continue to the next mode. I.e fast instead of direct, slow instead of fast, idle instead of slow. if ( (m_adv_mode_current == BLE_ADV_MODE_DIRECTED) &&(!m_adv_modes_config.ble_adv_directed_enabled || !peer_address_exists(m_peer_address.addr))) { m_adv_mode_current = BLE_ADV_MODE_DIRECTED_SLOW; } if ( (m_adv_mode_current == BLE_ADV_MODE_DIRECTED_SLOW) &&(!m_adv_modes_config.ble_adv_directed_slow_enabled || !peer_address_exists(m_peer_address.addr))) { m_adv_mode_current = BLE_ADV_MODE_FAST; } if (!m_adv_modes_config.ble_adv_fast_enabled && m_adv_mode_current == BLE_ADV_MODE_FAST) { m_adv_mode_current = BLE_ADV_MODE_SLOW; } if (!m_adv_modes_config.ble_adv_slow_enabled && m_adv_mode_current == BLE_ADV_MODE_SLOW) { m_adv_mode_current = BLE_ADV_MODE_IDLE; m_adv_evt = BLE_ADV_EVT_IDLE; } // Fetch the whitelist. if ( (m_evt_handler != NULL) && (m_adv_mode_current == BLE_ADV_MODE_FAST || m_adv_mode_current == BLE_ADV_MODE_SLOW) && (m_adv_modes_config.ble_adv_whitelist_enabled) && (!m_whitelist_temporarily_disabled)) { m_whitelist_reply_expected = true; m_evt_handler(BLE_ADV_EVT_WHITELIST_REQUEST); } else { m_whitelist_reply_expected = false; } // Initialize advertising parameters with default values. memset(&adv_params, 0, sizeof(adv_params)); adv_params.type = BLE_GAP_ADV_TYPE_ADV_IND; adv_params.p_peer_addr = NULL; adv_params.fp = BLE_GAP_ADV_FP_ANY; adv_params.p_whitelist = NULL; // Set advertising parameters and events according to selected advertising mode. switch (m_adv_mode_current) { case BLE_ADV_MODE_DIRECTED: LOG("[ADV]: Starting direct advertisement.\r\n"); adv_params.p_peer_addr = &m_peer_address; // Directed advertising. adv_params.type = BLE_GAP_ADV_TYPE_ADV_DIRECT_IND; adv_params.timeout = 0; adv_params.interval = 0; m_adv_evt = BLE_ADV_EVT_DIRECTED; break; case BLE_ADV_MODE_DIRECTED_SLOW: LOG("[ADV]: Starting direct advertisement.\r\n"); adv_params.p_peer_addr = &m_peer_address; // Directed advertising. adv_params.type = BLE_GAP_ADV_TYPE_ADV_DIRECT_IND; adv_params.timeout = m_adv_modes_config.ble_adv_directed_slow_timeout; adv_params.interval = m_adv_modes_config.ble_adv_directed_slow_interval; m_adv_evt = BLE_ADV_EVT_DIRECTED_SLOW; break; case BLE_ADV_MODE_FAST: adv_params.timeout = m_adv_modes_config.ble_adv_fast_timeout; adv_params.interval = m_adv_modes_config.ble_adv_fast_interval; if ( whitelist_has_entries(&m_whitelist) && m_adv_modes_config.ble_adv_whitelist_enabled && !m_whitelist_temporarily_disabled) { adv_params.fp = BLE_GAP_ADV_FP_FILTER_CONNREQ; adv_params.p_whitelist = &m_whitelist; m_advdata.flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED; err_code = ble_advdata_set(&m_advdata, NULL); if(err_code != NRF_SUCCESS) { return err_code; } m_adv_evt = BLE_ADV_EVT_FAST_WHITELIST; LOG("[ADV]: Starting fast advertisement with whitelist.\r\n"); } else { m_adv_evt = BLE_ADV_EVT_FAST; LOG("[ADV]: Starting fast advertisement.\r\n"); } break; case BLE_ADV_MODE_SLOW: adv_params.interval = m_adv_modes_config.ble_adv_slow_interval; adv_params.timeout = m_adv_modes_config.ble_adv_slow_timeout; if ( whitelist_has_entries(&m_whitelist) && m_adv_modes_config.ble_adv_whitelist_enabled && !m_whitelist_temporarily_disabled) { adv_params.fp = BLE_GAP_ADV_FP_FILTER_CONNREQ; adv_params.p_whitelist = &m_whitelist; m_advdata.flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED; err_code = ble_advdata_set(&m_advdata, NULL); if(err_code != NRF_SUCCESS) { return err_code; } m_adv_evt = BLE_ADV_EVT_SLOW_WHITELIST; LOG("[ADV]: Starting slow advertisement with whitelist.\r\n"); } else { m_adv_evt = BLE_ADV_EVT_SLOW; LOG("[ADV]: Starting slow advertisement.\r\n"); } break; default: break; } if (m_adv_mode_current != BLE_ADV_MODE_IDLE) { err_code = sd_ble_gap_adv_start(&adv_params); if(err_code != NRF_SUCCESS) { return err_code; } } if (m_evt_handler != NULL) { m_evt_handler(m_adv_evt); } return NRF_SUCCESS; }
void ble_advertising_on_ble_evt(ble_evt_t const * p_ble_evt) { static uint16_t current_slave_link_conn_handle = BLE_CONN_HANDLE_INVALID; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: #ifdef S130 if (p_ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_PERIPH) { current_slave_link_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; } #else current_slave_link_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; #endif break; // Upon disconnection, whitelist will be activated and direct advertising is started. case BLE_GAP_EVT_DISCONNECTED: { uint32_t err_code; m_whitelist_temporarily_disabled = false; m_direct_adv_cnt = m_adv_modes_config.ble_adv_directed_timeout; if (p_ble_evt->evt.gap_evt.conn_handle == current_slave_link_conn_handle) { err_code = ble_advertising_start(BLE_ADV_MODE_DIRECTED); if ((err_code != NRF_SUCCESS) && (m_error_handler != NULL)) { m_error_handler(err_code); } } break; } // Upon time-out, the next advertising mode is started, i.e. go from fast to slow or from slow to idle. case BLE_GAP_EVT_TIMEOUT: if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISING) { switch (m_adv_mode_current) { case BLE_ADV_MODE_DIRECTED: LOG("[ADV]: Timed out from directed advertising.\r\n"); if ((m_direct_adv_cnt > 0) && peer_address_exists(m_peer_address.addr)) { uint32_t err_code; m_direct_adv_cnt--; LOG("[ADV]: Remaining direct advertising attempts: %d\r\n", m_direct_adv_cnt); err_code = ble_advertising_start(BLE_ADV_MODE_DIRECTED); if ((err_code != NRF_SUCCESS) && (m_error_handler != NULL)) { m_error_handler(err_code); } } else { uint32_t err_code; err_code = ble_advertising_start(BLE_ADV_MODE_FAST); if ((err_code != NRF_SUCCESS) && (m_error_handler != NULL)) { m_error_handler(err_code); } } break; case BLE_ADV_MODE_FAST: { uint32_t err_code; m_adv_evt = BLE_ADV_EVT_FAST; LOG("[ADV]: Timed out from fast advertising, starting slow advertising.\r\n"); err_code = ble_advertising_start(BLE_ADV_MODE_SLOW); if ((err_code != NRF_SUCCESS) && (m_error_handler != NULL)) { m_error_handler(err_code); } break; } case BLE_ADV_MODE_SLOW: m_adv_evt = BLE_ADV_EVT_IDLE; LOG("[ADV]: Timed out from slow advertising, stopping advertising.\r\n"); if (m_evt_handler != NULL) { m_evt_handler(m_adv_evt); } break; default: // No implementation needed. break; } } break; default: // No implementation needed. break; } }