Nrf52840 not able to send data from central device to App.

Hi Everyone, 

                 I am using nrf52840 in my project which is used as a central device. I have my app through which I can send data to the central device. The device is also able to receive the data and process it. Now when I want to send back the data to the app I am getting hard fault handler. I am trying to send only 5 bytes of data. I have attached my files over here for reference. Please help me out. I am using sdk 17.0.2.

ble_aqrs_c.c

/**
 * Copyright (c) 2012 - 2020, Nordic Semiconductor ASA
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form, except as embedded into a Nordic
 *    Semiconductor ASA integrated circuit in a product or a software update for
 *    such product, must reproduce the above copyright notice, this list of
 *    conditions and the following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *
 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * 4. This software, with or without modification, must only be used with a
 *    Nordic Semiconductor ASA integrated circuit.
 *
 * 5. Any software provided in binary form under this license must not be reverse
 *    engineered, decompiled, modified and/or disassembled.
 *
 * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "sdk_common.h"

#include <stdlib.h>

#include "ble.h"
#include "ble_aqrs_c.h"
#include "ble_gattc.h"
#include "ble_srv_common.h"
#include "app_error.h"

#include "ble_aqrs.h"

#define NRF_LOG_MODULE_NAME ble_aqrs_c
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER();


/**@brief Function for intercepting the errors of GATTC and the BLE GATT Queue.
 *
 * @param[in] nrf_error   Error code.
 * @param[in] p_ctx       Parameter from the event handler.
 * @param[in] conn_handle Connection handle.
 */
static void gatt_error_handler(uint32_t   nrf_error,
                               void     * p_ctx,
                               uint16_t   conn_handle)
{
    ble_aqrs_c_t * p_ble_aqrs_c = (ble_aqrs_c_t *)p_ctx;

    NRF_LOG_DEBUG("A GATT Client error has occurred on conn_handle: 0X%X", conn_handle);

    if (p_ble_aqrs_c->error_handler != NULL)
    {
        p_ble_aqrs_c->error_handler(nrf_error);
    }
}


void ble_aqrs_c_on_db_disc_evt(ble_aqrs_c_t * p_ble_aqrs_c, ble_db_discovery_evt_t * p_evt)
{
    ble_aqrs_c_evt_t aqrs_c_evt;
    memset(&aqrs_c_evt,0,sizeof(ble_aqrs_c_evt_t));

    ble_gatt_db_char_t * p_chars = p_evt->params.discovered_db.charateristics;

    // Check if the aqrs was discovered.
    if (    (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE)
        &&  (p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_AQRS_SERVICE)
        &&  (p_evt->params.discovered_db.srv_uuid.type == p_ble_aqrs_c->uuid_type))
    {
        for (uint32_t i = 0; i < p_evt->params.discovered_db.char_count; i++)
        {
            switch (p_chars[i].characteristic.uuid.uuid)
            {
                case BLE_UUID_AQRS_SETTING_CHARACTERISTIC:
                    aqrs_c_evt.handles.aqrs_rx_handle = p_chars[i].characteristic.handle_value;
                    break;

                case BLE_UUID_AQRS_NOTIF_CHARACTERISTIC:
                    aqrs_c_evt.handles.aqrs_tx_handle = p_chars[i].characteristic.handle_value;
                    aqrs_c_evt.handles.aqrs_tx_cccd_handle = p_chars[i].cccd_handle;
                    break;

                default:
                    break;
            }
        }
        if (p_ble_aqrs_c->evt_handler != NULL)
        {
            aqrs_c_evt.conn_handle = p_evt->conn_handle;
            aqrs_c_evt.evt_type    = BLE_AQRS_C_EVT_DISCOVERY_COMPLETE;
            p_ble_aqrs_c->evt_handler(p_ble_aqrs_c, &aqrs_c_evt);
        }
    }
}

/**@brief     Function for handling Handle Value Notification received from the SoftDevice.
 *
 * @details   This function uses the Handle Value Notification received from the SoftDevice
 *            and checks if it is a notification of the AQRS TX characteristic from the peer.
 *            If it is, this function decodes the data and sends it to the application.
 *            
 * @param[in] p_ble_aqrs_c Pointer to the AQRS Client structure.
 * @param[in] p_ble_evt   Pointer to the BLE event received.
 */
static void on_hvx(ble_aqrs_c_t * p_ble_aqrs_c, ble_evt_t const * p_ble_evt)
{
    // HVX can only occur from client sending.
    if (   (p_ble_aqrs_c->handles.aqrs_tx_handle != BLE_GATT_HANDLE_INVALID)
        && (p_ble_evt->evt.gattc_evt.params.hvx.handle == p_ble_aqrs_c->handles.aqrs_tx_handle)
        && (p_ble_aqrs_c->evt_handler != NULL))
    {
        ble_aqrs_c_evt_t ble_aqrs_c_evt;

        ble_aqrs_c_evt.evt_type = BLE_AQRS_C_EVT_AQRS_TX_EVT;
        ble_aqrs_c_evt.p_data   = (uint8_t *)p_ble_evt->evt.gattc_evt.params.hvx.data;
        ble_aqrs_c_evt.data_len = p_ble_evt->evt.gattc_evt.params.hvx.len;

        p_ble_aqrs_c->evt_handler(p_ble_aqrs_c, &ble_aqrs_c_evt);
        NRF_LOG_DEBUG("Client sending data.");
    }
}

uint32_t ble_aqrs_c_init(ble_aqrs_c_t * p_ble_aqrs_c, ble_aqrs_c_init_t * p_ble_aqrs_c_init)
{
    uint32_t      err_code;
    ble_uuid_t    uart_uuid;
    ble_uuid128_t aqrs_base_uuid = AQRS_BASE_UUID;

    VERIFY_PARAM_NOT_NULL(p_ble_aqrs_c);
    VERIFY_PARAM_NOT_NULL(p_ble_aqrs_c_init);
    VERIFY_PARAM_NOT_NULL(p_ble_aqrs_c_init->p_gatt_queue);

    err_code = sd_ble_uuid_vs_add(&aqrs_base_uuid, &p_ble_aqrs_c->uuid_type);
    VERIFY_SUCCESS(err_code);

    uart_uuid.type = p_ble_aqrs_c->uuid_type;
    uart_uuid.uuid = BLE_UUID_AQRS_SERVICE;

    p_ble_aqrs_c->conn_handle           = BLE_CONN_HANDLE_INVALID;
    p_ble_aqrs_c->evt_handler           = p_ble_aqrs_c_init->evt_handler;
    p_ble_aqrs_c->error_handler         = p_ble_aqrs_c_init->error_handler;
    p_ble_aqrs_c->handles.aqrs_tx_handle = BLE_GATT_HANDLE_INVALID;
    p_ble_aqrs_c->handles.aqrs_rx_handle = BLE_GATT_HANDLE_INVALID;
    p_ble_aqrs_c->p_gatt_queue          = p_ble_aqrs_c_init->p_gatt_queue;

    return ble_db_discovery_evt_register(&uart_uuid);
}

void ble_aqrs_c_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
{
    ble_aqrs_c_t * p_ble_aqrs_c = (ble_aqrs_c_t *)p_context;

    if ((p_ble_aqrs_c == NULL) || (p_ble_evt == NULL))
    {
        return;
    }

    if ( (p_ble_aqrs_c->conn_handle == BLE_CONN_HANDLE_INVALID)
       ||(p_ble_aqrs_c->conn_handle != p_ble_evt->evt.gap_evt.conn_handle)
       )
    {
        return;
    }

    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GATTC_EVT_HVX:
            on_hvx(p_ble_aqrs_c, p_ble_evt);
            break;

        case BLE_GAP_EVT_DISCONNECTED:
            if (p_ble_evt->evt.gap_evt.conn_handle == p_ble_aqrs_c->conn_handle
                    && p_ble_aqrs_c->evt_handler != NULL)
            {
                ble_aqrs_c_evt_t aqrs_c_evt;

                aqrs_c_evt.evt_type = BLE_AQRS_C_EVT_DISCONNECTED;

                p_ble_aqrs_c->conn_handle = BLE_CONN_HANDLE_INVALID;
                p_ble_aqrs_c->evt_handler(p_ble_aqrs_c, &aqrs_c_evt);
            }
            break;

        default:
            // No implementation needed.
            break;
    }
}

/**@brief Function for creating a message for writing to the CCCD. */
static uint32_t cccd_configure(ble_aqrs_c_t * p_ble_aqrs_c, bool notification_enable)
{
    nrf_ble_gq_req_t cccd_req;
    uint8_t          cccd[BLE_CCCD_VALUE_LEN];
    uint16_t         cccd_val = notification_enable ? BLE_GATT_HVX_NOTIFICATION : 0;

    memset(&cccd_req, 0, sizeof(nrf_ble_gq_req_t));

    cccd[0] = LSB_16(cccd_val);
    cccd[1] = MSB_16(cccd_val);

    cccd_req.type                        = NRF_BLE_GQ_REQ_GATTC_WRITE;
    cccd_req.error_handler.cb            = gatt_error_handler;
    cccd_req.error_handler.p_ctx         = p_ble_aqrs_c;
    cccd_req.params.gattc_write.handle   = p_ble_aqrs_c->handles.aqrs_tx_cccd_handle;
    cccd_req.params.gattc_write.len      = BLE_CCCD_VALUE_LEN;
    cccd_req.params.gattc_write.offset   = 0;
    cccd_req.params.gattc_write.p_value  = cccd;
    cccd_req.params.gattc_write.write_op = BLE_GATT_OP_WRITE_REQ;
    cccd_req.params.gattc_write.flags    = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE;

    return nrf_ble_gq_item_add(p_ble_aqrs_c->p_gatt_queue, &cccd_req, p_ble_aqrs_c->conn_handle);
}


uint32_t ble_aqrs_c_tx_notif_enable(ble_aqrs_c_t * p_ble_aqrs_c)
{
    VERIFY_PARAM_NOT_NULL(p_ble_aqrs_c);

    if ( (p_ble_aqrs_c->conn_handle == BLE_CONN_HANDLE_INVALID)
       ||(p_ble_aqrs_c->handles.aqrs_tx_cccd_handle == BLE_GATT_HANDLE_INVALID)
       )
    {
        return NRF_ERROR_INVALID_STATE;
    }
    return cccd_configure(p_ble_aqrs_c, true);
}


uint32_t ble_aqrs_c_setting_send(ble_aqrs_c_t * p_ble_aqrs_c, uint8_t * p_string, uint16_t length)
{
    VERIFY_PARAM_NOT_NULL(p_ble_aqrs_c);

    nrf_ble_gq_req_t write_req;

    memset(&write_req, 0, sizeof(nrf_ble_gq_req_t));

    if (length > BLE_AQRS_MAX_DATA_LEN)
    {
        NRF_LOG_WARNING("Content too long.");
        return NRF_ERROR_INVALID_PARAM;
    }
    if (p_ble_aqrs_c->conn_handle == BLE_CONN_HANDLE_INVALID)
    {
        NRF_LOG_WARNING("Connection handle invalid.");
        return NRF_ERROR_INVALID_STATE;
    }

    write_req.type                        = NRF_BLE_GQ_REQ_GATTC_WRITE;
    write_req.error_handler.cb            = gatt_error_handler;
    write_req.error_handler.p_ctx         = p_ble_aqrs_c;
    write_req.params.gattc_write.handle   = p_ble_aqrs_c->handles.aqrs_rx_handle;
    write_req.params.gattc_write.len      = length;
    write_req.params.gattc_write.offset   = 0;
    write_req.params.gattc_write.p_value  = p_string;
    write_req.params.gattc_write.write_op = BLE_GATT_OP_WRITE_CMD;
    write_req.params.gattc_write.flags    = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE;

    return nrf_ble_gq_item_add(p_ble_aqrs_c->p_gatt_queue, &write_req, p_ble_aqrs_c->conn_handle);
}


uint32_t ble_aqrs_c_handles_assign(ble_aqrs_c_t               * p_ble_nus,
                                  uint16_t                    conn_handle,
                                  ble_aqrs_c_handles_t const * p_peer_handles)
{
    VERIFY_PARAM_NOT_NULL(p_ble_nus);

    p_ble_nus->conn_handle = conn_handle;
    if (p_peer_handles != NULL)
    {
        p_ble_nus->handles.aqrs_tx_cccd_handle = p_peer_handles->aqrs_tx_cccd_handle;
        p_ble_nus->handles.aqrs_tx_handle      = p_peer_handles->aqrs_tx_handle;
        p_ble_nus->handles.aqrs_rx_handle      = p_peer_handles->aqrs_rx_handle;
    }
    return nrf_ble_gq_conn_handle_register(p_ble_nus->p_gatt_queue, conn_handle);
}

ble_aqrs.h

/**
* Copyright (c) 2021, Argenox LLC
* Copyright (c) 2012 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
*    list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
*    Semiconductor ASA integrated circuit in a product or a software update for
*    such product, must reproduce the above copyright notice, this list of
*    conditions and the following disclaimer in the documentation and/or other
*    materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
*    contributors may be used to endorse or promote products derived from this
*    software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
*    Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
*    engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**@file
 *
 * @defgroup ble_aqrs Aquai Repeater Service
 * @{
 * @ingroup  ble_sdk_srv
 * @brief    Aquai Repeater Service Service implementation.
 *
 * @details The Aquai Service is a simple GATT-based service with TX and RX characteristics.
 *          Data received from the peer is passed to the application, and the data received
 *          from the application of this service is sent to the peer as Handle Value
 *          Notifications. This module demonstrates how to implement a custom GATT-based
 *          service and characteristics using the SoftDevice. The service
 *          is used by the application to send and receive ASCII text strings to and from the
 *          peer.
 *
 * @note    The application must register this module as BLE event observer using the
 *          NRF_SDH_BLE_OBSERVER macro. Example:
 *          @code
 *              ble_aqrs_t instance;
 *              NRF_SDH_BLE_OBSERVER(anything, BLE_AQRS_BLE_OBSERVER_PRIO,
 *                                   ble_aqrs_on_ble_evt, &instance);
 *          @endcode
 */
#ifndef BLE_AQRS_H__
#define BLE_AQRS_H__

#include <stdint.h>
#include <stdbool.h>
#include "sdk_config.h"
#include "ble.h"
#include "ble_srv_common.h"
#include "nrf_sdh_ble.h"
#include "ble_link_ctx_manager.h"

#ifdef __cplusplus
extern "C" {
#endif


#define BLE_UUID_AQRS_NOTIF_CHARACTERISTIC   0xD7E2               /**< The UUID of the Notification Characteristic. */
#define BLE_UUID_AQRS_SETTING_CHARACTERISTIC 0xD7E4               /**< The UUID of the Setting Characteristic. */

#define BLE_AQRS_MAX_NOTIF_CHAR_LEN        BLE_AQRS_MAX_DATA_LEN /**< Maximum length of the RX Characteristic (in bytes). */
#define BLE_AQRS_MAX_SETTING_CHAR_LEN      BLE_AQRS_MAX_DATA_LEN /**< Maximum length of the TX Characteristic (in bytes). */

#define AQRS_BASE_UUID                  {{0x66, 0x9a, 0x0c, 0x20, 0x00, 0x08, 0x6e, 0xaa, 0xe3, 0x11, 0x76, 0x34, 0xe0, 0xd6, 0x48, 0x75}} /**< Used vendor specific UUID. */



#define BLE_AQRS_BLE_OBSERVER_PRIO 2

/**@brief   Macro for defining a ble_aqrs instance.
 *
 * @param     _name            Name of the instance.
 * @param[in] _aqrs_max_clients Maximum number of AQRS clients connected at a time.
 * @hideinitializer
 */
#define BLE_AQRS_DEF(_name, _aqrs_max_clients)                      \
    BLE_LINK_CTX_MANAGER_DEF(CONCAT_2(_name, _link_ctx_storage),  \
                             (_aqrs_max_clients),                  \
                             sizeof(ble_aqrs_client_context_t));   \
    static ble_aqrs_t _name =                                      \
    {                                                             \
        .p_link_ctx_storage = &CONCAT_2(_name, _link_ctx_storage) \
    };                                                            \
    NRF_SDH_BLE_OBSERVER(_name ## _obs,                           \
                         BLE_AQRS_BLE_OBSERVER_PRIO,               \
                         ble_aqrs_on_ble_evt,                      \
                         &_name)

#define BLE_UUID_AQRS_SERVICE 0xd6e0 /**< The UUID of the Aquai Repeater Service. */

#define OPCODE_LENGTH        1
#define HANDLE_LENGTH        2

/**@brief   Maximum length of data (in bytes) that can be transmitted to the peer by the Aquai Repeater service module. */
#if defined(NRF_SDH_BLE_GATT_MAX_MTU_SIZE) && (NRF_SDH_BLE_GATT_MAX_MTU_SIZE != 0)
#define BLE_AQRS_MAX_DATA_LEN (NRF_SDH_BLE_GATT_MAX_MTU_SIZE - OPCODE_LENGTH - HANDLE_LENGTH)
#else
#define BLE_AQRS_MAX_DATA_LEN (BLE_GATT_MTU_SIZE_DEFAULT - OPCODE_LENGTH - HANDLE_LENGTH)
#warning NRF_SDH_BLE_GATT_MAX_MTU_SIZE is not defined.
#endif


/**@brief   Aquai Repeater Service event types. */
typedef enum {
    BLE_AQRS_EVT_RX_DATA,      /**< Data received. */
    BLE_AQRS_EVT_TX_RDY,       /**< Service is ready to accept new data to be transmitted. */
    BLE_AQRS_EVT_NOTIF_ENABLED, /**< Notification has been enabled. */
    BLE_AQRS_EVT_NOTIF_DISABLED, /**< Notification has been disabled. */
} ble_aqrs_evt_type_t;


/* Forward declaration of the ble_aqrs_t type. */
typedef struct ble_aqrs_s ble_aqrs_t;


/**@brief   Aquai Repeater Service @ref BLE_AQRS_EVT_RX_DATA event data.
 *
 * @details This structure is passed to an event when @ref BLE_AQRS_EVT_RX_DATA occurs.
 */
typedef struct {
    uint8_t const * p_data; /**< A pointer to the buffer with received data. */
    uint16_t        length; /**< Length of received data. */
} ble_aqrs_evt_rx_data_t;


/**@brief Aquai Repeater Service client context structure.
 *
 * @details This structure contains state context related to hosts.
 */
typedef struct {
    bool is_notification_enabled; /**< Variable to indicate if the peer has enabled notification of the RX characteristic.*/
} ble_aqrs_client_context_t;


/**@brief   Aquai Repeater Service event structure.
 *
 * @details This structure is passed to an event coming from service.
 */
typedef struct {
    ble_aqrs_evt_type_t         type;        /**< Event type. */
    ble_aqrs_t                * p_aqrs;       /**< A pointer to the instance. */
    uint16_t                   conn_handle; /**< Connection handle. */
    ble_aqrs_client_context_t * p_link_ctx;  /**< A pointer to the link context. */
    union {
        ble_aqrs_evt_rx_data_t rx_data; /**< @ref BLE_AQRS_EVT_RX_DATA event data. */
    } params;
} ble_aqrs_evt_t;

extern ble_aqrs_t * get_aqrs_service(void);//snehal-new-format1


/**@brief Aquai Repeater Service event handler type. */
typedef void (* ble_aqrs_data_handler_t) (ble_aqrs_evt_t * p_evt);


/**@brief   Aquai Repeater Service initialization structure.
 *
 * @details This structure contains the initialization information for the service. The application
 * must fill this structure and pass it to the service using the @ref ble_aqrs_init
 *          function.
 */
typedef struct {
    ble_aqrs_data_handler_t data_handler; /**< Event handler to be called for handling received data. */
} ble_aqrs_init_t;


/**@brief   Aquai Repeater Service structure.
 *
 * @details This structure contains status information related to the service.
 */
struct ble_aqrs_s {
    uint8_t                         uuid_type;          /**< UUID type for Aquai Repeater Service Base UUID. */
    uint16_t                        service_handle;     /**< Handle of Aquai Repeater Service (as provided by the SoftDevice). */
    ble_gatts_char_handles_t        tx_handles;         /**< Handles related to the TX characteristic (as provided by the SoftDevice). */
    ble_gatts_char_handles_t        rx_handles;         /**< Handles related to the RX characteristic (as provided by the SoftDevice). */
    blcm_link_ctx_storage_t * const p_link_ctx_storage; /**< Pointer to link context storage with handles of all current connections and its context. */
    ble_aqrs_data_handler_t          data_handler;       /**< Event handler to be called for handling received data. */
};


/**@brief   Function for initializing the Aquai Repeater Service.
 *
 * @param[out] p_aqrs      Aquai Repeater Service structure. This structure must be supplied
 *                        by the application. It is initialized by this function and will
 *                        later be used to identify this particular service instance.
 * @param[in] p_aqrs_init  Information needed to initialize the service.
 *
 * @retval NRF_SUCCESS If the service was successfully initialized. Otherwise, an error code is returned.
 * @retval NRF_ERROR_NULL If either of the pointers p_aqrs or p_aqrs_init is NULL.
 */
uint32_t ble_aqrs_init(ble_aqrs_t * p_aqrs, ble_aqrs_init_t const * p_aqrs_init);


/**@brief   Function for handling the Aquai Repeater Service's BLE events.
 *
 * @details The Aquai Repeater Service expects the application to call this function each time an
 * event is received from the SoftDevice. This function processes the event if it
 * is relevant and calls the Aquai Repeater Service event handler of the
 * application if necessary.
 *
 * @param[in] p_ble_evt     Event received from the SoftDevice.
 * @param[in] p_context     Aquai Repeater Service structure.
 */
void ble_aqrs_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context);


/**@brief   Function for sending a data to the peer.
 *
 * @details This function sends the input string as an RX characteristic notification to the
 *          peer.
 *
 * @param[in]     p_aqrs       Pointer to the Aquai Repeater Service structure.
 * @param[in]     p_data      String to be sent.
 * @param[in,out] p_length    Pointer Length of the string. Amount of sent bytes.
 * @param[in]     conn_handle Connection Handle of the destination client.
 *
 * @retval NRF_SUCCESS If the string was sent successfully. Otherwise, an error code is returned.
 */
uint32_t ble_aqrs_data_send(ble_aqrs_t * p_aqrs,
                            uint8_t   * p_data,
                            uint16_t  * p_length,
                            uint16_t    conn_handle);



extern ble_aqrs_t * get_aqrs_service(void);

#ifdef __cplusplus
}
#endif

#endif // BLE_AQRS_H__

/** @} */

ble_aqrs.c

/**
 * Copyright (c) 2021, Argenox LLC
 * Copyright (c) 2012 - 2020, Nordic Semiconductor ASA
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form, except as embedded into a Nordic
 *    Semiconductor ASA integrated circuit in a product or a software update for
 *    such product, must reproduce the above copyright notice, this list of
 *    conditions and the following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *
 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * 4. This software, with or without modification, must only be used with a
 *    Nordic Semiconductor ASA integrated circuit.
 *
 * 5. Any software provided in binary form under this license must not be reverse
 *    engineered, decompiled, modified and/or disassembled.
 *
 * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
#include "sdk_common.h"

#include "ble.h"
#include "ble_aqrs.h"
#include "ble_srv_common.h"
#include "nrf_ble_gq.h"

#define NRF_LOG_MODULE_NAME ble_aqrs
#if BLE_AQRS_CONFIG_LOG_ENABLED
#define NRF_LOG_LEVEL       BLE_AQRS_CONFIG_LOG_LEVEL
#define NRF_LOG_INFO_COLOR  BLE_AQRS_CONFIG_INFO_COLOR
#define NRF_LOG_DEBUG_COLOR BLE_AQRS_CONFIG_DEBUG_COLOR
#else // BLE_AQRS_CONFIG_LOG_ENABLED
#define NRF_LOG_LEVEL       0
#endif // BLE_AQRS_CONFIG_LOG_ENABLED
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER();


//#define BLE_UUID_AQRS_NOTIF_CHARACTERISTIC   0xD7E2               /**< The UUID of the Notification Characteristic. */
//#define BLE_UUID_AQRS_SETTING_CHARACTERISTIC 0xD7E4               /**< The UUID of the Setting Characteristic. */

//#define BLE_AQRS_MAX_NOTIF_CHAR_LEN        BLE_AQRS_MAX_DATA_LEN /**< Maximum length of the RX Characteristic (in bytes). */
//#define BLE_AQRS_MAX_SETTING_CHAR_LEN      BLE_AQRS_MAX_DATA_LEN /**< Maximum length of the TX Characteristic (in bytes). */

//#define AQRS_BASE_UUID                  {{0x66, 0x9a, 0x0c, 0x20, 0x00, 0x08, 0x6e, 0xaa, 0xe3, 0x11, 0x76, 0x34, 0xe0, 0xd6, 0x48, 0x75}} /**< Used vendor specific UUID. */




/**@brief Function for handling the @ref BLE_GAP_EVT_CONNECTED event from the SoftDevice.
 *
 * @param[in] p_aqrs     Aquai Shower Service structure.
 * @param[in] p_ble_evt Pointer to the event received from BLE stack.
 */
static void on_connect(ble_aqrs_t * p_aqrs, ble_evt_t const * p_ble_evt)
{
    ret_code_t                 err_code;
    ble_aqrs_evt_t              evt;
    ble_gatts_value_t          gatts_val;
    uint8_t                    cccd_value[2];
    ble_aqrs_client_context_t * p_client = NULL;

    err_code = blcm_link_ctx_get(p_aqrs->p_link_ctx_storage,
                                 p_ble_evt->evt.gap_evt.conn_handle,
                                 (void *) &p_client);
    if (err_code != NRF_SUCCESS) {
        NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.",
                      p_ble_evt->evt.gap_evt.conn_handle);
    }

    /* Check the hosts CCCD value to inform of readiness to send data using the RX characteristic */
    memset(&gatts_val, 0, sizeof(ble_gatts_value_t));
    gatts_val.p_value = cccd_value;
    gatts_val.len     = sizeof(cccd_value);
    gatts_val.offset  = 0;

    err_code = sd_ble_gatts_value_get(p_ble_evt->evt.gap_evt.conn_handle,
                                      p_aqrs->tx_handles.cccd_handle,
                                      &gatts_val);

    if ((err_code == NRF_SUCCESS)     &&
            (p_aqrs->data_handler != NULL) &&
            ble_srv_is_notification_enabled(gatts_val.p_value)) {
        if (p_client != NULL) {
            p_client->is_notification_enabled = true;
        }

        memset(&evt, 0, sizeof(ble_aqrs_evt_t));
        evt.type        = BLE_AQRS_EVT_NOTIF_ENABLED;
        evt.p_aqrs       = p_aqrs;
        evt.conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
        evt.p_link_ctx  = p_client;

        p_aqrs->data_handler(&evt);
    }
}


/**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the SoftDevice.
 *
 * @param[in] p_aqrs     Aquai Shower Service structure.
 * @param[in] p_ble_evt Pointer to the event received from BLE stack.
 */
static void on_write(ble_aqrs_t * p_aqrs, ble_evt_t const * p_ble_evt)
{
    ret_code_t                    err_code;
    ble_aqrs_evt_t                 evt;
    ble_aqrs_client_context_t    * p_client;
    ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;

    err_code = blcm_link_ctx_get(p_aqrs->p_link_ctx_storage,
                                 p_ble_evt->evt.gatts_evt.conn_handle,
                                 (void *) &p_client);
    if (err_code != NRF_SUCCESS) {
        NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.",
                      p_ble_evt->evt.gatts_evt.conn_handle);
    }

    memset(&evt, 0, sizeof(ble_aqrs_evt_t));
    evt.p_aqrs       = p_aqrs;
    evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
    evt.p_link_ctx  = p_client;

    if ((p_evt_write->handle == p_aqrs->tx_handles.cccd_handle) &&
            (p_evt_write->len == 2)) {
        if (p_client != NULL) {
            if (ble_srv_is_notification_enabled(p_evt_write->data)) {
                p_client->is_notification_enabled = true;
                evt.type                          = BLE_AQRS_EVT_NOTIF_ENABLED;
            } else {
                p_client->is_notification_enabled = false;
                evt.type                          = BLE_AQRS_EVT_NOTIF_DISABLED;
            }

            if (p_aqrs->data_handler != NULL) {
                p_aqrs->data_handler(&evt);
            }

        }
    } else if ((p_evt_write->handle == p_aqrs->rx_handles.value_handle) &&
               (p_aqrs->data_handler != NULL)) {
        evt.type                  = BLE_AQRS_EVT_RX_DATA;
        evt.params.rx_data.p_data = p_evt_write->data;
        evt.params.rx_data.length = p_evt_write->len;

        p_aqrs->data_handler(&evt);
    } else {
        // Do Nothing. This event is not relevant for this service.
    }
}


/**@brief Function for handling the @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event from the SoftDevice.
 *
 * @param[in] p_aqrs     Aquai Shower Service structure.
 * @param[in] p_ble_evt Pointer to the event received from BLE stack.
 */
static void on_hvx_tx_complete(ble_aqrs_t * p_aqrs, ble_evt_t const * p_ble_evt)
{
    ret_code_t                 err_code;
    ble_aqrs_evt_t              evt;
    ble_aqrs_client_context_t * p_client;

    err_code = blcm_link_ctx_get(p_aqrs->p_link_ctx_storage,
                                 p_ble_evt->evt.gatts_evt.conn_handle,
                                 (void *) &p_client);
    if (err_code != NRF_SUCCESS) {
        NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.",
                      p_ble_evt->evt.gatts_evt.conn_handle);
        return;
    }

    if ((p_client->is_notification_enabled) && (p_aqrs->data_handler != NULL)) {
        memset(&evt, 0, sizeof(ble_aqrs_evt_t));
        evt.type        = BLE_AQRS_EVT_TX_RDY;
        evt.p_aqrs       = p_aqrs;
        evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
        evt.p_link_ctx  = p_client;

        p_aqrs->data_handler(&evt);
    }
}


void ble_aqrs_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
{
    if ((p_context == NULL) || (p_ble_evt == NULL)) {
        return;
    }

    ble_aqrs_t * p_aqrs = (ble_aqrs_t *)p_context;

    switch (p_ble_evt->header.evt_id) {
    case BLE_GAP_EVT_CONNECTED:
        on_connect(p_aqrs, p_ble_evt);
        break;

    case BLE_GATTS_EVT_WRITE:
        on_write(p_aqrs, p_ble_evt);
        break;

    case BLE_GATTS_EVT_HVN_TX_COMPLETE:
        on_hvx_tx_complete(p_aqrs, p_ble_evt);
        break;

    default:
        // No implementation needed.
        break;
    }
}


uint32_t ble_aqrs_init(ble_aqrs_t * p_aqrs, ble_aqrs_init_t const * p_aqrs_init)
{
    ret_code_t            err_code;
    ble_uuid_t            ble_uuid;
    ble_uuid128_t         aqrs_base_uuid = AQRS_BASE_UUID;
    ble_add_char_params_t add_char_params;

    VERIFY_PARAM_NOT_NULL(p_aqrs);
    VERIFY_PARAM_NOT_NULL(p_aqrs_init);

    // Initialize the service structure.
    p_aqrs->data_handler = p_aqrs_init->data_handler;

    /**@snippet [Adding proprietary Service to the SoftDevice] */
    // Add a custom base UUID.
    err_code = sd_ble_uuid_vs_add(&aqrs_base_uuid, &p_aqrs->uuid_type);
    VERIFY_SUCCESS(err_code);

    ble_uuid.type = p_aqrs->uuid_type;
    ble_uuid.uuid = BLE_UUID_AQRS_SERVICE;

    // Add the service.
    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
                                        &ble_uuid,
                                        &p_aqrs->service_handle);
    /**@snippet [Adding proprietary Service to the SoftDevice] */
    VERIFY_SUCCESS(err_code);

    // Add the RX Characteristic.
    memset(&add_char_params, 0, sizeof(add_char_params));
    add_char_params.uuid                     = BLE_UUID_AQRS_SETTING_CHARACTERISTIC;
    add_char_params.uuid_type                = p_aqrs->uuid_type;
    add_char_params.max_len                  = BLE_AQRS_MAX_NOTIF_CHAR_LEN;
    add_char_params.init_len                 = sizeof(uint8_t);
    add_char_params.is_var_len               = true;
    add_char_params.char_props.write         = 1;
    add_char_params.char_props.write_wo_resp = 1;

    add_char_params.read_access  = SEC_OPEN;
    add_char_params.write_access = SEC_OPEN;

    err_code = characteristic_add(p_aqrs->service_handle, &add_char_params, &p_aqrs->rx_handles);
    if (err_code != NRF_SUCCESS) {
        return err_code;
    }

    // Add the TX Characteristic.
    /**@snippet [Adding proprietary characteristic to the SoftDevice] */
    memset(&add_char_params, 0, sizeof(add_char_params));
    add_char_params.uuid              = BLE_UUID_AQRS_NOTIF_CHARACTERISTIC;
    add_char_params.uuid_type         = p_aqrs->uuid_type;
    add_char_params.max_len           = BLE_AQRS_MAX_SETTING_CHAR_LEN;
    add_char_params.init_len          = sizeof(uint8_t);
    add_char_params.is_var_len        = true;
    add_char_params.char_props.notify = 1;

    add_char_params.read_access       = SEC_OPEN;
    add_char_params.write_access      = SEC_OPEN;
    add_char_params.cccd_write_access = SEC_OPEN;

    return characteristic_add(p_aqrs->service_handle, &add_char_params, &p_aqrs->tx_handles);
    /**@snippet [Adding proprietary characteristic to the SoftDevice] */
}


ble_aqrs_c.h

/**
 * Copyright (c) 2012 - 2020, Nordic Semiconductor ASA
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form, except as embedded into a Nordic
 *    Semiconductor ASA integrated circuit in a product or a software update for
 *    such product, must reproduce the above copyright notice, this list of
 *    conditions and the following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *
 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * 4. This software, with or without modification, must only be used with a
 *    Nordic Semiconductor ASA integrated circuit.
 *
 * 5. Any software provided in binary form under this license must not be reverse
 *    engineered, decompiled, modified and/or disassembled.
 *
 * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
/**@file
 *
 * @defgroup ble_aqrs_c Aquai Toilet Service Client
 * @{
 * @ingroup  ble_sdk_srv
 * @brief    Aquai Toilet Service Client module.
 *
 * @details  This module contains the APIs and types exposed by the Aquai Toilet Service Client
 *           module. The application can use these APIs and types to perform the discovery of
 *           the Aquai Toilet Service at the peer and to interact with it.
 *
 * @note    The application must register this module as the BLE event observer by using the
 *          NRF_SDH_BLE_OBSERVER macro. Example:
 *          @code
 *              ble_aqrs_c_t instance;
 *              NRF_SDH_BLE_OBSERVER(anything, BLE_AQRS_C_BLE_OBSERVER_PRIO,
 *                                   ble_aqrs_c_on_ble_evt, &instance);
 *          @endcode
 *
 */


#ifndef BLE_AQRS_C_H__
#define BLE_AQRS_C_H__

#include <stdint.h>
#include <stdbool.h>
#include "ble.h"
#include "ble_gatt.h"
#include "ble_db_discovery.h"
#include "ble_srv_common.h"
#include "nrf_ble_gq.h"
#include "nrf_sdh_ble.h"

#include "sdk_config.h"

#ifdef __cplusplus
extern "C" {
#endif

// <o> BLE_AQRS_C_BLE_OBSERVER_PRIO  
// <i> Priority with which BLE events are dispatched to the AQRS Client

#ifndef BLE_AQRS_C_BLE_OBSERVER_PRIO
#define BLE_AQRS_C_BLE_OBSERVER_PRIO 2
#endif

/**@brief   Macro for defining a ble_aqrs_c instance.
 *
 * @param   _name   Name of the instance.
 * @hideinitializer
 */
#define BLE_AQRS_C_DEF(_name)                                                                        \
static ble_aqrs_c_t _name;                                                                           \
NRF_SDH_BLE_OBSERVER(_name ## _obs,                                                                 \
                     BLE_AQRS_C_BLE_OBSERVER_PRIO,                                                   \
                     ble_aqrs_c_on_ble_evt, &_name)

/** @brief Macro for defining multiple ble_aqrs_c instances.
 *
 * @param   _name   Name of the array of instances.
 * @param   _cnt    Number of instances to define.
 * @hideinitializer
 */
#define BLE_AQRS_C_ARRAY_DEF(_name, _cnt)                 \
static ble_aqrs_c_t _name[_cnt];                          \
NRF_SDH_BLE_OBSERVERS(_name ## _obs,                     \
                      BLE_AQRS_C_BLE_OBSERVER_PRIO,       \
                      ble_aqrs_c_on_ble_evt, &_name, _cnt)


#define OPCODE_LENGTH 1
#define HANDLE_LENGTH 2

/**@brief   Maximum length of data (in bytes) that can be transmitted to the peer by the Aquai Toilet service module. */
#if defined(NRF_SDH_BLE_GATT_MAX_MTU_SIZE) && (NRF_SDH_BLE_GATT_MAX_MTU_SIZE != 0)
    #define BLE_AQRS_MAX_DATA_LEN (NRF_SDH_BLE_GATT_MAX_MTU_SIZE - OPCODE_LENGTH - HANDLE_LENGTH)
#else
    #define BLE_AQRS_MAX_DATA_LEN (BLE_GATT_MTU_SIZE_DEFAULT - OPCODE_LENGTH - HANDLE_LENGTH)
    #warning NRF_SDH_BLE_GATT_MAX_MTU_SIZE is not defined.
#endif


/**@brief AQRS Client event type. */
typedef enum
{
    BLE_AQRS_C_EVT_DISCOVERY_COMPLETE,   /**< Event indicating that the AQRS service and its characteristics were found. */
    BLE_AQRS_C_EVT_AQRS_TX_EVT,           /**< Event indicating that the central received something from a peer. */
    BLE_AQRS_C_EVT_DISCONNECTED          /**< Event indicating that the AQRS server disconnected. */
} ble_aqrs_c_evt_type_t;

/**@brief Handles on the connected peer device needed to interact with it. */
typedef struct
{
    uint16_t aqrs_tx_handle;      /**< Handle of the AQRS TX characteristic, as provided by a discovery. */
    uint16_t aqrs_tx_cccd_handle; /**< Handle of the CCCD of the AQRS TX characteristic, as provided by a discovery. */
    uint16_t aqrs_rx_handle;      /**< Handle of the AQRS RX characteristic, as provided by a discovery. */
} ble_aqrs_c_handles_t;

/**@brief Structure containing the AQRS event data received from the peer. */
typedef struct
{
    ble_aqrs_c_evt_type_t evt_type;
    uint16_t             conn_handle;
    uint16_t             max_data_len;
    uint8_t            * p_data;
    uint16_t             data_len;
    ble_aqrs_c_handles_t  handles;     /**< Handles on which the Aquai Toilet service characteristics were discovered on the peer device. This is filled if the evt_type is @ref BLE_AQRS_C_EVT_DISCOVERY_COMPLETE.*/
} ble_aqrs_c_evt_t;

// Forward declaration of the ble_aqrs_t type.
typedef struct ble_aqrs_c_s ble_aqrs_c_t;

/**@brief   Event handler type.
 *
 * @details This is the type of the event handler that is to be provided by the application
 *          of this module to receive events.
 */
typedef void (* ble_aqrs_c_evt_handler_t)(ble_aqrs_c_t * p_ble_aqrs_c, ble_aqrs_c_evt_t const * p_evt);

/**@brief AQRS Client structure. */
struct ble_aqrs_c_s
{
    uint8_t                   uuid_type;      /**< UUID type. */
    uint16_t                  conn_handle;    /**< Handle of the current connection. Set with @ref ble_aqrs_c_handles_assign when connected. */
    ble_aqrs_c_handles_t       handles;        /**< Handles on the connected peer device needed to interact with it. */
    ble_aqrs_c_evt_handler_t   evt_handler;    /**< Application event handler to be called when there is an event related to the AQRS. */
    ble_srv_error_handler_t   error_handler;  /**< Function to be called in case of an error. */
    nrf_ble_gq_t            * p_gatt_queue;   /**< Pointer to BLE GATT Queue instance. */
};

/**@brief AQRS Client initialization structure. */
typedef struct
{
    ble_aqrs_c_evt_handler_t   evt_handler;    /**< Application event handler to be called when there is an event related to the AQRS. */
    ble_srv_error_handler_t   error_handler;  /**< Function to be called in case of an error. */
    nrf_ble_gq_t            * p_gatt_queue;   /**< Pointer to BLE GATT Queue instance. */
} ble_aqrs_c_init_t;


/**@brief     Function for initializing the Aquai Toilet client module.
 *
 * @details   This function registers with the Database Discovery module
 *            for the AQRS. The Database Discovery module looks for the presence
 *            of a AQRS instance at the peer when a discovery is started.
 *            
 * @param[in] p_ble_aqrs_c      Pointer to the AQRS client structure.
 * @param[in] p_ble_aqrs_c_init Pointer to the AQRS initialization structure that contains the
 *                             initialization information.
 *
 * @retval    NRF_SUCCESS If the module was initialized successfully.
 * @retval    err_code    Otherwise, this function propagates the error code
 *                        returned by the Database Discovery module API
 *                        @ref ble_db_discovery_evt_register.
 */
uint32_t ble_aqrs_c_init(ble_aqrs_c_t * p_ble_aqrs_c, ble_aqrs_c_init_t * p_ble_aqrs_c_init);


/**@brief Function for handling events from the Database Discovery module.
 *
 * @details This function handles an event from the Database Discovery module, and determines
 *          whether it relates to the discovery of AQRS at the peer. If it does, the function
 *          calls the application's event handler to indicate that AQRS was
 *          discovered at the peer. The function also populates the event with service-related
 *          information before providing it to the application.
 *
 * @param[in] p_ble_aqrs_c Pointer to the AQRS client structure.
 * @param[in] p_evt       Pointer to the event received from the Database Discovery module.
 */
 void ble_aqrs_c_on_db_disc_evt(ble_aqrs_c_t * p_ble_aqrs_c, ble_db_discovery_evt_t * p_evt);


/**@brief     Function for handling BLE events from the SoftDevice.
 *
 * @details   This function handles the BLE events received from the SoftDevice. If a BLE
 *            event is relevant to the AQRS module, the function uses the event's data to update
 *            internal variables and, if necessary, send events to the application.
 *
 * @param[in] p_ble_evt     Pointer to the BLE event.
 * @param[in] p_context     Pointer to the AQRS client structure.
 */
void ble_aqrs_c_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context);


/**@brief   Function for requesting the peer to start sending notification of TX characteristic.
 *
 * @details This function enables notifications of the AQRS TX characteristic at the peer
 *          by writing to the CCCD of the AQRS TX characteristic.
 *
 * @param   p_ble_aqrs_c Pointer to the AQRS client structure.
 *
 * @retval  NRF_SUCCESS If the operation was successful. 
 * @retval  err_code 	Otherwise, this API propagates the error code returned by function @ref nrf_ble_gq_item_add.
 */
uint32_t ble_aqrs_c_tx_notif_enable(ble_aqrs_c_t * p_ble_aqrs_c);


/**@brief Function for sending a string to the server.
 *
 * @details This function writes the RX characteristic of the server.
 *
 * @param[in] p_ble_aqrs_c Pointer to the AQRS client structure.
 * @param[in] p_string    String to be sent.
 * @param[in] length      Length of the string.
 *
 * @retval NRF_SUCCESS If the string was sent successfully. 
 * @retval err_code    Otherwise, this API propagates the error code returned by function @ref nrf_ble_gq_item_add.
 */
uint32_t ble_aqrs_c_setting_send(ble_aqrs_c_t * p_ble_aqrs_c, uint8_t * p_string, uint16_t length);


/**@brief Function for assigning handles to this instance of aqrs_c.
 *
 * @details Call this function when a link has been established with a peer to
 *          associate the link to this instance of the module. This makes it
 *          possible to handle several links and associate each link to a particular
 *          instance of this module. The connection handle and attribute handles are
 *          provided from the discovery event @ref BLE_AQRS_C_EVT_DISCOVERY_COMPLETE.
 *
 * @param[in] p_ble_aqrs_c    Pointer to the AQRS client structure instance to associate with these
 *                           handles.
 * @param[in] conn_handle    Connection handle to associated with the given AQRS Instance.
 * @param[in] p_peer_handles Attribute handles on the AQRS server that you want this AQRS client to
 *                           interact with.
 *
 * @retval    NRF_SUCCESS    If the operation was successful.
 * @retval    NRF_ERROR_NULL If a p_aqrs was a NULL pointer.
 * @retval    err_code       Otherwise, this API propagates the error code returned 
 *                           by function @ref nrf_ble_gq_item_add.
 */
uint32_t ble_aqrs_c_handles_assign(ble_aqrs_c_t *               p_ble_aqrs_c,
                                  uint16_t                    conn_handle,
                                  ble_aqrs_c_handles_t const * p_peer_handles);


#ifdef __cplusplus
}
#endif

#endif // BLE_AQRS_C_H__

/** @} */

I am not understanding why it is giving hard fault handler. I am using "ble_aqrs_c_setting_send()" this function to send data from central device to mobile app.


err_code = ble_aqrs_c_setting_send(get_aqrs_service(), payload, len);
APP_ERROR_CHECK(err_code);

BLE_AQRS_DEF(m_aqrs, NRF_SDH_BLE_TOTAL_LINK_COUNT); /**< BLE Aquai Repeater service instance. */
NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */
BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */
NRF_BLE_QWRS_DEF(m_qwr, NRF_SDH_BLE_TOTAL_LINK_COUNT); /**< Context for the Queued Write module.*/

static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifiers. */
{
{BLE_UUID_AQRS_SERVICE, BLE_UUID_TYPE_VENDOR_BEGIN}
};

ble_aqrs_t * get_aqrs_service(void)
{
return &m_aqrs;
}

The error which i am getting is as follows:-

<error> hardfault: HARD FAULT at 0x0002AB38
<error> hardfault: R0: 0x000007D0 R1: 0xFFFFFFFF R2: 0x00000000 R3: 0x20704708
<error> hardfault: Bus Fault Address: 0x20704708

Please help me.

  • Hi

    Are you sure that it is the ble_aqrs_c_setting_send() function is what is trigging this hardfault specifically? I am assuming there is something with your custom service on the central side that is not set up correctly, but it's hard to tell by looking at your code what exactly it is. Are you certain the device is able to connect to and discover the correct service from the peripheral side? Do you see the data sent from the peripheral received correctly to the central application?

    Please check out this reply by my colleague Susheel here where he explains how to modify I.E. the ble_nus_c.c file to implement a custom central service to recognize a custom UUID and do discovery correctly, etc.

    Best regards,

    Simon

Related