Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

SDK15.0 Link Context Manager - is using conn_handle as an index a good idea?

Hi Nordic,

I am currently looking at using the link context manager introduced in SDK15.0 . I can see it could be useful for my application where each connection needs a different value.

The context manager allocates a block of memory for each context whose size is based on the number of clients and the ssize of each context

However, I can see a potential issue with using the connection

/**@brief Macro for defining a blcm_link_ctx_storage instance.
 *
 * @param[in]   _name            Name of the instance.
 * @param[in]   _max_clients     Maximum number of clients connected at a time.
 * @param[in]   _link_ctx_size   Context size in bytes for a single link.
 */
#define BLE_LINK_CTX_MANAGER_DEF(_name, _max_clients, _link_ctx_size)                               \
    STATIC_ASSERT((_max_clients) < BLE_CONN_STATE_MAX_CONNECTIONS);                                 \
    static uint32_t CONCAT_2(_name, _ctx_data_pool)[(_max_clients)*BYTES_TO_WORDS(_link_ctx_size)]; \
    static blcm_link_ctx_storage_t _name =                                                          \
    {                                                                                               \
        .p_ctx_data_pool = CONCAT_2(_name, _ctx_data_pool),                                         \
        .max_links_cnt   = (_max_clients),                                                          \
        .link_ctx_size   = sizeof(CONCAT_2(_name, _ctx_data_pool))/(_max_clients)                   \
    }

and uses the connection handle as an index into that blck of memory

ret_code_t blcm_link_ctx_get(blcm_link_ctx_storage_t const * const p_link_ctx_storage,
                             uint16_t                        const conn_handle,
                             void                         ** const pp_ctx_data)
{
    uint8_t conn_id;

    if (pp_ctx_data == NULL)
    {
        return NRF_ERROR_NULL;
    }
    else
    {
        *pp_ctx_data = NULL;
    }

    VERIFY_PARAM_NOT_NULL(p_link_ctx_storage);
    VERIFY_PARAM_NOT_NULL(p_link_ctx_storage->p_ctx_data_pool);
    VERIFY_TRUE((p_link_ctx_storage->link_ctx_size % BYTES_PER_WORD) == 0, NRF_ERROR_INVALID_PARAM);

    conn_id = ble_conn_state_conn_idx(conn_handle);

    if (conn_id == BLE_CONN_STATE_MAX_CONNECTIONS)
    {
        return NRF_ERROR_NOT_FOUND;
    }

    if (conn_id >= p_link_ctx_storage->max_links_cnt)
    {
        return NRF_ERROR_NO_MEM;
    }

    *pp_ctx_data = (void *) ((uint8_t *) p_link_ctx_storage->p_ctx_data_pool +
                             conn_id * p_link_ctx_storage->link_ctx_size);
    return NRF_SUCCESS;
}

But what happens if my device is acting as a cental and peripheral? Currently it looks like _max_clients must be equal to the number of central + peripheral connections because the connection handle could be somewhere between 0 and the number of central + peripheral connections. It seems pretty wasteful to allocate space for these extra connections, which will never be used.

For example, I have an application where i have 8 central connections and 5 peripheral connections.

The peripheral services are service1 and service2

The central services are service3, service4, and service5

This means that for each service I need to allocate space for 13 instances. Because the conn handles for my peripheral and central connections can range between 0 and 12.

Could this be improved by using the ble_conn_state_central_conn_count() and ble_conn_state_peripheral_conn_count() functions as indexes instead? You would need to know whether its a client or server

Also, line 71 in ble_link_ctx_manager.h is

    STATIC_ASSERT((_max_clients) < BLE_CONN_STATE_MAX_CONNECTIONS);

should this be   

STATIC_ASSERT((_max_clients) <= BLE_CONN_STATE_MAX_CONNECTIONS); 

?

Parents
  • This helper module is supposed to be used with GATT services (see BLE HIDS, IAS implementations) that require to keep some context data for each link in order to handle multiple connections. GATT server is GAP role agnostic, so any central or peripheral that connects to your device can potentially interact with your services and act as GATT client.

    "Could this be improved by using the ble_conn_state_central_conn_count() and ble_conn_state_peripheral_conn_count() functions as indexes instead? You would need to know whether its a client or server"

    These functions return the number of active peripheral/central connections, but the particular connection handle can be still in central + peripheral connections range. You would need to provide your own mapping function that will translate supplied connection handle to the index that is either within ble_conn_state_central_conn_count() or ble_conn_state_peripheral_conn_count() range.

    Yes, you are right - static assert should be:

    STATIC_ASSERT((_max_clients) <= BLE_CONN_STATE_MAX_CONNECTIONS);

Reply Children
No Data
Related