From 3061ecca3d0fdfb87dabbf5f63c9e06c2a30f53a Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Thu, 23 Aug 2018 17:08:59 +0200 Subject: o Initial import. --- .../ble_services/ble_ancs_c/ancs_app_attr_get.c | 367 ++++++++++++ .../ble_services/ble_ancs_c/ancs_app_attr_get.h | 66 +++ .../ble/ble_services/ble_ancs_c/ancs_attr_parser.c | 392 +++++++++++++ .../ble/ble_services/ble_ancs_c/ancs_attr_parser.h | 77 +++ .../ble/ble_services/ble_ancs_c/ancs_tx_buffer.c | 113 ++++ .../ble/ble_services/ble_ancs_c/ancs_tx_buffer.h | 103 ++++ .../ble/ble_services/ble_ancs_c/nrf_ble_ancs_c.c | 652 +++++++++++++++++++++ .../ble/ble_services/ble_ancs_c/nrf_ble_ancs_c.h | 604 +++++++++++++++++++ 8 files changed, 2374 insertions(+) create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_app_attr_get.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_app_attr_get.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_attr_parser.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_attr_parser.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_tx_buffer.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_tx_buffer.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/nrf_ble_ancs_c.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/nrf_ble_ancs_c.h (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c') diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_app_attr_get.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_app_attr_get.c new file mode 100644 index 0000000..38ed510 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_app_attr_get.c @@ -0,0 +1,367 @@ +/** + * Copyright (c) 2016 - 2018, 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 "ancs_tx_buffer.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 Size. */ + + +#define ANCS_GATTC_WRITE_PAYLOAD_LEN_MAX (BLE_GATT_ATT_MTU_DEFAULT - GATTC_OPCODE_SIZE - GATTC_ATTR_HANDLE_SIZE) /**< Maximum Length of the data we can send in one write. */ + + +/**@brief Enum to keep 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 determening if an attribute is desired to get. + * + * @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 be 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 Attribute. + * + * @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 Attribute. +*/ +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] conn_handle Connection handle for where the prepared write will be executed. + * @param[in] handle_value The handle that will receive 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_msg Pointer to the tx message that has been filled out and will be added to + * tx queue in this function. + */ +static void queued_write_tx_message(uint16_t conn_handle, + uint16_t handle_value, + uint16_t * p_offset, + uint32_t * p_index, + tx_message_t * p_msg) +{ + NRF_LOG_DEBUG("Starting new TX message."); + + p_msg->conn_handle = conn_handle; + p_msg->type = WRITE_REQ; + p_msg->req.write_req.gattc_params.len = *p_index; + p_msg->req.write_req.gattc_params.handle = handle_value; + p_msg->req.write_req.gattc_params.p_value = p_msg->req.write_req.gattc_value; + + p_msg->req.write_req.gattc_params.offset = *p_offset; + + p_msg->req.write_req.gattc_params.write_op = BLE_GATT_OP_PREP_WRITE_REQ; + + tx_buffer_insert(p_msg); +} + + +/**@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] 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_msg Pointer to the tx message that will be filled out in this function. + */ +static encode_app_attr_t app_attr_encode_cmd_id(ble_ancs_c_t * p_ancs, + uint32_t * index, + tx_message_t * p_msg) +{ + NRF_LOG_DEBUG("Encoding Command ID"); + + // Encode Command ID. + p_msg->req.write_req.gattc_value[(*index)++] = BLE_ANCS_COMMAND_ID_GET_APP_ATTRIBUTES; + return APP_ATTR_APP_ID; +} + +/**@brief Function for encoding the App Identifier 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 for the App which we will request App Attributes for. + * @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_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 will continue. + */ +static encode_app_attr_t app_attr_encode_app_id(ble_ancs_c_t * p_ancs, + uint32_t * p_index, + uint16_t * p_offset, + tx_message_t * p_msg, + const uint8_t * p_app_id, + const uint32_t app_id_len, + uint32_t * p_app_id_bytes_encoded_count) +{ + NRF_LOG_DEBUG("Encoding APP ID"); + if (*p_index >= ANCS_GATTC_WRITE_PAYLOAD_LEN_MAX) + { + queued_write_tx_message(p_ancs->conn_handle, p_ancs->service.control_point_char.handle_value, p_offset, p_index, p_msg); + *(p_offset) += *p_index; + *p_index = 0; + } + + //Encode App Identifier. + if (*p_app_id_bytes_encoded_count == app_id_len) + { + p_msg->req.write_req.gattc_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_msg->req.write_req.gattc_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 + * + * @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_msg Pointer to the tx message that will be filled out in this function. + * @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, + tx_message_t * p_msg, + uint32_t * p_attr_count, + uint32_t * attr_get_total_nb) +{ + NRF_LOG_DEBUG("Encoding Attribute ID"); + if ((*p_index) >= ANCS_GATTC_WRITE_PAYLOAD_LEN_MAX) + { + queued_write_tx_message(p_ancs->conn_handle, + p_ancs->service.control_point_char.handle_value, + p_offset, p_index, p_msg); + *(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_msg->req.write_req.gattc_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] conn_handle Connection handle for where the prepared write will be executed. + * @param[in] handle_value The handle that will receive the execute command. + * @param[in] p_msg Pointer to the message that will be filled out in this function and then + * added to the tx queue. + */ +static void app_attr_execute_write(uint16_t conn_handle, uint16_t handle_value, tx_message_t * p_msg) +{ + NRF_LOG_DEBUG("Sending Execute Write."); + memset(p_msg,0,sizeof(tx_message_t)); + + p_msg->req.write_req.gattc_params.handle = handle_value; + p_msg->req.write_req.gattc_params.p_value = p_msg->req.write_req.gattc_value; + p_msg->req.write_req.gattc_params.offset = 0; + p_msg->req.write_req.gattc_params.write_op = BLE_GATT_OP_EXEC_WRITE_REQ; + p_msg->req.write_req.gattc_params.flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE; + + p_msg->req.write_req.gattc_params.len = 0; + p_msg->conn_handle = conn_handle; + p_msg->type = WRITE_REQ; + + tx_buffer_insert(p_msg); +} + + +/**@brief Function for sending a get App Attributes request. + * + * @details Since the APP id may not fit in a single write, we use long write + * with a state machine to encode the Get App Attribute 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 for the App which we will request App Attributes for. + * @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; + p_ancs->number_of_requested_attr = 0; + + uint32_t attr_get_total_nb = app_attr_nb_to_get(p_ancs); + tx_message_t p_msg; + + memset(&p_msg, 0, sizeof(tx_message_t)); + + while (state != APP_ATTR_DONE) + { + switch (state) + { + case APP_ATTR_COMMAND_ID: + state = app_attr_encode_cmd_id(p_ancs, + &index, + &p_msg); + break; + case APP_ATTR_APP_ID: + state = app_attr_encode_app_id(p_ancs, + &index, + &offset, + &p_msg, + 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, + &p_msg, + &attr_bytes_encoded_count, + &attr_get_total_nb); + break; + case APP_ATTR_DONE: + break; + default: + break; + } + } + queued_write_tx_message(p_ancs->conn_handle, + p_ancs->service.control_point_char.handle_value, + &offset, + &index, + &p_msg); + + app_attr_execute_write(p_ancs->conn_handle, + p_ancs->service.control_point_char.handle_value, + &p_msg); + + p_ancs->parse_info.expected_number_of_attrs = p_ancs->number_of_requested_attr; + + tx_buffer_process(); + return NRF_SUCCESS; +} + + +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 requestes 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; +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_app_attr_get.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_app_attr_get.h new file mode 100644 index 0000000..c942f73 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_app_attr_get.h @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2012 - 2018, 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 + * @{ + */ + +/**@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__ + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_attr_parser.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_attr_parser.c new file mode 100644 index 0000000..60f18e0 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_attr_parser.c @@ -0,0 +1,392 @@ +/** + * Copyright (c) 2016 - 2018, 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; + } + } +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_attr_parser.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_attr_parser.h new file mode 100644 index 0000000..92cea55 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_attr_parser.h @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2012 - 2018, 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__ + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_tx_buffer.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_tx_buffer.c new file mode 100644 index 0000000..91e6886 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_tx_buffer.c @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2016 - 2018, 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_tx_buffer.h" + #include "sdk_macros.h" + #include "nrf_log.h" + #include "string.h" + + +static tx_message_t m_tx_buffer[TX_BUFFER_SIZE]; /**< Transmit buffer for messages to be transmitted to the Notification Provider. */ +static uint32_t m_tx_insert_index = 0; /**< Current index in the transmit buffer where the next message should be inserted. */ +static uint32_t m_tx_index = 0; /**< Current index in the transmit buffer from where the next message to be transmitted resides. */ + + +void tx_buffer_init(void) +{ + memset(m_tx_buffer, 0, sizeof(m_tx_buffer)); +} + + +void tx_buffer_insert(tx_message_t * p_msg) +{ + + memset(&(m_tx_buffer[m_tx_insert_index]), 0, sizeof(m_tx_buffer)/sizeof(tx_message_t)); + + m_tx_buffer[m_tx_insert_index].conn_handle = p_msg->conn_handle; + m_tx_buffer[m_tx_insert_index].type = p_msg->type; + + m_tx_buffer[m_tx_insert_index].req.write_req.gattc_params.handle = p_msg->req.write_req.gattc_params.handle; + m_tx_buffer[m_tx_insert_index].req.write_req.gattc_params.len = p_msg->req.write_req.gattc_params.len; + m_tx_buffer[m_tx_insert_index].req.write_req.gattc_params.write_op = p_msg->req.write_req.gattc_params.write_op; + m_tx_buffer[m_tx_insert_index].req.write_req.gattc_params.flags = p_msg->req.write_req.gattc_params.flags; + m_tx_buffer[m_tx_insert_index].req.write_req.gattc_params.p_value = m_tx_buffer[m_tx_insert_index].req.write_req.gattc_value; + m_tx_buffer[m_tx_insert_index].req.write_req.gattc_params.offset = p_msg->req.write_req.gattc_params.offset; + + if (p_msg->type == WRITE_REQ) + { + memcpy(m_tx_buffer[m_tx_insert_index].req.write_req.gattc_value, + p_msg->req.write_req.gattc_value, + WRITE_MESSAGE_LENGTH); + } + + m_tx_insert_index++; + m_tx_insert_index &= TX_BUFFER_MASK; +} + + + +void tx_buffer_process(void) +{ + if (m_tx_index != m_tx_insert_index) + { + uint32_t err_code; + + if (m_tx_buffer[m_tx_index].type == READ_REQ) + { + err_code = sd_ble_gattc_read(m_tx_buffer[m_tx_index].conn_handle, + m_tx_buffer[m_tx_index].req.read_handle, + 0); + } + else + { + err_code = sd_ble_gattc_write(m_tx_buffer[m_tx_index].conn_handle, + &m_tx_buffer[m_tx_index].req.write_req.gattc_params); + } + if (err_code == NRF_SUCCESS) + { + ++m_tx_index; + m_tx_index &= TX_BUFFER_MASK; + } + } +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_tx_buffer.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_tx_buffer.h new file mode 100644 index 0000000..6953438 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/ancs_tx_buffer.h @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2012 - 2018, 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_TX_BUFFER_H__ +#define ANCS_TX_BUFFER_H__ + +#include "nrf_ble_ancs_c.h" + +/** @file + * + * @addtogroup ble_ancs_c + * @{ + */ + +#define TX_BUFFER_MASK 0x07 //!< TX buffer mask. Must be a mask of contiguous zeroes followed by a contiguous sequence of ones: 000...111. +#define TX_BUFFER_SIZE (TX_BUFFER_MASK + 1) //!< Size of the send buffer, which is 1 bigger than the mask. +#define WRITE_MESSAGE_LENGTH 20 //!< Length of the write message for the CCCD/control point. + +/**@brief ANCS request types. + */ +typedef enum +{ + READ_REQ = 1, /**< Type identifying that this TX message is a read request. */ + WRITE_REQ /**< Type identifying that this TX message is a write request. */ +} tx_request_t; + + +/**@brief Structure for writing a message to the central, thus the Control Point or CCCD. + */ +typedef struct +{ + uint8_t gattc_value[WRITE_MESSAGE_LENGTH]; //!< The message to write. + ble_gattc_write_params_t gattc_params; //!< GATTC parameters for this message. +} write_params_t; + + +/**@brief Data to be transmitted to the connected master. + */ +typedef struct +{ + uint16_t conn_handle; //!< Connection handle to be used when transmitting this message. + tx_request_t type; //!< Type of this message (read or write message). + union + { + uint16_t read_handle; //!< Read request message. + write_params_t write_req; //!< Write request message. + } req; +} tx_message_t; + +/**@brief Function for clearing the TX buffer. + * + * @details Always call this function before using the TX buffer. +*/ +void tx_buffer_init(void); + +/**@brief Function for moving the pointer of the ring buffer to the next element. +*/ +void tx_buffer_insert(tx_message_t * p_msg); + +/**@brief Function for passing any pending request from the buffer to the stack. +*/ +void tx_buffer_process(void); + +/** @} */ + +#endif // ANCS_TX_BUFFER_H__ + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/nrf_ble_ancs_c.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/nrf_ble_ancs_c.c new file mode 100644 index 0000000..0ba177f --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/nrf_ble_ancs_c.c @@ -0,0 +1,652 @@ +/** + * Copyright (c) 2012 - 2018, 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_tx_buffer.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 patsin notifications. */ + +#define BLE_CCCD_NOTIFY_BIT_MASK 0x0001 /**< Enable 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 handling Disconnected event received from the SoftDevice. + * + * @details This function check if the disconnect event is happening on the link + * associated with the current instance of the module, if so it will set its + * conn_handle 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 if 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; + p_ancs->evt_handler(&evt); + } + else + { + evt.evt_type = BLE_ANCS_C_EVT_DISCOVERY_FAILED; + p_ancs->evt_handler(&evt); + } +} + + +/**@brief Function for checking if 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 data that was received from the Notification Provider. + * @param[in] hvx_len Length of the data that was received by 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 bond */ + 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_c Pointer to the Battery Service Client Structure. + * @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_c Pointer to the Battery Service Client Structure. + * @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 if 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); + } + // Check if there is any message to be sent across to the peer and send it. + tx_buffer_process(); +} + + +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 to initialize 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->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 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)); + tx_buffer_init(); + + // 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] conn_handle Connection handle on which to perform the configuration. + * @param[in] handle_cccd Handle of the CCCD. + * @param[in] enable Enable or disable GATTC notifications. + * + * @retval NRF_SUCCESS If the message was created successfully. + * @retval NRF_ERROR_INVALID_PARAM If one of the input parameters was invalid. + */ +static uint32_t cccd_configure(const uint16_t conn_handle, const uint16_t handle_cccd, bool enable) +{ + tx_message_t p_msg; + memset(&p_msg, 0, sizeof(tx_message_t)); + uint16_t cccd_val = enable ? BLE_CCCD_NOTIFY_BIT_MASK : 0; + + p_msg.req.write_req.gattc_params.handle = handle_cccd; + p_msg.req.write_req.gattc_params.len = 2; + p_msg.req.write_req.gattc_params.p_value = p_msg.req.write_req.gattc_value; + p_msg.req.write_req.gattc_params.offset = 0; + p_msg.req.write_req.gattc_params.write_op = BLE_GATT_OP_WRITE_REQ; + p_msg.req.write_req.gattc_value[0] = LSB_16(cccd_val); + p_msg.req.write_req.gattc_value[1] = MSB_16(cccd_val); + p_msg.conn_handle = conn_handle; + p_msg.type = WRITE_REQ; + + tx_buffer_insert(&p_msg); + + tx_buffer_process(); + return NRF_SUCCESS; +} + + +ret_code_t ble_ancs_c_notif_source_notif_enable(ble_ancs_c_t const * p_ancs) +{ + NRF_LOG_INFO("Enable Notification Source notifications. writing to handle: %i ", + p_ancs->service.notif_source_cccd.handle); + return cccd_configure(p_ancs->conn_handle, 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->conn_handle, 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 Data Source notifications. Writing to handle: %i ", + p_ancs->service.data_source_cccd.handle); + return cccd_configure(p_ancs->conn_handle, 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->conn_handle, 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) +{ + tx_message_t p_msg; + memset(&p_msg, 0, sizeof(tx_message_t)); + + uint32_t index = 0; + p_ancs->number_of_requested_attr = 0; + + + p_msg.req.write_req.gattc_params.handle = p_ancs->service.control_point_char.handle_value; + p_msg.req.write_req.gattc_params.p_value = p_msg.req.write_req.gattc_value; + p_msg.req.write_req.gattc_params.offset = 0; + p_msg.req.write_req.gattc_params.write_op = BLE_GATT_OP_WRITE_REQ; + + //Encode Command ID. + p_msg.req.write_req.gattc_value[index++] = BLE_ANCS_COMMAND_ID_GET_NOTIF_ATTRIBUTES; + + //Encode Notification UID. + index += uint32_encode(p_uid, &(p_msg.req.write_req.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) + { + p_msg.req.write_req.gattc_value[index++] = 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, + &(p_msg.req.write_req.gattc_value[index])); + } + p_ancs->number_of_requested_attr++; + } + } + p_msg.req.write_req.gattc_params.len = index; + p_msg.conn_handle = p_ancs->conn_handle; + p_msg.type = WRITE_REQ; + p_ancs->parse_info.expected_number_of_attrs = p_ancs->number_of_requested_attr; + + tx_buffer_insert(&p_msg); + tx_buffer_process(); + + return NRF_SUCCESS; +} + + +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); + + tx_message_t msg; + memset(&msg, 0, sizeof(tx_message_t)); + + uint16_t len = encode_notif_action(msg.req.write_req.gattc_value, uid, action_id); + + msg.req.write_req.gattc_params.handle = p_ancs->service.control_point_char.handle_value; + msg.req.write_req.gattc_params.p_value = msg.req.write_req.gattc_value; + msg.req.write_req.gattc_params.offset = 0; + msg.req.write_req.gattc_params.write_op = BLE_GATT_OP_WRITE_REQ; + + msg.req.write_req.gattc_params.len = len; + msg.conn_handle = p_ancs->conn_handle; + msg.type = WRITE_REQ; + + tx_buffer_insert(&msg); + tx_buffer_process(); + + return NRF_SUCCESS; +} + +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_SUCCESS; +} + +#endif// NRF_MODULE_ENABLED(BLE_ANCS_C) diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/nrf_ble_ancs_c.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/nrf_ble_ancs_c.h new file mode 100644 index 0000000..550583e --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/ble_ancs_c/nrf_ble_ancs_c.h @@ -0,0 +1,604 @@ +/** + * Copyright (c) 2012 - 2018, 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 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 iOS notification is the data received from the Notification Provider. + * - A GATTC notification is a way to transfer data with Bluetooth Smart. + * In this module, we receive iOS notifications using GATTC notifications. + * We use the full term (iOS notification or GATTC notification) 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 using + * @ref ble_ancs_c_notif_source_notif_enable. They 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. They + * arrive in the @ref BLE_ANCS_C_EVT_NOTIF_ATTRIBUTE event. + * @ref nrf_ble_ancs_c_app_attr_request can be used to request attributes of the app that issued + * the notifications. They arrive in the @ref BLE_ANCS_C_EVT_APP_ATTRIBUTE event. + * @ref nrf_ancs_perform_notif_action can be used 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 BLE event observer 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" + +#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 does 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 "E-mail" 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 "Buisness 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. Therefore, 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 (or entire) of an 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 if 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 wanted by our application. */ +typedef struct +{ + bool get; //!< Boolean to determine if 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 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 should 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 field will be filled if the @p evt_type is @ref BLE_ANCS_C_EVT_DISCOVERY_COMPLETE. + ble_ancs_c_evt_notif_t notif; //!< iOS notification. This field will be 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 field will be 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 field will be 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 being parsed. This field 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 we are currently parsing ( @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 will be copied into. + uint16_t current_attr_index; //!< Variable to keep track of how much (for a given attribute) we are done parsing. + uint32_t current_app_id_index; //!< Variable to keep track of how much (for a given app identifier) we are done parsing. +} 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. + 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 whether they should 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 whether they should 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 will 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 (from data_source characteristic) correctly. + ble_ancs_c_evt_t evt; //!< The event is filled with several iterations of the @ref ancs_parse_get_attrs_response function when requesting iOS notification attributes. So we must allocate memory for it here. +} 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. +} 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 the application's BLE stack events. + * + * @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 will handle an event from the database discovery module and determine + * if it relates to the discovery of ANCS at the peer. If so, it will + * call the application's event handler indicating that ANCS has been + * discovered at the peer. It also populates the event with the 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, an error code is returned. + */ +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, an error code is returned. + */ +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, an error code is returned. + */ +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, an error code is returned. + */ +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 will be registered. + * @param[in] id ID of the attribute that will be added. + * @param[in] p_data Pointer to a 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 were 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 will no longer be requested when + * @ref nrf_ble_ancs_c_request_attrs is called. + * + * @param[in] p_ancs ANCS client instance on which the attribute will be removed. + * @param[in] id ID of the attribute that will be removed. + * + * @retval NRF_SUCCESS If all operations were 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 will no longer be requested when + * @ref nrf_ble_ancs_c_app_attr_request is called. + * + * @param[in] p_ancs ANCS client instance on which the attribute will be removed. + * @param[in] id ID of the attribute that will be removed. + * + * @retval NRF_SUCCESS If all operations were 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 will be registered. + * @param[in] id ID of the attribute that will be added. + * @param[in] p_data Pointer to a 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 were 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 were 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 were 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 was successful. + * @retval NRF_ERROR_NULL If @p p_ancs was a NULL pointer. + */ +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 this link to this instance of the module. This makes it + * possible to handle several link and associate each link to a particular + * instance of this module. The connection handle and attribute handles will be + * provided from the discovery event @ref BLE_ANCS_C_EVT_DISCOVERY_COMPLETE. + * + * @param[in] p_ancs Pointer to the ANCS client structure instance to associate with these + * handles. + * @param[in] conn_handle Connection handle to associate 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 was successful. + * @retval NRF_ERROR_NULL If @p p_ancs was a NULL pointer. + */ +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__ + +/** @} */ + -- cgit v1.2.3