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; }
/**@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); } } }
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; } }
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; }
/**@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); } }