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;
}
Exemplo n.º 2
0
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;
    }
}