This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Mismatch between connection handles in ble_nus?

I'm using the nus_c service with multiple central connections. Obviously, I need the connection handle in my event handler - ble_nus_c_evt_handler(ble_nus_c_t* p_ble_nus_c, const ble_nus_c_evt_t* p_ble_nus_evt).

I've noticed that when BLE_NUS_C_EVT_NUS_RX_EVT is raised, the connection handle in the NUS context object and the event object are different: p_ble_nus_c->conn_handle == 1, as expected, while p_ble_nus_evt->conn_handle == 0.

I've traced it down to on_hvx() in ble_nus_c.c, not setting the connection handle from the GATTC event to the ble_nus_c_evt_t structure it dispatches.

Is this by design or a bug?

Parents
  • Hi,

    Yes, the on_hvx() is not setting the conn_handle for the BLE_NUS_C_EVT_NUS_RX_EVT event, but you have access to the conn_handle in the p_ble_nus_c struct. Ideally it should also be set for the ble_nus_c_evt, i.e. ble_nus_c_evt.conn_handle = p_ble_nus_c->conn_handle; in on_hvx().

    When the nus_c service was initially designed, the nRF5 series only had support for one connection. Later the code was refactored and ble_nus_c_handles_assign() was added so we can keep track of what connection belongs to what instance of NUS.

    So if the overall goal is to use the nus_c service in multiple connections, I recommend that you create a separate NUS and DB structure instance for each connection:

    static ble_nus_c_t              m_ble_nus_c[TOTAL_LINK_COUNT];
    static uint8_t                  m_ble_nus_c_count;  
    static ble_db_discovery_t       m_ble_db_discovery[TOTAL_LINK_COUNT];
    

    Then each instance of NUS would have to be assigned a connection handle with ble_nus_c_handles_assign() when you get the event BLE_NUS_C_EVT_DISCOVERY_COMPLETE. In nus_c_init() and db_discovery_init() you will need to initialize each instance. In nus_c_init() this could look something like this:

    static void nus_c_init(void)
    {
        uint32_t         err_code;
        ble_nus_c_init_t nus_c_init_t;
    
        nus_c_init_t.evt_handler = ble_nus_c_evt_handler;
        
    	for (m_ble_nus_c_count = 0; m_ble_nus_c_count < TOTAL_LINK_COUNT; m_ble_nus_c_count++)
        {
            err_code = ble_nus_c_init(&m_ble_nus_c[m_ble_nus_c_count], &nus_c_init_t);
            APP_ERROR_CHECK(err_code);
        }
        m_ble_nus_c_count = 0;
    }
    

    The db_disc_handler() function would look something like this:

    static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
    {
        ble_nus_c_on_db_disc_evt(&m_ble_nus_c[p_evt->conn_handle], p_evt);
    }
    

    In ble_evt_dispatch(), ble_db_discovery_on_ble_evt() and ble_nus_c_on_ble_evt() should be changed to something like this:

    uint16_t conn_handle;
    conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    
    ble_db_discovery_on_ble_evt(&m_ble_db_discovery[conn_handle], p_ble_evt);
    ble_nus_c_on_ble_evt(&m_ble_nus_c[conn_handle],p_ble_evt);
    

    You should also take a look at the multilink central example in the SDK to see how this example handles multiple connections.

  • Hello Sigurd,

    where should i set "ble_nus_c_handles_assign(..)" function?

    All the definition are follow the sample code as you provided.

    Thanks.

Reply Children
Related