Error handling of sd_ble_gap_disconnect

Hi,

I got an error BLE_ERROR_INVALID_CONN_HANDLE at the function sd_ble_gap_disconnect. I know that this error has to do with the fact that an invalid connection handle is given.

That's why I first check if there is a link, and if so then disconnect. See my code below:

    uint32_t err_code;
    ble_conn_state_conn_handle_list_t conn_handles = ble_conn_state_conn_handles();
    uint32_t periph_link_cnt = ble_conn_state_peripheral_conn_count();
    NRF_LOG_DEBUG("conn handles len: %d", conn_handles.len);
    NRF_LOG_DEBUG("periph_link_cnt: %d", periph_link_cnt);
    if (periph_link_cnt > 0) {
        for (uint8_t i = 0; i < conn_handles.len; i++) {
            NRF_LOG_DEBUG("idle connection, disconnect conn_handle %d", conn_handles.conn_handles[i]);
            err_code = sd_ble_gap_disconnect(conn_handles.conn_handles[i],
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
       }
   }

Our app does a manual disconnect, by writing a certain value to a custom char I've written, to invoke disconnect from the device, and also from the android app itself. If we don't do the disconnect from device sometimes Android stack doesn't disconnect and the stack gets corrupted, but that's another topic. Anyway, that's why we always do a manual disconnect from device. Mostly this goes well, but in some situations I think the android disconnect happens after the checking if there is a link_cnt. So it will go into the if loop and there it tries to do a disconnect, but then there are no conn_handles anymore.

So my main question is, can I just skip this error handling of sd_ble_gap_disconnect? Are these errors just for information, or can it corrupt the bluetooth stack in a way and should it be fixed by the application by a reboot? Because I testes a couple times to invoke a manual disconnect without being connected and no error handling, and everything went fine.

Parents
  • Hello,

    From where do you call the snippet that you included?

    I have two theories.

    1: You are not "properly connected" yet, meaning the connection handle that you are trying to disconnect from is not yet set.

    2: You have already disconnected from that connection handle from elsewhere in your code.

    Perhaps you can show me where you call it? Is it in some event? Does it happen every time you call this snippet? Have you tried debugging? What is the value of the connection handle that you are trying to disconnect from?

    Best regards,

    Edvin

  • Hi Edvin,

    This code snippet is from a self created function disconnect(). I call this function from a couple of places.

    - A timer, to check if an idle connection exist and then disconnects
    - A custom characteristic where the app writes a value to, in order to "disconnect from the device"

    I think I exactly know why this happens, it's because when the app sends that value to the characteristic, and then immediately also disconnects from the app, so the bluetooth stack has a disconnect, which is faster then the "if" loop, so the connection handle is lost, and then it tries to disconnect again. (hope you can follow it ;)).

    But my main question was actually, is it necessary to have an error check there anyway, or can I just skip the error checking there since it's not really harmful to disconnect while there is no connection? I mean it won't corrupt the bluetooth stack right?

Reply
  • Hi Edvin,

    This code snippet is from a self created function disconnect(). I call this function from a couple of places.

    - A timer, to check if an idle connection exist and then disconnects
    - A custom characteristic where the app writes a value to, in order to "disconnect from the device"

    I think I exactly know why this happens, it's because when the app sends that value to the characteristic, and then immediately also disconnects from the app, so the bluetooth stack has a disconnect, which is faster then the "if" loop, so the connection handle is lost, and then it tries to disconnect again. (hope you can follow it ;)).

    But my main question was actually, is it necessary to have an error check there anyway, or can I just skip the error checking there since it's not really harmful to disconnect while there is no connection? I mean it won't corrupt the bluetooth stack right?

Children
  • The point of the error check is so that you (the developer) knows what's going on. By this, you figured out that the device was already disconnected when you tried to disconnect. 

    In general, I would suggest that you ignore this specific return value from this function, but still error check for other return values. But whether other scenarios are likely to happen, it is difficult to say.

    I suggest:

        uint32_t err_code;
        ble_conn_state_conn_handle_list_t conn_handles = ble_conn_state_conn_handles();
        uint32_t periph_link_cnt = ble_conn_state_peripheral_conn_count();
        NRF_LOG_DEBUG("conn handles len: %d", conn_handles.len);
        NRF_LOG_DEBUG("periph_link_cnt: %d", periph_link_cnt);
        if (periph_link_cnt > 0) {
            for (uint8_t i = 0; i < conn_handles.len; i++) {
                NRF_LOG_DEBUG("idle connection, disconnect conn_handle %d", conn_handles.conn_handles[i]);
                err_code = sd_ble_gap_disconnect(conn_handles.conn_handles[i],
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                if (err_code != BLE_ERROR_INVALID_CONN_HANDLE)
                {
                    APP_ERROR_CHECK(err_code);
                }
                else
                {
                    NRF_LOG_DEBUG("Already disconnected");
                }
           }
       }

    Whether you add the log saying already disconnected is of course up to you.

    Best regards,

    Edvin

Related