Esempio n. 1
0
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;
}
Esempio n. 2
0
/**@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;
        }
    }
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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);
    }
}