| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- /* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
- *
- * The information contained herein is property of Nordic Semiconductor ASA.
- * Terms and conditions of usage are described in detail in NORDIC
- * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
- *
- * Licensees are granted free, non-transferable use of the information. NO
- * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
- * the file.
- *
- */
- #include "ble_conn_params.h"
- #include <stdlib.h>
- #include "nordic_common.h"
- #include "ble_hci.h"
- #include "app_timer.h"
- #include "ble_srv_common.h"
- #include "app_util.h"
- static ble_conn_params_init_t m_conn_params_config; /**< Configuration as specified by the application. */
- static ble_gap_conn_params_t m_preferred_conn_params; /**< Connection parameters preferred by the application. */
- static uint8_t m_update_count; /**< Number of Connection Parameter Update messages that has currently been sent. */
- static uint16_t m_conn_handle; /**< Current connection handle. */
- static ble_gap_conn_params_t m_current_conn_params; /**< Connection parameters received in the most recent Connect event. */
- APP_TIMER_DEF(m_conn_params_timer_id); /**< Connection parameters timer. */
- static bool m_change_param = false;
- static bool is_conn_params_ok(ble_gap_conn_params_t * p_conn_params)
- {
- // Check if interval is within the acceptable range.
- // NOTE: Using max_conn_interval in the received event data because this contains
- // the client's connection interval.
- if (
- (p_conn_params->max_conn_interval >= m_preferred_conn_params.min_conn_interval)
- &&
- (p_conn_params->max_conn_interval <= m_preferred_conn_params.max_conn_interval)
- )
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- static void update_timeout_handler(void * p_context)
- {
- UNUSED_PARAMETER(p_context);
- if (m_conn_handle != BLE_CONN_HANDLE_INVALID)
- {
- // Check if we have reached the maximum number of attempts
- m_update_count++;
- if (m_update_count <= m_conn_params_config.max_conn_params_update_count)
- {
- uint32_t err_code;
- // Parameters are not ok, send connection parameters update request.
- err_code = sd_ble_gap_conn_param_update(m_conn_handle, &m_preferred_conn_params);
- if ((err_code != NRF_SUCCESS) && (m_conn_params_config.error_handler != NULL))
- {
- m_conn_params_config.error_handler(err_code);
- }
- }
- else
- {
- m_update_count = 0;
- // Negotiation failed, disconnect automatically if this has been configured
- if (m_conn_params_config.disconnect_on_fail)
- {
- uint32_t err_code;
- err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
- if ((err_code != NRF_SUCCESS) && (m_conn_params_config.error_handler != NULL))
- {
- m_conn_params_config.error_handler(err_code);
- }
- }
- // Notify the application that the procedure has failed
- if (m_conn_params_config.evt_handler != NULL)
- {
- ble_conn_params_evt_t evt;
- evt.evt_type = BLE_CONN_PARAMS_EVT_FAILED;
- m_conn_params_config.evt_handler(&evt);
- }
- }
- }
- }
- uint32_t ble_conn_params_init(const ble_conn_params_init_t * p_init)
- {
- uint32_t err_code;
- m_conn_params_config = *p_init;
- m_change_param = false;
- if (p_init->p_conn_params != NULL)
- {
- m_preferred_conn_params = *p_init->p_conn_params;
- // Set the connection params in stack
- err_code = sd_ble_gap_ppcp_set(&m_preferred_conn_params);
- if (err_code != NRF_SUCCESS)
- {
- return err_code;
- }
- }
- else
- {
- // Fetch the connection params from stack
- err_code = sd_ble_gap_ppcp_get(&m_preferred_conn_params);
- if (err_code != NRF_SUCCESS)
- {
- return err_code;
- }
- }
- m_conn_handle = BLE_CONN_HANDLE_INVALID;
- m_update_count = 0;
- return app_timer_create(&m_conn_params_timer_id,
- APP_TIMER_MODE_SINGLE_SHOT,
- update_timeout_handler);
- }
- uint32_t ble_conn_params_stop(void)
- {
- return app_timer_stop(m_conn_params_timer_id);
- }
- static void conn_params_negotiation(void)
- {
- // Start negotiation if the received connection parameters are not acceptable
- if (!is_conn_params_ok(&m_current_conn_params))
- {
- uint32_t err_code;
- uint32_t timeout_ticks;
- if (m_change_param)
- {
- // Notify the application that the procedure has failed
- if (m_conn_params_config.evt_handler != NULL)
- {
- ble_conn_params_evt_t evt;
- evt.evt_type = BLE_CONN_PARAMS_EVT_FAILED;
- m_conn_params_config.evt_handler(&evt);
- }
- }
- else
- {
- if (m_update_count == 0)
- {
- // First connection parameter update
- timeout_ticks = m_conn_params_config.first_conn_params_update_delay;
- }
- else
- {
- timeout_ticks = m_conn_params_config.next_conn_params_update_delay;
- }
- err_code = app_timer_start(m_conn_params_timer_id, timeout_ticks, NULL);
- if ((err_code != NRF_SUCCESS) && (m_conn_params_config.error_handler != NULL))
- {
- m_conn_params_config.error_handler(err_code);
- }
- }
- }
- else
- {
- // Notify the application that the procedure has succeded
- if (m_conn_params_config.evt_handler != NULL)
- {
- ble_conn_params_evt_t evt;
- evt.evt_type = BLE_CONN_PARAMS_EVT_SUCCEEDED;
- m_conn_params_config.evt_handler(&evt);
- }
- }
- m_change_param = false;
- }
- static void on_connect(ble_evt_t * p_ble_evt)
- {
- // Save connection parameters
- m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
- m_current_conn_params = p_ble_evt->evt.gap_evt.params.connected.conn_params;
- m_update_count = 0; // Connection parameter negotiation should re-start every connection
- // Check if we shall handle negotiation on connect
- if (m_conn_params_config.start_on_notify_cccd_handle == BLE_GATT_HANDLE_INVALID)
- {
- conn_params_negotiation();
- }
- }
- static void on_disconnect(ble_evt_t * p_ble_evt)
- {
- uint32_t err_code;
- m_conn_handle = BLE_CONN_HANDLE_INVALID;
- // Stop timer if running
- m_update_count = 0; // Connection parameters updates should happen during every connection
- err_code = app_timer_stop(m_conn_params_timer_id);
- if ((err_code != NRF_SUCCESS) && (m_conn_params_config.error_handler != NULL))
- {
- m_conn_params_config.error_handler(err_code);
- }
- }
- static void on_write(ble_evt_t * p_ble_evt)
- {
- ble_gatts_evt_write_t * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
- // Check if this the correct CCCD
- if (
- (p_evt_write->handle == m_conn_params_config.start_on_notify_cccd_handle)
- &&
- (p_evt_write->len == 2)
- )
- {
- // Check if this is a 'start notification'
- if (ble_srv_is_notification_enabled(p_evt_write->data))
- {
- // Do connection parameter negotiation if necessary
- conn_params_negotiation();
- }
- else
- {
- uint32_t err_code;
- // Stop timer if running
- err_code = app_timer_stop(m_conn_params_timer_id);
- if ((err_code != NRF_SUCCESS) && (m_conn_params_config.error_handler != NULL))
- {
- m_conn_params_config.error_handler(err_code);
- }
- }
- }
- }
- static void on_conn_params_update(ble_evt_t * p_ble_evt)
- {
- // Copy the parameters
- m_current_conn_params = p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params;
- conn_params_negotiation();
- }
- void ble_conn_params_on_ble_evt(ble_evt_t * p_ble_evt)
- {
- switch (p_ble_evt->header.evt_id)
- {
- case BLE_GAP_EVT_CONNECTED:
- on_connect(p_ble_evt);
- break;
- case BLE_GAP_EVT_DISCONNECTED:
- on_disconnect(p_ble_evt);
- break;
- case BLE_GATTS_EVT_WRITE:
- on_write(p_ble_evt);
- break;
- case BLE_GAP_EVT_CONN_PARAM_UPDATE:
- on_conn_params_update(p_ble_evt);
- break;
- default:
- // No implementation needed.
- break;
- }
- }
- uint32_t ble_conn_params_change_conn_params(ble_gap_conn_params_t * new_params)
- {
- uint32_t err_code;
- m_preferred_conn_params = *new_params;
- // Set the connection params in stack
- err_code = sd_ble_gap_ppcp_set(&m_preferred_conn_params);
- if (err_code == NRF_SUCCESS)
- {
- if (!is_conn_params_ok(&m_current_conn_params))
- {
- m_change_param = true;
- err_code = sd_ble_gap_conn_param_update(m_conn_handle, &m_preferred_conn_params);
- m_update_count = 1;
- }
- else
- {
- // Notify the application that the procedure has succeded
- if (m_conn_params_config.evt_handler != NULL)
- {
- ble_conn_params_evt_t evt;
- evt.evt_type = BLE_CONN_PARAMS_EVT_SUCCEEDED;
- m_conn_params_config.evt_handler(&evt);
- }
- err_code = NRF_SUCCESS;
- }
- }
- return err_code;
- }
|