Beispiel #1
0
/**@brief Function for sending service changed indications if it is pending on any connections.
 */
static void service_changed_pending_flags_check(void)
{
    sdk_mapped_flags_t service_changed_pending_flags;

    service_changed_pending_flags = ble_conn_state_user_flag_collection(m_gcm.flag_id_service_changed_pending);
    if (sdk_mapped_flags_any_set(service_changed_pending_flags))
    {
        sdk_mapped_flags_key_list_t conn_handle_list;
        conn_handle_list = ble_conn_state_conn_handles();

        for (uint32_t i = 0; i < conn_handle_list.len; i++)
        {
            if (    ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i],
                                                 m_gcm.flag_id_service_changed_pending)
                && !ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i],
                                                 m_gcm.flag_id_service_changed_sent))
            {
                service_changed_send_in_evt(conn_handle_list.flag_keys[i]);
            }
        }
    }
}
Beispiel #2
0
/**@brief Function finding a free position in m_connections.
 *
 * @detail All connection handles in the m_connections array are checked against the connection
 *         state module. The index of the first one that is not a connection handle for a current
 *         connection is returned. This position in the array can safely be used for a new connection.
 *
 * @return Either the index of a free position in the array or IM_NO_INVALID_CONN_HANDLES if no free
           position exists.
 */
uint8_t get_free_connection()
{
    for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++)
    {
        // Query the connection state module to check if the
        // connection handle does not belong to a valid connection.
        if (!ble_conn_state_user_flag_get(m_connections[i].conn_handle, m_conn_state_user_flag_id))
        {
            return i;
        }
    }
    // If all connection handles belong to a valid connection, return IM_NO_INVALID_CONN_HANDLES.
    return IM_NO_INVALID_CONN_HANDLES;
}
Beispiel #3
0
/**@brief Function finding a particular connection handle m_connections.
 *
 * @param[in]  conn_handle  The handle to find.
 *
 * @return Either the index of the conn_handle in the array or IM_NO_INVALID_CONN_HANDLES if the
 *         handle was not found.
 */
uint8_t get_connection_by_conn_handle(uint16_t conn_handle)
{
    if (ble_conn_state_user_flag_get(conn_handle, m_conn_state_user_flag_id))
    {
        for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++)
        {
            if (m_connections[i].conn_handle == conn_handle)
            {
                return i;
            }
        }
    }
    // If all connection handles belong to a valid connection, return IM_NO_INVALID_CONN_HANDLES.
    return IM_NO_INVALID_CONN_HANDLES;
}
Beispiel #4
0
ret_code_t pm_link_status_get(uint16_t conn_handle, pm_link_status_t * p_link_status)
{
    VERIFY_PARAM_NOT_NULL(p_link_status);
    if (conn_handle == BLE_CONN_HANDLE_INVALID)
    {
        return NRF_ERROR_INVALID_PARAM;
    }
    // Read the bonded status from the user flag that is maintained by events.
    p_link_status->bonded = ble_conn_state_user_flag_get(conn_handle, m_pm.bonding_flag_id);
    // Read the connected, encrypted and mitm status from the connection state module.
    p_link_status->connected = ble_conn_state_valid(conn_handle);
    p_link_status->encrypted = ble_conn_state_encrypted(conn_handle);
    p_link_status->mitm_protected = ble_conn_state_mitm_protected(conn_handle);
    return NRF_SUCCESS;
}
Beispiel #5
0
ret_code_t pm_conn_sec_status_get(uint16_t conn_handle, pm_conn_sec_status_t * p_conn_sec_status)
{
    VERIFY_MODULE_INITIALIZED();
    VERIFY_PARAM_NOT_NULL(p_conn_sec_status);

    ble_conn_state_status_t status = ble_conn_state_status(conn_handle);

    if (status == BLE_CONN_STATUS_INVALID)
    {
        return BLE_ERROR_INVALID_CONN_HANDLE;
    }

    p_conn_sec_status->connected      = (status == BLE_CONN_STATUS_CONNECTED);
    p_conn_sec_status->bonded         = ble_conn_state_user_flag_get(conn_handle, m_bonding_flag_id);
    p_conn_sec_status->encrypted      = ble_conn_state_encrypted(conn_handle);
    p_conn_sec_status->mitm_protected = ble_conn_state_mitm_protected(conn_handle);
    return NRF_SUCCESS;
}
Beispiel #6
0
/**@brief Function for performing the Local DB update procedure if it is pending on any connections.
 */
static void update_pending_flags_check(void)
{
    sdk_mapped_flags_t update_pending_flags;

    update_pending_flags = ble_conn_state_user_flag_collection(m_gcm.flag_id_local_db_update_pending);
    if (sdk_mapped_flags_any_set(update_pending_flags))
    {
        sdk_mapped_flags_key_list_t conn_handle_list;
        conn_handle_list = ble_conn_state_conn_handles();

        for (uint32_t i = 0; i < conn_handle_list.len; i++)
        {
            if (ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i], m_gcm.flag_id_local_db_update_pending))
            {
                local_db_update_in_evt(conn_handle_list.flag_keys[i]);
            }
        }
    }
}
Beispiel #7
0
/**@brief Event handler for events from the Security Manager module.
 *        This handler is extern in the Security Manager module.
 *
 * @param[in]  p_sm_evt  The incoming Security Manager event.
 */
void pm_sm_evt_handler(sm_evt_t const * p_sm_evt)
{
    bool find_peer_id = true;
    bool send_evt     = true;
    pm_evt_t pm_evt;
    memset(&pm_evt, 0, sizeof(pm_evt_t));
    pm_evt.conn_handle = p_sm_evt->conn_handle;

    switch (p_sm_evt->evt_id)
    {
        case SM_EVT_SLAVE_SECURITY_REQ:
            find_peer_id = false;
            send_evt     = false;
            break;

        case SM_EVT_SEC_PROCEDURE_START:
        {
            pm_evt.evt_id = PM_EVT_CONN_SEC_START;
            bool pairing = p_sm_evt->params.sec_procedure_start.procedure
                                != PM_LINK_SECURED_PROCEDURE_ENCRYPTION;
            bool bonding = p_sm_evt->params.sec_procedure_start.procedure
                                == PM_LINK_SECURED_PROCEDURE_BONDING;
            ble_conn_state_user_flag_set(p_sm_evt->conn_handle, m_pairing_flag_id, pairing);
            ble_conn_state_user_flag_set(p_sm_evt->conn_handle, m_bonding_flag_id, bonding);
            break;
        }

        case SM_EVT_PAIRING_SUCCESS:
            pm_evt.evt_id = PM_EVT_CONN_SEC_SUCCEEDED;
            pm_evt.params.conn_sec_succeeded.procedure =
                        p_sm_evt->params.pairing_success.bonded
                        ? PM_LINK_SECURED_PROCEDURE_BONDING
                        : PM_LINK_SECURED_PROCEDURE_PAIRING;
            ble_conn_state_user_flag_set(p_sm_evt->conn_handle, m_pairing_flag_id, true);
            ble_conn_state_user_flag_set(p_sm_evt->conn_handle,
                                         m_bonding_flag_id,
                                         p_sm_evt->params.pairing_success.bonded
            );
            break;

        case SM_EVT_PAIRING_FAIL:
            pm_evt.evt_id = PM_EVT_CONN_SEC_FAILED;
            pm_evt.params.conn_sec_failed.procedure =
                        ble_conn_state_user_flag_get(p_sm_evt->conn_handle, m_bonding_flag_id)
                        ? PM_LINK_SECURED_PROCEDURE_BONDING
                        : PM_LINK_SECURED_PROCEDURE_PAIRING;
            pm_evt.params.conn_sec_failed.error_src
                = p_sm_evt->params.pairing_failed.error_src;
            pm_evt.params.conn_sec_failed.error
                = p_sm_evt->params.pairing_failed.error;
            break;

        case SM_EVT_LINK_ENCRYPTION_UPDATE:
            if (!ble_conn_state_user_flag_get(p_sm_evt->conn_handle, m_pairing_flag_id))
            {
                pm_evt.evt_id = PM_EVT_CONN_SEC_SUCCEEDED;
                pm_evt.params.conn_sec_succeeded.procedure = PM_LINK_SECURED_PROCEDURE_ENCRYPTION;
            }
            else
            {
                find_peer_id = false;
                send_evt     = false;
            }
            break;

        case SM_EVT_LINK_ENCRYPTION_FAILED:
            pm_evt.evt_id = PM_EVT_CONN_SEC_FAILED;
            pm_evt.params.conn_sec_failed.procedure
                            = PM_LINK_SECURED_PROCEDURE_ENCRYPTION;
            pm_evt.params.conn_sec_failed.error_src
                            = p_sm_evt->params.link_encryption_failed.error_src;
            pm_evt.params.conn_sec_failed.error
                            = p_sm_evt->params.link_encryption_failed.error;
            break;

        case SM_EVT_BONDING_INFO_STORED:
            pm_evt.evt_id  = PM_EVT_PEER_DATA_UPDATE_SUCCEEDED;
            pm_evt.peer_id = p_sm_evt->params.bonding_info_stored.peer_id;
            pm_evt.params.peer_data_update_succeeded.data_id = PM_PEER_DATA_ID_BONDING;
            pm_evt.params.peer_data_update_succeeded.action  = PM_PEER_DATA_OP_UPDATE;
            find_peer_id = false;
            break;

        case SM_EVT_ERROR_BONDING_INFO:
            pm_evt.evt_id = PM_EVT_PEER_DATA_UPDATE_FAILED;
            pm_evt.peer_id = p_sm_evt->params.error_bonding_info.peer_id;
            pm_evt.params.peer_data_update_failed.data_id = PM_PEER_DATA_ID_BONDING;
            pm_evt.params.peer_data_update_failed.action  = PM_PEER_DATA_OP_UPDATE;
            pm_evt.params.peer_data_update_failed.error
                = p_sm_evt->params.error_bonding_info.error;
            find_peer_id = false;
            break;

        case SM_EVT_ERROR_UNEXPECTED:
            pm_evt.evt_id = PM_EVT_ERROR_UNEXPECTED;
            pm_evt.params.error_unexpected.error = p_sm_evt->params.error_unexpected.error;
            break;

        case SM_EVT_ERROR_NO_MEM:
            pm_evt.evt_id = PM_EVT_STORAGE_FULL;
            break;

        case SM_EVT_ERROR_SMP_TIMEOUT:
            pm_evt.evt_id = PM_EVT_CONN_SEC_FAILED;
            pm_evt.params.conn_sec_failed.procedure
                        = ble_conn_state_user_flag_get(p_sm_evt->conn_handle, m_bonding_flag_id)
                        ? PM_LINK_SECURED_PROCEDURE_BONDING
                        : PM_LINK_SECURED_PROCEDURE_PAIRING;
            pm_evt.params.conn_sec_failed.error_src  = BLE_GAP_SEC_STATUS_SOURCE_LOCAL;
            pm_evt.params.conn_sec_failed.error      = PM_CONN_SEC_ERROR_SMP_TIMEOUT;
            break;

        case SM_EVT_CONN_SEC_CONFIG_REQ:
            pm_evt.evt_id = PM_EVT_CONN_SEC_CONFIG_REQ;
            break;

        default:
            send_evt = false;
            break;
    }

    if (find_peer_id)
    {
        pm_evt.peer_id = im_peer_id_get_by_conn_handle(p_sm_evt->conn_handle);
    }

    if (send_evt)
    {
        evt_send(&pm_evt);
    }
}