ret_code_t pm_peer_new(pm_peer_id_t * p_new_peer_id, pm_peer_data_bonding_t * p_bonding_data, pm_store_token_t * p_token) { ret_code_t err_code; pm_peer_id_t peer_id; pm_peer_data_flash_t peer_data; VERIFY_MODULE_INITIALIZED(); VERIFY_PARAM_NOT_NULL(p_bonding_data); VERIFY_PARAM_NOT_NULL(p_new_peer_id); memset(&peer_data, 0, sizeof(pm_peer_data_flash_t)); // Search through existing bonds to look for a duplicate. pds_peer_data_iterate_prepare(); // @note emdi: should maybe use a critical section, since data is not copied while iterating. while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data)) { if (im_is_duplicate_bonding_data(p_bonding_data, peer_data.p_bonding_data)) { *p_new_peer_id = peer_id; return NRF_SUCCESS; } } // If no duplicate data is found, prepare to write a new bond to flash. *p_new_peer_id = pdb_peer_allocate(); if (*p_new_peer_id == PM_PEER_ID_INVALID) { return NRF_ERROR_NO_MEM; } memset(&peer_data, 0, sizeof(pm_peer_data_flash_t)); peer_data.data_id = PM_PEER_DATA_ID_BONDING; peer_data.p_bonding_data = p_bonding_data; peer_data.length_words = BYTES_TO_WORDS(sizeof(pm_peer_data_bonding_t)); err_code = pdb_raw_store(*p_new_peer_id, &peer_data, p_token); if (err_code != NRF_SUCCESS) { if (im_peer_free(*p_new_peer_id) != NRF_SUCCESS) { return NRF_ERROR_INTERNAL; } // NRF_ERROR_STORAGE_FULL, if no space in flash. // NRF_ERROR_BUSY, if flash filesystem was busy. // NRF_ERROR_INTENRAL, on internal error. return err_code; } return NRF_SUCCESS; }
/**@brief Event handler for events from the Peer Database module. * This function is extern in Peer Database. * * @param[in] p_event The event that has happend with peer id and flags. */ void im_pdb_evt_handler(pdb_evt_t const * p_event) { ret_code_t ret; pm_peer_id_t peer_id; pm_peer_data_flash_t peer_data; pm_peer_data_flash_t peer_data_duplicate; NRF_PM_DEBUG_CHECK(m_module_initialized); NRF_PM_DEBUG_CHECK(p_event != NULL); if ((p_event->evt_id != PDB_EVT_WRITE_BUF_STORED) || (p_event->data_id != PM_PEER_DATA_ID_BONDING)) { return; } // If new data about peer id has been stored it is compared to other peers peer ids in // search of duplicates. ret = pdb_peer_data_ptr_get(p_event->peer_id, PM_PEER_DATA_ID_BONDING, &peer_data); if (ret != NRF_SUCCESS) { // @note emdi: this shouldn't happen, since the data was just stored, right? NRF_PM_DEBUG_CHECK(false); return; } pds_peer_data_iterate_prepare(); while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data_duplicate)) { if (p_event->peer_id == peer_id) { // Skip the iteration if the bonding data retrieved is for a peer // with the same ID as the one contained in the event. continue; } if (im_is_duplicate_bonding_data(peer_data.p_bonding_data, peer_data_duplicate.p_bonding_data)) { im_evt_t im_evt; im_evt.conn_handle = im_conn_handle_get(p_event->peer_id); im_evt.evt_id = IM_EVT_DUPLICATE_ID; im_evt.params.duplicate_id.peer_id_1 = p_event->peer_id; im_evt.params.duplicate_id.peer_id_2 = peer_id; evt_send(&im_evt); break; } } }
pm_peer_id_t im_peer_id_get_by_master_id(ble_gap_master_id_t * p_master_id) { pm_peer_id_t peer_id; pm_peer_data_flash_t peer_data; NRF_PM_DEBUG_CHECK(m_module_initialized); NRF_PM_DEBUG_CHECK(p_master_id != NULL); pds_peer_data_iterate_prepare(); // For each stored peer, check if the master_id matches p_master_id while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data)) { if (im_master_ids_compare(p_master_id, &peer_data.p_bonding_data->own_ltk.master_id) || im_master_ids_compare(p_master_id, &peer_data.p_bonding_data->peer_ltk.master_id)) { // If a matching master ID is found then return the peer ID. return peer_id; } } // If no matching master ID is found return PM_PEER_ID_INVALID. return PM_PEER_ID_INVALID; }
void im_ble_evt_handler(ble_evt_t * ble_evt) { ble_gap_evt_t gap_evt; pm_peer_id_t bonded_matching_peer_id; NRF_PM_DEBUG_CHECK(m_module_initialized); if (ble_evt->header.evt_id != BLE_GAP_EVT_CONNECTED) { // Nothing to do. return; } gap_evt = ble_evt->evt.gap_evt; bonded_matching_peer_id = PM_PEER_ID_INVALID; if ( gap_evt.params.connected.peer_addr.addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE) { /* Search the database for bonding data matching the one that triggered the event. * Public and static addresses can be matched on address alone, while resolvable * random addresses can be resolved agains known IRKs. Non-resolvable random addresses * are never matching because they are not longterm form of identification. */ pm_peer_id_t peer_id; pm_peer_data_flash_t peer_data; pds_peer_data_iterate_prepare(); switch (gap_evt.params.connected.peer_addr.addr_type) { case BLE_GAP_ADDR_TYPE_PUBLIC: case BLE_GAP_ADDR_TYPE_RANDOM_STATIC: { while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data)) { if (addr_compare(&gap_evt.params.connected.peer_addr, &peer_data.p_bonding_data->peer_id.id_addr_info)) { bonded_matching_peer_id = peer_id; break; } } } break; case BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE: { while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data)) { if (im_address_resolve(&gap_evt.params.connected.peer_addr, &peer_data.p_bonding_data->peer_id.id_info)) { bonded_matching_peer_id = peer_id; break; } } } break; default: NRF_PM_DEBUG_CHECK(false); break; } } uint8_t new_index = new_connection(gap_evt.conn_handle, &gap_evt.params.connected.peer_addr); UNUSED_VARIABLE(new_index); if (bonded_matching_peer_id != PM_PEER_ID_INVALID) { im_new_peer_id(gap_evt.conn_handle, bonded_matching_peer_id); // Send a bonded peer event im_evt_t im_evt; im_evt.conn_handle = gap_evt.conn_handle; im_evt.evt_id = IM_EVT_BONDED_PEER_CONNECTED; evt_send(&im_evt); } }