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.