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

NRF_ERROR_INVALID_STATE error on new characteristic

I am trying to modify the existing Thingy-52 code to have a 'new' characteristic.  I used the existing Thingy code to 'clone' a new characteristic (a 2nd microphone channel).  My problem is that whenever I try to write to the channel I get an NRF_ERROR_INVALID_STATE error from sd_ble_gatts_hvx() that is used to send the data.  In researching NRF_ERROR_INVALID_STATE it appears there can be 3 causes of this failure, 1 - invalid connection state, 2 - Notifications/indications not enabled, 3 - MTU exchange ongoing.  I am thinking that somehow notifications are not enabled.  Is this done from the 'app'/client side of things?  Where are notifications enabled.
Just to answer setup questions... here is my code: 
Added a new BLE characteristic to Thingy Sound service for right stereo sound channel
Step #1)  Add UUID of new characteristic to list (ble_tss.h)
#define BLE_UUID_TSS_CONFIG_CHAR      0x0501   /**< The UUID of the config char */
#define BLE_UUID_TSS_SPKR_CHAR        0x0502   /**< The UUID of the speaker char */
#define BLE_UUID_TSS_SPKR_STAT_CHAR   0x0503   /**< The UUID of the speaker char */
#define BLE_UUID_TSS_MIC_CHAR         0x0504   /**< The UUID of the microphone char */
#ifdef STEREO
#define BLE_UUID_TSS_RIGHT_MIC_CHAR   0x0505   /**< The UUID of the right mic char */
#endif
Step #2) Changed sound service structure to include right mic handle (ble_tss.h)
struct ble_tss_s
{
    uint8_t                  uuid_type;         /**< UUID type for Thingy Sound Service Base UUID. */
    uint16_t                 service_handle;    /**< Handle of Thingy Sound Service (as provided by the S110 SoftDevice). */
    ble_gatts_char_handles_t spkr_handles;      /**< Handles related to the speaker characteristic (from S132 SoftDevice). */
    ble_gatts_char_handles_t mic_handles;       /**< Handles related to the microphone characteristic (from S132 SoftDevice). */
    ble_gatts_char_handles_t right_mic_handles; /**< Handles related to the right microphone characteristic (from S132 SoftDevice). */
    ble_gatts_char_handles_t spkr_stat_handles; /**< Handles related to the speaker status characteristic (from S132 SoftDevice). */
    ble_gatts_char_handles_t config_handles;    /**< Handles related to the config characteristic (from S132 SoftDevice). */
    uint16_t                 conn_handle;       /**< Handle of the current connection (as provided by the S110 SoftDevice). */
                                                /**< BLE_CONN_HANDLE_INVALID if not in a connection. */
    bool                     is_mic_notif_enabled; /**< Variable to indicate if the peer has enabled notification of the char*/
    bool                     is_spkr_stat_notif_enabled; /**< Variable to indicate if the peer has enabled notification of char.*/
    ble_tss_evt_handler_t    evt_handler;                /**< Event handler to be called for handling received data. */
};
typedef struct ble_tss_s ble_tss_t;
 
Step #3) Initialize sound service for new characteristic.
thingy_init() → m_sound_init(): sets ble event handler, sound service init routine, data handlers (step 4)
 uint32_t m_sound_init(m_ble_service_handle_t * p_handle)
{
    uint32_t           err_code;
    drv_speaker_init_t speaker_init;
     NULL_PARAM_CHECK(p_handle);
     NRF_LOG_INFO("Sound_init \r\n");
     p_handle->ble_evt_cb = sound_on_ble_evt;
     p_handle->init_cb    = sound_service_init;
     return drv_mic_init(drv_mic_data_handler, drv_right_mic_data_handler);
}
 
Step 4) Set data handlers, initialize audio streams.
static drv_mic_data_handler_t m_left_data_handler;
static drv_mic_data_handler_t m_right_data_handler;
uint32_t drv_mic_init(drv_mic_data_handler_t left_data_handler, drv_mic_data_handler_t right_data_handler)
{
    uint32_t err_code;
    m_audio_enabled = false;
    m_left_data_handler   = left_data_handler;
    m_right_data_handler  = right_data_handler;
    for(uint32_t i = 0; i < PDM_BUF_NUM; i++)
    {
        m_pdm_buf[i].free = true;
    }
     mic_power_off();
     return drv_audio_init(m_audio_buffer_handler);
}
 
// Initialize BLE Thingy Sound service
 
thingy_init() → m_ble_init() → services_init() → ble_tss_init()
 uint32_t ble_tss_init(ble_tss_t * p_tss, const ble_tss_init_t * p_tss_init)
{
    uint32_t      err_code;
    ble_uuid_t    ble_uuid;
    ble_uuid128_t tss_base_uuid = TSS_BASE_UUID;
    VERIFY_PARAM_NOT_NULL(p_tss);
    VERIFY_PARAM_NOT_NULL(p_tss_init);
    // Initialize the service structure.
    p_tss->conn_handle                  = BLE_CONN_HANDLE_INVALID;
    p_tss->evt_handler                  = p_tss_init->evt_handler;
    p_tss->is_mic_notif_enabled         = false;
    p_tss->is_spkr_stat_notif_enabled   = false;
     // Add a custom base UUID.
    err_code = sd_ble_uuid_vs_add(&tss_base_uuid, &p_tss->uuid_type);
    VERIFY_SUCCESS(err_code);
     ble_uuid.type = p_tss->uuid_type;
    ble_uuid.uuid = BLE_UUID_TSS_SERVICE;
     // Add the service.
    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
                                        &ble_uuid,
                                        &p_tss->service_handle);
    VERIFY_SUCCESS(err_code);
     // Add the config Characteristic.
    err_code = config_char_add(p_tss, p_tss_init);
    VERIFY_SUCCESS(err_code);
     // Add the speaker Characteristic.
    err_code = spkr_char_add(p_tss, p_tss_init);
    VERIFY_SUCCESS(err_code);
     // Add the speaker Characteristic.
    err_code = spkr_stat_char_add(p_tss, p_tss_init);
    VERIFY_SUCCESS(err_code);
     // Add the microphone Characteristic.
    err_code = mic_char_add(p_tss, p_tss_init);
    VERIFY_SUCCESS(err_code);
 
    // Add the right channel microphone Characteristic.
    err_code = right_mic_char_add(p_tss, p_tss_init);
    VERIFY_SUCCESS(err_code);
 
    return NRF_SUCCESS;
}
Step 5: Data handler- drv_right_mic_data_handler.  When data comes in from PDM it eventually triggers a packet of information to be sent by drv_right_mic_data_handler().  This sequence works correctly up to the point that the data is sent.  Ble_tss_right_mic_set() error with value of 8 – NRF_ERROR_INVALID_STATE
static uint32_t drv_right_mic_data_handler(m_audio_frame_t * p_frame)
{
    uint32_t err_code;
     if (p_frame->data_size != CONFIG_AUDIO_FRAME_SIZE_BYTES)
    {
        NRF_LOG_WARNING("drv_right_mic_data_handler: size = %d \r\n", p_frame->data_size);
    }
    err_code = ble_tss_right_mic_set(&m_tss, p_frame->data, p_frame->data_size);
    if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("drv_right_mic_data_handler: Failed to send\r\n");
        }
    }
    return NRF_SUCCESS;
}
uint32_t ble_tss_right_mic_set(ble_tss_t * p_tss, uint8_t * p_data, uint16_t size)
{
    ble_gatts_hvx_params_t hvx_params;
 
    VERIFY_PARAM_NOT_NULL(p_tss);
 
    if ((p_tss->conn_handle == BLE_CONN_HANDLE_INVALID) || (!p_tss->is_mic_notif_enabled))
    {
        return NRF_ERROR_INVALID_STATE;
    }
 
    if (size > BLE_TSS_MIC_FRAME_SIZE)
    {
        return NRF_ERROR_INVALID_PARAM;
    }
 
    memset(&hvx_params, 0, sizeof(hvx_params));
 
    hvx_params.handle = p_tss->right_mic_handles.value_handle;
    hvx_params.p_data = p_data;
    hvx_params.p_len  = &size;
    hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
 
    return sd_ble_gatts_hvx(p_tss->conn_handle, &hvx_params);
}
Parents Reply Children
Related