Error When Reading Characteristic

Hi,

I am using nRF5 SDK v17.2.0 on a legacy product. I have code that looks like this:

    ret_code_t rc = sd_ble_gatts_rw_authorize_reply(event->evt.common_evt.conn_handle, &authParams);

    if (rc == NRF_SUCCESS)
    {
        NRF_LOG_INFO("Event history - read %d events starting at %d", eventListContent.events().get_length(), originalOffset);
    }
    else
    {
        NRF_LOG_ERROR("Failed to reply to event history read request. RC: %d", rc);
    }

When reading the characteristic repeatedly, I sometimes see something like this printed out:

00> <info> app: Event history - read 8 events starting at 0
00> <info> app: Event history - read 8 events starting at 8
00> <info> app: Event history - read 8 events starting at 16
00> <info> app: Event history - read 8 events starting at 24
00> <info> app: Event history - read 8 events starting at 32
00> <error> app: Failed to reply to event history read request. RC: 8
00> <info> app: Event history - read 8 events starting at 48
00> <info> app: Event history - read 8 events starting at 56
00> <info> app: Event history - read 0 events starting at 64

Return code of 8 corresponds to NRF_ERROR_INVALID_STATE. Why would I get that?

  • Hi,

    From the API documenation for sd_ble_gatts_rw_authorize_reply() it can return NRF_ERROR_INVALID_STATE due to "Invalid Connection State or no authorization request pending".

    I assume you would have logged if there was a disconnect, so that is probably not the case? A next step then could be to logg all BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST events and all calls you make to sd_ble_gatts_rw_authorize_reply() to make sure you never call is when there is no active authorize request. If you do, the error is expected.

  • Hi,

    Thank you for your reply. My code looks something like this:

    Header file:

    NRF_SDH_BLE_OBSERVER(_name ## _obs, 2, OnBleEvt, &_name)

    Source file:

    void OnBleEvt(ble_evt_t const *event, [[maybe_unused]] void *context)
    {
        ble_gatts_evt_rw_authorize_request_t const *eventAuthorize =
            &event->evt.gatts_evt.params.authorize_request;
    
        switch (eventAuthorize->type)
        {
        case BLE_GATTS_AUTHORIZE_TYPE_READ:
            switch (eventAuthorize->request.read.uuid.uuid)
            {
            case CTFS_CHAR_EVENT_HISTORY_UUID:
                OnAuthorizeHandleReadEventHistory(event);
            break;
            // more characteristics here
            }
        break;
        }
    }

    "sd_ble_gatts_rw_authorize_reply()" is called in the "OnAuthorizeHandleReadEventHistory()" up above. So I don't think I'm calling this in a wrong place.

  • Hi,

    I am not able to see the larger picture from these snippets. I have also had a look at the SoftDevice implementation, and I believe the two reasons described in he API documentation are the only two possible explanations for getting NRF_ERROR_INVALID_STATE returned from sd_ble_gatts_rw_authorize_reply().

    So my recommendation remain to debug and get a clear picture of when you get the event and when sd_ble_gatts_rw_authorize_reply() is called. Note that sd_ble_gatts_rw_authorize_reply() can be called from SDK code as well (and if it is, you cannot call it again from the same request, as the second call will then fail with NRF_ERROR_INVALID_STATE, as i should as the request is then already handled).

  • My firmware has quite a few characteristics. If some of them are read on an interval, with similar logic in place (sd_ble_gatts_rw_authorize_reply() for each one), would it be possible that more than one read is happening and thus the firmware failing with this error?

  • That should not be the case. Only one authorized read/write operation is allowed at a time per connection. (If your device has multiple concurrent connections there is of perhaps a bigger potential for a mixup here, but I do not know if that is the case?)

Related