#include "ble_gap.h" #include "advertising.h" #include "ble_advdata.h" #include "ble_advertising.h" #include "ble_nus.h" #include "connection.h" #include "defs.h" #include "int_comm.h" #include "nrf_log.h" #include "pm.h" #include "power.h" #define APP_ADV_INTERVAL \ 64 /**< The advertising interval (in units of 0.625 ms. This value \ corresponds to 40 ms). */ #define APP_ADV_DURATION \ 18000 /**< The advertising duration (180 seconds) in units of 10 \ milliseconds. */ #define NUS_SERVICE_UUID_TYPE \ BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service \ (vendor specific). */ static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */ {{BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}}; BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */ /**@brief Function for handling advertising events. * * @details This function will be called for advertising events which are passed * to the application. * * @param[in] ble_adv_evt Advertising event. */ static void on_adv_evt(ble_adv_evt_t ble_adv_evt) { uint32_t err_code; switch (ble_adv_evt) { case BLE_ADV_EVT_DIRECTED_HIGH_DUTY: NRF_LOG_INFO("High Duty Directed advertising."); send_status_event(); break; case BLE_ADV_EVT_DIRECTED: NRF_LOG_INFO("Directed advertising."); send_status_event(); break; case BLE_ADV_EVT_FAST: NRF_LOG_INFO("Fast advertising."); send_status_event(); break; case BLE_ADV_EVT_SLOW: NRF_LOG_INFO("Slow advertising."); send_status_event(); break; case BLE_ADV_EVT_FAST_WHITELIST: NRF_LOG_INFO("Fast advertising with whitelist."); send_status_event(); break; case BLE_ADV_EVT_SLOW_WHITELIST: NRF_LOG_INFO("Slow advertising with whitelist."); send_status_event(); break; case BLE_ADV_EVT_IDLE: send_status_event(); // sleep_mode_enter(); break; case BLE_ADV_EVT_WHITELIST_REQUEST: { ble_gap_addr_t whitelist_addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; ble_gap_irk_t whitelist_irks[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; uint32_t addr_cnt = BLE_GAP_WHITELIST_ADDR_MAX_COUNT; uint32_t irk_cnt = BLE_GAP_WHITELIST_ADDR_MAX_COUNT; err_code = pm_whitelist_get(whitelist_addrs, &addr_cnt, whitelist_irks, &irk_cnt); if (err_code != NRF_ERROR_NOT_FOUND) { APP_ERROR_CHECK(err_code); } else { break; } NRF_LOG_DEBUG( "pm_whitelist_get returns %d addr in whitelist and %d irk whitelist", addr_cnt, irk_cnt); // Set the correct identities list (no excluding peers with no Central // Address Resolution). identities_set(PM_PEER_ID_LIST_SKIP_NO_IRK); // Apply the whitelist. err_code = ble_advertising_whitelist_reply( &m_advertising, whitelist_addrs, addr_cnt, whitelist_irks, irk_cnt); APP_ERROR_CHECK(err_code); } break; // BLE_ADV_EVT_WHITELIST_REQUEST case BLE_ADV_EVT_PEER_ADDR_REQUEST: { pm_peer_data_bonding_t peer_bonding_data; // Only Give peer address if we have a handle to the bonded peer. if (get_peer_id() != PM_PEER_ID_INVALID) { err_code = pm_peer_data_bonding_load(get_peer_id(), &peer_bonding_data); if (err_code != NRF_ERROR_NOT_FOUND) { APP_ERROR_CHECK(err_code); // Manipulate identities to exclude peers with no Central Address // Resolution. identities_set(PM_PEER_ID_LIST_SKIP_ALL); ble_gap_addr_t *p_peer_addr = &(peer_bonding_data.peer_ble_id.id_addr_info); err_code = ble_advertising_peer_addr_reply(&m_advertising, p_peer_addr); APP_ERROR_CHECK(err_code); } } } break; // BLE_ADV_EVT_PEER_ADDR_REQUEST default: break; } } void advertising_init(void) { uint32_t err_code; uint8_t adv_flags; ble_advertising_init_t init; memset(&init, 0, sizeof(init)); adv_flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; init.advdata.name_type = BLE_ADVDATA_FULL_NAME; init.advdata.include_appearance = false; init.advdata.flags = adv_flags; init.advdata.uuids_complete.uuid_cnt = 0; init.advdata.uuids_complete.p_uuids = NULL; init.config.ble_adv_whitelist_enabled = true; init.config.ble_adv_directed_high_duty_enabled = true; init.config.ble_adv_directed_enabled = false; init.config.ble_adv_directed_interval = 0; init.config.ble_adv_directed_timeout = 0; init.config.ble_adv_fast_enabled = true; init.config.ble_adv_fast_interval = APP_ADV_INTERVAL; init.config.ble_adv_fast_timeout = APP_ADV_DURATION; init.evt_handler = on_adv_evt; init.srdata.uuids_more_available.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]); init.srdata.uuids_more_available.p_uuids = m_adv_uuids; err_code = ble_advertising_init(&m_advertising, &init); APP_ERROR_CHECK(err_code); ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG); } void advertising_start(bool whitelist) { m_advertising.adv_modes_config.ble_adv_on_disconnect_disabled = false; if (m_advertising.adv_mode_current != BLE_ADV_MODE_DIRECTED_HIGH_DUTY) { if (m_advertising.adv_mode_current != BLE_ADV_MODE_FAST && get_connection_handle() == BLE_CONN_HANDLE_INVALID) { whitelist_set(PM_PEER_ID_LIST_SKIP_NO_ID_ADDR); ret_code_t ret = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); APP_ERROR_CHECK(ret); } if (!whitelist) { ret_code_t ret = ble_advertising_restart_without_whitelist(&m_advertising); APP_ERROR_CHECK(ret); } } } void advertising_stop(void) { m_advertising.adv_modes_config.ble_adv_on_disconnect_disabled = true; ret_code_t ret = ble_advertising_start(&m_advertising, BLE_ADV_MODE_IDLE); APP_ERROR_CHECK(ret); // ret =sd_ble_gap_disconnect(get_connection_handle(), // BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(ret); } void advertising_restart_without_whitelist(void) { ret_code_t ret = ble_advertising_restart_without_whitelist(&m_advertising); APP_ERROR_CHECK(ret); } bool is_advertising(void) { return m_advertising.adv_mode_current != BLE_ADV_MODE_IDLE; } bool is_advertising_wl(void) { return m_advertising.whitelist_in_use; }