初始版本

This commit is contained in:
xiaozhengsheng
2025-08-19 09:49:41 +08:00
parent 10f1ddf1c1
commit 6df0f7d96e
2974 changed files with 1712873 additions and 54 deletions

View File

@@ -0,0 +1,390 @@
/**
* Copyright (c) 2016 - 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.
*
*/
/* Disclaimer: This client implementation of the Apple Notification Center Service can and will be changed at any time by Nordic Semiconductor ASA.
* Server implementations such as the ones found in iOS can be changed at any time by Apple and may cause this client implementation to stop working.
*/
#include "ancs_app_attr_get.h"
#include "nrf_ble_ancs_c.h"
#include "sdk_macros.h"
#include "nrf_log.h"
#include "string.h"
#define GATTC_OPCODE_SIZE 1 /**< Size of the GATTC OPCODE. */
#define GATTC_ATTR_HANDLE_SIZE 4 /**< Size of the attribute handle. */
#define ANCS_GATTC_WRITE_PAYLOAD_LEN_MAX (BLE_GATT_ATT_MTU_DEFAULT - GATTC_OPCODE_SIZE - GATTC_ATTR_HANDLE_SIZE) /**< Maximum length of the data that can be sent in one write. */
/**@brief Enumeration for keeping track of the state-based encoding while requesting app attributes. */
typedef enum
{
APP_ATTR_COMMAND_ID, /**< Currently encoding the command ID. */
APP_ATTR_APP_ID, /**< Currently encoding the app ID. */
APP_ATTR_ATTR_ID, /**< Currently encoding the attribute ID. */
APP_ATTR_DONE /**< Encoding done. */
}encode_app_attr_t;
/**@brief Function for determining whether an attribute is requested.
*
* @param[in] p_ancs iOS notification structure. This structure must be supplied by
* the application. It identifies the particular client instance to use.
*
* @return True If it is requested
* @return False If it is not requested.
*/
static bool app_attr_is_requested(ble_ancs_c_t * p_ancs, uint32_t attr_id)
{
if (p_ancs->ancs_app_attr_list[attr_id].get == true)
{
return true;
}
return false;
}
/**@brief Function for counting the number of attributes that will be requested upon a "get app attributes" command.
*
* @param[in] p_ancs iOS notification structure. This structure must be supplied by
* the application. It identifies the particular client instance to use.
*
* @return Number of attributes that will be requested upon a "get app attributes" command.
*/
static uint32_t app_attr_nb_to_get(ble_ancs_c_t * p_ancs)
{
uint32_t attr_nb_to_get = 0;
for (uint32_t i = 0; i < (sizeof(p_ancs->ancs_app_attr_list)/sizeof(ble_ancs_c_attr_list_t)); i++)
{
if (app_attr_is_requested(p_ancs,i))
{
attr_nb_to_get++;
}
}
return attr_nb_to_get;
}
/**@brief Function for encoding the command ID as part of assembling a "get app attributes" command.
*
* @param[in] p_ancs iOS notification structure. This structure must be supplied by
* the application. It identifies the particular client instance to use.
* @param[in] handle_value The handle that receives the execute command.
* @param[in] p_offset Pointer to the offset for the write.
* @param[in] p_index Pointer to the length encoded so far for the current write.
* @param[in,out] p_gq_req Pointer to the BLE GATT request structure.
*/
static ret_code_t queued_write_tx_message(ble_ancs_c_t * p_ancs,
uint16_t handle_value,
uint16_t * p_offset,
uint32_t * p_index,
nrf_ble_gq_req_t * p_gq_req)
{
NRF_LOG_DEBUG("Starting new tx message.");
p_gq_req->type = NRF_BLE_GQ_REQ_GATTC_WRITE;
p_gq_req->error_handler.cb = p_ancs->gatt_err_handler;
p_gq_req->error_handler.p_ctx = p_ancs;
p_gq_req->params.gattc_write.len = *p_index;
p_gq_req->params.gattc_write.offset = *p_offset;
p_gq_req->params.gattc_write.write_op = BLE_GATT_OP_PREP_WRITE_REQ;
p_gq_req->params.gattc_write.handle = handle_value;
return nrf_ble_gq_item_add(p_ancs->p_gatt_queue, p_gq_req, p_ancs->conn_handle);
}
/**@brief Function for encoding the command ID as part of assembling a "get app attributes" command.
*
* @param[in] p_index Pointer to the length encoded so far for the current write.
* @param[in,out] p_gq_req Pointer to the BLE GATT request structure.
*/
static encode_app_attr_t app_attr_encode_cmd_id(uint32_t * index,
nrf_ble_gq_req_t * p_gq_req)
{
uint8_t * p_value = (uint8_t *)p_gq_req->params.gattc_write.p_value;
NRF_LOG_DEBUG("Encoding command ID.");
// Encode Command ID.
p_value[(*index)++] = BLE_ANCS_COMMAND_ID_GET_APP_ATTRIBUTES;
return APP_ATTR_APP_ID;
}
/**@brief Function for encoding the app ID as part of assembling a "get app attributes" command.
*
* @param[in] p_ancs iOS notification structure. This structure must be supplied by
* the application. It identifies the particular client instance to use.
* @param[in] p_app_id The app ID of the app for which to request app attributes.
* @param[in] app_id_len Length of the app ID.
* @param[in] p_index Pointer to the length encoded so far for the current write.
* @param[in] p_offset Pointer to the accumulated offset for the next write.
* @param[in] p_gq_req Pointer to the BLE GATT request structure.
* @param[in] p_app_id_bytes_encoded_count Variable to keep count of the encoded app ID bytes.
* As long as it is lower than the length of the app ID,
* parsing continues.
*/
static encode_app_attr_t app_attr_encode_app_id(ble_ancs_c_t * p_ancs,
uint32_t * p_index,
uint16_t * p_offset,
nrf_ble_gq_req_t * p_gq_req,
const uint8_t * p_app_id,
const uint32_t app_id_len,
uint32_t * p_app_id_bytes_encoded_count)
{
ret_code_t err_code;
uint8_t * p_value = (uint8_t *)p_gq_req->params.gattc_write.p_value;
NRF_LOG_DEBUG("Encoding app ID.");
if (*p_index >= ANCS_GATTC_WRITE_PAYLOAD_LEN_MAX)
{
err_code = queued_write_tx_message(p_ancs,
p_ancs->service.control_point_char.handle_value,
p_offset,
p_index,
p_gq_req);
if ((err_code != NRF_SUCCESS) && (p_ancs->error_handler != NULL))
{
p_ancs->error_handler(err_code);
}
*(p_offset) += *p_index;
*p_index = 0;
}
//Encode app identifier.
if (*p_app_id_bytes_encoded_count == app_id_len)
{
p_value[(*p_index)++] = '\0';
(*p_app_id_bytes_encoded_count)++;
}
NRF_LOG_DEBUG("%c", p_app_id[(*p_app_id_bytes_encoded_count)]);
if (*p_app_id_bytes_encoded_count < app_id_len)
{
p_value[(*p_index)++] = p_app_id[(*p_app_id_bytes_encoded_count)++];
}
if (*p_app_id_bytes_encoded_count > app_id_len)
{
return APP_ATTR_ATTR_ID;
}
return APP_ATTR_APP_ID;
}
/**@brief Function for encoding the attribute ID as part of assembling a "get app attributes" command.
*
* @param[in] p_ancs iOS notification structure. This structure must be supplied by
* the application. It identifies the particular client instance to use.
* @param[in] p_index Pointer to the length encoded so far for the current write.
* @param[in] p_offset Pointer to the accumulated offset for the next write.
* @param[in,out] p_gq_req Pointer to the BLE GATT request structure.
* @param[in] p_attr_count Pointer to a variable that iterates the possible app attributes.
*/
static encode_app_attr_t app_attr_encode_attr_id(ble_ancs_c_t * p_ancs,
uint32_t * p_index,
uint16_t * p_offset,
nrf_ble_gq_req_t * p_gq_req,
uint32_t * p_attr_count,
uint32_t * attr_get_total_nb)
{
ret_code_t err_code;
uint8_t * p_value = (uint8_t *)p_gq_req->params.gattc_write.p_value;
NRF_LOG_DEBUG("Encoding attribute ID.");
if ((*p_index) >= ANCS_GATTC_WRITE_PAYLOAD_LEN_MAX)
{
err_code = queued_write_tx_message(p_ancs,
p_ancs->service.control_point_char.handle_value,
p_offset,
p_index,
p_gq_req);
if ((err_code != NRF_SUCCESS) && (p_ancs->error_handler != NULL))
{
p_ancs->error_handler(err_code);
}
*(p_offset) += *p_index;
*p_index = 0;
}
//Encode Attribute ID.
if (*p_attr_count < BLE_ANCS_NB_OF_APP_ATTR)
{
if (app_attr_is_requested(p_ancs, *p_attr_count))
{
p_value[(*p_index)] = *p_attr_count;
p_ancs->number_of_requested_attr++;
(*p_index)++;
NRF_LOG_DEBUG("offset %i", *p_offset);
}
(*p_attr_count)++;
}
if (*p_attr_count == BLE_ANCS_NB_OF_APP_ATTR)
{
return APP_ATTR_DONE;
}
return APP_ATTR_APP_ID;
}
/**@brief Function for writing the "execute write" command to a handle for a given connection.
*
* @param[in] p_ancs iOS notification structure. This structure must be supplied by
* the application. It identifies the particular client instance to use.
* @param[in] handle_value Handle that receives the "execute write" command.
* @param[in] p_gq_req Pointer to the BLE GATT request structure.
*/
static ret_code_t app_attr_execute_write(ble_ancs_c_t * p_ancs,
uint16_t handle_value,
nrf_ble_gq_req_t * p_gq_req)
{
NRF_LOG_DEBUG("Sending Execute Write command.");
memset(p_gq_req, 0, sizeof(nrf_ble_gq_req_t));
p_gq_req->type = NRF_BLE_GQ_REQ_GATTC_WRITE;
p_gq_req->error_handler.cb = p_ancs->gatt_err_handler;
p_gq_req->error_handler.p_ctx = p_ancs;
p_gq_req->params.gattc_write.handle = handle_value;
p_gq_req->params.gattc_write.offset = 0;
p_gq_req->params.gattc_write.write_op = BLE_GATT_OP_EXEC_WRITE_REQ;
p_gq_req->params.gattc_write.flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE;
p_gq_req->params.gattc_write.len = 0;
return nrf_ble_gq_item_add(p_ancs->p_gatt_queue, p_gq_req, p_ancs->conn_handle);
}
/**@brief Function for sending a "get app attributes" request.
*
* @details Since the app ID may not fit in a single write, long write
* with a state machine is used to encode the "get app attributes" request.
*
* @param[in] p_ancs iOS notification structure. This structure must be supplied by
* the application. It identifies the particular client instance to use.
* @param[in] p_app_id The app ID of the app for which to request app attributes.
* @param[in] app_id_len Length of the app ID.
*
*/
static uint32_t app_attr_get(ble_ancs_c_t * p_ancs,
const uint8_t * p_app_id,
uint32_t app_id_len)
{
uint32_t index = 0;
uint32_t attr_bytes_encoded_count = 0;
uint16_t offset = 0;
uint32_t app_id_bytes_encoded_count = 0;
encode_app_attr_t state = APP_ATTR_COMMAND_ID;
ret_code_t err_code;
p_ancs->number_of_requested_attr = 0;
uint32_t attr_get_total_nb = app_attr_nb_to_get(p_ancs);
nrf_ble_gq_req_t ancs_req;
uint8_t gatt_value[BLE_ANCS_WRITE_MAX_MSG_LENGTH];
memset(&ancs_req, 0, sizeof(nrf_ble_gq_req_t));
ancs_req.params.gattc_write.p_value = gatt_value;
while (state != APP_ATTR_DONE)
{
switch (state)
{
case APP_ATTR_COMMAND_ID:
state = app_attr_encode_cmd_id(&index,
&ancs_req);
break;
case APP_ATTR_APP_ID:
state = app_attr_encode_app_id(p_ancs,
&index,
&offset,
&ancs_req,
p_app_id,
app_id_len,
&app_id_bytes_encoded_count);
break;
case APP_ATTR_ATTR_ID:
state = app_attr_encode_attr_id(p_ancs,
&index,
&offset,
&ancs_req,
&attr_bytes_encoded_count,
&attr_get_total_nb);
break;
case APP_ATTR_DONE:
break;
default:
break;
}
}
err_code = queued_write_tx_message(p_ancs,
p_ancs->service.control_point_char.handle_value,
&offset,
&index,
&ancs_req);
VERIFY_SUCCESS(err_code);
err_code = app_attr_execute_write(p_ancs,
p_ancs->service.control_point_char.handle_value,
&ancs_req);
p_ancs->parse_info.expected_number_of_attrs = p_ancs->number_of_requested_attr;
return err_code;
}
uint32_t ancs_c_app_attr_request(ble_ancs_c_t * p_ancs,
const uint8_t * p_app_id,
uint32_t len)
{
uint32_t err_code;
if (len == 0)
{
return NRF_ERROR_DATA_SIZE;
}
if (p_app_id[len] != '\0') // App ID to be requested must be null-terminated.
{
return NRF_ERROR_INVALID_PARAM;
}
p_ancs->parse_info.parse_state = COMMAND_ID;
err_code = app_attr_get(p_ancs, p_app_id, len);
VERIFY_SUCCESS(err_code);
return NRF_SUCCESS;
}

View File

@@ -0,0 +1,68 @@
/**
* 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.
*
*/
#ifndef ANCS_APP_ATTR_GET_H__
#define ANCS_APP_ATTR_GET_H__
#include "nrf_ble_ancs_c.h"
/** @file
*
* @addtogroup ble_ancs_c
* @{
*/
#define BLE_ANCS_WRITE_MAX_MSG_LENGTH 20 /**< Maximum GATTC write length. */
/**@brief Function for requesting attributes for an app.
*
* @param[in] p_ancs iOS notification structure. This structure must be supplied by
* the application. It identifies the particular client instance to use.
* @param[in] app_id App identifier of the app for which to request app attributes.
* @param[in] len Length of the app identifier.
*
* @retval NRF_SUCCESS If all operations were successful. Otherwise, an error code is returned.
*/
uint32_t ancs_c_app_attr_request(ble_ancs_c_t * p_ancs,
const uint8_t * app_id,
uint32_t len);
/** @} */
#endif // ANCS_APP_ATTR_GET_H__

View File

@@ -0,0 +1,392 @@
/**
* Copyright (c) 2016 - 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.
*
*/
/* Disclaimer: This client implementation of the Apple Notification Center Service can and will be changed at any time by Nordic Semiconductor ASA.
* Server implementations such as the ones found in iOS can be changed at any time by Apple and may cause this client implementation to stop working.
*/
#include "nrf_ble_ancs_c.h"
#include "ancs_attr_parser.h"
#include "nrf_log.h"
static bool all_req_attrs_parsed(ble_ancs_c_t * p_ancs)
{
if (p_ancs->parse_info.expected_number_of_attrs == 0)
{
return true;
}
return false;
}
static bool attr_is_requested(ble_ancs_c_t * p_ancs, ble_ancs_c_attr_t attr)
{
if (p_ancs->parse_info.p_attr_list[attr.attr_id].get == true)
{
return true;
}
return false;
}
/**@brief Function for parsing command id and notification id.
* Used in the @ref parse_get_notif_attrs_response state machine.
*
* @details UID and command ID will be received only once at the beginning of the first
* GATTC notification of a new attribute request for a given iOS notification.
*
* @param[in] p_ancs Pointer to an ANCS instance to which the event belongs.
* @param[in] p_data_src Pointer to data that was received from the Notification Provider.
* @param[in] index Pointer to an index that helps us keep track of the current data to be parsed.
*
* @return The next parse state.
*/
static ble_ancs_c_parse_state_t command_id_parse(ble_ancs_c_t * p_ancs,
const uint8_t * p_data_src,
uint32_t * index)
{
ble_ancs_c_parse_state_t parse_state;
p_ancs->parse_info.command_id = (ble_ancs_c_cmd_id_val_t) p_data_src[(*index)++];
switch (p_ancs->parse_info.command_id)
{
case BLE_ANCS_COMMAND_ID_GET_NOTIF_ATTRIBUTES:
p_ancs->evt.evt_type = BLE_ANCS_C_EVT_NOTIF_ATTRIBUTE;
p_ancs->parse_info.p_attr_list = p_ancs->ancs_notif_attr_list;
p_ancs->parse_info.nb_of_attr = BLE_ANCS_NB_OF_NOTIF_ATTR;
parse_state = NOTIF_UID;
break;
case BLE_ANCS_COMMAND_ID_GET_APP_ATTRIBUTES:
p_ancs->evt.evt_type = BLE_ANCS_C_EVT_APP_ATTRIBUTE;
p_ancs->parse_info.p_attr_list = p_ancs->ancs_app_attr_list;
p_ancs->parse_info.nb_of_attr = BLE_ANCS_NB_OF_APP_ATTR;
parse_state = APP_ID;
break;
default:
//no valid command_id, abort the rest of the parsing procedure.
NRF_LOG_DEBUG("Invalid Command ID");
parse_state = DONE;
break;
}
return parse_state;
}
static ble_ancs_c_parse_state_t notif_uid_parse(ble_ancs_c_t * p_ancs,
const uint8_t * p_data_src,
uint32_t * index)
{
p_ancs->evt.notif_uid = uint32_decode(&p_data_src[*index]);
*index += sizeof(uint32_t);
return ATTR_ID;
}
static ble_ancs_c_parse_state_t app_id_parse(ble_ancs_c_t * p_ancs,
const uint8_t * p_data_src,
uint32_t * index)
{
p_ancs->evt.app_id[p_ancs->parse_info.current_app_id_index] = p_data_src[(*index)++];
if (p_ancs->evt.app_id[p_ancs->parse_info.current_app_id_index] != '\0')
{
p_ancs->parse_info.current_app_id_index++;
return APP_ID;
}
else
{
return ATTR_ID;
}
}
/**@brief Function for parsing the id of an iOS attribute.
* Used in the @ref parse_get_notif_attrs_response state machine.
*
* @details We only request attributes that are registered with @ref ble_ancs_c_attr_add
* once they have been reveiced we stop parsing.
*
* @param[in] p_ancs Pointer to an ANCS instance to which the event belongs.
* @param[in] p_data_src Pointer to data that was received from the Notification Provider.
* @param[in] index Pointer to an index that helps us keep track of the current data to be parsed.
*
* @return The next parse state.
*/
static ble_ancs_c_parse_state_t attr_id_parse(ble_ancs_c_t * p_ancs,
const uint8_t * p_data_src,
uint32_t * index)
{
p_ancs->evt.attr.attr_id = p_data_src[(*index)++];
if (p_ancs->evt.attr.attr_id >= p_ancs->parse_info.nb_of_attr)
{
NRF_LOG_DEBUG("Attribute ID Invalid.");
return DONE;
}
p_ancs->evt.attr.p_attr_data = p_ancs->parse_info.p_attr_list[p_ancs->evt.attr.attr_id].p_attr_data;
if (all_req_attrs_parsed(p_ancs))
{
NRF_LOG_DEBUG("All requested attributes received. ");
return DONE;
}
else
{
if (attr_is_requested(p_ancs, p_ancs->evt.attr))
{
p_ancs->parse_info.expected_number_of_attrs--;
}
NRF_LOG_DEBUG("Attribute ID %i ", p_ancs->evt.attr.attr_id);
return ATTR_LEN1;
}
}
/**@brief Function for parsing the length of an iOS attribute.
* Used in the @ref parse_get_notif_attrs_response state machine.
*
* @details The Length is 2 bytes. Since there is a chance we reveice the bytes in two different
* GATTC notifications, we parse only the first byte here and then set the state machine
* ready to parse the next byte.
*
* @param[in] p_ancs Pointer to an ANCS instance to which the event belongs.
* @param[in] p_data_src Pointer to data that was received from the Notification Provider.
* @param[in] index Pointer to an index that helps us keep track of the current data to be parsed.
*
* @return The next parse state.
*/
static ble_ancs_c_parse_state_t attr_len1_parse(ble_ancs_c_t * p_ancs, const uint8_t * p_data_src, uint32_t * index)
{
p_ancs->evt.attr.attr_len = p_data_src[(*index)++];
return ATTR_LEN2;
}
/**@brief Function for parsing the length of an iOS attribute.
* Used in the @ref parse_get_notif_attrs_response state machine.
*
* @details Second byte of the length field. If the length is zero, it means that the attribute is not
* present and the state machine is set to parse the next attribute.
*
* @param[in] p_ancs Pointer to an ANCS instance to which the event belongs.
* @param[in] p_data_src Pointer to data that was received from the Notification Provider.
* @param[in] index Pointer to an index that helps us keep track of the current data to be parsed.
*
* @return The next parse state.
*/
static ble_ancs_c_parse_state_t attr_len2_parse(ble_ancs_c_t * p_ancs, const uint8_t * p_data_src, uint32_t * index)
{
p_ancs->evt.attr.attr_len |= (p_data_src[(*index)++] << 8);
p_ancs->parse_info.current_attr_index = 0;
if (p_ancs->evt.attr.attr_len != 0)
{
//If the attribute has a length but there is no allocated space for this attribute
if ((p_ancs->parse_info.p_attr_list[p_ancs->evt.attr.attr_id].attr_len == 0) ||
(p_ancs->parse_info.p_attr_list[p_ancs->evt.attr.attr_id].p_attr_data == NULL))
{
return ATTR_SKIP;
}
else
{
return ATTR_DATA;
}
}
else
{
NRF_LOG_DEBUG("Attribute LEN %i ", p_ancs->evt.attr.attr_len);
if (attr_is_requested(p_ancs, p_ancs->evt.attr))
{
p_ancs->evt_handler(&p_ancs->evt);
}
if (all_req_attrs_parsed(p_ancs))
{
return DONE;
}
else
{
return ATTR_ID;
}
}
}
/**@brief Function for parsing the data of an iOS attribute.
* Used in the @ref parse_get_notif_attrs_response state machine.
*
* @details Read the data of the attribute into our local buffer.
*
* @param[in] p_ancs Pointer to an ANCS instance to which the event belongs.
* @param[in] p_data_src Pointer to data that was received from the Notification Provider.
* @param[in] index Pointer to an index that helps us keep track of the current data to be parsed.
*
* @return The next parse state.
*/
static ble_ancs_c_parse_state_t attr_data_parse(ble_ancs_c_t * p_ancs,
const uint8_t * p_data_src,
uint32_t * index)
{
// We have not reached the end of the attribute, nor our max allocated internal size.
// Proceed with copying data over to our buffer.
if ( (p_ancs->parse_info.current_attr_index < p_ancs->parse_info.p_attr_list[p_ancs->evt.attr.attr_id].attr_len)
&& (p_ancs->parse_info.current_attr_index < p_ancs->evt.attr.attr_len))
{
//NRF_LOG_DEBUG("Byte copied to buffer: %c", p_data_src[(*index)]); // Un-comment this line to see every byte of an attribute as it is parsed. Commented out by default since it can overflow the uart buffer.
p_ancs->evt.attr.p_attr_data[p_ancs->parse_info.current_attr_index++] = p_data_src[(*index)++];
}
// We have reached the end of the attribute, or our max allocated internal size.
// Stop copying data over to our buffer. NUL-terminate at the current index.
if ( (p_ancs->parse_info.current_attr_index == p_ancs->evt.attr.attr_len) ||
(p_ancs->parse_info.current_attr_index == p_ancs->parse_info.p_attr_list[p_ancs->evt.attr.attr_id].attr_len - 1))
{
if (attr_is_requested(p_ancs, p_ancs->evt.attr))
{
p_ancs->evt.attr.p_attr_data[p_ancs->parse_info.current_attr_index] = '\0';
}
// If our max buffer size is smaller than the remaining attribute data, we must
// increase index to skip the data until the start of the next attribute.
if (p_ancs->parse_info.current_attr_index < p_ancs->evt.attr.attr_len)
{
return ATTR_SKIP;
}
NRF_LOG_DEBUG("Attribute finished!");
if (attr_is_requested(p_ancs, p_ancs->evt.attr))
{
p_ancs->evt_handler(&p_ancs->evt);
}
if (all_req_attrs_parsed(p_ancs))
{
return DONE;
}
else
{
return ATTR_ID;
}
}
return ATTR_DATA;
}
static ble_ancs_c_parse_state_t attr_skip(ble_ancs_c_t * p_ancs, const uint8_t * p_data_src, uint32_t * index)
{
// We have not reached the end of the attribute, nor our max allocated internal size.
// Proceed with copying data over to our buffer.
if (p_ancs->parse_info.current_attr_index < p_ancs->evt.attr.attr_len)
{
p_ancs->parse_info.current_attr_index++;
(*index)++;
}
// At the end of the attribute, determine if it should be passed to event handler and
// continue parsing the next attribute ID if we are not done with all the attributes.
if (p_ancs->parse_info.current_attr_index == p_ancs->evt.attr.attr_len)
{
if (attr_is_requested(p_ancs, p_ancs->evt.attr))
{
p_ancs->evt_handler(&p_ancs->evt);
}
if (all_req_attrs_parsed(p_ancs))
{
return DONE;
}
else
{
return ATTR_ID;
}
}
return ATTR_SKIP;
}
void ancs_parse_get_attrs_response(ble_ancs_c_t * p_ancs,
const uint8_t * p_data_src,
const uint16_t hvx_data_len)
{
uint32_t index;
for (index = 0; index < hvx_data_len;)
{
switch (p_ancs->parse_info.parse_state)
{
case COMMAND_ID:
p_ancs->parse_info.parse_state = command_id_parse(p_ancs, p_data_src, &index);
break;
case NOTIF_UID:
p_ancs->parse_info.parse_state = notif_uid_parse(p_ancs, p_data_src, &index);
break;
case APP_ID:
p_ancs->parse_info.parse_state = app_id_parse(p_ancs, p_data_src, &index);
break;
case ATTR_ID:
p_ancs->parse_info.parse_state = attr_id_parse(p_ancs, p_data_src, &index);
break;
case ATTR_LEN1:
p_ancs->parse_info.parse_state = attr_len1_parse(p_ancs, p_data_src, &index);
break;
case ATTR_LEN2:
p_ancs->parse_info.parse_state = attr_len2_parse(p_ancs, p_data_src, &index);
break;
case ATTR_DATA:
p_ancs->parse_info.parse_state = attr_data_parse(p_ancs, p_data_src, &index);
break;
case ATTR_SKIP:
p_ancs->parse_info.parse_state = attr_skip(p_ancs, p_data_src, &index);
break;
case DONE:
NRF_LOG_DEBUG("Parse state: Done ");
index = hvx_data_len;
break;
default:
// Default case will never trigger intentionally. Go to the DONE state to minimize the consequences.
p_ancs->parse_info.parse_state = DONE;
break;
}
}
}

View File

@@ -0,0 +1,77 @@
/**
* 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.
*
*/
#ifndef BLE_ANCS_ATTR_PARSER_H__
#define BLE_ANCS_ATTR_PARSER_H__
#include "nrf_ble_ancs_c.h"
/** @file
*
* @addtogroup ble_ancs_c
* @{
*/
/**@brief Function for parsing notification or app attribute response data.
*
* @details The data that comes from the Notification Provider can be much longer than what
* would fit in a single GATTC notification. Therefore, this function relies on a
* state-oriented switch case.
* UID and command ID will be received only once at the beginning of the first
* GATTC notification of a new attribute request for a given iOS notification.
* After this, we can loop several ATTR_ID > LENGTH > DATA > ATTR_ID > LENGTH > DATA until
* we have received all attributes we wanted as a Notification Consumer.
* The Notification Provider can also simply stop sending attributes.
*
* 1 byte | 4 bytes |1 byte |2 bytes |... X bytes ... |1 bytes| 2 bytes| ... X bytes ...
* --------|-------------|-------|--------|----------------|-------|--------|----------------
* CMD_ID | NOTIF_UID |ATTR_ID| LENGTH | DATA |ATTR_ID| LENGTH | DATA
*
* @param[in] p_ancs Pointer to an ANCS instance to which the event belongs.
* @param[in] p_data_src Pointer to data that was received from the Notification Provider.
* @param[in] hvx_data_len Length of the data that was received from the Notification Provider.
*/
void ancs_parse_get_attrs_response(ble_ancs_c_t * p_ancs,
const uint8_t * p_data_src,
const uint16_t hvx_data_len);
/** @} */
#endif // BLE_ANCS_ATTR_PARSER_H__

View File

@@ -0,0 +1,683 @@
/**
* 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.
*
*/
/* Disclaimer: This client implementation of the Apple Notification Center Service can and will be changed at any time by Nordic Semiconductor ASA.
* Server implementations such as the ones found in iOS can be changed at any time by Apple and may cause this client implementation to stop working.
*/
#include "sdk_common.h"
#if NRF_MODULE_ENABLED(BLE_ANCS_C)
#include "nrf_ble_ancs_c.h"
#include "ancs_attr_parser.h"
#include "ancs_app_attr_get.h"
#include "ble_err.h"
#include "ble_srv_common.h"
#include "ble_db_discovery.h"
#include "app_error.h"
#define NRF_LOG_MODULE_NAME ble_ancs_c
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER();
#define BLE_ANCS_NOTIF_EVT_ID_INDEX 0 /**< Index of the Event ID field when parsing notifications. */
#define BLE_ANCS_NOTIF_FLAGS_INDEX 1 /**< Index of the Flags field when parsing notifications. */
#define BLE_ANCS_NOTIF_CATEGORY_ID_INDEX 2 /**< Index of the Category ID field when parsing notifications. */
#define BLE_ANCS_NOTIF_CATEGORY_CNT_INDEX 3 /**< Index of the Category Count field when parsing notifications. */
#define BLE_ANCS_NOTIF_NOTIF_UID 4 /**< Index of the Notification UID field when parsing notifications. */
#define BLE_CCCD_NOTIFY_BIT_MASK 0x0001 /**< Enables notification bit. */
#define TIME_STRING_LEN 15 /**< Unicode Technical Standard (UTS) #35 date format pattern "yyyyMMdd'T'HHmmSS" + "'\0'". */
/**@brief 128-bit service UUID for the Apple Notification Center Service. */
ble_uuid128_t const ble_ancs_base_uuid128 =
{
{
// 7905F431-B5CE-4E99-A40F-4B1E122D00D0
0xd0, 0x00, 0x2d, 0x12, 0x1e, 0x4b, 0x0f, 0xa4,
0x99, 0x4e, 0xce, 0xb5, 0x31, 0xf4, 0x05, 0x79
}
};
/**@brief 128-bit control point UUID. */
ble_uuid128_t const ble_ancs_cp_base_uuid128 =
{
{
// 69d1d8f3-45e1-49a8-9821-9BBDFDAAD9D9
0xd9, 0xd9, 0xaa, 0xfd, 0xbd, 0x9b, 0x21, 0x98,
0xa8, 0x49, 0xe1, 0x45, 0xf3, 0xd8, 0xd1, 0x69
}
};
/**@brief 128-bit notification source UUID. */
ble_uuid128_t const ble_ancs_ns_base_uuid128 =
{
{
// 9FBF120D-6301-42D9-8C58-25E699A21DBD
0xbd, 0x1d, 0xa2, 0x99, 0xe6, 0x25, 0x58, 0x8c,
0xd9, 0x42, 0x01, 0x63, 0x0d, 0x12, 0xbf, 0x9f
}
};
/**@brief 128-bit data source UUID. */
ble_uuid128_t const ble_ancs_ds_base_uuid128 =
{
{
// 22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB
0xfb, 0x7b, 0x7c, 0xce, 0x6a, 0xb3, 0x44, 0xbe,
0xb5, 0x4b, 0xd6, 0x24, 0xe9, 0xc6, 0xea, 0x22
}
};
/**@brief Function for intercepting errors of GATTC and 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_ancs_c_t * p_ancs = (ble_ancs_c_t *)p_ctx;
NRF_LOG_DEBUG("A GATT Client error has occurred on conn_handle: 0x%x", conn_handle);
if (p_ancs->error_handler != NULL)
{
p_ancs->error_handler(nrf_error);
}
}
/**@brief Function for handling Disconnected event received from the SoftDevice.
*
* @details This function checks whether the disconnect event is happening on the link
* associated with the current instance of the module. If the event is happening,
* the function sets the conn_handle of the instance to invalid.
*
* @param[in] p_ancs Pointer to the ANCS client structure.
* @param[in] p_ble_evt Pointer to the BLE event received.
*/
static void on_disconnected(ble_ancs_c_t * p_ancs, ble_evt_t const * p_ble_evt)
{
if (p_ancs->conn_handle == p_ble_evt->evt.gap_evt.conn_handle)
{
p_ancs->conn_handle = BLE_CONN_HANDLE_INVALID;
}
}
void ble_ancs_c_on_db_disc_evt(ble_ancs_c_t * p_ancs, ble_db_discovery_evt_t * p_evt)
{
NRF_LOG_DEBUG("Database Discovery handler called with event 0x%x", p_evt->evt_type);
ble_ancs_c_evt_t evt;
ble_gatt_db_char_t * p_chars;
p_chars = p_evt->params.discovered_db.charateristics;
// Check whether the ANCS Service was discovered.
if ( (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE)
&& (p_evt->params.discovered_db.srv_uuid.uuid == ANCS_UUID_SERVICE)
&& (p_evt->params.discovered_db.srv_uuid.type == p_ancs->service.service.uuid.type))
{
// Find the handles of the ANCS characteristic.
for (uint32_t i = 0; i < p_evt->params.discovered_db.char_count; i++)
{
switch (p_chars[i].characteristic.uuid.uuid)
{
case ANCS_UUID_CHAR_CONTROL_POINT:
NRF_LOG_INFO("Control Point characteristic found.");
memcpy(&evt.service.control_point_char,
&p_chars[i].characteristic,
sizeof(ble_gattc_char_t));
break;
case ANCS_UUID_CHAR_DATA_SOURCE:
NRF_LOG_INFO("Data Source characteristic found.");
memcpy(&evt.service.data_source_char,
&p_chars[i].characteristic,
sizeof(ble_gattc_char_t));
evt.service.data_source_cccd.handle = p_chars[i].cccd_handle;
break;
case ANCS_UUID_CHAR_NOTIFICATION_SOURCE:
NRF_LOG_INFO("Notification Point characteristic found.");
memcpy(&evt.service.notif_source_char,
&p_chars[i].characteristic,
sizeof(ble_gattc_char_t));
evt.service.notif_source_cccd.handle = p_chars[i].cccd_handle;
break;
default:
break;
}
}
evt.evt_type = BLE_ANCS_C_EVT_DISCOVERY_COMPLETE;
evt.conn_handle = p_evt->conn_handle;
}
else if ((p_evt->evt_type == BLE_DB_DISCOVERY_SRV_NOT_FOUND) ||
(p_evt->evt_type == BLE_DB_DISCOVERY_ERROR))
{
evt.evt_type = BLE_ANCS_C_EVT_DISCOVERY_FAILED;
}
else
{
return;
}
p_ancs->evt_handler(&evt);
}
/**@brief Function for checking whether the data in an iOS notification is out of bounds.
*
* @param[in] notif An iOS notification.
*
* @retval NRF_SUCCESS If the notification is within bounds.
* @retval NRF_ERROR_INVALID_PARAM If the notification is out of bounds.
*/
static uint32_t ble_ancs_verify_notification_format(ble_ancs_c_evt_notif_t const * notif)
{
if ( (notif->evt_id >= BLE_ANCS_NB_OF_EVT_ID)
|| (notif->category_id >= BLE_ANCS_NB_OF_CATEGORY_ID))
{
return NRF_ERROR_INVALID_PARAM;
}
return NRF_SUCCESS;
}
/**@brief Function for receiving and validating notifications received from the Notification Provider.
*
* @param[in] p_ancs Pointer to an ANCS instance to which the event belongs.
* @param[in] p_data_src Pointer to the data that was received from the Notification Provider.
* @param[in] hvx_len Length of the data that was received from the Notification Provider.
*/
static void parse_notif(ble_ancs_c_t const * p_ancs,
uint8_t const * p_data_src,
uint16_t const hvx_data_len)
{
ble_ancs_c_evt_t ancs_evt;
uint32_t err_code;
if (hvx_data_len != BLE_ANCS_NOTIFICATION_DATA_LENGTH)
{
ancs_evt.evt_type = BLE_ANCS_C_EVT_INVALID_NOTIF;
p_ancs->evt_handler(&ancs_evt);
}
/*lint --e{415} --e{416} -save suppress Warning 415: possible access out of bound*/
ancs_evt.notif.evt_id =
(ble_ancs_c_evt_id_values_t) p_data_src[BLE_ANCS_NOTIF_EVT_ID_INDEX];
ancs_evt.notif.evt_flags.silent =
(p_data_src[BLE_ANCS_NOTIF_FLAGS_INDEX] >> BLE_ANCS_EVENT_FLAG_SILENT) & 0x01;
ancs_evt.notif.evt_flags.important =
(p_data_src[BLE_ANCS_NOTIF_FLAGS_INDEX] >> BLE_ANCS_EVENT_FLAG_IMPORTANT) & 0x01;
ancs_evt.notif.evt_flags.pre_existing =
(p_data_src[BLE_ANCS_NOTIF_FLAGS_INDEX] >> BLE_ANCS_EVENT_FLAG_PREEXISTING) & 0x01;
ancs_evt.notif.evt_flags.positive_action =
(p_data_src[BLE_ANCS_NOTIF_FLAGS_INDEX] >> BLE_ANCS_EVENT_FLAG_POSITIVE_ACTION) & 0x01;
ancs_evt.notif.evt_flags.negative_action =
(p_data_src[BLE_ANCS_NOTIF_FLAGS_INDEX] >> BLE_ANCS_EVENT_FLAG_NEGATIVE_ACTION) & 0x01;
ancs_evt.notif.category_id =
(ble_ancs_c_category_id_val_t) p_data_src[BLE_ANCS_NOTIF_CATEGORY_ID_INDEX];
ancs_evt.notif.category_count = p_data_src[BLE_ANCS_NOTIF_CATEGORY_CNT_INDEX];
ancs_evt.notif.notif_uid = uint32_decode(&p_data_src[BLE_ANCS_NOTIF_NOTIF_UID]);
/*lint -restore*/
err_code = ble_ancs_verify_notification_format(&ancs_evt.notif);
if (err_code == NRF_SUCCESS)
{
ancs_evt.evt_type = BLE_ANCS_C_EVT_NOTIF;
}
else
{
ancs_evt.evt_type = BLE_ANCS_C_EVT_INVALID_NOTIF;
}
p_ancs->evt_handler(&ancs_evt);
}
ret_code_t nrf_ble_ancs_c_app_attr_request(ble_ancs_c_t * p_ancs,
uint8_t const * p_app_id,
uint32_t len)
{
return ancs_c_app_attr_request(p_ancs, p_app_id, len);
}
/**@brief Function for receiving and validating notifications received from the Notification Provider.
*
* @param[in] p_ancs Pointer to an ANCS instance to which the event belongs.
* @param[in] p_ble_evt Bluetooth stack event.
*/
static void on_evt_gattc_notif(ble_ancs_c_t * p_ancs, ble_evt_t const * p_ble_evt)
{
ble_gattc_evt_hvx_t const * p_notif = &p_ble_evt->evt.gattc_evt.params.hvx;
if (p_ble_evt->evt.gattc_evt.conn_handle != p_ancs->conn_handle)
{
return;
}
if (p_notif->handle == p_ancs->service.notif_source_char.handle_value)
{
parse_notif(p_ancs, p_notif->data, p_notif->len);
}
else if (p_notif->handle == p_ancs->service.data_source_char.handle_value)
{
ancs_parse_get_attrs_response(p_ancs, p_notif->data, p_notif->len);
}
else
{
// No applicable action.
}
}
/**@brief Function for handling error response events.
*
* @param[in] p_ancs Pointer to an ANCS instance to which the event belongs.
* @param[in] p_ble_evt Pointer to the SoftDevice event.
*/
static void on_ctrlpt_error_rsp(ble_ancs_c_t * p_ancs, ble_evt_t const * p_ble_evt)
{
ble_ancs_c_evt_t ancs_evt;
ancs_evt.evt_type = BLE_ANCS_C_EVT_NP_ERROR;
ancs_evt.err_code_np = p_ble_evt->evt.gattc_evt.gatt_status;
p_ancs->evt_handler(&ancs_evt);
}
/**@brief Function for handling write response events.
*
* @param[in] p_ancs Pointer to an ANCS instance to which the event belongs.
* @param[in] p_ble_evt Pointer to the SoftDevice event.
*/
static void on_write_rsp(ble_ancs_c_t * p_ancs, ble_evt_t const* p_ble_evt)
{
// Check if the event is on the link for this instance.
if (p_ancs->conn_handle != p_ble_evt->evt.gattc_evt.conn_handle)
{
return;
}
if ((p_ble_evt->evt.gattc_evt.error_handle != BLE_GATT_HANDLE_INVALID)
&& (p_ble_evt->evt.gattc_evt.error_handle == p_ancs->service.control_point_char.handle_value))
{
on_ctrlpt_error_rsp(p_ancs,p_ble_evt);
}
}
void ble_ancs_c_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
{
ble_ancs_c_t * p_ancs = (ble_ancs_c_t *)p_context;
uint16_t evt = p_ble_evt->header.evt_id;
switch (evt)
{
case BLE_GATTC_EVT_WRITE_RSP:
on_write_rsp(p_ancs, p_ble_evt);
break;
case BLE_GATTC_EVT_HVX:
on_evt_gattc_notif(p_ancs, p_ble_evt);
break;
case BLE_GAP_EVT_DISCONNECTED:
on_disconnected(p_ancs, p_ble_evt);
break;
default:
break;
}
}
ret_code_t ble_ancs_c_init(ble_ancs_c_t * p_ancs, ble_ancs_c_init_t const * p_ancs_init)
{
uint32_t err_code;
// Verify that the parameters needed for initializing this instance of ANCS are not NULL.
VERIFY_PARAM_NOT_NULL(p_ancs);
VERIFY_PARAM_NOT_NULL(p_ancs_init);
VERIFY_PARAM_NOT_NULL(p_ancs_init->evt_handler);
// Initialize state for the attribute-parsing state machine.
p_ancs->parse_info.parse_state = COMMAND_ID;
p_ancs->parse_info.p_data_dest = NULL;
p_ancs->parse_info.current_attr_index = 0;
p_ancs->parse_info.current_app_id_index = 0;
p_ancs->evt_handler = p_ancs_init->evt_handler;
p_ancs->error_handler = p_ancs_init->error_handler;
p_ancs->conn_handle = BLE_CONN_HANDLE_INVALID;
p_ancs->p_gatt_queue = p_ancs_init->p_gatt_queue;
p_ancs->gatt_err_handler = gatt_error_handler;
p_ancs->service.data_source_cccd.uuid.uuid = BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG;
p_ancs->service.notif_source_cccd.uuid.uuid = BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG;
// Make sure that the instance of service is clear. GATT handles inside the service and characteristics are set to @ref BLE_GATT_HANDLE_INVALID.
memset(&p_ancs->service, 0, sizeof(ble_ancs_c_service_t));
// Assign UUID types.
err_code = sd_ble_uuid_vs_add(&ble_ancs_base_uuid128, &p_ancs->service.service.uuid.type);
VERIFY_SUCCESS(err_code);
err_code = sd_ble_uuid_vs_add(&ble_ancs_cp_base_uuid128, &p_ancs->service.control_point_char.uuid.type);
VERIFY_SUCCESS(err_code);
err_code = sd_ble_uuid_vs_add(&ble_ancs_ns_base_uuid128, &p_ancs->service.notif_source_char.uuid.type);
VERIFY_SUCCESS(err_code);
err_code = sd_ble_uuid_vs_add(&ble_ancs_ds_base_uuid128, &p_ancs->service.data_source_char.uuid.type);
VERIFY_SUCCESS(err_code);
// Assign UUID to the service.
p_ancs->service.service.uuid.uuid = ANCS_UUID_SERVICE;
p_ancs->service.service.uuid.type = p_ancs->service.service.uuid.type;
return ble_db_discovery_evt_register(&p_ancs->service.service.uuid);
}
/**@brief Function for creating a tx message for writing a CCCD.
*
* @param[in] p_ancs Pointer to the iOS notification structure. This structure must be supplied by
* the application. It identifies the particular client instance to use.
* @param[in] handle_cccd Handle of the CCCD.
* @param[in] enable Enables or disables GATTC notifications.
*
* @retval NRF_SUCCESS If the message is created successfully.
* @retval NRF_ERROR_INVALID_PARAM If one of the input parameters is invalid.
* @retval err_code Otherwise, this API propagates the error code returned by function
* @ref nrf_ble_gq_item_add.
*/
static uint32_t cccd_configure(ble_ancs_c_t const * const p_ancs,
uint16_t const handle_cccd,
bool notification_enable)
{
nrf_ble_gq_req_t ancs_c_req;
uint8_t cccd[BLE_CCCD_VALUE_LEN];
uint16_t cccd_val = notification_enable ? BLE_GATT_HVX_NOTIFICATION : 0;
cccd[0] = LSB_16(cccd_val);
cccd[1] = MSB_16(cccd_val);
memset(&ancs_c_req, 0, sizeof(nrf_ble_gq_req_t));
ancs_c_req.type = NRF_BLE_GQ_REQ_GATTC_WRITE;
ancs_c_req.error_handler.cb = p_ancs->gatt_err_handler;
ancs_c_req.error_handler.p_ctx = (ble_ancs_c_t *)p_ancs;
ancs_c_req.params.gattc_write.handle = handle_cccd;
ancs_c_req.params.gattc_write.len = BLE_CCCD_VALUE_LEN;
ancs_c_req.params.gattc_write.offset = 0;
ancs_c_req.params.gattc_write.write_op = BLE_GATT_OP_WRITE_REQ;
ancs_c_req.params.gattc_write.p_value = cccd;
return nrf_ble_gq_item_add(p_ancs->p_gatt_queue, &ancs_c_req, p_ancs->conn_handle);
}
ret_code_t ble_ancs_c_notif_source_notif_enable(ble_ancs_c_t const * p_ancs)
{
NRF_LOG_INFO("Enable Notification Source. Writing to CCCD handle: %i. ",
p_ancs->service.notif_source_cccd.handle);
return cccd_configure(p_ancs, p_ancs->service.notif_source_cccd.handle, true);
}
ret_code_t ble_ancs_c_notif_source_notif_disable(ble_ancs_c_t const * p_ancs)
{
return cccd_configure(p_ancs, p_ancs->service.notif_source_cccd.handle, false);
}
ret_code_t ble_ancs_c_data_source_notif_enable(ble_ancs_c_t const * p_ancs)
{
NRF_LOG_INFO("Enable Notification Data Source. Writing to CCCD handle: %i. ",
p_ancs->service.data_source_cccd.handle);
return cccd_configure(p_ancs, p_ancs->service.data_source_cccd.handle, true);
}
ret_code_t ble_ancs_c_data_source_notif_disable(ble_ancs_c_t const * p_ancs)
{
return cccd_configure(p_ancs, p_ancs->service.data_source_cccd.handle, false);
}
uint32_t ble_ancs_get_notif_attrs(ble_ancs_c_t * p_ancs,
uint32_t const p_uid)
{
nrf_ble_gq_req_t ancs_req;
uint8_t gattc_value[BLE_ANCS_WRITE_MAX_MSG_LENGTH];
memset(&ancs_req, 0, sizeof(nrf_ble_gq_req_t));
uint32_t index = 0;
p_ancs->number_of_requested_attr = 0;
ancs_req.type = NRF_BLE_GQ_REQ_GATTC_WRITE;
ancs_req.error_handler.cb = p_ancs->gatt_err_handler;
ancs_req.error_handler.p_ctx = p_ancs;
ancs_req.params.gattc_write.handle = p_ancs->service.control_point_char.handle_value;
ancs_req.params.gattc_write.offset = 0;
ancs_req.params.gattc_write.write_op = BLE_GATT_OP_WRITE_REQ;
ancs_req.params.gattc_write.p_value = gattc_value;
//Encode Command ID.
gattc_value[index++] = BLE_ANCS_COMMAND_ID_GET_NOTIF_ATTRIBUTES;
//Encode Notification UID.
index += uint32_encode(p_uid, &(gattc_value[index]));
//Encode Attribute ID.
for (uint32_t attr = 0; attr < BLE_ANCS_NB_OF_NOTIF_ATTR; attr++)
{
if (p_ancs->ancs_notif_attr_list[attr].get == true)
{
gattc_value[index++] = (uint8_t)attr;
if ((attr == BLE_ANCS_NOTIF_ATTR_ID_TITLE) ||
(attr == BLE_ANCS_NOTIF_ATTR_ID_SUBTITLE) ||
(attr == BLE_ANCS_NOTIF_ATTR_ID_MESSAGE))
{
//Encode Length field. Only applicable for Title, Subtitle, and Message.
index += uint16_encode(p_ancs->ancs_notif_attr_list[attr].attr_len,
&(gattc_value[index]));
}
p_ancs->number_of_requested_attr++;
}
}
ancs_req.params.gattc_write.len = index;
p_ancs->parse_info.expected_number_of_attrs = p_ancs->number_of_requested_attr;
return nrf_ble_gq_item_add(p_ancs->p_gatt_queue, &ancs_req, p_ancs->conn_handle);
}
ret_code_t nrf_ble_ancs_c_attr_add(ble_ancs_c_t * p_ancs,
ble_ancs_c_notif_attr_id_val_t const id,
uint8_t * p_data,
uint16_t const len)
{
VERIFY_PARAM_NOT_NULL(p_data);
if ((len == 0) || (len > BLE_ANCS_ATTR_DATA_MAX))
{
return NRF_ERROR_INVALID_LENGTH;
}
p_ancs->ancs_notif_attr_list[id].get = true;
p_ancs->ancs_notif_attr_list[id].attr_len = len;
p_ancs->ancs_notif_attr_list[id].p_attr_data = p_data;
return NRF_SUCCESS;
}
ret_code_t nrf_ble_ancs_c_app_attr_add(ble_ancs_c_t * p_ancs,
ble_ancs_c_app_attr_id_val_t const id,
uint8_t * p_data,
uint16_t const len)
{
VERIFY_PARAM_NOT_NULL(p_ancs);
VERIFY_PARAM_NOT_NULL(p_data);
if ((len == 0) || (len > BLE_ANCS_ATTR_DATA_MAX))
{
return NRF_ERROR_INVALID_LENGTH;
}
p_ancs->ancs_app_attr_list[id].get = true;
p_ancs->ancs_app_attr_list[id].attr_len = len;
p_ancs->ancs_app_attr_list[id].p_attr_data = p_data;
return NRF_SUCCESS;
}
ret_code_t ble_ancs_c_app_attr_remove(ble_ancs_c_t * p_ancs,
ble_ancs_c_app_attr_id_val_t const id)
{
p_ancs->ancs_app_attr_list[id].get = false;
p_ancs->ancs_app_attr_list[id].attr_len = 0;
p_ancs->ancs_app_attr_list[id].p_attr_data = NULL;
return NRF_SUCCESS;
}
ret_code_t ble_ancs_c_notif_attr_remove(ble_ancs_c_t * p_ancs,
ble_ancs_c_notif_attr_id_val_t const id)
{
p_ancs->ancs_notif_attr_list[id].get = false;
p_ancs->ancs_notif_attr_list[id].attr_len = 0;
p_ancs->ancs_notif_attr_list[id].p_attr_data = NULL;
return NRF_SUCCESS;
}
ret_code_t nrf_ble_ancs_c_attr_req_clear_all(ble_ancs_c_t * p_ancs)
{
memset(p_ancs->ancs_notif_attr_list, 0 , sizeof(p_ancs->ancs_notif_attr_list));
memset(p_ancs->ancs_app_attr_list, 0 , sizeof(p_ancs->ancs_app_attr_list));
return NRF_SUCCESS;
}
ret_code_t nrf_ble_ancs_c_request_attrs(ble_ancs_c_t * p_ancs,
ble_ancs_c_evt_notif_t const * p_notif)
{
uint32_t err_code;
err_code = ble_ancs_verify_notification_format(p_notif);
VERIFY_SUCCESS(err_code);
err_code = ble_ancs_get_notif_attrs(p_ancs, p_notif->notif_uid);
p_ancs->parse_info.parse_state = COMMAND_ID;
VERIFY_SUCCESS(err_code);
return NRF_SUCCESS;
}
static uint16_t encode_notif_action(uint8_t * p_encoded_data, uint32_t uid, ble_ancs_c_action_id_values_t action_id)
{
uint8_t index = 0;
p_encoded_data[index++] = BLE_ANCS_COMMAND_ID_GET_PERFORM_NOTIF_ACTION;
index += uint32_encode(uid, &p_encoded_data[index]);
p_encoded_data[index++] = (uint8_t)action_id;
return index;
}
ret_code_t nrf_ancs_perform_notif_action(ble_ancs_c_t * p_ancs, uint32_t uid, ble_ancs_c_action_id_values_t action_id)
{
VERIFY_PARAM_NOT_NULL(p_ancs);
nrf_ble_gq_req_t ancs_req;
uint8_t gattc_value[BLE_ANCS_WRITE_MAX_MSG_LENGTH];
memset(&ancs_req, 0, sizeof(nrf_ble_gq_req_t));
uint16_t len = encode_notif_action(gattc_value, uid, action_id);
ancs_req.type = NRF_BLE_GQ_REQ_GATTC_WRITE;
ancs_req.error_handler.cb = p_ancs->gatt_err_handler;
ancs_req.error_handler.p_ctx = p_ancs;
ancs_req.params.gattc_write.handle = p_ancs->service.control_point_char.handle_value;
ancs_req.params.gattc_write.p_value = gattc_value;
ancs_req.params.gattc_write.offset = 0;
ancs_req.params.gattc_write.write_op = BLE_GATT_OP_WRITE_REQ;
ancs_req.params.gattc_write.len = len;
return nrf_ble_gq_item_add(p_ancs->p_gatt_queue, &ancs_req, p_ancs->conn_handle);
}
ret_code_t nrf_ble_ancs_c_handles_assign(ble_ancs_c_t * p_ancs,
uint16_t const conn_handle,
ble_ancs_c_service_t const * p_peer_handles)
{
VERIFY_PARAM_NOT_NULL(p_ancs);
p_ancs->conn_handle = conn_handle;
if (p_peer_handles != NULL)
{
p_ancs->service.control_point_char.handle_value = p_peer_handles->control_point_char.handle_value;
p_ancs->service.data_source_cccd.handle = p_peer_handles->data_source_cccd.handle;
p_ancs->service.data_source_char.handle_value = p_peer_handles->data_source_char.handle_value;
p_ancs->service.notif_source_cccd.handle = p_peer_handles->notif_source_cccd.handle;
p_ancs->service.notif_source_char.handle_value = p_peer_handles->notif_source_char.handle_value;
}
return nrf_ble_gq_conn_handle_register(p_ancs->p_gatt_queue, conn_handle);
}
#endif// NRF_MODULE_ENABLED(BLE_ANCS_C)

View File

@@ -0,0 +1,620 @@
/**
* 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_ancs_c Apple Notification Service Client
* @{
* @ingroup ble_sdk_srv
*
* @brief Apple Notification Center Service Client module.
*
* @details Disclaimer: This client implementation of the Apple Notification Center Service can
* be changed at any time by Nordic Semiconductor ASA. Server implementations such as the
* ones found in iOS can be changed at any time by Apple and may cause this client
* implementation to stop working.
*
* This module implements the Apple Notification Center Service (ANCS) client.
* This client can be used as a Notification Consumer (NC) that receives data
* notifications from a Notification Provider (NP). The NP is typically an iOS
* device that is acting as a server. For terminology and up-to-date specs, see
* http://developer.apple.com.
*
* The term "notification" is used in two different meanings:
* - An <i>iOS notification</i> is the data received from the Notification Provider.
* - A <i>GATTC notification</i> is a way to transfer data with <i>Bluetooth</i> Smart.
* In this module, iOS notifications are received through the GATTC notifications.
* The full term (iOS notification or GATTC notification) is used where required to avoid confusion.
*
* Upon initializing the module, you must add the different iOS notification attributes you
* would like to receive for iOS notifications (see @ref nrf_ble_ancs_c_attr_add).
*
* Once a connection is established with a central device, the module does a service discovery to
* discover the ANCS server handles. If this succeeds (@ref BLE_ANCS_C_EVT_DISCOVERY_COMPLETE),
* the handles for the ANCS server are part of the @ref ble_ancs_c_evt_t structure and must be
* assigned to an ANCS_C instance using the @ref nrf_ble_ancs_c_handles_assign function. For more
* information about service discovery, see the @ref lib_ble_db_discovery documentation.
*
* The application can now subscribe to iOS notifications with
* @ref ble_ancs_c_notif_source_notif_enable. The notifications arrive in the @ref BLE_ANCS_C_EVT_NOTIF event.
* @ref nrf_ble_ancs_c_request_attrs can be used to request attributes for the notifications. The attributes
* arrive in the @ref BLE_ANCS_C_EVT_NOTIF_ATTRIBUTE event.
* Use @ref nrf_ble_ancs_c_app_attr_request to request attributes of the app that issued
* the notifications. The app attributes arrive in the @ref BLE_ANCS_C_EVT_APP_ATTRIBUTE event.
* Use @ref nrf_ancs_perform_notif_action to make the Notification Provider perform an
* action based on the provided notification.
*
* @msc
* hscale = "1.5";
* Application, ANCS_C;
* |||;
* Application=>ANCS_C [label = "ble_ancs_c_attr_add(attribute)"];
* Application=>ANCS_C [label = "ble_ancs_c_init(ancs_instance, event_handler)"];
* ...;
* Application<<=ANCS_C [label = "BLE_ANCS_C_EVT_DISCOVERY_COMPLETE"];
* Application=>ANCS_C [label = "ble_ancs_c_handles_assign(ancs_instance, conn_handle, service_handles)"];
* Application=>ANCS_C [label = "ble_ancs_c_notif_source_notif_enable(ancs_instance)"];
* Application=>ANCS_C [label = "ble_ancs_c_data_source_notif_enable(ancs_instance)"];
* |||;
* ...;
* |||;
* Application<<=ANCS_C [label = "BLE_ANCS_C_EVT_NOTIF"];
* |||;
* ...;
* |||;
* Application=>ANCS_C [label = "ble_ancs_c_request_attrs(attr_id, buffer)"];
* Application<<=ANCS_C [label = "BLE_ANCS_C_EVT_NOTIF_ATTRIBUTE"];
* |||;
* @endmsc
*
* @note The application must register this module as the BLE event observer by using the
* NRF_SDH_BLE_OBSERVER macro. Example:
* @code
* ble_ancs_c_t instance;
* NRF_SDH_BLE_OBSERVER(anything, BLE_ANCS_C_BLE_OBSERVER_PRIO,
* ble_ancs_c_on_ble_evt, &instance);
* @endcode
*/
#ifndef BLE_ANCS_C_H__
#define BLE_ANCS_C_H__
#include "ble_types.h"
#include "ble_srv_common.h"
#include "sdk_errors.h"
#include "ble_db_discovery.h"
#include "nrf_sdh_ble.h"
#include "nrf_ble_gq.h"
#ifdef __cplusplus
extern "C" {
#endif
/**@brief Macro for defining a ble_ancs_c instance.
*
* @param _name Name of the instance.
* @hideinitializer
*/
#define BLE_ANCS_C_DEF(_name) \
static ble_ancs_c_t _name; \
NRF_SDH_BLE_OBSERVER(_name ## _obs, \
BLE_ANCS_C_BLE_OBSERVER_PRIO, \
ble_ancs_c_on_ble_evt, &_name)
/** @brief Macro for defining multiple ble_ancs_c instances.
*
* @param _name Name of the array of instances.
* @param _cnt Number of instances to define.
* @hideinitializer
*/
#define BLE_ANCS_C_ARRAY_DEF(_name, _cnt) \
sstatic ble_ancs_c_t _name[_cnt]; \
NRF_SDH_BLE_OBSERVERS(_name ## _obs, \
BLE_ANCS_C_BLE_OBSERVER_PRIO, \
ble_ancs_c_on_ble_evt, &_name, _cnt)
#define BLE_ANCS_ATTR_DATA_MAX 32 //!< Maximum data length of an iOS notification attribute.
#define BLE_ANCS_NB_OF_CATEGORY_ID 12 //!< Number of iOS notification categories: Other, Incoming Call, Missed Call, Voice Mail, Social, Schedule, Email, News, Health and Fitness, Business and Finance, Location, Entertainment.
#define BLE_ANCS_NB_OF_NOTIF_ATTR 8 //!< Number of iOS notification attributes: AppIdentifier, Title, Subtitle, Message, MessageSize, Date, PositiveActionLabel, NegativeActionLabel.
#define BLE_ANCS_NB_OF_APP_ATTR 1 //!< Number of iOS application attributes: DisplayName.
#define BLE_ANCS_NB_OF_EVT_ID 3 //!< Number of iOS notification events: Added, Modified, Removed.
/** @brief Length of the iOS notification data.
*
* @details 8 bytes:
* Event ID |Event flags |Category ID |Category count|Notification UID
* ---------|------------|------------|--------------|----------------
* 1 byte | 1 byte | 1 byte | 1 byte | 4 bytes
*/
#define BLE_ANCS_NOTIFICATION_DATA_LENGTH 8
#define ANCS_UUID_SERVICE 0xF431 //!< 16-bit service UUID for the Apple Notification Center Service.
#define ANCS_UUID_CHAR_CONTROL_POINT 0xD8F3 //!< 16-bit control point UUID.
#define ANCS_UUID_CHAR_DATA_SOURCE 0xC6E9 //!< 16-bit data source UUID.
#define ANCS_UUID_CHAR_NOTIFICATION_SOURCE 0x120D //!< 16-bit notification source UUID.
#define BLE_ANCS_EVENT_FLAG_SILENT 0 //!< 0b.......1 Silent: First (LSB) bit is set. All flags can be active at the same time.
#define BLE_ANCS_EVENT_FLAG_IMPORTANT 1 //!< 0b......1. Important: Second (LSB) bit is set. All flags can be active at the same time.
#define BLE_ANCS_EVENT_FLAG_PREEXISTING 2 //!< 0b.....1.. Pre-existing: Third (LSB) bit is set. All flags can be active at the same time.
#define BLE_ANCS_EVENT_FLAG_POSITIVE_ACTION 3 //!< 0b....1... Positive action: Fourth (LSB) bit is set. All flags can be active at the same time.
#define BLE_ANCS_EVENT_FLAG_NEGATIVE_ACTION 4 //!< 0b...1.... Negative action: Fifth (LSB) bit is set. All flags can be active at the same time.
/** @defgroup BLE_ANCS_NP_ERROR_CODES Notification Provider (iOS) Error Codes
* @{ */
#define BLE_ANCS_NP_UNKNOWN_COMMAND 0x01A0 //!< The command ID is unknown to the NP.
#define BLE_ANCS_NP_INVALID_COMMAND 0x01A1 //!< The command format is invalid.
#define BLE_ANCS_NP_INVALID_PARAMETER 0x01A2 //!< One or more parameters do not exist in the NP.
#define BLE_ANCS_NP_ACTION_FAILED 0x01A3 //!< The action failed to be performed by the NP.
/** @} */
/**@brief Event types that are passed from client to application on an event. */
typedef enum
{
BLE_ANCS_C_EVT_DISCOVERY_COMPLETE, /**< A successful connection has been established and the service was found on the connected peer. */
BLE_ANCS_C_EVT_DISCOVERY_FAILED, /**< It was not possible to discover the service or characteristics of the connected peer. */
BLE_ANCS_C_EVT_NOTIF, /**< An iOS notification was received on the notification source control point. */
BLE_ANCS_C_EVT_INVALID_NOTIF, /**< An iOS notification was received on the notification source control point, but the format is invalid. */
BLE_ANCS_C_EVT_NOTIF_ATTRIBUTE, /**< A received iOS notification attribute has been parsed. */
BLE_ANCS_C_EVT_APP_ATTRIBUTE, /**< An iOS app attribute has been parsed. */
BLE_ANCS_C_EVT_NP_ERROR, /**< An error has been sent on the ANCS Control Point from the iOS Notification Provider. */
} ble_ancs_c_evt_type_t;
/**@brief Category IDs for iOS notifications. */
typedef enum
{
BLE_ANCS_CATEGORY_ID_OTHER, /**< The iOS notification belongs to the "Other" category. */
BLE_ANCS_CATEGORY_ID_INCOMING_CALL, /**< The iOS notification belongs to the "Incoming Call" category. */
BLE_ANCS_CATEGORY_ID_MISSED_CALL, /**< The iOS notification belongs to the "Missed Call" category. */
BLE_ANCS_CATEGORY_ID_VOICE_MAIL, /**< The iOS notification belongs to the "Voice Mail" category. */
BLE_ANCS_CATEGORY_ID_SOCIAL, /**< The iOS notification belongs to the "Social" category. */
BLE_ANCS_CATEGORY_ID_SCHEDULE, /**< The iOS notification belongs to the "Schedule" category. */
BLE_ANCS_CATEGORY_ID_EMAIL, /**< The iOS notification belongs to the "Email" category. */
BLE_ANCS_CATEGORY_ID_NEWS, /**< The iOS notification belongs to the "News" category. */
BLE_ANCS_CATEGORY_ID_HEALTH_AND_FITNESS, /**< The iOS notification belongs to the "Health and Fitness" category. */
BLE_ANCS_CATEGORY_ID_BUSINESS_AND_FINANCE, /**< The iOS notification belongs to the "Business and Finance" category. */
BLE_ANCS_CATEGORY_ID_LOCATION, /**< The iOS notification belongs to the "Location" category. */
BLE_ANCS_CATEGORY_ID_ENTERTAINMENT /**< The iOS notification belongs to the "Entertainment" category. */
} ble_ancs_c_category_id_val_t;
/**@brief Event IDs for iOS notifications. */
typedef enum
{
BLE_ANCS_EVENT_ID_NOTIFICATION_ADDED, /**< The iOS notification was added. */
BLE_ANCS_EVENT_ID_NOTIFICATION_MODIFIED, /**< The iOS notification was modified. */
BLE_ANCS_EVENT_ID_NOTIFICATION_REMOVED /**< The iOS notification was removed. */
} ble_ancs_c_evt_id_values_t;
/**@brief Control point command IDs that the Notification Consumer can send to the Notification Provider. */
typedef enum
{
BLE_ANCS_COMMAND_ID_GET_NOTIF_ATTRIBUTES, /**< Requests attributes to be sent from the NP to the NC for a given notification. */
BLE_ANCS_COMMAND_ID_GET_APP_ATTRIBUTES, /**< Requests attributes to be sent from the NP to the NC for a given iOS app. */
BLE_ANCS_COMMAND_ID_GET_PERFORM_NOTIF_ACTION, /**< Requests an action to be performed on a given notification. For example, dismiss an alarm. */
} ble_ancs_c_cmd_id_val_t;
/**@brief IDs for actions that can be performed for iOS notifications. */
typedef enum
{
ACTION_ID_POSITIVE = 0, /**< Positive action. */
ACTION_ID_NEGATIVE /**< Negative action. */
} ble_ancs_c_action_id_values_t;
/**@brief App attribute ID values.
* @details Currently, only one value is defined. However, the number of app
* attributes might increase. For this reason, they are stored in an enumeration.
*/
typedef enum
{
BLE_ANCS_APP_ATTR_ID_DISPLAY_NAME = 0 /**< Command used to get the display name for an app identifier. */
} ble_ancs_c_app_attr_id_val_t;
/**@brief IDs for iOS notification attributes. */
typedef enum
{
BLE_ANCS_NOTIF_ATTR_ID_APP_IDENTIFIER = 0, /**< Identifies that the attribute data is of an "App Identifier" type. */
BLE_ANCS_NOTIF_ATTR_ID_TITLE, /**< Identifies that the attribute data is a "Title". */
BLE_ANCS_NOTIF_ATTR_ID_SUBTITLE, /**< Identifies that the attribute data is a "Subtitle". */
BLE_ANCS_NOTIF_ATTR_ID_MESSAGE, /**< Identifies that the attribute data is a "Message". */
BLE_ANCS_NOTIF_ATTR_ID_MESSAGE_SIZE, /**< Identifies that the attribute data is a "Message Size". */
BLE_ANCS_NOTIF_ATTR_ID_DATE, /**< Identifies that the attribute data is a "Date". */
BLE_ANCS_NOTIF_ATTR_ID_POSITIVE_ACTION_LABEL, /**< The notification has a "Positive action" that can be executed associated with it. */
BLE_ANCS_NOTIF_ATTR_ID_NEGATIVE_ACTION_LABEL, /**< The notification has a "Negative action" that can be executed associated with it. */
} ble_ancs_c_notif_attr_id_val_t;
/**@brief Flags for iOS notifications. */
typedef struct
{
uint8_t silent : 1; //!< If this flag is set, the notification has a low priority.
uint8_t important : 1; //!< If this flag is set, the notification has a high priority.
uint8_t pre_existing : 1; //!< If this flag is set, the notification is pre-existing.
uint8_t positive_action : 1; //!< If this flag is set, the notification has a positive action that can be taken.
uint8_t negative_action : 1; //!< If this flag is set, the notification has a negative action that can be taken.
} ble_ancs_c_notif_flags_t;
/**@brief Parsing states for received iOS notification and app attributes. */
typedef enum
{
COMMAND_ID, /**< Parsing the command ID. */
NOTIF_UID, /**< Parsing the notification UID. */
APP_ID, /**< Parsing app ID. */
ATTR_ID, /**< Parsing attribute ID. */
ATTR_LEN1, /**< Parsing the LSB of the attribute length. */
ATTR_LEN2, /**< Parsing the MSB of the attribute length. */
ATTR_DATA, /**< Parsing the attribute data. */
ATTR_SKIP, /**< Parsing is skipped for the rest of an attribute (or entire attribute). */
DONE, /**< Parsing for one attribute is done. */
} ble_ancs_c_parse_state_t;
/**@brief iOS notification structure. */
typedef struct
{
uint32_t notif_uid; //!< Notification UID.
ble_ancs_c_evt_id_values_t evt_id; //!< Whether the notification was added, removed, or modified.
ble_ancs_c_notif_flags_t evt_flags; //!< Bitmask to signal whether a special condition applies to the notification. For example, "Silent" or "Important".
ble_ancs_c_category_id_val_t category_id; //!< Classification of the notification type. For example, email or location.
uint8_t category_count; //!< Current number of active notifications for this category ID.
} ble_ancs_c_evt_notif_t;
/**@brief iOS attribute structure. This type is used for both notification attributes and app attributes. */
typedef struct
{
uint16_t attr_len; //!< Length of the received attribute data.
uint32_t attr_id; //!< Classification of the attribute type. For example, "Title" or "Date".
uint8_t * p_attr_data; //!< Pointer to where the memory is allocated for storing incoming attributes.
} ble_ancs_c_attr_t;
/**@brief iOS notification attribute structure for incoming attributes. */
typedef struct
{
uint32_t notif_uid; //!< UID of the notification that the attribute belongs to.
ble_ancs_c_attr_t attrs; //!< A received attribute.
} ble_ancs_c_evt_attr_t;
typedef struct
{
uint16_t attr_len; //!< Length of the received attribute data.
uint32_t attr_id; //!< Classification of the attribute type. For example, "Title" or "Date".
uint8_t * p_attr_data; //!< Pointer to where the memory is allocated for storing incoming attributes.
} ble_ancs_c_evt_app_attr_t;
/**@brief iOS notification attribute content requested by the application. */
typedef struct
{
bool get; //!< Boolean to determine whether this attribute will be requested from the Notification Provider.
uint32_t attr_id; //!< Attribute ID: AppIdentifier(0), Title(1), Subtitle(2), Message(3), MessageSize(4), Date(5), PositiveActionLabel(6), NegativeActionLabel(7).
uint16_t attr_len; //!< Length of the attribute. If more data is received from the Notification Provider, all the data beyond this length is discarded.
uint8_t * p_attr_data; //!< Pointer to where the memory is allocated for storing incoming attributes.
} ble_ancs_c_attr_list_t;
/**@brief Structure used for holding the Apple Notification Center Service found during the
discovery process.
*/
typedef struct
{
ble_gattc_service_t service; //!< The GATT Service holding the discovered Apple Notification Center Service. (0xF431).
ble_gattc_char_t control_point_char; //!< ANCS Control Point Characteristic. Allows interaction with the peer (0xD8F3).
ble_gattc_char_t notif_source_char; //!< ANCS Notification Source Characteristic. Keeps track of arrival, modification, and removal of notifications (0x120D).
ble_gattc_desc_t notif_source_cccd; //!< ANCS Notification Source Characteristic Descriptor. Enables or disables GATT notifications.
ble_gattc_char_t data_source_char; //!< ANCS Data Source Characteristic, where attribute data for the notifications is received from peer (0xC6E9).
ble_gattc_desc_t data_source_cccd; //!< ANCS Data Source Characteristic Descriptor. Enables or disables GATT notifications.
} ble_ancs_c_service_t;
/**@brief ANCS client module event structure.
*
* @details The structure contains the event that is to be handled by the main application.
*/
typedef struct
{
ble_ancs_c_evt_type_t evt_type; //!< Type of event.
uint16_t conn_handle; //!< Connection handle on which the ANCS service was discovered on the peer device. This is filled if the @p evt_type is @ref BLE_ANCS_C_EVT_DISCOVERY_COMPLETE.
ble_ancs_c_evt_notif_t notif; //!< iOS notification. This is filled if @p evt_type is @ref BLE_ANCS_C_EVT_NOTIF.
uint16_t err_code_np; //!< An error coming from the Notification Provider. This is filled with @ref BLE_ANCS_NP_ERROR_CODES if @p evt_type is @ref BLE_ANCS_C_EVT_NP_ERROR.
ble_ancs_c_attr_t attr; //!< iOS notification attribute or app attribute, depending on the event type.
uint32_t notif_uid; //!< Notification UID.
uint8_t app_id[BLE_ANCS_ATTR_DATA_MAX]; //!< App identifier.
ble_ancs_c_service_t service; //!< Information on the discovered Alert Notification Service. This is filled if the @p evt_type is @ref BLE_ANCS_C_EVT_DISCOVERY_COMPLETE.
} ble_ancs_c_evt_t;
/**@brief iOS notification event handler type. */
typedef void (*ble_ancs_c_evt_handler_t) (ble_ancs_c_evt_t * p_evt);
typedef struct
{
ble_ancs_c_attr_list_t * p_attr_list; //!< The current list of attributes that are being parsed. This will point to either @ref ble_ancs_c_t::ancs_notif_attr_list or @ref ble_ancs_c_t::ancs_app_attr_list.
uint32_t nb_of_attr; //!< Number of possible attributes. When parsing begins, it is set to either @ref BLE_ANCS_NB_OF_NOTIF_ATTR or @ref BLE_ANCS_NB_OF_APP_ATTR.
uint32_t expected_number_of_attrs; //!< The number of attributes expected upon receiving attributes. Keeps track of when to stop reading incoming attributes.
ble_ancs_c_parse_state_t parse_state; //!< ANCS notification attribute parsing state.
ble_ancs_c_cmd_id_val_t command_id; //!< Variable to keep track of what command type is being parsed ( @ref BLE_ANCS_COMMAND_ID_GET_NOTIF_ATTRIBUTES or @ref BLE_ANCS_COMMAND_ID_GET_APP_ATTRIBUTES).
uint8_t * p_data_dest; //!< Attribute that the parsed data is copied into.
uint16_t current_attr_index; //!< Variable to keep track of the parsing progress, for the given attribute.
uint32_t current_app_id_index; //!< Variable to keep track of the parsing progress, for the given app identifier.
} ble_ancs_parse_sm_t;
/**@brief iOS notification structure, which contains various status information for the client. */
typedef struct
{
ble_ancs_c_evt_handler_t evt_handler; //!< Event handler to be called for handling events in the Apple Notification client application.
ble_srv_error_handler_t error_handler; //!< Function to be called in case of an error.
nrf_ble_gq_req_error_cb_t gatt_err_handler; //!< Error handler to be called in case of an error from SoftDevice.
uint16_t conn_handle; //!< Handle of the current connection. Set with @ref nrf_ble_ancs_c_handles_assign when connected.
ble_ancs_c_service_t service; //!< Structure to store the different handles and UUIDs related to the service.
ble_ancs_c_attr_list_t ancs_notif_attr_list[BLE_ANCS_NB_OF_NOTIF_ATTR]; //!< For all attributes: contains information about whether the attributes are to be requested upon attribute request, and the length and buffer of where to store attribute data.
ble_ancs_c_attr_list_t ancs_app_attr_list[BLE_ANCS_NB_OF_APP_ATTR]; //!< For all app attributes: contains information about whether the attributes are to be requested upon attribute request, and the length and buffer of where to store attribute data.
uint32_t number_of_requested_attr; //!< The number of attributes that are to be requested when an iOS notification attribute request is made.
ble_ancs_parse_sm_t parse_info; //!< Structure containing different information used to parse incoming attributes correctly (from data_source characteristic).
ble_ancs_c_evt_t evt; //!< Allocate memory for the event here. The event is filled with several iterations of the @ref ancs_parse_get_attrs_response function when requesting iOS notification attributes.
nrf_ble_gq_t * p_gatt_queue; //!< Pointer to the BLE GATT Queue instance.
} ble_ancs_c_t;
/**@brief Apple Notification client init structure, which contains all options and data needed for
* initialization of the client. */
typedef struct
{
ble_ancs_c_evt_handler_t evt_handler; //!< Event handler to be called for handling events in the Battery Service.
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 the BLE GATT Queue instance.
} ble_ancs_c_init_t;
/**@brief Apple Notification Center Service UUIDs. */
extern const ble_uuid128_t ble_ancs_base_uuid128; //!< Service UUID.
extern const ble_uuid128_t ble_ancs_cp_base_uuid128; //!< Control Point UUID.
extern const ble_uuid128_t ble_ancs_ns_base_uuid128; //!< Notification Source UUID.
extern const ble_uuid128_t ble_ancs_ds_base_uuid128; //!< Data Source UUID.
/**@brief Function for handling BLE stack events of the application.
*
* @details Handles all events from the BLE stack that are of interest to the ANCS client.
*
* @param[in] p_ble_evt Event received from the BLE stack.
* @param[in] p_context ANCS client structure.
*/
void ble_ancs_c_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context);
/**@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 ANCS at the peer. If it does, this function
* calls the application's event handler to indicate that ANCS was
* discovered at the peer. The function also populates the event with service-related
* information before providing it to the application.
*
* @param[in] p_ancs Pointer to the ANCS client structure.
* @param[in] p_evt Pointer to the event received from the Database Discovery module.
*/
void ble_ancs_c_on_db_disc_evt(ble_ancs_c_t * p_ancs, ble_db_discovery_evt_t * p_evt);
/**@brief Function for initializing the ANCS client.
*
* @param[out] p_ancs ANCS client structure. This structure must be
* supplied by the application. It is initialized by this function
* and will later be used to identify this particular client instance.
* @param[in] p_ancs_init Information needed to initialize the client.
*
* @retval NRF_SUCCESS If the client was initialized successfully. Otherwise, an error code is returned.
*/
ret_code_t ble_ancs_c_init(ble_ancs_c_t * p_ancs, ble_ancs_c_init_t const * p_ancs_init);
/**@brief Function for writing to the CCCD to enable notifications from the Apple Notification Service.
*
* @param[in] p_ancs iOS notification structure. This structure must be supplied by
* the application. It identifies the particular client instance to use.
*
* @retval NRF_SUCCESS If writing to the CCCD was successful. Otherwise,
* this API propagates the error code returned by function
* @ref nrf_ble_gq_item_add.
*/
ret_code_t ble_ancs_c_notif_source_notif_enable(ble_ancs_c_t const * p_ancs);
/**@brief Function for writing to the CCCD to enable data source notifications from the ANCS.
*
* @param[in] p_ancs iOS notification structure. This structure must be supplied by
* the application. It identifies the particular client instance to use.
*
* @retval NRF_SUCCESS If writing to the CCCD was successful. Otherwise,
* this API propagates the error code returned by function
* @ref nrf_ble_gq_item_add.
*/
ret_code_t ble_ancs_c_data_source_notif_enable(ble_ancs_c_t const * p_ancs);
/**@brief Function for writing to the CCCD to disable notifications from the ANCS.
*
* @param[in] p_ancs iOS notification structure. This structure must be supplied by
* the application. It identifies the particular client instance to use.
*
* @retval NRF_SUCCESS If writing to the CCCD was successful. Otherwise
* this API propagates the error code returned by function
* @ref nrf_ble_gq_item_add.
*/
ret_code_t ble_ancs_c_notif_source_notif_disable(ble_ancs_c_t const * p_ancs);
/**@brief Function for writing to the CCCD to disable data source notifications from the ANCS.
*
* @param[in] p_ancs iOS notification structure. This structure must be supplied by
* the application. It identifies the particular client instance to use.
*
* @retval NRF_SUCCESS If writing to the CCCD was successful. Otherwise,
* this API propagates the error code returned by function
* @ref nrf_ble_gq_item_add.
*/
ret_code_t ble_ancs_c_data_source_notif_disable(ble_ancs_c_t const * p_ancs);
/**@brief Function for registering attributes that will be requested when @ref nrf_ble_ancs_c_request_attrs
* is called.
*
* @param[in] p_ancs ANCS client instance on which the attribute is registered.
* @param[in] id ID of the attribute that is added.
* @param[in] p_data Pointer to the buffer where the data of the attribute can be stored.
* @param[in] len Length of the buffer where the data of the attribute can be stored.
* @retval NRF_SUCCESS If all operations are successful. Otherwise, an error code is returned.
*/
ret_code_t nrf_ble_ancs_c_attr_add(ble_ancs_c_t * p_ancs,
ble_ancs_c_notif_attr_id_val_t const id,
uint8_t * p_data,
uint16_t const len);
/**@brief Function for removing attributes, so that they are no longer requested when
* @ref nrf_ble_ancs_c_request_attrs is called.
*
* @param[in] p_ancs ANCS client instance on which the attribute is removed.
* @param[in] id ID of the attribute that is removed.
*
* @retval NRF_SUCCESS If all operations are successful. Otherwise, an error code is returned.
*/
ret_code_t nrf_ble_ancs_c_attr_remove(ble_ancs_c_t * p_ancs,
ble_ancs_c_notif_attr_id_val_t const id);
/**@brief Function for removing attributes, so that they are no longer requested when
* @ref nrf_ble_ancs_c_app_attr_request is called.
*
* @param[in] p_ancs ANCS client instance on which the attribute is removed.
* @param[in] id ID of the attribute that is removed.
*
* @retval NRF_SUCCESS If all operations are successful. Otherwise, an error code is returned.
*/
ret_code_t nrf_ble_ancs_c_app_attr_remove(ble_ancs_c_t * p_ancs,
ble_ancs_c_app_attr_id_val_t const id);
/**@brief Function for registering attributes that will be requested when @ref nrf_ble_ancs_c_app_attr_request
* is called.
*
* @param[in] p_ancs ANCS client instance on which the attribute is registered.
* @param[in] id ID of the attribute that is added.
* @param[in] p_data Pointer to the buffer where the data of the attribute can be stored.
* @param[in] len Length of the buffer where the data of the attribute can be stored.
*
* @retval NRF_SUCCESS If all operations are successful. Otherwise, an error code is returned.
*/
ret_code_t nrf_ble_ancs_c_app_attr_add(ble_ancs_c_t * p_ancs,
ble_ancs_c_app_attr_id_val_t const id,
uint8_t * p_data,
uint16_t const len);
/**@brief Function for clearing the list of notification attributes and app attributes that
* would be requested from NP.
*
* @param[in] p_ancs iOS notification structure. This structure must be supplied by
* the application. It identifies the particular client instance to use.
**/
ret_code_t nrf_ble_ancs_c_attr_req_clear_all(ble_ancs_c_t * p_ancs);
/**@brief Function for requesting attributes for a notification.
*
* @param[in] p_ancs iOS notification structure. This structure must be supplied by
* the application. It identifies the particular client instance to use.
* @param[in] p_notif Pointer to the notification whose attributes will be requested from
* the Notification Provider.
*
* @retval NRF_SUCCESS If all operations are successful. Otherwise, an error code is returned.
*/
ret_code_t nrf_ble_ancs_c_request_attrs(ble_ancs_c_t * p_ancs,
ble_ancs_c_evt_notif_t const * p_notif);
/**@brief Function for requesting attributes for a given app.
*
* @param[in] p_ancs iOS notification structure. This structure must be supplied by
* the application. It identifies the particular client instance to use.
* @param[in] p_app_id App identifier of the app for which the app attributes are requested.
* @param[in] len Length of the app identifier.
*
* @retval NRF_SUCCESS If all operations are successful. Otherwise, an error code is returned.
*/
ret_code_t nrf_ble_ancs_c_app_attr_request(ble_ancs_c_t * p_ancs,
uint8_t const * p_app_id,
uint32_t len);
/**@brief Function for performing a notification action.
*
* @param[in] p_ancs iOS notification structure. This structure must be supplied by
* the application. It identifies the particular client instance to use.
* @param[in] uuid The UUID of the notification for which to perform the action.
* @param[in] action_id Perform a positive or negative action.
*
* @retval NRF_SUCCESS If the operation is successful.
* @retval NRF_ERROR_NULL If @p p_ancs is a NULL pointer.
* @retval err_code Otherwise, this API propagates the error code returned by function
* @ref nrf_ble_gq_item_add.
*/
ret_code_t nrf_ancs_perform_notif_action(ble_ancs_c_t * p_ancs,
uint32_t uuid,
ble_ancs_c_action_id_values_t action_id);
/**@brief Function for assigning a handle to this instance of ancs_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_ANCS_C_EVT_DISCOVERY_COMPLETE.
*
* @param[in] p_ancs Pointer to the ANCS client structure instance for associating the link.
* @param[in] conn_handle Connection handle to associated with the given ANCS instance.
* @param[in] p_service Attribute handles on the ANCS server that you want this ANCS client to
* interact with.
*
* @retval NRF_SUCCESS If the operation is successful.
* @retval NRF_ERROR_NULL If @p p_ancs is a NULL pointer.
* @retval err_code Otherwise, this API propagates the error code returned by function
* @ref nrf_ble_gq_conn_handle_register.
*/
ret_code_t nrf_ble_ancs_c_handles_assign(ble_ancs_c_t * p_ancs,
uint16_t const conn_handle,
ble_ancs_c_service_t const * p_service);
#ifdef __cplusplus
}
#endif
#endif // BLE_ANCS_C_H__
/** @} */