Example #1
0
/**@brief Function for handling the Application's BLE Stack events.
 *
 * @param[in]   p_ble_evt   Bluetooth stack event.
 */
static void on_ble_evt(ble_evt_t * p_ble_evt)
{
    uint32_t                         err_code;
    static ble_gap_evt_auth_status_t m_auth_status;
    ble_gap_enc_info_t *             p_enc_info;

    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            led_off(LED);
            m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            break;

        case BLE_GAP_EVT_DISCONNECTED:
            m_conn_handle = BLE_CONN_HANDLE_INVALID;
            advertising_start();
            break;

        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
            err_code = sd_ble_gap_sec_params_reply(m_conn_handle,
                                                   BLE_GAP_SEC_STATUS_SUCCESS,
                                                   &m_sec_params);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
            err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GAP_EVT_AUTH_STATUS:
            m_auth_status = p_ble_evt->evt.gap_evt.params.auth_status;
            break;

        case BLE_GAP_EVT_SEC_INFO_REQUEST:
            p_enc_info = &m_auth_status.periph_keys.enc_info;
            if (p_enc_info->div == p_ble_evt->evt.gap_evt.params.sec_info_request.div)
            {
                err_code = sd_ble_gap_sec_info_reply(m_conn_handle, p_enc_info, NULL);
                APP_ERROR_CHECK(err_code);
            }
            else
            {
                // No keys found for this device
                err_code = sd_ble_gap_sec_info_reply(m_conn_handle, NULL, NULL);
                APP_ERROR_CHECK(err_code);
            }
            break;

        default:
            // No implementation needed.
            break;
    }
}
uint32_t conn_mw_ble_gap_sec_info_reply(uint8_t const * const p_rx_buf,
                                        uint32_t              rx_buf_len,
                                        uint8_t * const       p_tx_buf,
                                        uint32_t * const      p_tx_buf_len)
{
    SER_ASSERT_NOT_NULL(p_rx_buf);
    SER_ASSERT_NOT_NULL(p_tx_buf);
    SER_ASSERT_NOT_NULL(p_tx_buf_len);

    uint32_t err_code = NRF_SUCCESS;
    uint32_t sd_err_code;

    uint16_t conn_handle;

    ble_gap_enc_info_t   enc_info;
    ble_gap_enc_info_t * p_enc_info = &enc_info;

    ble_gap_sign_info_t   sign_info;
    ble_gap_sign_info_t * p_sign_info = &sign_info;

    err_code = ble_gap_sec_info_reply_req_dec(p_rx_buf,
                                              rx_buf_len,
                                              &conn_handle,
                                              &p_enc_info,
                                              &p_sign_info);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    sd_err_code = sd_ble_gap_sec_info_reply(conn_handle, p_enc_info, p_sign_info);

    err_code = ble_gap_sec_info_reply_rsp_enc(sd_err_code, p_tx_buf, p_tx_buf_len);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    return err_code;
}
Example #3
0
/**@brief      Function for handling the Security Info Request event received from the BLE stack.
 *
 * @param[in]  p_ble_evt   Event received from the BLE stack.
 */
static void on_sec_info_request(ble_evt_t * p_ble_evt)
{
    uint32_t err_code;

    err_code = master_find_in_db(p_ble_evt->evt.gap_evt.params.sec_info_request.div);
    if (err_code == NRF_SUCCESS)
    {
        // Bond information has been found and loaded for security procedures. Reflect this in the
        // status variable
        m_bond_loaded = true;

        // Master found in the list of bonded master. Use the encryption info for this master.
        err_code = sd_ble_gap_sec_info_reply(m_conn_handle,
                                             &m_master.bond.auth_status.periph_keys.enc_info,
                                             NULL);
        if (err_code != NRF_SUCCESS)
        {
            m_bondmngr_config.error_handler(err_code);
        }

        // Do not set the sys_attr yet, should be set only when sec_update is successful.
    }
    else if (err_code == NRF_ERROR_NOT_FOUND)
    {
        m_master.bond.master_id_info = p_ble_evt->evt.gap_evt.params.sec_info_request;

        // New master.
        err_code = sd_ble_gap_sec_info_reply(m_conn_handle, NULL, NULL);
        if (err_code != NRF_SUCCESS)
        {
            m_bondmngr_config.error_handler(err_code);
        }

        // Initialize the sys_attr.
        err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0);
    }

    if (err_code != NRF_SUCCESS)
    {
        m_bondmngr_config.error_handler(err_code);
    }
}
Example #4
0
/**@brief      This function handles the Security Info Request event received from the BLE stack.
 *
 * @param[in]  p_ble_evt   Event received from the BLE stack.
 */
static void on_sec_info_request(ble_evt_t * p_ble_evt)
{
    uint32_t err_code;

    m_master.bond.master_id_info = p_ble_evt->evt.gap_evt.params.sec_info_request;
    
    err_code = master_find_in_db(m_master.bond.master_id_info.div);
    if (err_code == NRF_SUCCESS)
    {
        // Master found in the list of bonded master. Use the encryption info for this master.
        err_code = sd_ble_gap_sec_info_reply(m_conn_handle, 
                                             &m_master.bond.auth_status.periph_keys.enc_info,
                                             NULL);
        if (err_code != NRF_SUCCESS)
        {
            m_bondmngr_config.error_handler(err_code);
        }
        
        // In addition set the corresponding sys_attr
        err_code = master_sys_attr_set(&m_master);
    }
    else if (err_code == NRF_ERROR_NOT_FOUND)
    {
        // New master
        err_code = sd_ble_gap_sec_info_reply(m_conn_handle, NULL, NULL);
        if (err_code != NRF_SUCCESS)
        {
            m_bondmngr_config.error_handler(err_code);
        }
        
        // Initialize the sys_attr
        err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0);
    }
    
    if (err_code != NRF_SUCCESS)
    {
        m_bondmngr_config.error_handler(err_code);
    }
}
Example #5
0
/**@brief Function for handling the Application's BLE Stack events.
 *
 * @param[in]   p_ble_evt   Bluetooth stack event.
 */
static void on_ble_evt(ble_evt_t * p_ble_evt) {
    uint32_t                         err_code;

    switch (p_ble_evt->header.evt_id) {
        case BLE_GAP_EVT_CONNECTED:
            app.conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            //advertising_stop();
            break;

        case BLE_GAP_EVT_DISCONNECTED:
            app.conn_handle = BLE_CONN_HANDLE_INVALID;
            advertising_start();
            break;

        case BLE_GATTS_EVT_WRITE:
            break;

        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
            err_code = sd_ble_gap_sec_params_reply(app.conn_handle,
                    BLE_GAP_SEC_STATUS_SUCCESS, &m_sec_params, NULL);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
            err_code = sd_ble_gatts_sys_attr_set(app.conn_handle, NULL, 0, 0);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GAP_EVT_AUTH_STATUS:
            break;

        case BLE_GAP_EVT_SEC_INFO_REQUEST:
            // No keys found for this device.
            err_code = sd_ble_gap_sec_info_reply(app.conn_handle, NULL, NULL, NULL);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GAP_EVT_TIMEOUT:
            if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISING) {
                err_code = sd_power_system_off();
                APP_ERROR_CHECK(err_code);
            }
            break;

        default:
            break;
    }
}
Example #6
0
/**@brief Application's BLE Stack event handler.
 *
 * @param[in]   p_ble_evt   Bluetooth stack event.
 */
void bleApp_onEvt(ble_evt_t * p_ble_evt) {
    uint32_t                         err_code = NRF_SUCCESS;
    static ble_gap_evt_auth_status_t m_auth_status;
    ble_gap_enc_info_t *             p_enc_info;

    switch (p_ble_evt->header.evt_id)
    {
    case BLE_GAP_EVT_CONNECTED:
	m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
	led_setState(LED_BLUE, LED_STATE_ON);
	break;

    case BLE_GAP_EVT_DISCONNECTED:
	m_conn_handle = BLE_CONN_HANDLE_INVALID;
	led_setState(LED_BLUE, LED_STATE_OFF);
	if (advertisingEnabled) {
	    bleApp_advertisingStart();
	}
	break;

    case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
	err_code = sd_ble_gap_sec_params_reply(m_conn_handle,
					       BLE_GAP_SEC_STATUS_SUCCESS,
					       &m_sec_params);
	break;

    case BLE_GATTS_EVT_SYS_ATTR_MISSING:
	err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0);
	break;

    case BLE_GAP_EVT_AUTH_STATUS:
	m_auth_status = p_ble_evt->evt.gap_evt.params.auth_status;
	break;

    case BLE_GAP_EVT_SEC_INFO_REQUEST:
	p_enc_info = &m_auth_status.periph_keys.enc_info;
	if (p_enc_info->div == p_ble_evt->evt.gap_evt.params.sec_info_request.div)
	{
	    err_code = sd_ble_gap_sec_info_reply(m_conn_handle, p_enc_info, NULL);
	}
	else
	{
	    // No keys found for this device
	    err_code = sd_ble_gap_sec_info_reply(m_conn_handle, NULL, NULL);
	}
	break;

    case BLE_GAP_EVT_TIMEOUT:
	if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISEMENT) {
	    led_setState(LED_BLUE, LED_STATE_OFF);

	    // Go to system-off mode (this function will not return; wakeup will cause a reset)
	    //GPIO_WAKEUP_BUTTON_CONFIG(WAKEUP_BUTTON_PIN);
	    //err_code = sd_power_system_off();
	}
	break;

    case BLE_GAP_EVT_RSSI_CHANGED:
	break;

    default:
	break;
    }

    APP_ERROR_CHECK(err_code);
}
/**
 * @brief Handler for all BLE events
 */
void ble_event_handler(ble_evt_t* p_ble_evt)
{
    static ble_gap_evt_auth_status_t   m_auth_status;
    ble_gap_enc_info_t*         p_enc_info;
    ble_gatts_evt_write_t*      p_evt_write;
    uint32_t                    retval;

    if (p_ble_evt == NULL)
        return;

    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            nrf_gpio_pin_clear(PIN_LED_ADVERTISING);
            nrf_gpio_pin_set(PIN_LED_CONNECTED);
            nrf_gpio_pin_clear(PIN_LED_DATA);

            ble_connection_handle = p_ble_evt->evt.gap_evt.conn_handle;

            //on_ble_connected();

            break;

        case BLE_GAP_EVT_DISCONNECTED:
            nrf_gpio_pin_clear(PIN_LED_ADVERTISING);
            nrf_gpio_pin_clear(PIN_LED_CONNECTED);
            nrf_gpio_pin_clear(PIN_LED_DATA);

            ble_connection_handle = BLE_CONN_HANDLE_INVALID;

            //on_ble_disconnected();

            //start_advertising();
            // TODO: Something's not working properly upon disconnect preventing reconnect
            NVIC_SystemReset();

            break;

        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
            retval =
                sd_ble_gap_sec_params_reply(
                    ble_connection_handle,
                    BLE_GAP_SEC_STATUS_SUCCESS,
                    &ble_security_parameters
                    );
            APP_ERROR_CHECK(retval);
            break;

        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
            retval =
                    sd_ble_gatts_sys_attr_set(ble_connection_handle, NULL, 0);
            APP_ERROR_CHECK(retval);
            break;

        case BLE_GAP_EVT_AUTH_STATUS:
            m_auth_status = p_ble_evt->evt.gap_evt.params.auth_status;
            break;

        case BLE_GAP_EVT_SEC_INFO_REQUEST:
            p_enc_info = &m_auth_status.periph_keys.enc_info;
            if (p_enc_info->div == p_ble_evt->evt.gap_evt.params.sec_info_request.div)
            {
                retval =
                        sd_ble_gap_sec_info_reply(ble_connection_handle, p_enc_info, NULL);
                APP_ERROR_CHECK(retval);
            }
            else
            {
                // No keys found for this device
                retval =
                        sd_ble_gap_sec_info_reply(ble_connection_handle, NULL, NULL);
                APP_ERROR_CHECK(retval);
            }
            break;

        case BLE_GATTS_EVT_WRITE:
            nrf_gpio_pin_set(PIN_LED_DATA);

            p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;

            if (p_evt_write->handle == tree_service.characteristic_set_led_color_handles.value_handle)
            {
                on_characteristic_written(tree_service.characteristic_set_led_color_uuid.uuid, p_evt_write->data, p_evt_write->len);
            }
            break;

        case BLE_GAP_EVT_TIMEOUT:
            if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISEMENT)
            {
                // Go to system-off mode (this function will not return; wakeup will cause a reset)
                //err_code = sd_power_system_off();
            }
            NVIC_SystemReset();
            break;
/*
        case BLE_EVT_TX_COMPLETE:
            if (!ble_buffer_available)
                tx_complete = true;
            break;
*/
        default:
            //printf("unimplemented event\n");
            break;
    }
}
Example #8
0
void nRF51822::poll() {
  uint32_t   evtBuf[BLE_STACK_EVT_MSG_BUF_SIZE] __attribute__ ((__aligned__(BLE_EVTS_PTR_ALIGNMENT)));
  uint16_t   evtLen = sizeof(evtBuf);
  ble_evt_t* bleEvt = (ble_evt_t*)evtBuf;

  if (sd_ble_evt_get((uint8_t*)evtBuf, &evtLen) == NRF_SUCCESS) {
    switch (bleEvt->header.evt_id) {
      case BLE_EVT_TX_COMPLETE:
#ifdef NRF_51822_DEBUG
        Serial.print(F("Evt TX complete "));
        Serial.println(bleEvt->evt.common_evt.params.tx_complete.count);
#endif
        this->_txBufferCount++;
        break;

      case BLE_GAP_EVT_CONNECTED:
#ifdef NRF_51822_DEBUG
        char address[18];

        BLEUtil::addressToString(bleEvt->evt.gap_evt.params.connected.peer_addr.addr, address);

        Serial.print(F("Evt Connected "));
        Serial.println(address);
#endif

        this->_connectionHandle = bleEvt->evt.gap_evt.conn_handle;

        sd_ble_tx_buffer_count_get(&this->_txBufferCount);

        if (this->_eventListener) {
          this->_eventListener->BLEDeviceConnected(*this, bleEvt->evt.gap_evt.params.connected.peer_addr.addr);
        }

        if (this->_minimumConnectionInterval >= BLE_GAP_CP_MIN_CONN_INTVL_MIN &&
            this->_maximumConnectionInterval <= BLE_GAP_CP_MAX_CONN_INTVL_MAX) {
          ble_gap_conn_params_t gap_conn_params;

          gap_conn_params.min_conn_interval = this->_minimumConnectionInterval;  // in 1.25ms units
          gap_conn_params.max_conn_interval = this->_maximumConnectionInterval;  // in 1.25ms unit
          gap_conn_params.slave_latency     = 0;
          gap_conn_params.conn_sup_timeout  = 4000 / 10; // in 10ms unit

          sd_ble_gap_conn_param_update(this->_connectionHandle, &gap_conn_params);
        }

        if (this->_numRemoteServices > 0) {
          sd_ble_gattc_primary_services_discover(this->_connectionHandle, 1, NULL);
        }
        break;

      case BLE_GAP_EVT_DISCONNECTED:
#ifdef NRF_51822_DEBUG
        Serial.println(F("Evt Disconnected"));
#endif
        this->_connectionHandle = BLE_CONN_HANDLE_INVALID;
        this->_txBufferCount = 0;

        for (int i = 0; i < this->_numLocalCharacteristics; i++) {
          struct localCharacteristicInfo* localCharacteristicInfo = &this->_localCharacteristicInfo[i];

          localCharacteristicInfo->notifySubscribed = false;
          localCharacteristicInfo->indicateSubscribed = false;

          if (localCharacteristicInfo->characteristic->subscribed()) {
            if (this->_eventListener) {
              this->_eventListener->BLEDeviceCharacteristicSubscribedChanged(*this, *localCharacteristicInfo->characteristic, false);
            }
          }
        }

        if (this->_eventListener) {
          this->_eventListener->BLEDeviceDisconnected(*this);
        }

        // clear remote handle info
        for (int i = 0; i < this->_numRemoteServices; i++) {
          memset(&this->_remoteServiceInfo[i].handlesRange, 0, sizeof(this->_remoteServiceInfo[i].handlesRange));
        }

        for (int i = 0; i < this->_numRemoteCharacteristics; i++) {
          memset(&this->_remoteCharacteristicInfo[i].properties, 0, sizeof(this->_remoteCharacteristicInfo[i].properties));
          this->_remoteCharacteristicInfo[i].valueHandle = 0;
        }

        this->_remoteRequestInProgress = false;

        this->startAdvertising();
        break;

      case BLE_GAP_EVT_CONN_PARAM_UPDATE:
#ifdef NRF_51822_DEBUG
        Serial.print(F("Evt Conn Param Update 0x"));
        Serial.print(bleEvt->evt.gap_evt.params.conn_param_update.conn_params.min_conn_interval, HEX);
        Serial.print(F(" 0x"));
        Serial.print(bleEvt->evt.gap_evt.params.conn_param_update.conn_params.max_conn_interval, HEX);
        Serial.print(F(" 0x"));
        Serial.print(bleEvt->evt.gap_evt.params.conn_param_update.conn_params.slave_latency, HEX);
        Serial.print(F(" 0x"));
        Serial.print(bleEvt->evt.gap_evt.params.conn_param_update.conn_params.conn_sup_timeout, HEX);
        Serial.println();
#endif
        break;

      case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
#ifdef NRF_51822_DEBUG
        Serial.print(F("Evt Sec Params Request "));
#ifndef NRF51_S130
        Serial.print(bleEvt->evt.gap_evt.params.sec_params_request.peer_params.timeout);
        Serial.print(F(" "));
#endif
        Serial.print(bleEvt->evt.gap_evt.params.sec_params_request.peer_params.bond);
        Serial.print(F(" "));
        Serial.print(bleEvt->evt.gap_evt.params.sec_params_request.peer_params.mitm);
        Serial.print(F(" "));
        Serial.print(bleEvt->evt.gap_evt.params.sec_params_request.peer_params.io_caps);
        Serial.print(F(" "));
        Serial.print(bleEvt->evt.gap_evt.params.sec_params_request.peer_params.oob);
        Serial.print(F(" "));
        Serial.print(bleEvt->evt.gap_evt.params.sec_params_request.peer_params.min_key_size);
        Serial.print(F(" "));
        Serial.print(bleEvt->evt.gap_evt.params.sec_params_request.peer_params.max_key_size);
        Serial.println();
#endif

        if (this->_bondStore && !this->_bondStore->hasData()) {
          // only allow bonding if bond store exists and there is no data

          ble_gap_sec_params_t gapSecParams;

#ifdef NRF51_S130
          gapSecParams.kdist_periph.enc = 1;
#else
          gapSecParams.timeout          = 30; // must be 30s
#endif
          gapSecParams.bond             = true;
          gapSecParams.mitm             = false;
          gapSecParams.io_caps          = BLE_GAP_IO_CAPS_NONE;
          gapSecParams.oob              = false;
          gapSecParams.min_key_size     = 7;
          gapSecParams.max_key_size     = 16;

#ifdef NRF51_S130
          ble_gap_sec_keyset_t keyset;

          keyset.keys_central.p_enc_key  = NULL;
          keyset.keys_central.p_id_key   = NULL;
          keyset.keys_central.p_sign_key = NULL;
          keyset.keys_periph.p_enc_key   = this->_encKey;
          keyset.keys_periph.p_id_key    = NULL;
          keyset.keys_periph.p_sign_key  = NULL;

          sd_ble_gap_sec_params_reply(this->_connectionHandle, BLE_GAP_SEC_STATUS_SUCCESS, &gapSecParams, &keyset);
#else
          sd_ble_gap_sec_params_reply(this->_connectionHandle, BLE_GAP_SEC_STATUS_SUCCESS, &gapSecParams);
#endif
        } else {
#ifdef NRF51_S130
          sd_ble_gap_sec_params_reply(this->_connectionHandle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
#else
          sd_ble_gap_sec_params_reply(this->_connectionHandle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL);
#endif
        }
        break;

      case BLE_GAP_EVT_SEC_INFO_REQUEST:
#ifdef NRF_51822_DEBUG
        Serial.print(F("Evt Sec Info Request "));
        // Serial.print(bleEvt->evt.gap_evt.params.sec_info_request.peer_addr);
        // Serial.print(F(" "));
#ifdef NRF51_S130
        Serial.print(bleEvt->evt.gap_evt.params.sec_info_request.master_id.ediv);
#else
        Serial.print(bleEvt->evt.gap_evt.params.sec_info_request.div);
#endif
        Serial.print(F(" "));
        Serial.print(bleEvt->evt.gap_evt.params.sec_info_request.enc_info);
        Serial.print(F(" "));
        Serial.print(bleEvt->evt.gap_evt.params.sec_info_request.id_info);
        Serial.print(F(" "));
        Serial.print(bleEvt->evt.gap_evt.params.sec_info_request.sign_info);
        Serial.println();
#endif
#ifdef NRF51_S130
        if (this->_encKey->master_id.ediv == bleEvt->evt.gap_evt.params.sec_info_request.master_id.ediv) {
          sd_ble_gap_sec_info_reply(this->_connectionHandle, &this->_encKey->enc_info, NULL, NULL);
        } else {
          sd_ble_gap_sec_info_reply(this->_connectionHandle, NULL, NULL, NULL);
        }
#else
        if (this->_authStatus->periph_keys.enc_info.div == bleEvt->evt.gap_evt.params.sec_info_request.div) {
          sd_ble_gap_sec_info_reply(this->_connectionHandle, &this->_authStatus->periph_keys.enc_info, NULL);
        } else {
          sd_ble_gap_sec_info_reply(this->_connectionHandle, NULL, NULL);
        }
#endif
        break;

      case BLE_GAP_EVT_AUTH_STATUS:
#ifdef NRF_51822_DEBUG
        Serial.println(F("Evt Auth Status"));
        Serial.println(bleEvt->evt.gap_evt.params.auth_status.auth_status);
#endif
        if (BLE_GAP_SEC_STATUS_SUCCESS == bleEvt->evt.gap_evt.params.auth_status.auth_status) {
#ifndef NRF51_S130
          *this->_authStatus = bleEvt->evt.gap_evt.params.auth_status;
#endif
          if (this->_bondStore) {
#ifdef NRF_51822_DEBUG
            Serial.println(F("Storing bond data"));
#endif
#ifdef NRF51_S130
            this->_bondStore->putData(this->_bondData, 0, sizeof(this->_bondData));
#else
            this->_bondStore->putData(this->_authStatusBuffer, 0, sizeof(this->_authStatusBuffer));
#endif
          }

          if (this->_eventListener) {
            this->_eventListener->BLEDeviceBonded(*this);
          }
        }
        break;

      case BLE_GAP_EVT_CONN_SEC_UPDATE:
#ifdef NRF_51822_DEBUG
        Serial.print(F("Evt Conn Sec Update "));
        Serial.print(bleEvt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.sm);
        Serial.print(F(" "));
        Serial.print(bleEvt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv);
        Serial.print(F(" "));
        Serial.print(bleEvt->evt.gap_evt.params.conn_sec_update.conn_sec.encr_key_size);
        Serial.println();
#endif
        break;

      case BLE_GATTS_EVT_WRITE: {
#ifdef NRF_51822_DEBUG
        Serial.print(F("Evt Write, handle = "));
        Serial.println(bleEvt->evt.gatts_evt.params.write.handle, DEC);

        BLEUtil::printBuffer(bleEvt->evt.gatts_evt.params.write.data, bleEvt->evt.gatts_evt.params.write.len);
#endif

        uint16_t handle = bleEvt->evt.gatts_evt.params.write.handle;

        for (int i = 0; i < this->_numLocalCharacteristics; i++) {
          struct localCharacteristicInfo* localCharacteristicInfo = &this->_localCharacteristicInfo[i];

          if (localCharacteristicInfo->handles.value_handle == handle) {
            if (this->_eventListener) {
              this->_eventListener->BLEDeviceCharacteristicValueChanged(*this, *localCharacteristicInfo->characteristic, bleEvt->evt.gatts_evt.params.write.data, bleEvt->evt.gatts_evt.params.write.len);
            }
            break;
          } else if (localCharacteristicInfo->handles.cccd_handle == handle) {
            uint16_t value = bleEvt->evt.gatts_evt.params.write.data[0] | (bleEvt->evt.gatts_evt.params.write.data[1] << 8);

            localCharacteristicInfo->notifySubscribed = (value & 0x0001);
            localCharacteristicInfo->indicateSubscribed = (value & 0x0002);

            bool subscribed = (localCharacteristicInfo->notifySubscribed || localCharacteristicInfo->indicateSubscribed);

            if (subscribed != localCharacteristicInfo->characteristic->subscribed()) {
              if (this->_eventListener) {
                this->_eventListener->BLEDeviceCharacteristicSubscribedChanged(*this, *localCharacteristicInfo->characteristic, subscribed);
              }
              break;
            }
          }
        }
        break;
      }

      case BLE_GATTS_EVT_SYS_ATTR_MISSING:
#ifdef NRF_51822_DEBUG
        Serial.print(F("Evt Sys Attr Missing "));
        Serial.println(bleEvt->evt.gatts_evt.params.sys_attr_missing.hint);
#endif
#ifdef NRF51_S130
        sd_ble_gatts_sys_attr_set(this->_connectionHandle, NULL, 0, 0);
#else
        sd_ble_gatts_sys_attr_set(this->_connectionHandle, NULL, 0);
#endif
        break;

      case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
#ifdef NRF_51822_DEBUG
        Serial.print(F("Evt Prim Srvc Disc Rsp 0x"));
        Serial.println(bleEvt->evt.gattc_evt.gatt_status, HEX);
#endif
        if (bleEvt->evt.gattc_evt.gatt_status == BLE_GATT_STATUS_SUCCESS) {
          uint16_t count = bleEvt->evt.gattc_evt.params.prim_srvc_disc_rsp.count;
          for (int i = 0; i < count; i++) {
            for (int j = 0; j < this->_numRemoteServices; j++) {
              if ((bleEvt->evt.gattc_evt.params.prim_srvc_disc_rsp.services[i].uuid.type == this->_remoteServiceInfo[j].uuid.type) &&
                  (bleEvt->evt.gattc_evt.params.prim_srvc_disc_rsp.services[i].uuid.uuid == this->_remoteServiceInfo[j].uuid.uuid)) {
                this->_remoteServiceInfo[j].handlesRange = bleEvt->evt.gattc_evt.params.prim_srvc_disc_rsp.services[i].handle_range;
                break;
              }
            }
          }

          uint16_t startHandle = bleEvt->evt.gattc_evt.params.prim_srvc_disc_rsp.services[count - 1].handle_range.end_handle + 1;

          sd_ble_gattc_primary_services_discover(this->_connectionHandle, startHandle, NULL);
        } else {
          // done discovering services
          for (int i = 0; i < this->_numRemoteServices; i++) {
            if (this->_remoteServiceInfo[i].handlesRange.start_handle != 0 && this->_remoteServiceInfo[i].handlesRange.end_handle != 0) {
              this->_remoteServiceDiscoveryIndex = i;

              sd_ble_gattc_characteristics_discover(this->_connectionHandle, &this->_remoteServiceInfo[i].handlesRange);
              break;
            }
          }
        }
        break;

      case BLE_GATTC_EVT_CHAR_DISC_RSP:
#ifdef NRF_51822_DEBUG
        Serial.print(F("Evt Char Disc Rsp 0x"));
        Serial.println(bleEvt->evt.gattc_evt.gatt_status, HEX);
#endif
        if (bleEvt->evt.gattc_evt.gatt_status == BLE_GATT_STATUS_SUCCESS) {
          ble_gattc_handle_range_t serviceHandlesRange = this->_remoteServiceInfo[this->_remoteServiceDiscoveryIndex].handlesRange;

          uint16_t count = bleEvt->evt.gattc_evt.params.char_disc_rsp.count;

          for (int i = 0; i < count; i++) {
            for (int j = 0; j < this->_numRemoteCharacteristics; j++) {
              if ((this->_remoteServiceInfo[this->_remoteServiceDiscoveryIndex].service == this->_remoteCharacteristicInfo[j].service) &&
                  (bleEvt->evt.gattc_evt.params.char_disc_rsp.chars[i].uuid.type == this->_remoteCharacteristicInfo[j].uuid.type) &&
                  (bleEvt->evt.gattc_evt.params.char_disc_rsp.chars[i].uuid.uuid == this->_remoteCharacteristicInfo[j].uuid.uuid)) {
                this->_remoteCharacteristicInfo[j].properties = bleEvt->evt.gattc_evt.params.char_disc_rsp.chars[i].char_props;
                this->_remoteCharacteristicInfo[j].valueHandle = bleEvt->evt.gattc_evt.params.char_disc_rsp.chars[i].handle_value;
              }
            }

            serviceHandlesRange.start_handle = bleEvt->evt.gattc_evt.params.char_disc_rsp.chars[i].handle_value;
          }

          sd_ble_gattc_characteristics_discover(this->_connectionHandle, &serviceHandlesRange);
        } else {
          bool discoverCharacteristics = false;

          for (int i = this->_remoteServiceDiscoveryIndex + 1; i < this->_numRemoteServices; i++) {
            if (this->_remoteServiceInfo[i].handlesRange.start_handle != 0 && this->_remoteServiceInfo[i].handlesRange.end_handle != 0) {
              this->_remoteServiceDiscoveryIndex = i;

              sd_ble_gattc_characteristics_discover(this->_connectionHandle, &this->_remoteServiceInfo[i].handlesRange);
              discoverCharacteristics = true;
              break;
            }
          }

          if (!discoverCharacteristics) {
            if (this->_eventListener) {
              this->_eventListener->BLEDeviceRemoteServicesDiscovered(*this);
            }
          }
        }
        break;

      case BLE_GATTC_EVT_READ_RSP: {
#ifdef NRF_51822_DEBUG
        Serial.print(F("Evt Read Rsp 0x"));
        Serial.println(bleEvt->evt.gattc_evt.gatt_status, HEX);
        Serial.println(bleEvt->evt.gattc_evt.params.read_rsp.handle, DEC);
        BLEUtil::printBuffer(bleEvt->evt.gattc_evt.params.read_rsp.data, bleEvt->evt.gattc_evt.params.read_rsp.len);
#endif
        this->_remoteRequestInProgress = false;

        if (bleEvt->evt.gattc_evt.gatt_status == BLE_GATT_STATUS_ATTERR_INSUF_AUTHENTICATION &&
            this->_bondStore) {
          ble_gap_sec_params_t gapSecParams;

#ifdef NRF51_S130
          gapSecParams.kdist_periph.enc = 1;
#else
          gapSecParams.timeout          = 30; // must be 30s
#endif
          gapSecParams.bond             = true;
          gapSecParams.mitm             = false;
          gapSecParams.io_caps          = BLE_GAP_IO_CAPS_NONE;
          gapSecParams.oob              = false;
          gapSecParams.min_key_size     = 7;
          gapSecParams.max_key_size     = 16;

          sd_ble_gap_authenticate(this->_connectionHandle, &gapSecParams);
        } else {
          uint16_t handle = bleEvt->evt.gattc_evt.params.read_rsp.handle;

          for (int i = 0; i < this->_numRemoteCharacteristics; i++) {
            if (this->_remoteCharacteristicInfo[i].valueHandle == handle) {
              if (this->_eventListener) {
                this->_eventListener->BLEDeviceRemoteCharacteristicValueChanged(*this, *this->_remoteCharacteristicInfo[i].characteristic, bleEvt->evt.gattc_evt.params.read_rsp.data, bleEvt->evt.gattc_evt.params.read_rsp. len);
              }
              break;
            }
          }
        }
        break;
      }

      case BLE_GATTC_EVT_WRITE_RSP:
#ifdef NRF_51822_DEBUG
        Serial.print(F("Evt Write Rsp 0x"));
        Serial.println(bleEvt->evt.gattc_evt.gatt_status, HEX);
        Serial.println(bleEvt->evt.gattc_evt.params.write_rsp.handle, DEC);
#endif
        this->_remoteRequestInProgress = false;

        if (bleEvt->evt.gattc_evt.gatt_status == BLE_GATT_STATUS_ATTERR_INSUF_AUTHENTICATION &&
            this->_bondStore) {
          ble_gap_sec_params_t gapSecParams;

#ifdef NRF51_S130
          gapSecParams.kdist_periph.enc = 1;
#else
          gapSecParams.timeout          = 30; // must be 30s
#endif
          gapSecParams.bond             = true;
          gapSecParams.mitm             = false;
          gapSecParams.io_caps          = BLE_GAP_IO_CAPS_NONE;
          gapSecParams.oob              = false;
          gapSecParams.min_key_size     = 7;
          gapSecParams.max_key_size     = 16;

          sd_ble_gap_authenticate(this->_connectionHandle, &gapSecParams);
        }
        break;

      case BLE_GATTC_EVT_HVX: {
#ifdef NRF_51822_DEBUG
        Serial.print(F("Evt Hvx 0x"));
        Serial.println(bleEvt->evt.gattc_evt.gatt_status, HEX);
        Serial.println(bleEvt->evt.gattc_evt.params.hvx.handle, DEC);
#endif
        uint16_t handle = bleEvt->evt.gattc_evt.params.hvx.handle;

        if (bleEvt->evt.gattc_evt.params.hvx.type == BLE_GATT_HVX_INDICATION) {
          sd_ble_gattc_hv_confirm(this->_connectionHandle, handle);
        }

        for (int i = 0; i < this->_numRemoteCharacteristics; i++) {
          if (this->_remoteCharacteristicInfo[i].valueHandle == handle) {
            if (this->_eventListener) {
              this->_eventListener->BLEDeviceRemoteCharacteristicValueChanged(*this, *this->_remoteCharacteristicInfo[i].characteristic, bleEvt->evt.gattc_evt.params.read_rsp.data, bleEvt->evt.gattc_evt.params.read_rsp. len);
            }
            break;
          }
        }
        break;
      }

      default:
#ifdef NRF_51822_DEBUG
        Serial.print(F("bleEvt->header.evt_id = 0x"));
        Serial.print(bleEvt->header.evt_id, HEX);
        Serial.print(F(" "));
        Serial.println(bleEvt->header.evt_len);
#endif
        break;
    }
  }

  // sd_app_evt_wait();
}
Example #9
0
/**@brief       Function for the Application's S110 SoftDevice event handler.
 *
 * @param[in]   p_ble_evt   S110 SoftDevice event.
 */
static void on_ble_evt(ble_evt_t * p_ble_evt)
{
    uint32_t                         err_code;
    static ble_gap_sec_keyset_t      s_sec_keyset;
    ble_gap_enc_info_t *             p_enc_info;
    
    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
            APP_ERROR_CHECK(err_code);
            m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            break;
            
        case BLE_GAP_EVT_DISCONNECTED:
            err_code = bsp_indication_set(BSP_INDICATE_IDLE);
            APP_ERROR_CHECK(err_code);
            m_conn_handle = BLE_CONN_HANDLE_INVALID;
            advertising_start();
            break;
            
        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
            s_sec_keyset.keys_periph.p_enc_key = NULL;
            err_code = sd_ble_gap_sec_params_reply(m_conn_handle, 
                                                   BLE_GAP_SEC_STATUS_SUCCESS, 
                                                   &m_sec_params,
                                                   &s_sec_keyset);
            APP_ERROR_CHECK(err_code);
            break;
            
        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
            err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GAP_EVT_AUTH_STATUS:
            // TODO: Adoptation to s110v8.0.0, is this needed anymore ?
            break;
            
        case BLE_GAP_EVT_SEC_INFO_REQUEST:
            if (s_sec_keyset.keys_periph.p_enc_key != NULL)
            {
                p_enc_info = &s_sec_keyset.keys_periph.p_enc_key->enc_info;
                err_code = sd_ble_gap_sec_info_reply(m_conn_handle, p_enc_info, NULL, NULL);
                APP_ERROR_CHECK(err_code);
            }
            else
            {
                // No keys found for this device.
                err_code = sd_ble_gap_sec_info_reply(m_conn_handle, NULL, NULL, NULL);
                APP_ERROR_CHECK(err_code);
            }
            break;

        case BLE_GAP_EVT_TIMEOUT:
            if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISING)
            { 
                err_code = bsp_indication_set(BSP_INDICATE_IDLE);
                APP_ERROR_CHECK(err_code);
                // Configure buttons with sense level low as wakeup source.
                err_code = bsp_buttons_enable(1 << WAKEUP_BUTTON_ID);
                APP_ERROR_CHECK(err_code);
                // Go to system-off mode (this function will not return; wakeup will cause a reset).
                err_code = sd_power_system_off();    
                APP_ERROR_CHECK(err_code);
            }
            break;

        default:
            // No implementation needed.
            break;
    }
}
Example #10
0
/**@brief       Function for the Application's S110 SoftDevice event handler.
 *
 * @param[in]   p_ble_evt   S110 SoftDevice event.
 */
static void on_ble_evt(ble_evt_t * p_ble_evt)
{
    uint32_t                         err_code;
    static ble_gap_evt_auth_status_t m_auth_status;
    ble_gap_enc_info_t *             p_enc_info;
    
    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            nrf_gpio_pin_set(CONNECTED_LED_PIN_NO);
            nrf_gpio_pin_clear(ADVERTISING_LED_PIN_NO);
            m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;

            break;
            
        case BLE_GAP_EVT_DISCONNECTED:
            nrf_gpio_pin_clear(CONNECTED_LED_PIN_NO);
            m_conn_handle = BLE_CONN_HANDLE_INVALID;

            advertising_start();

            break;
            
        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
            err_code = sd_ble_gap_sec_params_reply(m_conn_handle, 
                                                   BLE_GAP_SEC_STATUS_SUCCESS, 
                                                   &m_sec_params);
            APP_ERROR_CHECK(err_code);
            break;
            
        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
            err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GAP_EVT_AUTH_STATUS:
            m_auth_status = p_ble_evt->evt.gap_evt.params.auth_status;
            break;
            
        case BLE_GAP_EVT_SEC_INFO_REQUEST:
            p_enc_info = &m_auth_status.periph_keys.enc_info;
            if (p_enc_info->div == p_ble_evt->evt.gap_evt.params.sec_info_request.div)
            {
                err_code = sd_ble_gap_sec_info_reply(m_conn_handle, p_enc_info, NULL);
                APP_ERROR_CHECK(err_code);
            }
            else
            {
                // No keys found for this device
                err_code = sd_ble_gap_sec_info_reply(m_conn_handle, NULL, NULL);
                APP_ERROR_CHECK(err_code);
            }
            break;

        case BLE_GAP_EVT_TIMEOUT:
            if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISEMENT)
            { 
                nrf_gpio_pin_clear(ADVERTISING_LED_PIN_NO);

                // Configure buttons with sense level low as wakeup source.
                nrf_gpio_cfg_sense_input(WAKEUP_BUTTON_PIN,
                                         BUTTON_PULL,
                                         NRF_GPIO_PIN_SENSE_LOW);
                
                // Go to system-off mode (this function will not return; wakeup will cause a reset)
                err_code = sd_power_system_off();    
                APP_ERROR_CHECK(err_code);
            }
            break;
        case BLE_EVT_TX_COMPLETE:
            if(!ble_buffer_available) tx_complete = true;
            break;

        default:
            // No implementation needed.
            break;
    }
}
Example #11
0
static void on_ble_evt(ble_evt_t * p_ble_evt)
{
    uint32_t                         err_code;
    
    // security-related
    static ble_gap_evt_auth_status_t m_auth_status;
    bool                             master_id_matches;
    ble_gap_sec_kdist_t *            p_distributed_keys;
    ble_gap_enc_info_t *             p_enc_info;
    ble_gap_irk_t *                  p_id_info;
    ble_gap_sign_info_t *            p_sign_info;
    static ble_gap_enc_key_t         m_enc_key;           /**< Encryption Key (Encryption Info and Master ID). */
    static ble_gap_id_key_t          m_id_key;            /**< Identity Key (IRK and address). */
    static ble_gap_sign_info_t       m_sign_key;          /**< Signing Key (Connection Signature Resolving Key). */
    static ble_gap_sec_keyset_t      m_keys = {.keys_periph = {&m_enc_key, &m_id_key, &m_sign_key}};


    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:  //on BLE connect event
            m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            BLEonConnect();
            break;
        case BLE_GAP_EVT_DISCONNECTED:  //on BLE disconnect event
            m_conn_handle = BLE_CONN_HANDLE_INVALID;
            //debug_log("Disconnect reason: %d\r\n",(int)p_ble_evt->evt.gap_evt.params.disconnected.reason);
            BLEonDisconnect();
            break;
        case BLE_GAP_EVT_ADV_REPORT:  //On receipt of a response to an advertising request (during a scan)
            BLEonAdvReport(&(p_ble_evt->evt.gap_evt.params.adv_report));
            break;
        
        case BLE_GAP_EVT_TIMEOUT:
            if(p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_SCAN)  {
                //debug_log("Scan ended\r\n");
                BLEonScanTimeout();
            }
            /*else  {
                debug_log("Timeout.  src=%d\r\n", p_ble_evt->evt.gap_evt.params.timeout.src);
            }*/
            break;
            
        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
            err_code = sd_ble_gap_sec_params_reply(m_conn_handle,
                                                   BLE_GAP_SEC_STATUS_SUCCESS,
                                                   &m_sec_params,
                                                   &m_keys);
            BLE_ERROR_CHECK(err_code);
            break;
        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
            err_code = sd_ble_gatts_sys_attr_set(m_conn_handle,
                                                 NULL,
                                                 0,
                                                 BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS | BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS);
            BLE_ERROR_CHECK(err_code);
            break;
        case BLE_GAP_EVT_AUTH_STATUS:
            m_auth_status = p_ble_evt->evt.gap_evt.params.auth_status;
            break;
        case BLE_GAP_EVT_SEC_INFO_REQUEST:
            master_id_matches  = memcmp(&p_ble_evt->evt.gap_evt.params.sec_info_request.master_id,
                                        &m_enc_key.master_id,
                                        sizeof(ble_gap_master_id_t)) == 0;
            p_distributed_keys = &m_auth_status.kdist_periph;

            p_enc_info  = (p_distributed_keys->enc  && master_id_matches) ? &m_enc_key.enc_info : NULL;
            p_id_info   = (p_distributed_keys->id   && master_id_matches) ? &m_id_key.id_info   : NULL;
            p_sign_info = (p_distributed_keys->sign && master_id_matches) ? &m_sign_key         : NULL;

            err_code = sd_ble_gap_sec_info_reply(m_conn_handle, p_enc_info, p_id_info, p_sign_info);
                BLE_ERROR_CHECK(err_code);
            break;

        default:
            break;
    }
}
Example #12
0
/**@brief Function for handling the Application's BLE Stack events.
 *
 * @param[in]   p_ble_evt   Bluetooth stack event.
 */
static void on_ble_evt(ble_evt_t * p_ble_evt)
{
    uint32_t                         err_code;
    static uint16_t                  s_conn_handle = BLE_CONN_HANDLE_INVALID;
    static ble_gap_sec_keyset_t      s_sec_keyset;
    ble_gap_enc_info_t *             p_enc_info;

    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
            APP_ERROR_CHECK(err_code);
            s_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            break;
            
        case BLE_GAP_EVT_DISCONNECTED:
            err_code = bsp_indication_set(BSP_INDICATE_IDLE);
            APP_ERROR_CHECK(err_code);
            advertising_start();
            break;

        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
            s_sec_keyset.keys_central.p_enc_key = NULL;
            s_sec_keyset.keys_central.p_id_key  = NULL;
            s_sec_keyset.keys_central.p_enc_key = NULL;
            err_code = sd_ble_gap_sec_params_reply(s_conn_handle, 
                                                   BLE_GAP_SEC_STATUS_SUCCESS,        
                                                   &m_sec_params,
                                                   &s_sec_keyset);
            APP_ERROR_CHECK(err_code);
            break;
            
        case BLE_GAP_EVT_AUTH_STATUS:
            break;

        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
            err_code = sd_ble_gatts_sys_attr_set(s_conn_handle, NULL, 0, 0);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GAP_EVT_SEC_INFO_REQUEST:
            if (s_sec_keyset.keys_periph.p_enc_key != NULL)
            {
                p_enc_info = &s_sec_keyset.keys_periph.p_enc_key->enc_info;

                err_code = sd_ble_gap_sec_info_reply(s_conn_handle, p_enc_info, NULL, NULL);
                APP_ERROR_CHECK(err_code);
            }
            else
            {
                // No keys found for this device.
                err_code = sd_ble_gap_sec_info_reply(s_conn_handle, NULL, NULL, NULL);
                APP_ERROR_CHECK(err_code);
            }
            break;

        case BLE_GAP_EVT_TIMEOUT:
            if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISING)
            { 
                err_code = bsp_indication_set(BSP_INDICATE_IDLE);
                APP_ERROR_CHECK(err_code);

                err_code = app_button_disable();
                APP_ERROR_CHECK(err_code);
                
                if (err_code == NRF_SUCCESS)
                {
                    // Configure buttons with sense level low as wakeup source.
                    // err_code = bsp_buttons_enable((1 << BLE_BUTTON_ID) | (1 << GZLL_BUTTON_ID));

//                    nrf_gpio_cfg_sense_input(BLE_BUTTON_PIN_NO,
//                                             BUTTON_PULL,
//                                             NRF_GPIO_PIN_SENSE_LOW);
//                
//                    nrf_gpio_cfg_sense_input(GZLL_BUTTON_PIN_NO,
//                                             BUTTON_PULL,
//                                             NRF_GPIO_PIN_SENSE_LOW);

                    // Go to system-off mode.
                    // (this function will not return; wakeup will cause a reset)
                    err_code = sd_power_system_off();
                    APP_ERROR_CHECK(err_code);
                }
            }
            break;
            
        default: 
            // No implementation needed.
            break;
    }
}
Example #13
0
/**@brief Function for handling the Application's BLE Stack events.
 *
 * @param[in] p_ble_evt Bluetooth stack event.
 */
static void on_ble_evt(ble_evt_t * p_ble_evt) {
	uint32_t err_code = NRF_SUCCESS;
	static ble_gap_evt_auth_status_t m_auth_status;
	ble_gap_enc_info_t * p_enc_info;
	switch (p_ble_evt->header.evt_id) {
	case BLE_GAP_EVT_CONNECTED:
		nrf_gpio_pin_set(CONNECTED_LED_PIN_N);
		nrf_gpio_pin_clear(ADVERTISING_LED_PIN_N);
		m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;

		err_code = app_button_enable();
		break;
	case BLE_GAP_EVT_DISCONNECTED:
		nrf_gpio_pin_clear(CONNECTED_LED_PIN_N);
		m_conn_handle = BLE_CONN_HANDLE_INVALID;

		err_code = app_button_disable();
		if (err_code == NRF_SUCCESS) {
			advertising_start();
		}
		break;
	case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
		err_code = sd_ble_gap_sec_params_reply(m_conn_handle,
				BLE_GAP_SEC_STATUS_SUCCESS, &m_sec_params);
		break;
	case BLE_GATTS_EVT_SYS_ATTR_MISSING:
		err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0);
		break;

	case BLE_GAP_EVT_AUTH_STATUS:
		m_auth_status = p_ble_evt->evt.gap_evt.params.auth_status;
		break;
	case BLE_GAP_EVT_SEC_INFO_REQUEST:
		p_enc_info = &m_auth_status.periph_keys.enc_info;
		if (p_enc_info->div
				== p_ble_evt->evt.gap_evt.params.sec_info_request.div) {
			err_code = sd_ble_gap_sec_info_reply(m_conn_handle, p_enc_info,
					NULL);
		} else {
// No keys found for this device
			err_code = sd_ble_gap_sec_info_reply(m_conn_handle, NULL, NULL);
		}
		break;

	case BLE_GAP_EVT_TIMEOUT:
		if (p_ble_evt->evt.gap_evt.params.timeout.src
				== BLE_GAP_TIMEOUT_SRC_ADVERTISEMENT) {
			nrf_gpio_pin_clear(ADVERTISING_LED_PIN_N);

// Go to system-off mode (this function will not return; wakeup will cause a reset)
			GPIO_WAKEUP_BUTTON_CONFIG(WAKEUP_BUTTON_PIN);
			uart_tx_str("reset by timeout");
			err_code = sd_power_system_off();
		}
		break;

	case BLE_GATTS_EVT_WRITE:
		break;

	case BLE_GAP_EVT_CONN_PARAM_UPDATE:
		nrf_gpio_pin_toggle (LEDBUTTON_LED_PIN_NO);
		break;

	default:
		break;
	}

	APP_ERROR_CHECK(err_code);
}
Example #14
0
bool GAPController::bleConnectionEventHandler(ble_evt_t* bleEvent)
{
	u32 err = 0;

	//Depending on the type of the BLE event, we have to do different stuff
	//Further Events: http://developer.nordicsemi.com/nRF51_SDK/doc/7.1.0/s120/html/a00746.html#gada486dd3c0cce897b23a887bed284fef
	switch (bleEvent->header.evt_id)
	{
	//************************** GAP *****************************
	//########## Connection with other device
	case BLE_GAP_EVT_CONNECTED:
	{
		currentlyConnecting = false;

		// Our advertisement stopped because we received a connection on this packet (we are peripheral)
		if (bleEvent->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_PERIPH){
			AdvertisingController::AdvertisingInterruptedBecauseOfIncomingConnectionHandler();
		}

		logt("C", "Connected device");

		//Connection stops advertising
		connectionSuccessCallback(bleEvent);

		return true;
	}
		//########## Another Device disconnected
	case BLE_GAP_EVT_DISCONNECTED:
	{
		logt("C", "Disconnected device %d", bleEvent->evt.gap_evt.params.disconnected.reason);
		disconnectionCallback(bleEvent);

		return true;
	}
		break;

	case BLE_GAP_EVT_TIMEOUT:
	{
		if (bleEvent->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN)
		{
			currentlyConnecting = false;

			connectionTimeoutCallback(bleEvent);
		}
		break;
	}
	//The other device requested an encrypted connection
	case BLE_GAP_EVT_SEC_INFO_REQUEST:
	{
		//With this request, we receive the key identifier and a random number
		//This identification is used to select the correct key
		//We skip that process and select our mesh network key
		//TODO: Check what to do when we want different keys for Modules e.g.
		ble_gap_evt_sec_info_request_t securityRequest = bleEvent->evt.gap_evt.params.sec_info_request;

		//This is our security key
		ble_gap_enc_info_t key;
		key.auth = 1; //This key is authenticated
		memcpy(&key.ltk, Node::getInstance()->persistentConfig.networkKey, 16); //Copy our mesh network key
		key.ltk_len = 16;

		//Reply  with our stored key
		err = sd_ble_gap_sec_info_reply(
			bleEvent->evt.gap_evt.conn_handle,
			&key, //This is our stored long term key
			NULL, //We do not have an identity resolving key
			NULL //We do not have signing info
		);
		APP_ERROR_CHECK(err);

		logt("SEC", "SEC_INFO_REQUEST received, replying with key. result %d",  err);

		break;
	}
	//This event tells us that the security keys are now in use
	case BLE_GAP_EVT_CONN_SEC_UPDATE:
	{
		u8 keySize = bleEvent->evt.gap_evt.params.conn_sec_update.conn_sec.encr_key_size;

		u8 level = bleEvent->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv;
		u8 securityMode = bleEvent->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.sm;

		logt("SEC", "Connection key is now %u bytes, level %u, securityMode %u", keySize, level, securityMode);

		if(connectionEncryptedCallback) connectionEncryptedCallback(bleEvent);



		break;

	}
	//Another device wants to initiate a secure connection
	//Currently not used because the other method worked pretty good
	/*case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
	{

		//Security parameters: What is provided and what capabilities do we have?
		ble_gap_sec_params_t securityParameters;
		securityParameters.bond = 0; //We do not want to bond
		securityParameters.mitm = 1; //We need man in the middle protection
		securityParameters.io_caps = BLE_GAP_IO_CAPS_KEYBOARD_ONLY; //Use this if we want OOB method
		securityParameters.oob = 1; //We have out of band data (our mesh network key)
		securityParameters.min_key_size = 16; //We want 128bit key
		securityParameters.max_key_size = 16; //yes, we do
		securityParameters.kdist_periph.enc = 1; //We will provide a long term key for the connection
		securityParameters.kdist_periph.id = 0; //We do not provide an identity resolving key
		securityParameters.kdist_periph.sign = 0; //We do not provide a signature resolving key
		//Mhhh, ....?
		securityParameters.kdist_central.enc = 1;
		securityParameters.kdist_central.id = 0;
		securityParameters.kdist_central.sign = 0;


		ble_gap_enc_key_t key;
		key.enc_info.auth = 1;
		memcpy(&key.enc_info.ltk, &Config->meshNetworkKey, 16);
		key.enc_info.ltk_len = 16;

		key.master_id.ediv = 123;
		key.master_id.rand[0] = 234;



		//Keys
		ble_gap_sec_keyset_t keys;

		keys.keys_periph.p_enc_key = &key;
		keys.keys_periph.p_id_key = NULL;
		keys.keys_periph.p_sign_key = NULL;

		keys.keys_central.p_enc_key = &key;
		keys.keys_central.p_id_key = NULL;
		keys.keys_central.p_sign_key = NULL;


		//If we are central
		if(TestModule::isCentral)
		{
			err = sd_ble_gap_sec_params_reply(
					bleEvent->evt.gap_evt.conn_handle,
					BLE_GAP_SEC_STATUS_SUCCESS,
					NULL,
					&keys
				);

			logt("SEC", "SEC_PARAMS_REQUEST received as central, replying with result %d", err);
		}


		//We assume that we are peripheral
		else if(!TestModule::isCentral)
		{ //TODO: Check if we are peripheral




			err = sd_ble_gap_sec_params_reply(
					bleEvent->evt.gap_evt.conn_handle,
					BLE_GAP_SEC_STATUS_SUCCESS,
					&securityParameters,
					&keys
			);
			APP_ERROR_CHECK(err);


		}

		logt("SEC", "SEC_PARAMS_REQUEST received as peripheral, replying with result %d", err);


		break;
	}
	case BLE_GAP_EVT_AUTH_KEY_REQUEST:
	{
		err = sd_ble_gap_auth_key_reply(
			bleEvent->evt.gap_evt.conn_handle,
			BLE_GAP_AUTH_KEY_TYPE_OOB,
			Config->meshNetworkKey
		);
		APP_ERROR_CHECK(err);

		logt("SEC", "AUTH_KEY_REQUEST received, replying with result %d", err);

		break;
	}
	case BLE_GAP_EVT_AUTH_STATUS:
	{
		logt("SEC", "AUTH_STATUS: status %u", bleEvent->evt.gap_evt.params.auth_status.auth_status);
		logt("SEC", "AUTH_STATUS: bonded %u", bleEvent->evt.gap_evt.params.auth_status.bonded);

			break;
	}*/


	default:
		break;
	}
	return false;
}
void BLETransceiver::onBleEvt(ble_evt_t * p_ble_evt)
{
	uint32_t                         err_code;
	static ble_gap_evt_auth_status_t m_auth_status;
	ble_gap_enc_info_t *             p_enc_info;

	LOG_VERBOSE_LN("BLE event received : %d", p_ble_evt->header.evt_id);

	switch (p_ble_evt->header.evt_id)
	{
	case BLE_GAP_EVT_CONNECTED:
		//RP - 14/01/2015 - notify
		u16_connHandle = p_ble_evt->evt.gap_evt.conn_handle;
		b_isAdvertising = false;
		if(p_transceiverListener)
		{
			p_transceiverListener->onConnection();
		}
		break;

	case BLE_GAP_EVT_DISCONNECTED:
		u16_connHandle = BLE_CONN_HANDLE_INVALID;
		if(p_transceiverListener)
		{
			p_transceiverListener->onDisconnection();
		}
		break;

	case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
		err_code = sd_ble_gap_sec_params_reply(u16_connHandle,
				BLE_GAP_SEC_STATUS_SUCCESS,
				&secParams);
		APP_ERROR_CHECK(err_code);
		break;

	case BLE_GATTS_EVT_SYS_ATTR_MISSING:
		err_code = sd_ble_gatts_sys_attr_set(u16_connHandle, NULL, 0);
		APP_ERROR_CHECK(err_code);
		break;

	case BLE_GAP_EVT_AUTH_STATUS:
		m_auth_status = p_ble_evt->evt.gap_evt.params.auth_status;
		break;

	case BLE_GAP_EVT_SEC_INFO_REQUEST:
		p_enc_info = &m_auth_status.periph_keys.enc_info;
		if (p_enc_info->div == p_ble_evt->evt.gap_evt.params.sec_info_request.div)
		{
			err_code = sd_ble_gap_sec_info_reply(u16_connHandle, p_enc_info, NULL);
			APP_ERROR_CHECK(err_code);
		}
		else
		{
			// No keys found for this device
			err_code = sd_ble_gap_sec_info_reply(u16_connHandle, NULL, NULL);
			APP_ERROR_CHECK(err_code);
		}
		break;

	case BLE_GAP_EVT_TIMEOUT:
		if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISEMENT)
		{
			//RP - 14/01/2015 - notify

			// Configure buttons with sense level low as wakeup source.

			//RP do not power off
			//                nrf_gpio_cfg_sense_input(WAKEUP_BUTTON_PIN,
			//                                         BUTTON_PULL,
			//                                         NRF_GPIO_PIN_SENSE_LOW);

			// Go to system-off mode (this function will not return; wakeup will cause a reset)
			//                err_code = sd_power_system_off();
			//                APP_ERROR_CHECK(err_code);
		}
		break;

	case BLE_GAP_EVT_RSSI_CHANGED:
		if(p_transceiverListener)
		{
			p_transceiverListener->onRSSIChange(p_ble_evt->evt.gap_evt.params.rssi_changed.rssi);
		}
		break;

	default:
		// No implementation needed.
		break;
	}
}
Example #16
0
/**@brief Function for handling the Application's BLE Stack events.
 *
 * @param[in]   p_ble_evt   Bluetooth stack event.
 */
static void on_ble_evt(ble_evt_t * p_ble_evt) {
    uint32_t                         err_code;

    switch (p_ble_evt->header.evt_id) {
        case BLE_GAP_EVT_CONNECTED:
            // continue advertising nonconnectably
            app.conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            m_adv_params.type = BLE_GAP_ADV_TYPE_ADV_NONCONN_IND;
            advertising_start();
            break;

        case BLE_GAP_EVT_DISCONNECTED:
            app.conn_handle = BLE_CONN_HANDLE_INVALID;

            // advertise connectivity
            advertising_stop();
            m_adv_params.type   = BLE_GAP_ADV_TYPE_ADV_IND;
            advertising_start();
            break;

        case BLE_GATTS_EVT_WRITE:
            {
                ble_gatts_evt_write_t* write_data = &(p_ble_evt->evt.gatts_evt.params.write);
                if (write_data->context.char_uuid.uuid == test_char_uuid16) {
                    if (write_data->data[0] == 0x42) {
                        //led_on(BLEES_LED_PIN);

                        // enable higher connection interval. Only lasts for this connection
                        ble_gap_conn_params_t   gap_conn_params;
                        memset(&gap_conn_params, 0, sizeof(gap_conn_params));
                        gap_conn_params.min_conn_interval = 0x06; // 7.5 ms
                        gap_conn_params.max_conn_interval = MSEC_TO_UNITS(30, UNIT_1_25_MS);
                        gap_conn_params.slave_latency     = 0;
                        gap_conn_params.conn_sup_timeout  = CONN_SUP_TIMEOUT;
                        err_code = sd_ble_gap_conn_param_update(app.conn_handle, &gap_conn_params);
                        APP_ERROR_CHECK(err_code);
                    }
                }
            }
            break;

        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
            err_code = sd_ble_gap_sec_params_reply(app.conn_handle,
                    BLE_GAP_SEC_STATUS_SUCCESS, &m_sec_params, NULL);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
            err_code = sd_ble_gatts_sys_attr_set(app.conn_handle, NULL, 0, 0);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GAP_EVT_AUTH_STATUS:
            break;

        case BLE_GAP_EVT_SEC_INFO_REQUEST:
            // No keys found for this device.
            err_code = sd_ble_gap_sec_info_reply(app.conn_handle, NULL, NULL, NULL);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GAP_EVT_TIMEOUT:
            if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISING) {
                err_code = sd_power_system_off();
                APP_ERROR_CHECK(err_code);
            }
            break;

        default:
            break;
    }
}
Example #17
0
/**@brief Function for handling the Application's BLE Stack events.
 *
 * @param[in] p_ble_evt  Bluetooth stack event.
 */
static void on_ble_evt(ble_evt_t * p_ble_evt)
{
  printf("on_ble_evt %d", p_ble_evt->header.evt_id);
    uint32_t                         err_code;
    static ble_gap_sec_keyset_t      s_sec_keyset;
    ble_gap_enc_info_t *             p_enc_info;
    
    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            bta_bleConnected();
            break;
            
        case BLE_GAP_EVT_DISCONNECTED:
            m_conn_handle = BLE_CONN_HANDLE_INVALID;
            bta_bleDisconnected();
            break;
            
        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
            s_sec_keyset.keys_periph.p_enc_key = NULL;
            err_code = sd_ble_gap_sec_params_reply(m_conn_handle, 
                                                   BLE_GAP_SEC_STATUS_SUCCESS, 
                                                   &m_sec_params,
                                                   &s_sec_keyset);
            APP_ERROR_CHECK(err_code);
            break;
            
        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
            err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GAP_EVT_AUTH_STATUS:
            // TODO: Adoptation to s110v8.0.0, is this needed anymore ?
            break;
            
        case BLE_GAP_EVT_SEC_INFO_REQUEST:
            if (s_sec_keyset.keys_periph.p_enc_key != NULL)
            {
                p_enc_info = &s_sec_keyset.keys_periph.p_enc_key->enc_info;
                err_code = sd_ble_gap_sec_info_reply(m_conn_handle, p_enc_info, NULL, NULL);
                APP_ERROR_CHECK(err_code);
            }
            else
            {
                // No keys found for this device.
                err_code = sd_ble_gap_sec_info_reply(m_conn_handle, NULL, NULL, NULL);
                APP_ERROR_CHECK(err_code);
            }
            break;

        case BLE_GAP_EVT_TIMEOUT:
            if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISING)
            { 
              bta_bleAdvertiseTimeout();
            }
            break;

        default:
            // No implementation needed.
            break;
    }
}
Example #18
0
/**@brief Function for handling the Application's BLE Stack events.
 *
 * @param[in]   p_ble_evt   Bluetooth stack event.
 */
static void on_ble_evt(ble_evt_t * p_ble_evt)
{
    uint32_t                         err_code;
    static ble_gap_evt_auth_status_t m_auth_status;
    ble_gap_enc_info_t *             p_enc_info;

    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            nrf_gpio_pin_set(CONNECTED_LED_PIN_NO);
            nrf_gpio_pin_clear(ADVERTISING_LED_PIN_NO);
            m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;

            /* YOUR_JOB: Uncomment this part if you are using the app_button module to handle button
                         events (assuming that the button events are only needed in connected
                         state). If this is uncommented out here,
                            1. Make sure that app_button_disable() is called when handling
                               BLE_GAP_EVT_DISCONNECTED below.
                            2. Make sure the app_button module is initialized.
            err_code = app_button_enable();
            APP_ERROR_CHECK(err_code);
            */
            break;

        case BLE_GAP_EVT_DISCONNECTED:
            nrf_gpio_pin_clear(CONNECTED_LED_PIN_NO);
            m_conn_handle = BLE_CONN_HANDLE_INVALID;

            /* YOUR_JOB: Uncomment this part if you are using the app_button module to handle button
                         events. This should be done to save power when not connected
                         to a peer.
            err_code = app_button_disable();
            APP_ERROR_CHECK(err_code);
            */
            
                advertising_start();
            break;

        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
            err_code = sd_ble_gap_sec_params_reply(m_conn_handle,
                                                   BLE_GAP_SEC_STATUS_SUCCESS,
                                                   &m_sec_params);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
            err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GAP_EVT_AUTH_STATUS:
            m_auth_status = p_ble_evt->evt.gap_evt.params.auth_status;
            break;

        case BLE_GAP_EVT_SEC_INFO_REQUEST:
            p_enc_info = &m_auth_status.periph_keys.enc_info;
            if (p_enc_info->div == p_ble_evt->evt.gap_evt.params.sec_info_request.div)
            {
                err_code = sd_ble_gap_sec_info_reply(m_conn_handle, p_enc_info, NULL);
                APP_ERROR_CHECK(err_code);
            }
            else
            {
                // No keys found for this device
                err_code = sd_ble_gap_sec_info_reply(m_conn_handle, NULL, NULL);
                APP_ERROR_CHECK(err_code);
            }
            break;

        case BLE_GAP_EVT_TIMEOUT:
            if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISEMENT)
            {
                nrf_gpio_pin_clear(ADVERTISING_LED_PIN_NO);

                // Configure buttons with sense level low as wakeup source.
                nrf_gpio_cfg_sense_input(WAKEUP_BUTTON_PIN,
                                         BUTTON_PULL,
                                         NRF_GPIO_PIN_SENSE_LOW);
                
                // Go to system-off mode (this function will not return; wakeup will cause a reset)                
                err_code = sd_power_system_off();
                APP_ERROR_CHECK(err_code);
            }
            break;

        default:
            // No implementation needed.
            break;
    }
}
Example #19
0
/**@brief Application's BLE Stack event handler.
 *
 * @param[in]   p_ble_evt   Bluetooth stack event.
 */
static void on_ble_evt(ble_evt_t * p_ble_evt)
{
    uint32_t                         err_code = NRF_SUCCESS;
    static ble_gap_evt_auth_status_t m_auth_status;
    ble_gap_enc_info_t *             p_enc_info;
    
    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            nrf_gpio_pin_set(LED_OTHER);
						BLESessionActive = 1;
        
            break;
            
        case BLE_GAP_EVT_DISCONNECTED:
            advertising_start();
				
						BLESessionActive = 0;
						sendRawData = 0;
            
						do_post_processing = true;
            nrf_gpio_pin_clear(LED_OTHER);
            
            break;
            
        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
            err_code = sd_ble_gap_sec_params_reply(m_conn_handle, 
                                                   BLE_GAP_SEC_STATUS_SUCCESS, 
                                                   &m_sec_params);
            APP_ERROR_CHECK(err_code);
            break;
            
        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
            err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GAP_EVT_AUTH_STATUS:
            m_auth_status = p_ble_evt->evt.gap_evt.params.auth_status;
            break;
            
        case BLE_GAP_EVT_SEC_INFO_REQUEST:
            p_enc_info = &m_auth_status.periph_keys.enc_info;
            if (p_enc_info->div == p_ble_evt->evt.gap_evt.params.sec_info_request.div)
            {
                err_code = sd_ble_gap_sec_info_reply(m_conn_handle, p_enc_info, NULL);
                APP_ERROR_CHECK(err_code);
            }
            else
            {
                // No keys found for this device
                err_code = sd_ble_gap_sec_info_reply(m_conn_handle, NULL, NULL);
                APP_ERROR_CHECK(err_code);
            }
            break;

        case BLE_GAP_EVT_TIMEOUT:
            if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISEMENT)
            { 
                //nrf_gpio_pin_clear(ADVERTISING_LED_PIN_NO);

                // Go to system-off mode (this function will not return; wakeup will cause a reset)
                GPIO_WAKEUP_BUTTON_CONFIG(WAKEUP_BUTTON_PIN);
                
                err_code = sd_power_system_off();    
                APP_ERROR_CHECK(err_code);
            }
            break;

        default:
            break;
    }

    APP_ERROR_CHECK(err_code);
}
Example #20
0
/**@brief Function for handling the Application's BLE Stack events.
 *
 * @param[in]   p_ble_evt   Bluetooth stack event.
 */
static void on_ble_evt(ble_evt_t * p_ble_evt)
{
    uint32_t                         err_code;
    static ble_gap_evt_auth_status_t m_auth_status;
    bool                             master_id_matches;
    ble_gap_sec_kdist_t *            p_distributed_keys;
    ble_gap_enc_info_t *             p_enc_info;
    ble_gap_irk_t *                  p_id_info;
    ble_gap_sign_info_t *            p_sign_info;

    static ble_gap_enc_key_t         m_enc_key;           /**< Encryption Key (Encryption Info and Master ID). */
    static ble_gap_id_key_t          m_id_key;            /**< Identity Key (IRK and address). */
    static ble_gap_sign_info_t       m_sign_key;          /**< Signing Key (Connection Signature Resolving Key). */
    static ble_gap_sec_keyset_t      m_keys = {.keys_periph = {&m_enc_key, &m_id_key, &m_sign_key}};

    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
            APP_ERROR_CHECK(err_code);
            m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;

            /* YOUR_JOB: Uncomment this part if you are using the app_button module to handle button
                         events (assuming that the button events are only needed in connected
                         state). If this is uncommented out here,
                            1. Make sure that app_button_disable() is called when handling
                               BLE_GAP_EVT_DISCONNECTED below.
                            2. Make sure the app_button module is initialized.
            err_code = app_button_enable();
            APP_ERROR_CHECK(err_code);
            */
            break;

        case BLE_GAP_EVT_DISCONNECTED:
            err_code = bsp_indication_set(BSP_INDICATE_IDLE);
            APP_ERROR_CHECK(err_code);
            m_conn_handle = BLE_CONN_HANDLE_INVALID;

            /* YOUR_JOB: Uncomment this part if you are using the app_button module to handle button
                         events. This should be done to save power when not connected
                         to a peer.
            err_code = app_button_disable();
            APP_ERROR_CHECK(err_code);
            */

            advertising_start();
            break;

        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
            err_code = sd_ble_gap_sec_params_reply(m_conn_handle,
                                                   BLE_GAP_SEC_STATUS_SUCCESS,
                                                   &m_sec_params,
                                                   &m_keys);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
            err_code = sd_ble_gatts_sys_attr_set(m_conn_handle,
                                                 NULL,
                                                 0,
                                                 BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS | BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GAP_EVT_AUTH_STATUS:
            m_auth_status = p_ble_evt->evt.gap_evt.params.auth_status;
            break;

        case BLE_GAP_EVT_SEC_INFO_REQUEST:
            master_id_matches  = memcmp(&p_ble_evt->evt.gap_evt.params.sec_info_request.master_id,
                                        &m_enc_key.master_id,
                                        sizeof(ble_gap_master_id_t)) == 0;
            p_distributed_keys = &m_auth_status.kdist_periph;

            p_enc_info  = (p_distributed_keys->enc  && master_id_matches) ? &m_enc_key.enc_info : NULL;
            p_id_info   = (p_distributed_keys->id   && master_id_matches) ? &m_id_key.id_info   : NULL;
            p_sign_info = (p_distributed_keys->sign && master_id_matches) ? &m_sign_key         : NULL;

            err_code = sd_ble_gap_sec_info_reply(m_conn_handle, p_enc_info, p_id_info, p_sign_info);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GAP_EVT_TIMEOUT:
            if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISING)
            {
                err_code = bsp_indication_set(BSP_INDICATE_IDLE);
                APP_ERROR_CHECK(err_code);
                // Configure buttons with sense level low as wakeup source.
                err_code = bsp_buttons_enable(1 << WAKEUP_BUTTON_ID);
                APP_ERROR_CHECK(err_code);
                // Go to system-off mode (this function will not return; wakeup will cause a reset)
                err_code = sd_power_system_off();
                APP_ERROR_CHECK(err_code);
            }
            break;

        default:
            // No implementation needed.
            break;
    }
}
/**@brief Function for handling the Application's BLE Stack events.
 *
 * @param[in]   p_ble_evt   Bluetooth stack event.
 */
static void on_ble_evt(ble_evt_t * p_ble_evt)
{
    uint32_t                         err_code;
    static ble_gap_evt_auth_status_t m_auth_status;
    bool                             master_id_matches;
    ble_gap_sec_kdist_t *            p_distributed_keys;
    ble_gap_enc_info_t *             p_enc_info;
    ble_gap_irk_t *                  p_id_info;
    ble_gap_sign_info_t *            p_sign_info;

    static ble_gap_enc_key_t         m_enc_key;           /**< Encryption Key (Encryption Info and Master ID). */
    static ble_gap_id_key_t          m_id_key;            /**< Identity Key (IRK and address). */
    static ble_gap_sign_info_t       m_sign_key;          /**< Signing Key (Connection Signature Resolving Key). */
    static ble_gap_sec_keyset_t      m_keys = {.keys_periph = {&m_enc_key, &m_id_key, &m_sign_key}};

    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            break;

        case BLE_GAP_EVT_DISCONNECTED:
            m_conn_handle = BLE_CONN_HANDLE_INVALID;         
            advertising_start();
            break;

        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
            err_code = sd_ble_gap_sec_params_reply(m_conn_handle,
                                                   BLE_GAP_SEC_STATUS_SUCCESS,
                                                   &m_sec_params,
                                                   &m_keys);
            APP_ERROR_CHECK(err_code);// Check for errors
            break;

        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
            err_code = sd_ble_gatts_sys_attr_set(m_conn_handle,
                                                 NULL,
                                                 0,
                                                 BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS | BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS);
            APP_ERROR_CHECK(err_code);// Check for errors
            break;

        case BLE_GAP_EVT_AUTH_STATUS:
            m_auth_status = p_ble_evt->evt.gap_evt.params.auth_status;
            break;

        case BLE_GAP_EVT_SEC_INFO_REQUEST:
            master_id_matches  = memcmp(&p_ble_evt->evt.gap_evt.params.sec_info_request.master_id,
                                        &m_enc_key.master_id,
                                        sizeof(ble_gap_master_id_t)) == 0;
            p_distributed_keys = &m_auth_status.kdist_periph;

            p_enc_info  = (p_distributed_keys->enc  && master_id_matches) ? &m_enc_key.enc_info : NULL;
            p_id_info   = (p_distributed_keys->id   && master_id_matches) ? &m_id_key.id_info   : NULL;
            p_sign_info = (p_distributed_keys->sign && master_id_matches) ? &m_sign_key         : NULL;

            err_code = sd_ble_gap_sec_info_reply(m_conn_handle, p_enc_info, p_id_info, p_sign_info);
            APP_ERROR_CHECK(err_code);// Check for errors
            break;

        case BLE_GAP_EVT_TIMEOUT:
            if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISING)
            {
                // Go to system-off mode (this function will not return; wakeup will cause a reset)                
                err_code = sd_power_system_off();
                APP_ERROR_CHECK(err_code);// Check for errors
            }
            break;

        default:
            // No implementation needed.
            break;
    }
}
/**@brief Function for handling the Application's BLE Stack events.
 *
 * @param[in]   p_ble_evt   Bluetooth stack event.
 */
static void on_ble_evt(ble_evt_t * p_ble_evt)
{
  uint32_t                         err_code;
  static ble_gap_evt_auth_status_t m_auth_status;
  static ble_gap_master_id_t p_master_id;
  static ble_gap_sec_keyset_t keys_exchanged;
  SEGGER_RTT_WriteString(0,"\n--> IN on_ble_evt (a BLE event has come into main.c\n");

  switch (p_ble_evt->header.evt_id)
  {
    case BLE_GAP_EVT_CONNECTED:
      SEGGER_RTT_WriteString(0,"\n... BLE_GAP_EVT_CONNECTED\n");
      m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;

      break;

    case BLE_GAP_EVT_DISCONNECTED:
      SEGGER_RTT_WriteString(0,"\n... BLE_GAP_EVT_DISCONNECTED\n");
      m_conn_handle = BLE_CONN_HANDLE_INVALID;
      advertising_start();
      break;

    case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
      SEGGER_RTT_WriteString(0,"\n... BLE_GAP_EVT_SEC_PARAMS_REQUEST\n");
      err_code = sd_ble_gap_sec_params_reply(m_conn_handle,
					     BLE_GAP_SEC_STATUS_SUCCESS,
					     &m_sec_params,&keys_exchanged);
      APP_ERROR_CHECK(err_code);
      break;

    case BLE_GATTS_EVT_SYS_ATTR_MISSING:
      SEGGER_RTT_WriteString(0,"\n... BLE_GATTS_EVT_SYS_ATTR_MISSING\n");
      err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0,BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS);
      APP_ERROR_CHECK(err_code);
      break;

    case BLE_GAP_EVT_AUTH_STATUS:
      SEGGER_RTT_WriteString(0,"\n... BLE_GAP_EVT_AUTH_STATUS\n");
      m_auth_status = p_ble_evt->evt.gap_evt.params.auth_status;
      break;

    case BLE_GAP_EVT_SEC_INFO_REQUEST:
      //p_enc_info = keys_exchanged.keys_central.p_enc_key
      SEGGER_RTT_WriteString(0,"\n... BLE_GAP_EVT_SEC_INFO_REQUEST\n");
      if (p_master_id.ediv == p_ble_evt->evt.gap_evt.params.sec_info_request.master_id.ediv)
	{
	  err_code = sd_ble_gap_sec_info_reply(m_conn_handle, &keys_exchanged.keys_central.p_enc_key->enc_info, &keys_exchanged.keys_central.p_id_key->id_info, NULL);
	  APP_ERROR_CHECK(err_code);
	  p_master_id.ediv = p_ble_evt->evt.gap_evt.params.sec_info_request.master_id.ediv;
	}
      else
	{
	  // No keys found for this device
	  err_code = sd_ble_gap_sec_info_reply(m_conn_handle, NULL, NULL,NULL);
	  APP_ERROR_CHECK(err_code);
	}
      break;

    case BLE_GAP_EVT_TIMEOUT:
      SEGGER_RTT_WriteString(0,"\n... BLE_GAP_EVT_TIMEOUT\n");
      if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISING)
	{
	  // Go to system-off mode (this function will not return; wakeup will cause a reset)
	  err_code = sd_power_system_off();
	  APP_ERROR_CHECK(err_code);
	}
      break;

    default:
      SEGGER_RTT_WriteString(0,"\n... Not handling a BLE event here.\n");
      // No implementation needed.
      break;
  }
}
Example #23
0
/**@brief Function for the Application's SoftDevice event handler.
 *
 * @param[in] p_ble_evt SoftDevice event.
 */
static void on_ble_evt(ble_evt_t * p_ble_evt)
{
    uint32_t err_code;

    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            dfu_set_status(DFUS_ADVERTISING_STOP);
            dfu_set_status(DFUS_CONNECTED);

            m_conn_handle    = p_ble_evt->evt.gap_evt.conn_handle;
            m_flags &= ~DFU_BLE_FLAG_IS_ADVERTISING;
            break;

        case BLE_GAP_EVT_DISCONNECTED:
            // Restart advertising so that the DFU Controller can reconnect if possible.
            dfu_set_status(DFUS_DISCONNECTED);
            err_code = advertising_start();
            APP_ERROR_CHECK(err_code);

            m_conn_handle = BLE_CONN_HANDLE_INVALID;

            break;

        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
            {
                err_code = sd_ble_gap_sec_params_reply(m_conn_handle,
                                                       BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP,
                                                       NULL,
                                                       NULL);
                APP_ERROR_CHECK(err_code);
            }
            break;

        case BLE_GATTS_EVT_TIMEOUT:
            if (p_ble_evt->evt.gatts_evt.params.timeout.src == BLE_GATT_TIMEOUT_SRC_PROTOCOL)
            {
                err_code = sd_ble_gap_disconnect(m_conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
            }
            break;

        case BLE_EVT_USER_MEM_REQUEST:
            err_code = sd_ble_user_mem_reply(m_conn_handle, NULL);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
            if (p_ble_evt->evt.gatts_evt.params.authorize_request.type
                != BLE_GATTS_AUTHORIZE_TYPE_INVALID)
            {
                if (on_rw_authorize_req(&m_dfu, p_ble_evt))
                {
                    err_code = on_ctrl_pt_write(&m_dfu, 
                           &(p_ble_evt->evt.gatts_evt.params.authorize_request.request.write));
#ifdef NRF_DFU_DEBUG_VERSION  
                    if (err_code != NRF_SUCCESS)
                    {
                        NRF_LOG_ERROR("Could not handle on_ctrl_pt_write. err_code: 0x%04x\r\n", err_code);
                    }
#else
                    // Swallow result
                    (void) err_code;
#endif
                }
            }
            break;

        case BLE_GAP_EVT_SEC_INFO_REQUEST:
            err_code = sd_ble_gap_sec_info_reply(p_ble_evt->evt.gap_evt.conn_handle, NULL, NULL, NULL);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
            err_code = sd_ble_gatts_sys_attr_set(p_ble_evt->evt.gap_evt.conn_handle, NULL, 0, 0);
            APP_ERROR_CHECK(err_code);
            break;
        
        case BLE_GATTS_EVT_WRITE:
            on_write(&m_dfu, p_ble_evt);
            break;

#if (NRF_SD_BLE_API_VERSION == 3)
        case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST:
            err_code = sd_ble_gatts_exchange_mtu_reply(p_ble_evt->evt.gatts_evt.conn_handle, 
                                                       NRF_BLE_MAX_MTU_SIZE);
            APP_ERROR_CHECK(err_code);
            break; // BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST
#endif
        
        default:
            // No implementation needed.
            break;
    }
}
Example #24
0
/**
 * @brief BLEスタックイベントハンドラ
 *
 * @param[in]   p_ble_evt   BLEスタックイベント
 */
static void ble_evt_handler(ble_evt_t *p_ble_evt)
{
    uint32_t                         err_code;
    static ble_gap_evt_auth_status_t m_auth_status;
	bool                             master_id_matches;
	ble_gap_sec_kdist_t *            p_distributed_keys;
    ble_gap_enc_info_t               *p_enc_info;
	ble_gap_irk_t *                  p_id_info;
	ble_gap_sign_info_t *            p_sign_info;

    static ble_gap_enc_key_t         m_enc_key;           /**< Encryption Key (Encryption Info and Master ID). */
    static ble_gap_id_key_t          m_id_key;            /**< Identity Key (IRK and address). */
    static ble_gap_sign_info_t       m_sign_key;          /**< Signing Key (Connection Signature Resolving Key). */
    static ble_gap_sec_keyset_t      sec_key = {.keys_periph = {&m_enc_key, &m_id_key, &m_sign_key}};


    switch (p_ble_evt->header.evt_id) {
    /*************
     * GAP event
     *************/

    //接続が成立したとき
    case BLE_GAP_EVT_CONNECTED:
        app_trace_log("BLE_GAP_EVT_CONNECTED\r\n");
        led_on(LED_PIN_NO_CONNECTED);
        led_off(LED_PIN_NO_ADVERTISING);
        m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
        break;

    //相手から切断されたとき
    //必要があればsd_ble_gatts_sys_attr_get()でSystem Attributeを取得し、保持しておく。
    //保持したSystem Attributeは、EVT_SYS_ATTR_MISSINGで返すことになる。
    case BLE_GAP_EVT_DISCONNECTED:
        app_trace_log("BLE_GAP_EVT_DISCONNECTED\r\n");
        led_off(LED_PIN_NO_CONNECTED);
        m_conn_handle = BLE_CONN_HANDLE_INVALID;

        app_ble_start();
        break;

    //SMP Paring要求を受信したとき
    //sd_ble_gap_sec_params_reply()で値を返したあと、SMP Paring Phase 2に状態遷移する
    case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
        app_trace_log("BLE_GAP_EVT_SEC_PARAMS_REQUEST\r\n");
        {
            ble_gap_sec_params_t sec_param;
            sec_param.bond         = SEC_PARAM_BOND;
            sec_param.mitm         = SEC_PARAM_MITM;
            sec_param.io_caps      = SEC_PARAM_IO_CAPABILITIES;
            sec_param.oob          = SEC_PARAM_OOB;
            sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE;
            sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE;
            err_code = sd_ble_gap_sec_params_reply(m_conn_handle,
                                               BLE_GAP_SEC_STATUS_SUCCESS,
                                               &sec_param,
                                               &sec_key);
            APP_ERROR_CHECK(err_code);
        }
        break;

    //Just Works(Bonding有り)の場合、SMP Paring Phase 3のあとでPeripheral Keyが渡される。
    //ここではPeripheral Keyを保存だけしておき、次のBLE_GAP_EVT_SEC_INFO_REQUESTで処理する。
    case BLE_GAP_EVT_AUTH_STATUS:
        app_trace_log("BLE_GAP_EVT_AUTH_STATUS\r\n");
        m_auth_status = p_ble_evt->evt.gap_evt.params.auth_status;
        break;

    //SMP Paringが終わったとき?
    case BLE_GAP_EVT_SEC_INFO_REQUEST:
        app_trace_log("BLE_GAP_EVT_SEC_INFO_REQUEST\r\n");
		master_id_matches  = memcmp(&p_ble_evt->evt.gap_evt.params.sec_info_request.master_id,
		                            &m_enc_key.master_id,
		                            sizeof(ble_gap_master_id_t)) == 0;
		p_distributed_keys = &m_auth_status.kdist_periph;

		p_enc_info  = (p_distributed_keys->enc  && master_id_matches) ? &m_enc_key.enc_info : NULL;
		p_id_info   = (p_distributed_keys->id   && master_id_matches) ? &m_id_key.id_info   : NULL;
		p_sign_info = (p_distributed_keys->sign && master_id_matches) ? &m_sign_key         : NULL;
		err_code = sd_ble_gap_sec_info_reply(m_conn_handle, p_enc_info, p_id_info, p_sign_info);
        APP_ERROR_CHECK(err_code);
        break;

    //Advertisingか認証のタイムアウト発生
    case BLE_GAP_EVT_TIMEOUT:
        app_trace_log("BLE_GAP_EVT_TIMEOUT\r\n");
        switch (p_ble_evt->evt.gap_evt.params.timeout.src) {
        case BLE_GAP_TIMEOUT_SRC_ADVERTISING: //Advertisingのタイムアウト
            /* Advertising LEDを消灯 */
            led_off(LED_PIN_NO_ADVERTISING);

            /* System-OFFにする(もう戻ってこない) */
            err_code = sd_power_system_off();
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GAP_TIMEOUT_SRC_SECURITY_REQUEST:  //Security requestのタイムアウト
            break;

        default:
            break;
        }
        break;

    /*********************
     * GATT Server event
     *********************/

    //接続後、Bondingした相手からSystem Attribute要求を受信したとき
    //System Attributeは、EVT_DISCONNECTEDで保持するが、今回は保持しないのでNULLを返す。
    case BLE_GATTS_EVT_SYS_ATTR_MISSING:
        app_trace_log("BLE_GATTS_EVT_SYS_ATTR_MISSING\r\n");
        err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0,
        			BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS | BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS);
        APP_ERROR_CHECK(err_code);
        break;

    default:
        // No implementation needed.
        break;
    }
}
Example #25
0
// handler for application's BLE Stack events
static void on_ble_evt(ble_evt_t * p_ble_evt) {
    uint32_t err_code;

    switch(p_ble_evt->header.evt_id) {
        case BLE_GAP_EVT_CONNECTED:
            app.conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            // resume advertising, but not connectably
            m_adv_params.type = BLE_GAP_ADV_TYPE_ADV_NONCONN_IND;
            advertising_start();
            break;
        
        case BLE_GAP_EVT_DISCONNECTED:
            app.conn_handle = BLE_CONN_HANDLE_INVALID;
            // go back to advertising connectably
            advertising_stop();
            m_adv_params.type = BLE_GAP_ADV_TYPE_ADV_IND;
            advertising_start();
            break;

        case BLE_GATTS_EVT_WRITE:
            //do to
            break;
        
        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
            err_code = sd_ble_gap_sec_params_reply(app.conn_handle,
                        BLE_GAP_SEC_STATUS_SUCCESS, &m_sec_params, NULL);
            APP_ERROR_CHECK(err_code);
            break;
        
        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
            err_code = sd_ble_gatts_sys_attr_set(app.conn_handle, NULL, 0, 0);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GAP_EVT_AUTH_STATUS:
            break;

        case BLE_GAP_EVT_SEC_INFO_REQUEST:
            // no keys found for this device
            err_code = sd_ble_gap_sec_info_reply(app.conn_handle, NULL, NULL, NULL);
            APP_ERROR_CHECK(err_code);
            break;
        
        case BLE_GAP_EVT_TIMEOUT:
            if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISING) {
                err_code = sd_power_system_off();
                APP_ERROR_CHECK(err_code);
            }
            break;
        
        case BLE_GATTS_EVT_TIMEOUT:
            if (p_ble_evt->evt.gatts_evt.params.timeout.src == BLE_GATT_TIMEOUT_SRC_PROTOCOL) {
                err_code = sd_ble_gap_disconnect(m_conn_handle,
                                                    BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
            }
            break;

        default:
            break;
    }
}