Example #1
0
ble_error_t nRF5xGap::getAddress(AddressType_t *typeP, Address_t address)
{
    ble_gap_addr_t dev_addr;
    if (sd_ble_gap_address_get(&dev_addr) != NRF_SUCCESS) {
        return BLE_ERROR_PARAM_OUT_OF_RANGE;
    }

    if (typeP != NULL) {
        *typeP = static_cast<AddressType_t>(dev_addr.addr_type);
    }
    if (address != NULL) {
        memcpy(address, dev_addr.addr, ADDR_LEN);
    }
    return BLE_ERROR_NONE;
}
Example #2
0
void MACaddress(char *addr) {
    uint32_t err_code;
    if (m_sps.conn_handle == BLE_CONN_HANDLE_INVALID) {
	app_uart_put_string("BLE not connected\r\n");
	return;
    }

    ble_gap_addr_t mac_addr;
    err_code = sd_ble_gap_address_get(&mac_addr);
    APP_ERROR_CHECK(err_code);

    sprintf(addr, "%02x%02x%02x%02x%02x%02x",
	    mac_addr.addr[5], mac_addr.addr[4], mac_addr.addr[3],
	    mac_addr.addr[2], mac_addr.addr[1], mac_addr.addr[0]);
}
Example #3
0
/**@brief Function for initializing the Advertising functionality.
 *
 * @details Encodes the required advertising data and passes it to the stack.
 *          Also builds a structure to be passed to the stack when starting advertising.
 */
static void advertising_init(void)
{
    uint32_t        err_code;
    ble_advdata_t   advdata;
    uint8_t         flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
    ble_gap_conn_sec_mode_t sec_mode;

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);

    err_code = sd_ble_gap_device_name_set(&sec_mode,
                                          (const uint8_t *)DEVICE_NAME,
                                          strlen(DEVICE_NAME));
    APP_ERROR_CHECK(err_code);

    err_code = sd_ble_gap_address_get(&m_local_ble_addr);
    APP_ERROR_CHECK(err_code);

    m_local_ble_addr.addr[5]   = 0x00;
    m_local_ble_addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC;

    err_code = sd_ble_gap_address_set(&m_local_ble_addr);
    APP_ERROR_CHECK(err_code);

    ble_uuid_t adv_uuids[] =
    {
        {BLE_UUID_IPSP_SERVICE, BLE_UUID_TYPE_BLE}
    };

    //Build and set advertising data.
    memset(&advdata, 0, sizeof(advdata));

    advdata.name_type               = BLE_ADVDATA_FULL_NAME;
    advdata.flags                   = flags;
    advdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]);
    advdata.uuids_complete.p_uuids  = adv_uuids;

    err_code = ble_advdata_set(&advdata, NULL);
    APP_ERROR_CHECK(err_code);

    // Initialize advertising parameters (used when starting advertising).
    memset(&m_adv_params, 0, sizeof(m_adv_params));

    m_adv_params.type        = BLE_GAP_ADV_TYPE_ADV_IND;
    m_adv_params.p_peer_addr = NULL;                             // Undirected advertisement.
    m_adv_params.fp          = BLE_GAP_ADV_FP_ANY;
    m_adv_params.interval    = APP_ADV_ADV_INTERVAL;
    m_adv_params.timeout     = APP_ADV_TIMEOUT;
}
Example #4
0
error_t btle_init(void)
{
    nrf_clock_lfclksrc_t clockSource;
    if (NRF_CLOCK->LFCLKSRC & (CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos)) {
        clockSource = NRF_CLOCK_LFCLKSRC_XTAL_20_PPM;
    } else {
        clockSource = NRF_CLOCK_LFCLKSRC_RC_250_PPM_4000MS_CALIBRATION;
    }
    SOFTDEVICE_HANDLER_INIT(clockSource, eventHandler);

    // Enable BLE stack
    /**
     * Using this call, the application can select whether to include the
     * Service Changed characteristic in the GATT Server. The default in all
     * previous releases has been to include the Service Changed characteristic,
     * but this affects how GATT clients behave. Specifically, it requires
     * clients to subscribe to this attribute and not to cache attribute handles
     * between connections unless the devices are bonded. If the application
     * does not need to change the structure of the GATT server attributes at
     * runtime this adds unnecessary complexity to the interaction with peer
     * clients. If the SoftDevice is enabled with the Service Changed
     * Characteristics turned off, then clients are allowed to cache attribute
     * handles making applications simpler on both sides.
     */
    static const bool IS_SRVC_CHANGED_CHARACT_PRESENT = true;
    ble_enable_params_t enableParams = {
        .gatts_enable_params = {
            .service_changed = IS_SRVC_CHANGED_CHARACT_PRESENT,
            .attr_tab_size = gatt_table_size
        }
    };
    if (sd_ble_enable(&enableParams) != NRF_SUCCESS) {
        return ERROR_INVALID_PARAM;
    }

    ble_gap_addr_t addr;
    if (sd_ble_gap_address_get(&addr) != NRF_SUCCESS) {
        return ERROR_INVALID_PARAM;
    }
    if (sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &addr) != NRF_SUCCESS) {
        return ERROR_INVALID_PARAM;
    }

    ASSERT_STATUS( softdevice_ble_evt_handler_set(btle_handler));
    ASSERT_STATUS( softdevice_sys_evt_handler_set(sys_evt_dispatch));

    return btle_gap_init();
}
Example #5
0
File: main.c Project: IOIOI/nRF51
/**@brief Function for initializing Beacon advertiser.
 */
static void beacon_adv_init(void)
{
    static uint8_t beacon_uuid[] = {BEACON_UUID};
    
    memcpy(beacon_init.uuid.uuid128, beacon_uuid, sizeof(beacon_uuid));
    beacon_init.adv_interval  = BEACON_ADV_INTERVAL;
    beacon_init.major         = BEACON_MAJOR;
    beacon_init.minor         = BEACON_MINOR;
    beacon_init.manuf_id      = APP_COMPANY_IDENTIFIER;
    beacon_init.rssi          = BEACON_RSSI;
    beacon_init.error_handler = beacon_advertiser_error_handler;
    
    uint32_t err_code = sd_ble_gap_address_get(&beacon_init.beacon_addr);
    APP_ERROR_CHECK(err_code);
    
    app_beacon_init(&beacon_init);
}
Example #6
0
void Node::PrintStatus(void)
{
	trace("**************" EOL);
	trace("This is Node %u in clusterId:%x with clusterSize:%d, networkId:%u" EOL, this->persistentConfig.nodeId, this->clusterId, this->clusterSize, persistentConfig.networkId);
	trace("Ack Field:%d, ChipId:%u, ConnectionLossCounter:%u, nodeType:%d" EOL, ackFieldDebugCopy, NRF_FICR->DEVICEID[1], persistentConfig.connectionLossCounter, this->persistentConfig.deviceType);

	ble_gap_addr_t p_addr;
	sd_ble_gap_address_get(&p_addr);
	trace("GAP Addr is %02X:%02X:%02X:%02X:%02X:%02X" EOL EOL, p_addr.addr[5], p_addr.addr[4], p_addr.addr[3], p_addr.addr[2], p_addr.addr[1], p_addr.addr[0]);

	//Print connection info
	trace("CONNECTIONS (freeIn:%u, freeOut:%u, pendingPackets:%u, txBuf:%u" EOL, cm->freeInConnections, cm->freeOutConnections, cm->pendingPackets, cm->txBufferFreeCount);
	cm->inConnection->PrintStatus();
	for (int i = 0; i < Config->meshMaxOutConnections; i++)
	{
		cm->outConnections[i]->PrintStatus();
	}
}
Example #7
0
//read mac address
static void get_mac_addr(uint8_t *p_mac_addr)
{
		uint32_t error_code;
		ble_gap_addr_t *p_mac_addr_t = (ble_gap_addr_t*)malloc(sizeof(ble_gap_addr_t));
		error_code = sd_ble_gap_address_get(p_mac_addr_t);
		//APP_ERROR_CHECK(error_code);
		uint8_t *d = p_mac_addr_t->addr;
		for ( uint8_t i = 6; i >0;)
		{	
			i--;
			p_mac_addr[5-i]= d[i];
		}
		free(p_mac_addr_t);
		p_mac_addr_t = NULL;

		SEGGER_RTT_printf(0,"mac=0x%x",p_mac_addr[0]);
			
}
Example #8
0
static uint32_t ble_device_addr_encode(uint8_t  * p_encoded_data,
                                       uint16_t * p_offset,
                                       uint16_t   max_size)
{
    uint32_t err_code;
    ble_gap_addr_t device_addr;

    // Check for buffer overflow.
    if (((*p_offset) + AD_TYPE_BLE_DEVICE_ADDR_SIZE) > max_size)
    {
        return NRF_ERROR_DATA_SIZE;
    }

    // Get BLE address.
    #if (NRF_SD_BLE_API_VERSION >= 3)
        err_code = sd_ble_gap_addr_get(&device_addr);
    #else
        err_code = sd_ble_gap_address_get(&device_addr);
    #endif
    VERIFY_SUCCESS(err_code);

    // Encode LE Bluetooth Device Address.
    p_encoded_data[*p_offset]  = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE +
                                               AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE);
    *p_offset                 += ADV_LENGTH_FIELD_SIZE;
    p_encoded_data[*p_offset]  = BLE_GAP_AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS;
    *p_offset                 += ADV_AD_TYPE_FIELD_SIZE;
    memcpy(&p_encoded_data[*p_offset], &device_addr.addr[0], BLE_GAP_ADDR_LEN);
    *p_offset                 += BLE_GAP_ADDR_LEN;
    if (BLE_GAP_ADDR_TYPE_PUBLIC == device_addr.addr_type)
    {
        p_encoded_data[*p_offset] = AD_TYPE_BLE_DEVICE_ADDR_TYPE_PUBLIC;
    }
    else
    {
        p_encoded_data[*p_offset] = AD_TYPE_BLE_DEVICE_ADDR_TYPE_RANDOM;
    }
    *p_offset += AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE;

    return NRF_SUCCESS;
}
Example #9
0
ret_code_t im_privacy_get(pm_privacy_params_t * p_privacy_params)
{
    #if (NRF_SD_BLE_API_VERSION == 2)

        ble_gap_addr_t cur_addr;
        ble_opt_t      cur_privacy_opt;

        NRF_PM_DEBUG_CHECK(p_privacy_params               != NULL);
        NRF_PM_DEBUG_CHECK(p_privacy_params->p_device_irk != NULL);

        cur_privacy_opt.gap_opt.privacy.p_irk = p_privacy_params->p_device_irk;

        // Can not fail.
        (void) sd_ble_gap_address_get(&cur_addr);

        if (   cur_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE
            || cur_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE)
        {
            p_privacy_params->privacy_mode      = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY;
            p_privacy_params->private_addr_type = cur_addr.addr_type;
        }
        else
        {
            p_privacy_params->privacy_mode = BLE_GAP_PRIVACY_MODE_OFF;
        }

        // Can not fail.
        (void) sd_ble_opt_get(BLE_GAP_OPT_PRIVACY, &cur_privacy_opt);

        p_privacy_params->private_addr_cycle_s = cur_privacy_opt.gap_opt.privacy.interval_s;

        return NRF_SUCCESS;

    #else

        return sd_ble_gap_privacy_get(p_privacy_params);

    #endif
}
Example #10
0
ret_code_t im_id_addr_set(ble_gap_addr_t const * p_addr)
{
    #if (NRF_SD_BLE_API_VERSION == 2)

        ret_code_t     ret;
        ble_gap_addr_t current_addr;

        NRF_PM_DEBUG_CHECK(p_addr != NULL);

        (void) sd_ble_gap_address_get(&current_addr);

        ret = address_set_v2(BLE_GAP_ADDR_CYCLE_MODE_NONE, (ble_gap_addr_t *)p_addr);
        if (ret != NRF_SUCCESS)
        {
            return ret;
        }

        if (   current_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE
            || current_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE)
        {
            // If currently using privacy, it must be re-enabled.
            // We force AUTO when privacy is enabled.
            ret = address_set_v2(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &current_addr);
            if (ret != NRF_SUCCESS)
            {
                return ret;
            }
        }

        memcpy(&m_current_id_addr, p_addr, sizeof(ble_gap_addr_t));

        return NRF_SUCCESS;

    #else

        return sd_ble_gap_addr_set(p_addr);

    #endif
}
uint32_t mesh_packet_set_local_addr(mesh_packet_t* p_packet)
{
#ifdef SOFTDEVICE_PRESENT
    ble_gap_addr_t my_addr;
    uint32_t error_code;
#if (NRF_SD_BLE_API_VERSION == 3)
    error_code = sd_ble_gap_addr_get(&my_addr);
#else
    error_code = sd_ble_gap_address_get(&my_addr);
#endif
    if (error_code != NRF_SUCCESS)
    {
        return error_code;
    }
    p_packet->header.addr_type = my_addr.addr_type;
    memcpy(p_packet->addr, my_addr.addr, BLE_GAP_ADDR_LEN);
#else
    memcpy(p_packet->addr, (uint32_t*) &NRF_FICR->DEVICEADDR[0], BLE_GAP_ADDR_LEN);
    p_packet->header.addr_type = NRF_FICR->DEVICEADDRTYPE;
#endif

    return NRF_SUCCESS;
}
Example #12
0
/**@brief Function for initializing the BLE stack.
 *
 * @details Initializes the SoftDevice and the BLE event interrupt.
 */
static void ble_stack_init (void) {
    uint32_t err_code;

    // Initialize the SoftDevice handler module.
    SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_RC_250_PPM_8000MS_CALIBRATION,
            false);

    // Enable BLE stack
    ble_enable_params_t ble_enable_params;
    memset(&ble_enable_params, 0, sizeof(ble_enable_params));
    ble_enable_params.gatts_enable_params.service_changed = IS_SRVC_CHANGED_CHARACT_PRESENT;
    err_code = sd_ble_enable(&ble_enable_params);
    APP_ERROR_CHECK(err_code);

    //Register with the SoftDevice handler module for BLE events.
    err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch);
    APP_ERROR_CHECK(err_code);

    // Register with the SoftDevice handler module for BLE events.
    err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);
    APP_ERROR_CHECK(err_code);

    // Set the MAC address of the device
    {
        ble_gap_addr_t gap_addr;

        // Get the current original address
        sd_ble_gap_address_get(&gap_addr);

        // Set the new BLE address with the Michigan OUI
        gap_addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC;
        memcpy(gap_addr.addr+2, MAC_ADDR+2, sizeof(gap_addr.addr)-2);
        err_code = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE,
                &gap_addr);
        APP_ERROR_CHECK(err_code);
    }
}
Example #13
0
ret_code_t im_init(void)
{
    NRF_PM_DEBUG_CHECK(!m_module_initialized);

    internal_state_reset();

    m_conn_state_user_flag_id = ble_conn_state_user_flag_acquire();
    if (m_conn_state_user_flag_id == BLE_CONN_STATE_USER_FLAG_INVALID)
    {
        return NRF_ERROR_INTERNAL;
    }

    #if (NRF_SD_BLE_API_VERSION == 2)
        ret_code_t ret_code = sd_ble_gap_address_get(&m_current_id_addr);
        if (ret_code != NRF_SUCCESS)
        {
            return NRF_ERROR_INTERNAL;
        }
    #endif

    m_module_initialized = true;

    return NRF_SUCCESS;
}
uint32_t mesh_srv_char_val_set(uint8_t index, uint8_t* data, uint16_t len, bool update_sender)
{
    if (!is_initialized)
    {
        return NRF_ERROR_INVALID_STATE;
    }
    
    if (index > g_mesh_service.value_count || index == 0)
    {
        return NRF_ERROR_INVALID_ADDR;
    }
    
    if (len > MAX_VALUE_LENGTH)
    {
        return NRF_ERROR_INVALID_LENGTH;
    }
    uint32_t error_code = 0;
    
    mesh_char_metadata_t* ch_md = &g_mesh_service.char_metadata[index - 1];
    
    /* this is now a new version of this data, signal to the rest of the mesh */
    ++ch_md->version_number;
    
    bool first_time = 
        (ch_md->flags & 
        (1 << MESH_MD_FLAGS_USED_POS)) == 0;
    
    if (first_time)
    {
        ch_md->flags |= 
            (1 << MESH_MD_FLAGS_INITIALIZED_POS) |
            (1 << MESH_MD_FLAGS_USED_POS);
        trickle_init(&ch_md->trickle);
    }
    else
    {
        trickle_rx_inconsistent(&ch_md->trickle);
    }
    
    if (update_sender || first_time)
    {
        ble_gap_addr_t my_addr;
        sd_ble_gap_address_get(&my_addr);
        memcpy(&ch_md->last_sender_addr, &my_addr, sizeof(ble_gap_addr_t));
        ch_md->flags |= (1 << MESH_MD_FLAGS_IS_ORIGIN_POS);
    }
        
    /* notify the connected central node, if any */
    if (g_active_conn_handle != CONN_HANDLE_INVALID)
    {
        ble_gatts_hvx_params_t notify_params;
        notify_params.handle = ch_md->char_value_handle;
        notify_params.offset = 0;
        notify_params.p_data = data;
        notify_params.p_len = &len;
        notify_params.type = BLE_GATT_HVX_NOTIFICATION;
        error_code = sd_ble_gatts_hvx(g_active_conn_handle, &notify_params);
        if (error_code != NRF_SUCCESS)
        {
            if (error_code == BLE_ERROR_INVALID_CONN_HANDLE)
            {
                g_active_conn_handle = CONN_HANDLE_INVALID;
            }
            else if (error_code == BLE_GATTS_EVT_SYS_ATTR_MISSING)
            {
                sd_ble_gatts_sys_attr_set(g_active_conn_handle, NULL, 0);
            }
            else
            {
                return NRF_ERROR_INTERNAL;
            }
        }
    }
    else
    {
        error_code = sd_ble_gatts_value_set(
            ch_md->char_value_handle, 
            0, &len, data);
        
        if (error_code != NRF_SUCCESS)
        {
            return NRF_ERROR_INTERNAL;
        }
    }
    
    return NRF_SUCCESS;
}
/**
 * @brief Initialize Generic Access Profile (GAP)
 */
void init_gap()
{
    ble_gap_conn_params_t   gap_conn_params;
    ble_gap_conn_sec_mode_t security_mode;

    /*
     * Set security mode
     */
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&security_mode);

    uint32_t retval =
        sd_ble_gap_device_name_set(
            &security_mode,
            (const uint8_t*) BLE_DEVICE_NAME,
            strlen(BLE_DEVICE_NAME)
            );
    APP_ERROR_CHECK(retval);

    /*
     * Set connection parameters
     */

    memset(&gap_conn_params, 0, sizeof(gap_conn_params));

    gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
    gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
    gap_conn_params.slave_latency     = SLAVE_LATENCY;
    gap_conn_params.conn_sup_timeout  = CONN_SUP_TIMEOUT;

    retval =
            sd_ble_gap_ppcp_set(&gap_conn_params);
    APP_ERROR_CHECK(retval);

    /*
     * Change MAC address, if necessary
     */
    ble_gap_addr_t gap_address;

    retval =
            sd_ble_gap_address_get(&gap_address);
    APP_ERROR_CHECK(retval);

/*
    printf("Dis' your default MAC: %x:%x:%x:%x:%x:%x\n",
          gap_address.addr[5],
          gap_address.addr[4],
          gap_address.addr[3],
          gap_address.addr[2],
          gap_address.addr[1],
          gap_address.addr[0]
    );
*/
    gap_address.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC;

    retval =
            sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &gap_address);
    APP_ERROR_CHECK(retval);

//    gap_address.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE;
//    sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &gap_address);
/*
    printf("MAC address, I choose you: %x:%x:%x:%x:%x:%x\n",
          gap_address.addr[5],
          gap_address.addr[4],
          gap_address.addr[3],
          gap_address.addr[2],
          gap_address.addr[1],
          gap_address.addr[0]
    );
*/
}
uint32_t softdevice_handler_init(nrf_clock_lfclksrc_t           clock_source,
                                 void *                         p_evt_buffer,
                                 uint16_t                       evt_buffer_size,
                                 softdevice_evt_schedule_func_t evt_schedule_func)
{
    uint32_t err_code;

    // Save configuration.
#if defined (BLE_STACK_SUPPORT_REQD) || defined (ANT_STACK_SUPPORT_REQD)
    // Check that buffer is not NULL.
    if (p_evt_buffer == NULL)
    {
        return NRF_ERROR_INVALID_PARAM;
    }

    // Check that buffer is correctly aligned.
    if (!is_word_aligned(p_evt_buffer))
    {
        return NRF_ERROR_INVALID_PARAM;
    }

    m_evt_buffer = (uint8_t *)p_evt_buffer;
#else
    // The variable p_evt_buffer is not needed if neither BLE Stack nor ANT stack support is
    // required.
    UNUSED_PARAMETER(p_evt_buffer);
#endif

#if defined (BLE_STACK_SUPPORT_REQD)
    m_ble_evt_buffer_size = evt_buffer_size;
#else
    // The variable evt_buffer_size is not needed if BLE Stack support is NOT required.
    UNUSED_PARAMETER(evt_buffer_size);
#endif

    m_evt_schedule_func = evt_schedule_func;

    // Initialize SoftDevice.

    err_code = sd_softdevice_enable(clock_source, softdevice_assertion_handler);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    /**
     * Using this call, the application can select whether to include the
     * Service Changed characteristic in the GATT Server. The default in all
     * previous releases has been to include the Service Changed characteristic,
     * but this affects how GATT clients behave. Specifically, it requires
     * clients to subscribe to this attribute and not to cache attribute handles
     * between connections unless the devices are bonded. If the application
     * does not need to change the structure of the GATT server attributes at
     * runtime this adds unnecessary complexity to the interaction with peer
     * clients. If the SoftDevice is enabled with the Service Changed
     * Characteristics turned off, then clients are allowed to cache attribute
     * handles making applications simpler on both sides.
     */
    ble_enable_params_t enableParams = {
        .gatts_enable_params = {
            .service_changed = 0
        }
    };
    if ((err_code = sd_ble_enable(&enableParams)) != NRF_SUCCESS) {
        return err_code;
    }

    ble_gap_addr_t addr;
    if ((err_code = sd_ble_gap_address_get(&addr)) != NRF_SUCCESS) {
        return err_code;
    }
    if ((err_code = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &addr)) != NRF_SUCCESS) {
        return err_code;
    }

    m_softdevice_enabled = true;
    // Enable BLE event interrupt (interrupt priority has already been set by the stack).
    return sd_nvic_EnableIRQ(SWI2_IRQn);
}