Пример #1
0
pm_peer_id_t im_peer_id_get_by_master_id(ble_gap_master_id_t * p_master_id)
{
    ret_code_t err_code;
    // For each stored peer, check if the master_id match p_master_id
    pm_peer_id_t compared_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID);
    while (compared_peer_id != PM_PEER_ID_INVALID)
    {
        pm_peer_data_flash_t        compared_data;
        ble_gap_master_id_t const * p_compared_master_id;

        err_code = pdb_read_buf_get(compared_peer_id, PM_PEER_DATA_ID_BONDING, &compared_data, NULL);
        if (err_code == NRF_SUCCESS)
        {
            p_compared_master_id = &compared_data.p_bonding_data->own_ltk.master_id;
            if (im_master_ids_compare(p_master_id, p_compared_master_id))
            {
                // If a matching master_id is found return the peer_id
                return compared_peer_id;
            }
            p_compared_master_id = &compared_data.p_bonding_data->peer_ltk.master_id;
            if (im_master_ids_compare(p_master_id, p_compared_master_id))
            {
                // If a matching master_id is found return the peer_id
                return compared_peer_id;
            }
        }
        compared_peer_id = pdb_next_peer_id_get(compared_peer_id);
    }
    // If no matching master_id is found return the PM_PEER_ID_INVALID
    return PM_PEER_ID_INVALID;
}
Пример #2
0
ret_code_t pm_peers_delete(void)
{
    VERIFY_MODULE_INITIALIZED();

    m_deleting_all = true;

    pm_peer_id_t current_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID);

    if (current_peer_id == PM_PEER_ID_INVALID)
    {
        // No peers bonded.
        m_deleting_all = false;

        pm_evt_t pm_delete_all_evt;
        memset(&pm_delete_all_evt, 0, sizeof(pm_evt_t));
        pm_delete_all_evt.evt_id      = PM_EVT_PEERS_DELETE_SUCCEEDED;
        pm_delete_all_evt.peer_id     = PM_PEER_ID_INVALID;
        pm_delete_all_evt.conn_handle = BLE_CONN_HANDLE_INVALID;

        evt_send(&pm_delete_all_evt);
    }

    while (current_peer_id != PM_PEER_ID_INVALID)
    {
        ret_code_t err_code = pm_peer_delete(current_peer_id);
        if (err_code != NRF_SUCCESS)
        {
            return NRF_ERROR_INTERNAL;
        }

        current_peer_id = pdb_next_peer_id_get(current_peer_id);
    }

    return NRF_SUCCESS;
}
Пример #3
0
void pm_peer_delete_all(void)
{
    pm_peer_id_t current_peer_id = PM_PEER_ID_INVALID;
    while (pdb_next_peer_id_get(PM_PEER_ID_INVALID) != PM_PEER_ID_INVALID)
    {
        current_peer_id = pdb_next_peer_id_get(current_peer_id);
        pm_peer_delete(current_peer_id);
    }
}
Пример #4
0
ret_code_t im_whitelist_custom(ble_gap_whitelist_t const * p_whitelist)
{
    ret_code_t err_code;

    pm_peer_id_t new_irk_whitelist_peer_ids[BLE_GAP_WHITELIST_IRK_MAX_COUNT];
    uint32_t n_new_irk_whitelist_peer_ids = 0;
    VERIFY_PARAM_NOT_NULL(p_whitelist);
    for (uint32_t i = 0; i < BLE_GAP_WHITELIST_IRK_MAX_COUNT; i++)
    {
        new_irk_whitelist_peer_ids[i] = PM_PEER_ID_INVALID;
    }
    pm_peer_id_t compared_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID);
    while (compared_peer_id != PM_PEER_ID_INVALID)
    {
        pm_peer_data_flash_t compared_data;
        err_code = pdb_read_buf_get(compared_peer_id, PM_PEER_DATA_ID_BONDING, &compared_data, NULL);
        if (err_code == NRF_SUCCESS)
        {
            for (uint32_t i = 0; i < p_whitelist->irk_count; i++)
            {
                bool valid_irk = is_valid_irk(&compared_data.p_bonding_data->peer_id.id_info);
                bool duplicate_irk = valid_irk &&
                                     (memcmp(p_whitelist->pp_irks[i]->irk,
                                             compared_data.p_bonding_data->peer_id.id_info.irk,
                                             BLE_GAP_SEC_KEY_LEN) == 0
                                     );
                if (duplicate_irk)
                {
                    new_irk_whitelist_peer_ids[i] = compared_peer_id;
                    n_new_irk_whitelist_peer_ids++;
                }
            }
        }
        compared_peer_id = pdb_next_peer_id_get(compared_peer_id);
    }
    if (n_new_irk_whitelist_peer_ids != p_whitelist->irk_count)
    {
        return NRF_ERROR_NOT_FOUND;
    }
    else
    {
        for (uint32_t i = 0; i < n_new_irk_whitelist_peer_ids; i++)
        {
            m_im.irk_whitelist_peer_ids[i] = new_irk_whitelist_peer_ids[i];
        }
        m_im.n_irk_whitelist_peer_ids = n_new_irk_whitelist_peer_ids;
        return NRF_SUCCESS;
    }
}
Пример #5
0
pm_peer_id_t pm_next_peer_id_get(pm_peer_id_t prev_peer_id)
{
    if (!MODULE_INITIALIZED)
    {
        return PM_PEER_ID_INVALID;
    }
    return pdb_next_peer_id_get(prev_peer_id);
}
Пример #6
0
/**@brief Event handler for events from the peer_database module.
 *
 * @param[in]  p_event The event that has happend with peer id and flags.
 */
static void pdb_evt_handler(pdb_evt_t const * p_event)
{
    ret_code_t err_code;
    if ((p_event != NULL) && (p_event->evt_id == PDB_EVT_WRITE_BUF_STORED))
    {
        // If new data about peer id has been stored it is compared to other peers peer ids in
        // search of duplicates.
        if (p_event->data_id == PM_PEER_DATA_ID_BONDING)
        {
            pm_peer_data_flash_t written_data;
            err_code = pdb_read_buf_get(p_event->peer_id, PM_PEER_DATA_ID_BONDING, &written_data, NULL);
            if (err_code == NRF_SUCCESS)
            {
                pm_peer_id_t compared_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID);
                while (compared_peer_id != PM_PEER_ID_INVALID)
                {
                    pm_peer_data_flash_t compared_data;
                    err_code = pdb_read_buf_get(compared_peer_id,
                                                PM_PEER_DATA_ID_BONDING,
                                                &compared_data,
                                                NULL);
                    if ( err_code == NRF_SUCCESS &&
                            p_event->peer_id != compared_peer_id &&
                            is_duplicate_bonding_data(written_data.p_bonding_data,
                                                      compared_data.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 = compared_peer_id;
                        evt_send(&im_evt);
                    }
                    compared_peer_id = pdb_next_peer_id_get(compared_peer_id);
                }
            }
        }
    }
}
Пример #7
0
ret_code_t pm_peer_ranks_get(pm_peer_id_t * p_highest_ranked_peer,
                             uint32_t     * p_highest_rank,
                             pm_peer_id_t * p_lowest_ranked_peer,
                             uint32_t     * p_lowest_rank)
{
    VERIFY_MODULE_INITIALIZED();

    pm_peer_id_t         peer_id      = pdb_next_peer_id_get(PM_PEER_ID_INVALID);
    uint32_t             peer_rank    = 0;
    //lint -save -e65 -e64
    pm_peer_data_t       peer_data    = {.length_words = BYTES_TO_WORDS(sizeof(peer_rank)),
                                         .p_peer_rank  = &peer_rank};
    //lint -restore
    ret_code_t           err_code     = pdb_peer_data_load(peer_id, PM_PEER_DATA_ID_PEER_RANK, &peer_data);
    uint32_t             highest_rank = 0;
    uint32_t             lowest_rank  = 0xFFFFFFFF;
    pm_peer_id_t         highest_ranked_peer = PM_PEER_ID_INVALID;
    pm_peer_id_t         lowest_ranked_peer  = PM_PEER_ID_INVALID;

    if (err_code == NRF_ERROR_INVALID_PARAM)
    {
        // No peer IDs exist.
        return NRF_ERROR_NOT_FOUND;
    }

    while ((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NOT_FOUND))
    {
        if (err_code == NRF_ERROR_NOT_FOUND)
        {
            peer_rank = 0;
        }
        if (peer_rank >= highest_rank)
        {
            highest_rank      = peer_rank;
            highest_ranked_peer = peer_id;
        }
        if (peer_rank < lowest_rank)
        {
            lowest_rank      = peer_rank;
            lowest_ranked_peer = peer_id;
        }
        peer_id = pdb_next_peer_id_get(peer_id);
        err_code = pdb_peer_data_load(peer_id, PM_PEER_DATA_ID_PEER_RANK, &peer_data);
    }
    if (peer_id == PM_PEER_ID_INVALID)
    {
        err_code = NRF_SUCCESS;
        if (p_highest_ranked_peer != NULL)
        {
            *p_highest_ranked_peer = highest_ranked_peer;
        }
        if (p_highest_rank != NULL)
        {
            *p_highest_rank = highest_rank;
        }
        if (p_lowest_ranked_peer != NULL)
        {
            *p_lowest_ranked_peer = lowest_ranked_peer;
        }
        if (p_lowest_rank != NULL)
        {
            *p_lowest_rank = lowest_rank;
        }
    }
    else
    {
        err_code = NRF_ERROR_INTERNAL;
    }
    return err_code;
}


/**@brief Function for initializing peer rank statistics.
 */
static void rank_init(void)
{
    ret_code_t err_code = pm_peer_ranks_get(&m_highest_ranked_peer,
                                            &m_current_highest_peer_rank,
                                            NULL,
                                            NULL);
    if ((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NOT_FOUND))
    {
        m_peer_rank_initialized = true;
    }
}
Пример #8
0
/**@brief Event handler for events from the Peer Database module.
 *        This handler is extern in the Peer Database module.
 *
 * @param[in]  p_pdb_evt  The incoming Peer Database event.
 */
void pm_pdb_evt_handler(pdb_evt_t const * p_pdb_evt)
{
    bool send_evt = true;
    pm_evt_t pm_evt;

    memset(&pm_evt, 0, sizeof(pm_evt_t));
    pm_evt.peer_id = p_pdb_evt->peer_id;
    pm_evt.conn_handle = im_conn_handle_get(pm_evt.peer_id);

    switch (p_pdb_evt->evt_id)
    {
        case PDB_EVT_WRITE_BUF_STORED:
            pm_evt.evt_id = PM_EVT_PEER_DATA_UPDATE_SUCCEEDED;
            pm_evt.params.peer_data_update_succeeded.data_id       = p_pdb_evt->data_id;
            pm_evt.params.peer_data_update_succeeded.action        = PM_PEER_DATA_OP_UPDATE;
            pm_evt.params.peer_data_update_succeeded.token         = PM_STORE_TOKEN_INVALID;
            pm_evt.params.peer_data_update_succeeded.flash_changed = true;
            break;

        case PDB_EVT_RAW_STORED:
            pm_evt.evt_id = PM_EVT_PEER_DATA_UPDATE_SUCCEEDED;
            pm_evt.params.peer_data_update_succeeded.data_id = p_pdb_evt->data_id;
            pm_evt.params.peer_data_update_succeeded.action  = PM_PEER_DATA_OP_UPDATE;
            pm_evt.params.peer_data_update_succeeded.token
                                            = p_pdb_evt->params.raw_stored_evt.store_token;
            pm_evt.params.peer_data_update_succeeded.flash_changed = true;

            if (    (m_peer_rank_token != PM_STORE_TOKEN_INVALID)
                && (m_peer_rank_token == p_pdb_evt->params.raw_stored_evt.store_token))
            {
                m_peer_rank_token     = PM_STORE_TOKEN_INVALID;
                m_highest_ranked_peer = pm_evt.peer_id;

                pm_evt.params.peer_data_update_succeeded.token = PM_STORE_TOKEN_INVALID;
            }
            break;

        case PDB_EVT_RAW_STORE_FAILED:
            pm_evt.evt_id = PM_EVT_PEER_DATA_UPDATE_FAILED;
            pm_evt.params.peer_data_update_failed.data_id = p_pdb_evt->data_id;
            pm_evt.params.peer_data_update_failed.action  = PM_PEER_DATA_OP_UPDATE;
            pm_evt.params.peer_data_update_failed.token
                                            = p_pdb_evt->params.error_raw_store_evt.store_token;
            pm_evt.params.peer_data_update_failed.error
                                            = p_pdb_evt->params.error_raw_store_evt.err_code;

            if (    (m_peer_rank_token != PM_STORE_TOKEN_INVALID)
                && (m_peer_rank_token == p_pdb_evt->params.raw_stored_evt.store_token))
            {
                m_peer_rank_token            = PM_STORE_TOKEN_INVALID;
                m_current_highest_peer_rank -= 1;

                pm_evt.params.peer_data_update_succeeded.token = PM_STORE_TOKEN_INVALID;
            }
            break;

        case PDB_EVT_CLEARED:
            pm_evt.evt_id = PM_EVT_PEER_DATA_UPDATE_SUCCEEDED;
            pm_evt.params.peer_data_update_succeeded.data_id = p_pdb_evt->data_id;
            pm_evt.params.peer_data_update_succeeded.action  = PM_PEER_DATA_OP_DELETE;
            pm_evt.params.peer_data_update_succeeded.token   = PM_STORE_TOKEN_INVALID;
            break;

        case PDB_EVT_CLEAR_FAILED:
            pm_evt.evt_id = PM_EVT_PEER_DATA_UPDATE_FAILED;
            pm_evt.params.peer_data_update_failed.data_id = p_pdb_evt->data_id;
            pm_evt.params.peer_data_update_failed.action  = PM_PEER_DATA_OP_DELETE;
            pm_evt.params.peer_data_update_failed.error
                                                    = p_pdb_evt->params.clear_failed_evt.err_code;
            break;

        case PDB_EVT_PEER_FREED:
            pm_evt.evt_id = PM_EVT_PEER_DELETE_SUCCEEDED;
            // Check that no peers marked for deletion are left.
            if (m_deleting_all
                && (pdb_next_peer_id_get(PM_PEER_ID_INVALID) == PM_PEER_ID_INVALID)
                && (pdb_next_deleted_peer_id_get(PM_PEER_ID_INVALID) == PM_PEER_ID_INVALID))
            {
                // pm_peers_delete() has been called and this is the last peer to be deleted.
                m_deleting_all = false;

                pm_evt_t pm_delete_all_evt;
                memset(&pm_delete_all_evt, 0, sizeof(pm_evt_t));
                pm_delete_all_evt.evt_id      = PM_EVT_PEERS_DELETE_SUCCEEDED;
                pm_delete_all_evt.peer_id     = PM_PEER_ID_INVALID;
                pm_delete_all_evt.conn_handle = BLE_CONN_HANDLE_INVALID;

                evt_send(&pm_delete_all_evt);
            }
            break;

        case PDB_EVT_PEER_FREE_FAILED:
            pm_evt.evt_id = PM_EVT_PEER_DELETE_FAILED;
            pm_evt.params.peer_delete_failed.error
                                                = p_pdb_evt->params.peer_free_failed_evt.err_code;
            if (m_deleting_all)
            {
                // pm_peers_delete() has been called and has thus failed.

                m_deleting_all = false;

                pm_evt_t pm_delete_all_evt;
                memset(&pm_delete_all_evt, 0, sizeof(pm_evt_t));
                pm_delete_all_evt.evt_id      = PM_EVT_PEERS_DELETE_FAILED;
                pm_delete_all_evt.peer_id     = PM_PEER_ID_INVALID;
                pm_delete_all_evt.conn_handle = BLE_CONN_HANDLE_INVALID;
                pm_delete_all_evt.params.peers_delete_failed_evt.error
                                              = p_pdb_evt->params.peer_free_failed_evt.err_code;

                evt_send(&pm_delete_all_evt);
            }
            break;

        case PDB_EVT_COMPRESSED:
            send_evt = false;
            // Do nothing
            break;

        case PDB_EVT_ERROR_NO_MEM:
            pm_evt.evt_id = PM_EVT_STORAGE_FULL;
            break;

        case PDB_EVT_ERROR_UNEXPECTED:
            pm_evt.evt_id = PM_EVT_ERROR_UNEXPECTED;
            break;

        default:
            send_evt = false;
            break;
    }

    if (send_evt)
    {
        evt_send(&pm_evt);
    }
}
Пример #9
0
void im_ble_evt_handler(ble_evt_t * ble_evt)
{
    ret_code_t err_code;
    switch (ble_evt->header.evt_id)
    {
    case BLE_GAP_EVT_CONNECTED:
    {
        pm_peer_id_t bonded_matching_peer_id = PM_PEER_ID_INVALID;

        if (ble_evt->evt.gap_evt.params.connected.irk_match == 1)
        {
            // The peer was matched using a whitelist.
            bonded_matching_peer_id
                = m_im.irk_whitelist_peer_ids[ble_evt->evt.gap_evt.params.connected.irk_match_idx];
        }
        else if (   ble_evt->evt.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 compared_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID);
            while (   (compared_peer_id        != PM_PEER_ID_INVALID)
                      && (bonded_matching_peer_id == PM_PEER_ID_INVALID))
            {
                pm_peer_data_flash_t compared_data;
                switch (ble_evt->evt.gap_evt.params.connected.peer_addr.addr_type)
                {
                case BLE_GAP_ADDR_TYPE_PUBLIC:
                /* fall-through */
                case BLE_GAP_ADDR_TYPE_RANDOM_STATIC:
                    err_code = pdb_read_buf_get(compared_peer_id,
                                                PM_PEER_DATA_ID_BONDING,
                                                &compared_data,
                                                NULL);
                    if ((err_code == NRF_SUCCESS) &&
                            addr_compare(&ble_evt->evt.gap_evt.params.connected.peer_addr,
                                         &compared_data.p_bonding_data->peer_id.id_addr_info)
                       )
                    {
                        bonded_matching_peer_id = compared_peer_id;
                    }
                    break;

                case BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE:
                    err_code = pdb_read_buf_get(compared_peer_id,
                                                PM_PEER_DATA_ID_BONDING,
                                                &compared_data,
                                                NULL);
                    if (err_code == NRF_SUCCESS &&
                            im_address_resolve(&ble_evt->evt.gap_evt.params.connected.peer_addr,
                                               &compared_data.p_bonding_data->peer_id.id_info)
                       )
                    {
                        bonded_matching_peer_id = compared_peer_id;
                    }
                    break;

                case BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE:
                    // Should not happen.
                    break;

                default:
                    break;
                }
                compared_peer_id = pdb_next_peer_id_get(compared_peer_id);
            }
        }
        uint8_t new_index = new_connection(ble_evt->evt.gap_evt.conn_handle, &ble_evt->evt.gap_evt.params.connected.peer_addr);
        UNUSED_VARIABLE(new_index);

        if (bonded_matching_peer_id != PM_PEER_ID_INVALID)
        {
            im_new_peer_id(ble_evt->evt.gap_evt.conn_handle, bonded_matching_peer_id);

            // Send a bonded peer event
            im_evt_t im_evt;
            im_evt.conn_handle = ble_evt->evt.gap_evt.conn_handle;
            im_evt.evt_id = IM_EVT_BONDED_PEER_CONNECTED;
            evt_send(&im_evt);
        }
    }
    }
}
Пример #10
0
pm_peer_id_t pm_next_peer_id_get(pm_peer_id_t prev_peer_id)
{
    return pdb_next_peer_id_get(prev_peer_id);
}