예제 #1
0
uint32_t conn_mw_ble_gatts_sys_attr_get(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);

    uint16_t conn_handle;

    uint8_t sys_attr[BLE_GATTS_VAR_ATTR_LEN_MAX];

    uint8_t *  p_sys_attr     = sys_attr;
    uint16_t   sys_attr_len   = sizeof (sys_attr);
    uint16_t * p_sys_attr_len = &sys_attr_len;
    
    uint32_t   flags;

    uint32_t err_code = NRF_SUCCESS;
    uint32_t sd_err_code;

    err_code = ble_gatts_sys_attr_get_req_dec(p_rx_buf, rx_buf_len, &conn_handle, &p_sys_attr,
                                              &p_sys_attr_len, &flags);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    sd_err_code = sd_ble_gatts_sys_attr_get(conn_handle, p_sys_attr, p_sys_attr_len, flags);

    err_code = ble_gatts_sys_attr_get_rsp_enc(sd_err_code, p_tx_buf, p_tx_buf_len, p_sys_attr,
                                              p_sys_attr_len);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    return err_code;
}
예제 #2
0
/**@brief Function for preparing the reset, disabling SoftDevice, and jumping to the bootloader.
 *
 * @param[in] conn_handle Connection handle for peer requesting to enter DFU mode.
 */
static void bootloader_start(uint16_t conn_handle)
{
    uint32_t err_code;
    uint16_t sys_serv_attr_len = sizeof(m_peer_data.sys_serv_attr);

    err_code = sd_ble_gatts_sys_attr_get(conn_handle,
                                         m_peer_data.sys_serv_attr,
                                         &sys_serv_attr_len,
                                         BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS);
    if (err_code != NRF_SUCCESS)
    {
        // Any error at this stage means the system service attributes could not be fetched.
        // This means the service changed indication cannot be sent in DFU mode, but connection
        // is still possible to establish.
    }

    m_reset_prepare();

    err_code = sd_power_gpregret_set(BOOTLOADER_DFU_START);
    APP_ERROR_CHECK(err_code);

    err_code = sd_softdevice_disable();
    APP_ERROR_CHECK(err_code);

    err_code = sd_softdevice_vector_table_base_set(NRF_UICR->BOOTLOADERADDR);
    APP_ERROR_CHECK(err_code);

    dfu_app_peer_data_set(conn_handle);

    NVIC_ClearPendingIRQ(SWI2_IRQn);
    interrupts_disable();
    bootloader_util_app_start(NRF_UICR->BOOTLOADERADDR);
}
static void storeSystemAttributes(Gap::Handle_t handle)
{
    if(manager->storage != NULL && deviceID < MICROBIT_BLE_MAXIMUM_BONDS)
    {
        ManagedString key("bleSysAttrs");

        KeyValuePair* bleSysAttrs = manager->storage->get(key);

        BLESysAttribute attrib;
        BLESysAttributeStore attribStore;

        uint16_t len = sizeof(attrib.sys_attr);

        sd_ble_gatts_sys_attr_get(handle, attrib.sys_attr, &len, BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS);

        //copy our stored sysAttrs
        if(bleSysAttrs != NULL)
        {
            memcpy(&attribStore, bleSysAttrs->value, sizeof(BLESysAttributeStore));
            delete bleSysAttrs;
        }

        //check if we need to update
        if(memcmp(attribStore.sys_attrs[deviceID].sys_attr, attrib.sys_attr, len) != 0)
        {
            attribStore.sys_attrs[deviceID] = attrib;
            manager->storage->put(key, (uint8_t *)&attribStore);
        }
    }
}
예제 #4
0
uint32_t ble_bondmngr_sys_attr_store(void)
{
    uint32_t err_code;
      
    if (m_master.sys_attr.sys_attr_size == 0)
    {
        // Connected to new master. So the flash block for System Attributes for this
        // master is empty. Hence no erase is needed. 
        
        uint16_t sys_attr_size = SYS_ATTR_BUFFER_MAX_LEN;
        
        // Fetch System Attributes from stack.
        err_code = sd_ble_gatts_sys_attr_get(m_conn_handle,
                                             m_master.sys_attr.sys_attr,
                                             &sys_attr_size);

        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
        
        m_master.sys_attr.master_handle = m_master.bond.master_handle;
        m_master.sys_attr.sys_attr_size = (uint16_t)sys_attr_size;
        
        // Copy the System Attributes to database.
        m_masters_db[m_masters_in_db_count].sys_attr = m_master.sys_attr;        

        // Write new master's System Attributes to flash
        return (sys_attr_store(&m_master.sys_attr));
    }
    else
    {
        // Will not write to flash because System Attributes of an old master would already be
        // in flash and so this operation needs a flash erase operation.
        return NRF_ERROR_INVALID_STATE;
    }
}
예제 #5
0
uint32_t ble_bondmngr_bonded_masters_store(void)
{
    uint32_t err_code;
    int      i;

    if (!m_is_bondmngr_initialized)
    {
        return NRF_ERROR_INVALID_STATE;
    }

    if (m_master.bond.master_handle != INVALID_MASTER_HANDLE)
    {
        // Fetch System Attributes from stack.
        uint16_t sys_attr_size = SYS_ATTR_BUFFER_MAX_LEN;
        
        err_code = sd_ble_gatts_sys_attr_get(m_conn_handle,
                                             m_master.sys_attr.sys_attr,
                                             &sys_attr_size);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
        
        m_master.sys_attr.master_handle = m_master.bond.master_handle;
        m_master.sys_attr.sys_attr_size = (uint16_t)sys_attr_size;
        
        // Update current master
        err_code = master_update();
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    }

    // Save Bonding Information if changed
    if (bond_info_changed())
    {
        // Erase flash page
        err_code = ble_flash_page_erase(m_bondmngr_config.flash_page_num_bond);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    
        // Store bond information for all masters
        m_bond_info_in_flash_count = 0;
        for (i = 0; i < m_masters_in_db_count; i++)
        {
            err_code = bond_info_store(&m_masters_db[i].bond);
            if (err_code != NRF_SUCCESS)
            {
                return err_code;
            }
        }
    }
    
    // Save System Attributes, if changed
    if (sys_attr_changed())
    {
        // Erase flash page
        err_code = ble_flash_page_erase(m_bondmngr_config.flash_page_num_sys_attr);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }

        // Store System Attributes for all masters
        m_sys_attr_in_flash_count = 0;
        for (i = 0; i < m_masters_in_db_count; i++)
        {
            err_code = sys_attr_store(&m_masters_db[i].sys_attr);
            if (err_code != NRF_SUCCESS)
            {
                return err_code;
            }
        }
    }
    
    m_conn_handle                   = BLE_CONN_HANDLE_INVALID;
    m_master.bond.master_handle     = INVALID_MASTER_HANDLE;
    m_master.sys_attr.master_handle = INVALID_MASTER_HANDLE;
    m_master.sys_attr.sys_attr_size = 0;
    
    return NRF_SUCCESS;
}
예제 #6
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;
    ble_gatts_rw_authorize_reply_params_t auth_reply;

    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            nrf_gpio_pin_clear(CONNECTED_LED_PIN_NO);

            PUTS("Connected");

            m_conn_handle    = p_ble_evt->evt.gap_evt.conn_handle;
            m_is_advertising = false;
            break;

        case BLE_GAP_EVT_DISCONNECTED:
            {
                uint8_t  sys_attr[128];
                uint16_t sys_attr_len = sizeof(sys_attr);
            
                PUTS("Disconnected");

                nrf_gpio_pin_set(CONNECTED_LED_PIN_NO);
        
                m_direct_adv_cnt = APP_DIRECTED_ADV_TIMEOUT;

                err_code = sd_ble_gatts_sys_attr_get(m_conn_handle, 
                                                     sys_attr, 
                                                     &sys_attr_len, 
                                                     BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS);

                if ((err_code != NRF_SUCCESS) && 
                    (err_code != NRF_ERROR_NOT_FOUND)) {

                    APP_ERROR_CHECK(err_code);
                }
            }
            if (!m_tear_down_in_progress)
            {
                // The Disconnected event is because of an external event. (Link loss or
                // disconnect triggered by the DFU Controller before the firmware update was
                // complete).
                // Restart advertising so that the DFU Controller can reconnect if possible.
                advertising_start();
            }

            m_conn_handle = BLE_CONN_HANDLE_INVALID;

            break;

        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
            {
                ble_gap_sec_keyset_t keys;
                ble_gap_enc_key_t    enc_key;
                ble_gap_id_key_t     id_key;

                id_key.id_addr_info = m_ble_peer_data.addr;
                id_key.id_info      = m_ble_peer_data.irk;
                enc_key             = m_ble_peer_data.enc_key;

                keys.keys_central.p_id_key  = &id_key;
                keys.keys_central.p_enc_key = &enc_key;

                err_code = sd_ble_gap_sec_params_reply(m_conn_handle,
                                                       BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP,
                                                       &m_sec_params,
                                                       &keys);
                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_GAP_EVT_TIMEOUT:
            if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISING)
            {
                m_is_advertising = false;
                m_direct_adv_cnt--;
                if (m_direct_adv_cnt == 0)
                {
                    dfu_update_status_t update_status = {.status_code = DFU_TIMEOUT};
                    bootloader_dfu_update_process(update_status);
                }
                else
                {
/**@brief Function for decoding a command packet with RPC_SD_BLE_GATTS_SYS_ATTR_GET opcode.
 *
 * This function will decode the command, call the BLE Stack API, and also send command response
 * to the peer through the the transport layer.
 *
 * @param[in] p_command         The encoded structure that needs to be decoded and passed on
 *                              to the BLE Stack API.
 * @param[in] command_len       The length of the encoded command read from transport layer.
 *
 * @retval NRF_SUCCESS               If the decoding of the command was successful, the SoftDevice
 *                                   API was called, and the command response was sent to peer,
 *                                   otherwise an error code.
 * @retval NRF_ERROR_INVALID_LENGTH  If the content length of the packet is not conforming to the
 *                                   codec specification.
 */
static uint32_t gatts_sys_attr_get_handle(uint8_t const * const p_command, uint32_t command_len)
{
    uint32_t err_code;
    uint8_t  resp_data[BLE_GATTS_VAR_ATTR_LEN_MAX];
    uint16_t conn_handle;

    uint32_t   index              = 0;
    uint16_t   attr_data_length   = 0;
    uint8_t *  p_attr_data        = &resp_data[3];
    uint16_t * p_attr_data_length = &attr_data_length;

    conn_handle  = uint16_decode(&p_command[index]);
    index       += sizeof(uint16_t);
    RPC_DECODER_LENGTH_CHECK(command_len, index, SD_BLE_GATTS_SYS_ATTR_GET);

    if (p_command[index++] == RPC_BLE_FIELD_PRESENT)
    {
        attr_data_length  = uint16_decode(&p_command[index]);
        index            += sizeof(uint16_t);
    }
    else
    {
        p_attr_data_length = NULL;
    }

    RPC_DECODER_LENGTH_CHECK(command_len, index, SD_BLE_GATTS_SYS_ATTR_GET);

    if (p_command[index++] == RPC_BLE_FIELD_NOT_PRESENT)
    {
        p_attr_data = NULL;
    }

    RPC_DECODER_LENGTH_CHECK(command_len, index, SD_BLE_GATTS_SYS_ATTR_GET);

    err_code = sd_ble_gatts_sys_attr_get(conn_handle, p_attr_data, p_attr_data_length);

    if (err_code == NRF_SUCCESS)
    {
        index  = 0;
        index += uint16_encode(*p_attr_data_length, &resp_data[0]);

        if (p_attr_data == NULL)
        {
            resp_data[index++] = RPC_BLE_FIELD_NOT_PRESENT;
        }
        else
        {
            resp_data[index++]  = RPC_BLE_FIELD_PRESENT;
            index              += *p_attr_data_length;
        }

        return ble_rpc_cmd_resp_data_send(SD_BLE_GATTS_SYS_ATTR_GET,
                                          err_code,
                                          resp_data,
                                          index);
    }
    else
    {
        return ble_rpc_cmd_resp_send(SD_BLE_GATTS_SYS_ATTR_GET, err_code);
    }
}