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. --- .../experimental_ble_ots/ble_hvx_buffering.c | 102 ++++ .../experimental_ble_ots/ble_hvx_buffering.h | 104 ++++ .../ble_services/experimental_ble_ots/ble_ots.c | 249 +++++++++ .../ble_services/experimental_ble_ots/ble_ots.h | 472 ++++++++++++++++ .../experimental_ble_ots/ble_ots_l2cap.c | 437 +++++++++++++++ .../experimental_ble_ots/ble_ots_l2cap.h | 117 ++++ .../experimental_ble_ots/ble_ots_oacp.c | 606 +++++++++++++++++++++ .../experimental_ble_ots/ble_ots_oacp.h | 90 +++ .../experimental_ble_ots/ble_ots_object.c | 577 ++++++++++++++++++++ .../experimental_ble_ots/ble_ots_object.h | 86 +++ 10 files changed, 2840 insertions(+) create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_hvx_buffering.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_hvx_buffering.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_l2cap.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_l2cap.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_oacp.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_oacp.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_object.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_object.h (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots') diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_hvx_buffering.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_hvx_buffering.c new file mode 100644 index 0000000..80b3afc --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_hvx_buffering.c @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2017 - 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. + * + */ + +#include "ble_hvx_buffering.h" +#include + +uint32_t ble_hvx_init(ble_hvx_buf_t * p_ble_hvx_buf) +{ + if (p_ble_hvx_buf == NULL) + { + return NRF_ERROR_NULL; + } + + p_ble_hvx_buf->insert_index = 0; + p_ble_hvx_buf->read_index = 0; + + return NRF_SUCCESS; +} + +ble_hvx_t * ble_hvx_get_p_to_next_hvx(ble_hvx_buf_t * p_ble_hvx_buf) +{ + ble_hvx_t * p_hvx; + p_hvx = &p_ble_hvx_buf->buf[p_ble_hvx_buf->insert_index++]; + + p_hvx->params.p_data = p_hvx->data; + p_hvx->params.p_len = &p_hvx->data_len; + + p_ble_hvx_buf->insert_index &= BLE_HVX_BUF_MASK; + return p_hvx; +} + + +uint32_t ble_hvx_buffer_process(ble_hvx_buf_t * p_ble_hvx_buf) +{ + uint32_t err_code; + while (p_ble_hvx_buf->read_index != p_ble_hvx_buf->insert_index) + { + + ble_gatts_hvx_params_t * p_hvx_params; + + p_hvx_params = &p_ble_hvx_buf->buf[p_ble_hvx_buf->read_index].params; + err_code = sd_ble_gatts_hvx(p_ble_hvx_buf->buf[p_ble_hvx_buf->read_index].conn_handle, p_hvx_params); + + if (err_code == NRF_SUCCESS) + { + p_ble_hvx_buf->read_index++; + p_ble_hvx_buf->read_index &= BLE_HVX_BUF_MASK; + } + else + { + if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) + { + return NRF_SUCCESS; // not a critical error. + } + else + { + // remove element from buffer + p_ble_hvx_buf->insert_index--; + p_ble_hvx_buf->insert_index &= BLE_HVX_BUF_MASK; + return err_code; + } + } + } + return NRF_SUCCESS; +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_hvx_buffering.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_hvx_buffering.h new file mode 100644 index 0000000..005e123 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_hvx_buffering.h @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2017 - 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_sdk_srv_ots_buf Object Transfer Service, HVX buffering + * @{ + * @ingroup ble_ots + * @brief Object Transfer Service module + * + * @details This module is responsible for buffering indications and notifications. + */ + +#ifndef BLE_HVX_BUFFERING_H__ +#define BLE_HVX_BUFFERING_H__ + + +#include +#include "ble_types.h" +#include "ble_gatts.h" + +#define BLE_HVX_BUF_LEN (1 << 3) // 8 +#define BLE_HVX_BUF_MASK (BLE_HVX_BUF_LEN-1) + +/**@brief ble_hvx_t represents one notification/indication. */ +typedef struct { + uint16_t conn_handle; /**< The associated connection handle. */ + uint8_t data[BLE_GATT_ATT_MTU_DEFAULT]; /**< The hvx data. */ + uint16_t data_len; + ble_gatts_hvx_params_t params; /**< Parameters of the hvx. */ +} ble_hvx_t; + +/**@brief ble_hvx_buf_t is the structure holding the state of the hvx buffering module. */ +typedef struct { + ble_hvx_t buf[BLE_HVX_BUF_LEN]; /**< A buffer of nofications/indications. */ + + uint8_t insert_index; + uint8_t read_index; +} ble_hvx_buf_t; + +/**@brief Function for initializing the HVX buffer module. + * + * @param[out] p_ble_hvx_buf HVX buffering structure. + * @return NRF_SUCCESS If the given paramer is valid. + */ +uint32_t ble_hvx_init(ble_hvx_buf_t * p_ble_hvx_buf); + +/**@brief Function for obtaining the pointer to the next hvx. The user can then fill out the hvx structure. + * + * @param[in] p_ble_hvx_buf HVX buffering structure. + * @return ble_hvx_t * If there is a free ble_hvx_t. + * @return NULL If there is no free ble_hvx_t, or an invalid parameter is supplied. + */ +ble_hvx_t * ble_hvx_get_p_to_next_hvx(ble_hvx_buf_t * p_ble_hvx_buf); + +/**@brief Function for sending something from the HVX buffer. + * + * @param[in] p_ble_hvx_buf HVX buffering structure. + * @return NRF_SUCCESS If a indication/notification was successfully sent. + */ +uint32_t ble_hvx_buffer_process(ble_hvx_buf_t * p_ble_hvx_buf); + + +#endif // BLE_HVX_BUFFERING_H__ + +/** @} */ + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots.c new file mode 100644 index 0000000..b4076c4 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots.c @@ -0,0 +1,249 @@ +/** + * Copyright (c) 2017 - 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. + * + */ + +#include +#include +#include "ble_ots.h" +#include "ble_ots_object.h" +#include "ble_ots_oacp.h" +#include "fds.h" + +#define BLE_OTS_MAX_OBJ_TYPE_SIZE 16 +#define BLE_OTS_OBJ_CHANGED_SIZE 7 +#define OTS_INVALID_ID 0xFF + +#define SIZE_DATE_TIME 7 + +#define BLE_OTS_INVALID_OCTET_OFFSET BLE_GATT_STATUS_ATTERR_APP_BEGIN + 1 +#define BLE_OTS_INVALID_METADATA BLE_GATT_STATUS_ATTERR_APP_BEGIN + 2 +#define BLE_OTS_CONCURRENCY_LIMIT_EXCEEDED BLE_GATT_STATUS_ATTERR_APP_BEGIN + 3 + + +#define BLE_OTS_OACP_SUPPORT_FEATURE_CREATE_bp 0 +#define BLE_OTS_OACP_SUPPORT_FEATURE_DELETE_bp 1 +#define BLE_OTS_OACP_SUPPORT_FEATURE_CALC_CHECKSUM_bp 2 +#define BLE_OTS_OACP_SUPPORT_FEATURE_EXECUTE_bp 3 +#define BLE_OTS_OACP_SUPPORT_FEATURE_READ_bp 4 +#define BLE_OTS_OACP_SUPPORT_FEATURE_WRITE_bp 5 +#define BLE_OTS_OACP_SUPPORT_FEATURE_APPEND_bp 6 +#define BLE_OTS_OACP_SUPPORT_FEATURE_TRUNCATE_bp 7 +#define BLE_OTS_OACP_SUPPORT_FEATURE_PATCH_bp 8 +#define BLE_OTS_OACP_SUPPORT_FEATURE_ABORT_bp 9 + +#define BLE_OTS_OLCP_SUPPORT_FEATURE_GOTO_bp 0 +#define BLE_OTS_OLCP_SUPPORT_FEATURE_ORDER_bp 1 +#define BLE_OTS_OLCP_SUPPORT_FEATURE_REQ_NUM_OBJECTS_bp 2 +#define BLE_OTS_OLCP_SUPPORT_FEATURE_CLEAR_MARKING_bp 3 + +/**@brief Function for adding the features characteristic. + * + * @param[in] p_ots Object Transfer Service structure. + * @param[in] read_access Read security level for the feature characteristic. + * @param[in] p_feature_char_handles Pointer to the handles for the feature characteristic. + */ +static uint32_t feature_char_add(ble_ots_t * const p_ots, + security_req_t read_access, + ble_gatts_char_handles_t * p_feature_char_handles) +{ + ble_add_char_params_t add_char_params; + + uint8_t feature[BLE_OTS_FEATURE_LEN]; + + uint32_t oacp_features; + uint32_t olcp_features; + + oacp_features = 0; + oacp_features |= (1 << BLE_OTS_OACP_SUPPORT_FEATURE_READ_bp); + oacp_features |= (1 << BLE_OTS_OACP_SUPPORT_FEATURE_APPEND_bp); + oacp_features |= (1 << BLE_OTS_OACP_SUPPORT_FEATURE_TRUNCATE_bp); + oacp_features |= (1 << BLE_OTS_OACP_SUPPORT_FEATURE_PATCH_bp); + oacp_features |= (1 << BLE_OTS_OACP_SUPPORT_FEATURE_ABORT_bp); + + olcp_features = 0; + + uint32_t i = 0; + i += uint32_encode(oacp_features, &feature[i]); + i += uint32_encode(olcp_features, &feature[i]); + + memset(&add_char_params, 0, sizeof(add_char_params)); + + add_char_params.uuid = BLE_UUID_OTS_FEATURES; + add_char_params.uuid_type = BLE_UUID_TYPE_BLE; + add_char_params.max_len = BLE_OTS_FEATURE_LEN; + add_char_params.init_len = BLE_OTS_FEATURE_LEN; + add_char_params.p_init_value = &feature[0]; + add_char_params.char_props.read = 1; + add_char_params.read_access = read_access; + + return characteristic_add(p_ots->service_handle, + &add_char_params, + p_feature_char_handles); +} + +/**@brief Function for handling the Connect event. + * + * @param[in] p_ots Object Transfer Service structure. + * @param[in] p_ble_evt Event received from the BLE stack. + */ +static void on_connect(ble_ots_t * p_ots, ble_evt_t const * p_ble_evt) +{ + p_ots->conn_handle = p_ble_evt->evt.gap_evt.conn_handle; +} + +/**@brief Function for handling the BLE_GAP_EVT_DISCONNECTED event. + * + * @param[in] p_ots OTS Service Structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static void on_disconnect(ble_ots_t * p_ots, ble_evt_t const * p_ble_evt) +{ + p_ots->conn_handle = BLE_CONN_HANDLE_INVALID; +} + +uint32_t ble_ots_init(ble_ots_t * p_ots, ble_ots_init_t * p_ots_init) +{ + if ((p_ots == NULL) || (p_ots_init == NULL)) + { + return NRF_ERROR_NULL; + } + + if (p_ots_init->p_object == NULL) + { + return NRF_ERROR_NULL; + } + + p_ots->conn_handle = BLE_CONN_HANDLE_INVALID; + p_ots->error_handler = p_ots_init->error_handler; + p_ots->evt_handler = p_ots_init->evt_handler; + p_ots->p_current_object = p_ots_init->p_object; + p_ots->error_handler = p_ots_init->error_handler; + p_ots->evt_handler = p_ots_init->evt_handler; + p_ots->p_current_object = p_ots_init->p_object; + + + ble_uuid_t service_uuid = + { + .uuid = BLE_UUID_OTS_SERVICE, + .type = BLE_UUID_TYPE_BLE + }; + uint32_t err_code; + + err_code = fds_init(); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, + &service_uuid, + &(p_ots->service_handle)); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + err_code = feature_char_add(p_ots, p_ots_init->feature_char_read_access, &p_ots->feature_handles); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + err_code = ble_ots_object_representation_init(&p_ots->object_chars, &p_ots_init->object_chars_init); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + err_code = ble_ots_oacp_init(&p_ots->oacp_chars, &p_ots_init->oacp_init); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + p_ots->oacp_chars.ots_l2cap.conn_mps = p_ots_init->rx_mps; + p_ots->oacp_chars.ots_l2cap.conn_mtu = p_ots_init->rx_mtu; + + return NRF_SUCCESS; +} + +/**@brief Function for handling the BLE_EVT_TX_COMPLETE event. Calls the hvx buffering module. + * @param[in] p_ots Object Transfer Service structure. */ +static inline void on_tx_complete(ble_ots_t * p_ots) +{ + uint32_t err_code; + err_code = ble_hvx_buffer_process(&p_ots->hvx_buf); + if (err_code != NRF_SUCCESS) + { + p_ots->error_handler(err_code); + } + +} + +void ble_ots_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) +{ + ble_ots_t * p_ots; + p_ots = (ble_ots_t*) p_context; + + if ((p_ots == NULL) || (p_ble_evt == NULL)) + { + return; + } + ble_ots_oacp_on_ble_evt(&p_ots->oacp_chars, p_ble_evt); + ble_ots_object_on_ble_evt(&p_ots->object_chars, p_ble_evt); + + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + on_connect(p_ots, p_ble_evt); + break; + + case BLE_GAP_EVT_DISCONNECTED: + on_disconnect(p_ots, p_ble_evt); + break; + + case BLE_GATTS_EVT_HVN_TX_COMPLETE: + on_tx_complete(p_ots); + break; + + default: + // No implementation needed. + break; + } +} + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots.h new file mode 100644 index 0000000..634bfd4 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots.h @@ -0,0 +1,472 @@ +/** + * Copyright (c) 2017 - 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_ots Object Transfer Service + * @{ + * @ingroup ble_sdk_srv + * @brief Object Transfer Service module + * + * @details This is the main module of the OTS service. + */ + +#ifndef BLE_OTS_H__ +#define BLE_OTS_H__ + +#include +#include "ble_srv_common.h" +#include "ble_date_time.h" +#include "ble_hvx_buffering.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Macro for defining a ble_ots instance. + * + * @param _name Name of the instance. + * @hideinitializer + */ +#define BLE_OTS_DEF(_name) \ +static ble_ots_t _name; \ +NRF_SDH_BLE_OBSERVER(_name ## _ble_obs, \ + BLE_OTS_BLE_OBSERVER_PRIO, \ + ble_ots_on_ble_evt, &_name) \ + + +#define NRF_BLE_OTS_SIZE_CHAR_LEN (2*sizeof(uint32_t)) +#define BLE_OTS_FEATURE_LEN (2*sizeof(uint32_t)) +#define BLE_OTS_NAME_MAX_SIZE 128 +#define BLE_OTS_MAX_OBJ_SIZE 1028 +#define BLE_OTS_INVALID_CID 0x0000 /**< Invalid connection ID. */ +#define BLE_OTS_PSM 0x0025 +#define BLE_OTS_MAX_OACP_SIZE 21 +#define BLE_OTS_WRITE_MODE_TRUNCATE (1 << 1) +#define BLE_OTS_WRITE_MODE_NO_TRUNCATE 0 + +// Forward declarations. +typedef struct ble_ots_s ble_ots_t; +typedef struct ble_ots_oacp_s ble_ots_oacp_t; +typedef struct ble_ots_l2cap_s ble_ots_l2cap_t; + + +/*------------------------------------------ BLE OTS OBJECT --------------------------------------*/ + +/**@brief Properties of an Object Transfer Service object. */ +typedef union +{ + struct + { + bool is_delete_permitted :1; + bool is_execute_permitted :1; + bool is_read_permitted :1; + bool is_write_permitted :1; + bool is_append_permitted :1; + bool is_truncate_permitted:1; /**< When writing using truncate mode, and the written length is shorter than the object, the object size is decreased. */ + bool is_patch_permitted :1; /**< When patching, a part of the object is replaced. */ + bool is_marked :1; + } decoded; + uint32_t raw; +} ble_ots_obj_properties_t; + +/**@brief A structure representing the object type. */ +typedef struct +{ + uint8_t len; /**< The length of the object type in bytes. 2 and 16 are the only valid type lengths. */ + union + { + uint16_t type16; + uint8_t type128[16]; + } param; +} ble_ots_obj_type_t; + +/**@brief The structure representing one Object Transfer Service object. */ +typedef struct +{ + uint8_t name[BLE_OTS_NAME_MAX_SIZE]; /**< The name of the object. If the name is "", the object will be invalidated on disconnect. */ + uint8_t data[BLE_OTS_MAX_OBJ_SIZE]; + ble_ots_obj_type_t type; + ble_ots_obj_properties_t properties; + uint32_t current_size; + uint32_t alloc_len; + bool is_valid; /**< States if the object will be shown in a list. */ + bool is_locked; /**< When an object is written or read, the object will be locked. */ +} ble_ots_object_t; + +/**@brief The definition of an event from the object characteristics. */ +typedef struct +{ + enum + { + BLE_OTS_OBJECT_EVT_NAME_CHANGED, + BLE_OTS_OBJECT_EVT_PROPERTIES_CHANGED, + } type; + union + { + ble_ots_object_t * p_object; + } evt; +} ble_ots_object_evt_t; + +/**@brief Initialization properties of the Object Transfer Service Object characteristics. */ +typedef struct +{ + ble_ots_t * p_ots; + security_req_t name_read_access; + security_req_t name_write_access; + security_req_t type_read_access; + security_req_t size_read_access; + security_req_t properties_read_access; + security_req_t properties_write_access; +} ble_ots_object_chars_init_t; + +/**@brief The structure holding the state of the OTS object characteristics. */ +typedef struct +{ + ble_ots_t * p_ots; + ble_gatts_char_handles_t obj_name_handles; + ble_gatts_char_handles_t obj_type_handles; + ble_gatts_char_handles_t obj_size_handles; + ble_gatts_char_handles_t obj_properties_handles; +} ble_ots_object_chars_t; + + +/*------------------------------------------ BLE OTS L2CAP ---------------------------------------*/ + +/**@brief L2cap event types. */ +typedef enum +{ + BLE_OTS_L2CAP_EVT_CH_CONNECTED, + BLE_OTS_L2CAP_EVT_CH_DISCONNECTED, + BLE_OTS_L2CAP_EVT_SEND_COMPLETE, + BLE_OTS_L2CAP_EVT_RECV_COMPLETE, +} ble_ots_l2cap_evt_type_t; + +/**@brief l2cap event. */ +typedef struct +{ + ble_ots_l2cap_evt_type_t type; + struct + { + uint8_t * p_data; + uint16_t len; + } param; +} ble_ots_l2cap_evt_t; + +/**@brief L2CAP event handler. */ +typedef void (*ble_ots_l2cap_evt_handler_t)(ble_ots_l2cap_t * p_ots_l2cap, + ble_ots_l2cap_evt_t * p_evt); + +/**@brief The structure holding the l2cap connection oriented channels state. */ +struct ble_ots_l2cap_s +{ + ble_ots_l2cap_evt_handler_t evt_handler; + ble_ots_oacp_t * p_ots_oacp; + enum + { + NOT_CONNECTED, + CONNECTED, + SENDING, + RECEIVING + } state; + ble_data_t tx_transfer_buffer; + ble_l2cap_ch_rx_params_t rx_params; + ble_l2cap_ch_tx_params_t tx_params; + uint16_t remaining_bytes; /**< The number of remaining bytes in the current transfer. */ + uint16_t transfered_bytes; + uint16_t transfer_len; /**< The total number of bytes in the current transfer. */ + uint16_t local_cid; /**< Connection id of the current connection. */ + uint16_t conn_mtu; /**< The maximum transmission unit, that is the number of packets that can be sent or received. */ + uint16_t conn_mps; /**< MPS defines the maximum payload size in bytes. */ +}; + +/**@brief The initialization structure of the l2cap module. */ +typedef struct +{ + ble_ots_oacp_t * p_ots_oacp; + ble_ots_l2cap_evt_handler_t evt_handler; + uint8_t * p_transfer_buffer; /**< The user must provide buffer for transfers. */ + uint16_t buffer_len; /**< Length of the transfer buffer. */ +} ble_ots_l2cap_init_t; + + +/*------------------------------------------ BLE OTS OCAP ----------------------------------------*/ + +/**< Types of Object Action Control Point Procedures. */ +typedef enum +{ + BLE_OTS_OACP_PROC_CREATE = 0x01, //!< Create object. + BLE_OTS_OACP_PROC_DELETE = 0x02, //!< Delete object. + BLE_OTS_OACP_PROC_CALC_CHKSUM = 0x03, //!< Calculate Checksum. + BLE_OTS_OACP_PROC_EXECUTE = 0x04, //!< Execute Object. + BLE_OTS_OACP_PROC_READ = 0x05, //!< Read object. + BLE_OTS_OACP_PROC_WRITE = 0x06, //!< Write object. + BLE_OTS_OACP_PROC_ABORT = 0x07, //!< Abort object. + BLE_OTS_OACP_PROC_RESP = 0x60 //!< Procedure response. +} ble_ots_oacp_proc_type_t; + +/**< Object Action Control Point return codes. */ +typedef enum +{ + BLE_OTS_OACP_RES_SUCCESS = 0x01, //!< Success. + BLE_OTS_OACP_RES_OPCODE_NOT_SUP = 0x02, //!< Not supported + BLE_OTS_OACP_RES_INV_PARAM = 0x03, //!< Invalid parameter + BLE_OTS_OACP_RES_INSUFF_RES = 0x04, //!< Insufficient resources. + BLE_OTS_OACP_RES_INV_OBJ = 0x05, //!< Invalid object. + BLE_OTS_OACP_RES_CHAN_UNAVAIL = 0x06, //!< Channel unavailable. + BLE_OTS_OACP_RES_UNSUP_TYPE = 0x07, //!< Unsupported procedure. + BLE_OTS_OACP_RES_NOT_PERMITTED = 0x08, //!< Procedure not permitted. + BLE_OTS_OACP_RES_OBJ_LOCKED = 0x09, //!< Object locked. + BLE_OTS_OACP_RES_OPER_FAILED = 0x0A //!< Operation Failed. +} ble_ots_oacp_res_code_t; + +/**< Object Action Control Point procedure definition. */ +typedef struct +{ + ble_ots_oacp_proc_type_t type; + union + { + struct + { + uint32_t size; + ble_ots_obj_type_t * p_obj_type; + } create_params; + struct + { + uint32_t offset; + uint32_t length; + } checksum_params; + struct + { + uint8_t cmd_data_len; + uint8_t * p_cmd_data; + } execute_params; + struct + { + uint32_t offset; + uint32_t length; + } read_params; + struct + { + uint32_t offset; + uint32_t length; + uint8_t write_mode; + } write_params; + } params; +} ble_ots_oacp_proc_t; + +/**@brief Definition of an OACP event. */ +typedef struct +{ + enum + { + BLE_OTS_OACP_EVT_EXECUTE, + BLE_OTS_OACP_EVT_REQ_READ, + BLE_OTS_OACP_EVT_INCREASE_ALLOC_LEN, + BLE_OTS_OACP_EVT_REQ_WRITE, + BLE_OTS_OACP_EVT_ABORT, + } type; + union + { + ble_ots_object_t * p_object; + struct + { + uint8_t cmd_data_len; + uint8_t * p_cmd_data; + } execute_params; + } evt; +} ble_ots_oacp_evt_t; + +/**@brief OACP initialization properties. */ +typedef struct +{ + ble_ots_t * p_ots; + uint32_t on_create_obj_properties_raw; /**< The encoded properties of a newly created object.*/ + security_req_t write_access; /**< The write security level for the OACP. */ + security_req_t cccd_write_access; /**< The write security level for the OACP CCCD. */ + uint8_t * p_l2cap_buffer; + uint16_t l2cap_buffer_len; +} ble_ots_oacp_init_t; + +struct ble_ots_oacp_s +{ + ble_ots_t * p_ots; + uint32_t on_create_obj_properties_raw; /**< The encoded properties of a newly created object.*/ + ble_ots_l2cap_t ots_l2cap; /**< L2CAP connection oriented channel module. */ + ble_gatts_char_handles_t oacp_handles; /**< The characteristic handles of the OACP. */ +}; + + +/*------------------------------------------ BLE OTS ---------------------------------------------*/ + +/**@brief The event type indicates which module the event is connected to.*/ +typedef enum +{ + BLE_OTS_EVT_OACP, + BLE_OTS_EVT_OBJECT, + BLE_OTS_EVT_INDICATION_ENABLED, + BLE_OTS_EVT_INDICATION_DISABLED, + BLE_OTS_EVT_OBJECT_RECEIVED /**< If this event is received, data is now available in the current object.*/ +} ble_ots_evt_type_t; + +/**@brief This structure represents the state of the Object Transfer Service. */ +typedef struct +{ + ble_ots_evt_type_t type; + union + { + ble_ots_oacp_evt_t oacp_evt; + ble_ots_object_evt_t object_evt; + + } evt; /**< Event data. */ +} ble_ots_evt_t; + +/**@brief OTS event handler. */ +typedef void (*ble_ots_evt_handler_t) (ble_ots_t * p_ots, ble_ots_evt_t * p_evt); + +/**@brief Structure for initializing the OTS. */ +typedef struct +{ + ble_ots_evt_handler_t evt_handler; + ble_srv_error_handler_t error_handler; + ble_ots_object_t * p_object; /**< Pointer to the object. */ + security_req_t feature_char_read_access; /**< Read security level for the feature characteristic value. */ + ble_ots_object_chars_init_t object_chars_init; /**< The initialization structure of the object characteristics. */ + ble_ots_oacp_init_t oacp_init; /**< The initialization structure of the object action control point. */ + uint16_t rx_mps; /**< Size of L2CAP Rx MPS (must be at least BLE_L2CAP_MPS_MIN).*/ + uint16_t rx_mtu; /**< Size of L2CAP Rx MTU (must be at least BLE_L2CAP_MTU_MIN).*/ +} ble_ots_init_t; + +struct ble_ots_s +{ + uint16_t conn_handle; /**< Connection handle of service. */ + uint16_t service_handle; /**< THe service handle of OTS. */ + ble_ots_evt_handler_t evt_handler; + ble_srv_error_handler_t error_handler; + ble_gatts_char_handles_t feature_handles; + ble_ots_object_chars_t object_chars; /**< The structure holding the object characteristics representation. */ + ble_ots_oacp_t oacp_chars; /**< The structure holding the object action control point characteristics representation. */ + ble_ots_object_t * p_current_object; /**< Pointer to the currently selected object. */ + ble_hvx_buf_t hvx_buf; /**< A buffer holding unsent handle value indications/notifications. */ +}; + + +/**@brief Function for initializing the Object Transfer Service. + * + * @param[out] p_ots Object Transfer Service structure. This structure will have to be supplied by + * the application. It will be initialized by this function, and will later + * be used to identify this particular service instance. + * @param[in] p_ots_init Information needed to initialize the service. + * + * @return NRF_SUCCESS on successful initialization of service, otherwise an error code. + */ +uint32_t ble_ots_init(ble_ots_t * p_ots, ble_ots_init_t * p_ots_init); + +/**@brief Function for handling the Application's BLE Stack events. + * + * @details Handles all events from the BLE stack of interest to the Object Transfer Service. + * + * @param[in] p_ble_evt Event received from the BLE stack. + * @param[in] p_context Object Transfer Service structure. + */ +void ble_ots_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context); + +/**@brief Function for setting the name of an object. + * + * @details If p_object is the current selected object, and the notifications is enabled, the client will be notified that the object has changed. + * @note If the name of the object is "" on disconnection, the object will be invalidated. + * + * @param[in] p_ots_object_chars Object Transfer Service Object Characteristics structure. + * @param[in] p_object Pointer to the object where the name will be changed. + * @param[in] new_name The new name of the object. + * + * @return NRF_SUCCESS On success, otherwise an error code. + */ +uint32_t ble_ots_object_set_name(ble_ots_object_chars_t * p_ots_object_chars, + ble_ots_object_t * p_object, + char const * new_name); + +/**@brief Function for setting the type of an object. + * + * @details If p_object is the current selected object, and the notifications is enabled, the client will be notified that the object has changed. + * @param[in] p_ots_object_chars Object Transfer Service Object Characteristics structure. + * @param[in] p_object Pointer to the object where the type will be changed. + * @param[in] p_new_type Pointer to the new type of the object. + * + * @return NRF_SUCCESS On success, otherwise an error code. + */ +uint32_t ble_ots_object_set_type(ble_ots_object_chars_t * p_ots_object_chars, + ble_ots_object_t * p_object, + ble_ots_obj_type_t * p_new_type); + +/**@brief Function for setting the current size of an object. + * + * @details If p_object is the current selected object, and the notifications is enabled, the client will be notified that the object has changed. + * @note If the new current size is smaller than the current size, the object will be truncated. + * + * @param[in] p_ots_object_chars Object Transfer Service Object Characteristics structure. + * @param[in] p_object Pointer to the object where the current size will be changed. + * @param[in] new_current_size The new current size of the object. + * + * @return NRF_SUCCESS On success, otherwise an error code. + */ +uint32_t ble_ots_object_set_current_size(ble_ots_object_chars_t * p_ots_object_chars, + ble_ots_object_t * p_object, + uint32_t new_current_size); + +/**@brief Function for setting the properties of an object. + * + * @details If p_object is the current selected object, and the notifications is enabled, the client will be notified that the object has changed. + * + * @param[in] p_ots_object_chars Object Transfer Service Object Characteristics structure. + * @param[in] p_object Pointer to the object where the properties will be changed. + * @param[in] p_new_properties The properties of the object. + * + * @return NRF_SUCCESS On success, otherwise an error code. + */ +uint32_t ble_ots_object_set_properties(ble_ots_object_chars_t * p_ots_object_chars, + ble_ots_object_t * p_object, + ble_ots_obj_properties_t * p_new_properties); + + + +#endif // BLE_OTS_H__ + +/** @} */ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_l2cap.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_l2cap.c new file mode 100644 index 0000000..b51e086 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_l2cap.c @@ -0,0 +1,437 @@ +/** + * Copyright (c) 2017 - 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. + * + */ +#include "ble_ots_l2cap.h" + +#include +#include "ble_l2cap.h" + +#include "ble_ots.h" +#include "ble_ots_oacp.h" + +#define NRF_LOG_MODULE_NAME ble_ots_l2cap +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define SDU_SIZE 256 + + +static uint8_t data[SDU_SIZE]; +static ble_data_t m_sdu_buf = +{ + .p_data = data, + .len = SDU_SIZE +}; + +bool ble_ots_l2cap_is_channel_available(ble_ots_l2cap_t * p_ots_l2cap) +{ + return p_ots_l2cap->state == CONNECTED; +} + +uint32_t ble_ots_l2cap_abort_transmission(ble_ots_l2cap_t * p_ots_l2cap) +{ + if (p_ots_l2cap == NULL) + { + return NRF_ERROR_NULL; + } + return NRF_ERROR_INVALID_PARAM; +} + +uint32_t ble_ots_l2cap_init(ble_ots_l2cap_t * p_ots_l2cap, ble_ots_l2cap_init_t * p_ots_l2cap_init) +{ + if (p_ots_l2cap == NULL || p_ots_l2cap_init == NULL) + { + return NRF_ERROR_NULL; + } + if (p_ots_l2cap_init->p_transfer_buffer == NULL || p_ots_l2cap_init->buffer_len == 0) + { + return NRF_ERROR_INVALID_PARAM; + } + if (p_ots_l2cap_init->p_ots_oacp == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + if (p_ots_l2cap_init->evt_handler == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + + memset(p_ots_l2cap, 0, sizeof(ble_ots_l2cap_t)); + + p_ots_l2cap->local_cid = BLE_OTS_INVALID_CID; + + p_ots_l2cap->p_ots_oacp = p_ots_l2cap_init->p_ots_oacp; + p_ots_l2cap->evt_handler = p_ots_l2cap_init->evt_handler; + p_ots_l2cap->rx_params.sdu_buf.len = m_sdu_buf.len; + p_ots_l2cap->rx_params.sdu_buf.p_data = m_sdu_buf.p_data; + + p_ots_l2cap->state = NOT_CONNECTED; + + return NRF_SUCCESS; +} + + + +/**@brief This function resumes sending data after an interrupt in the transfer. + * + * @param[in] p_ots_l2cap Object Transfer Service structure. + */ +static void ble_ots_l2cap_resume_send(ble_ots_l2cap_t * p_ots_l2cap) +{ + uint16_t transmit_size; + ble_data_t data_buf; + + transmit_size = MIN(p_ots_l2cap->tx_params.tx_mtu, p_ots_l2cap->remaining_bytes); + + data_buf.p_data = &p_ots_l2cap->tx_transfer_buffer.p_data[p_ots_l2cap->transfer_len - p_ots_l2cap->remaining_bytes]; + data_buf.len = transmit_size; + + + uint32_t err_code = sd_ble_l2cap_ch_tx(p_ots_l2cap->p_ots_oacp->p_ots->conn_handle, + p_ots_l2cap->local_cid, + &data_buf); + + if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_BUSY) + { + if (p_ots_l2cap->p_ots_oacp->p_ots->error_handler != NULL) + { + p_ots_l2cap->p_ots_oacp->p_ots->error_handler(err_code); + return; + } + } +} + + +uint32_t ble_ots_l2cap_start_send(ble_ots_l2cap_t * p_ots_l2cap, uint8_t * p_data, uint16_t data_len) +{ + if (p_ots_l2cap == NULL) + { + return NRF_ERROR_NULL; + } + if (p_data == NULL) + { + return NRF_ERROR_NULL; + } + if (data_len == 0) + { + return NRF_ERROR_INVALID_LENGTH; + } + if (p_ots_l2cap->local_cid == BLE_L2CAP_CID_INVALID) + { + return NRF_ERROR_INVALID_STATE; + } + if (p_ots_l2cap->state != CONNECTED) + { + return NRF_ERROR_INVALID_STATE; + } + + p_ots_l2cap->tx_transfer_buffer.p_data = p_data; + p_ots_l2cap->tx_transfer_buffer.len = data_len; + + p_ots_l2cap->remaining_bytes = data_len; + p_ots_l2cap->transfer_len = data_len; + + p_ots_l2cap->state = SENDING; + + ble_ots_l2cap_resume_send(p_ots_l2cap); + + return NRF_SUCCESS; +} + +uint32_t ble_ots_l2cap_start_recv(ble_ots_l2cap_t * p_ots_l2cap, uint16_t len) +{ + uint32_t err_code; + + if (p_ots_l2cap == NULL) + { + return NRF_ERROR_NULL; + } + if (p_ots_l2cap->state != CONNECTED) + { + return NRF_ERROR_INVALID_STATE; + } + if (p_ots_l2cap->local_cid == BLE_L2CAP_CID_INVALID) + { + return NRF_ERROR_INVALID_STATE; + } + p_ots_l2cap->transfered_bytes = 0; + p_ots_l2cap->remaining_bytes = len; + p_ots_l2cap->transfer_len = len; + + err_code = sd_ble_l2cap_ch_rx(p_ots_l2cap->p_ots_oacp->p_ots->conn_handle, + p_ots_l2cap->local_cid, + &p_ots_l2cap->rx_params.sdu_buf); + if (err_code == NRF_SUCCESS) + { + p_ots_l2cap->state = RECEIVING; + } + + return err_code; +} + +/**@brief This function is called on a channel setup request. It responds with the connection parameters. + * @param[in] p_ots_l2cap Object transfer service l2cap module structure. + * @param[in] p_ble_evt Event received from the BLE stack. + */ +static inline void on_l2cap_ch_setup_request(ble_ots_l2cap_t * p_ots_l2cap, ble_evt_t const * p_ble_evt) +{ + uint32_t err_code; + ble_l2cap_ch_setup_params_t ch_setup_params = {{0}}; + + if (p_ble_evt->evt.l2cap_evt.params.ch_setup_request.le_psm != BLE_OTS_PSM) + { + ch_setup_params.status = BLE_L2CAP_CH_STATUS_CODE_LE_PSM_NOT_SUPPORTED; + NRF_LOG_WARNING("l2cap setup request for PSM 0x%x, rejecting since OTS PSM is 0x%x", + p_ble_evt->evt.l2cap_evt.params.ch_setup_request.le_psm, + BLE_L2CAP_CH_STATUS_CODE_LE_PSM_NOT_SUPPORTED); + } + + else + { + ch_setup_params.status = BLE_L2CAP_CH_STATUS_CODE_SUCCESS; + + ch_setup_params.rx_params.rx_mps = p_ots_l2cap->conn_mps; + if (ch_setup_params.rx_params.rx_mps < BLE_L2CAP_MPS_MIN) + { + ch_setup_params.rx_params.rx_mps = BLE_L2CAP_MPS_MIN; + } + ch_setup_params.rx_params.rx_mtu = p_ots_l2cap->conn_mtu; + if (ch_setup_params.rx_params.rx_mtu < BLE_L2CAP_MTU_MIN) + { + ch_setup_params.rx_params.rx_mtu = BLE_L2CAP_MTU_MIN; + } + ch_setup_params.rx_params.sdu_buf.p_data = NULL; + } + + p_ots_l2cap->local_cid = p_ble_evt->evt.l2cap_evt.local_cid; + + err_code = sd_ble_l2cap_ch_setup(p_ots_l2cap->p_ots_oacp->p_ots->conn_handle, + &p_ots_l2cap->local_cid, + &ch_setup_params); + if (err_code != NRF_SUCCESS) + { + if (p_ots_l2cap->p_ots_oacp->p_ots->error_handler != NULL) + { + p_ots_l2cap->p_ots_oacp->p_ots->error_handler(err_code); + } + + } + NRF_LOG_INFO("Accepted L2CAP Channel"); +} + + +/**@brief This function is called on a channel setup request. The parameters are stored. Events are forwarded. + * + * @param[in] p_ots_l2cap Object transfer service l2cap module structure. + * @param[in] p_ble_evt Event received from the BLE stack. + */ +static inline void on_l2cap_ch_setup(ble_ots_l2cap_t * p_ots_l2cap, ble_evt_t const * p_ble_evt) +{ + p_ots_l2cap->local_cid = p_ble_evt->evt.l2cap_evt.local_cid; + p_ots_l2cap->tx_params.credits = p_ble_evt->evt.l2cap_evt.params.ch_setup.tx_params.credits; + p_ots_l2cap->tx_params.tx_mps = p_ble_evt->evt.l2cap_evt.params.ch_setup.tx_params.tx_mps; + p_ots_l2cap->tx_params.tx_mtu = p_ble_evt->evt.l2cap_evt.params.ch_setup.tx_params.tx_mtu; + ble_ots_l2cap_evt_t evt; + + evt.type = BLE_OTS_L2CAP_EVT_CH_CONNECTED; + + p_ots_l2cap->state = CONNECTED; + p_ots_l2cap->evt_handler(p_ots_l2cap, &evt); +} + + +/**@brief Function for handling the BLE_L2CAP_EVT_CH_RELEASED event. + * + * @param[in] p_ots_l2cap Object transfer service l2cap module structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static inline void on_l2cap_ch_released(ble_ots_l2cap_t * p_ots_l2cap, ble_evt_t const * p_ble_evt) +{ + if(p_ots_l2cap->local_cid != p_ble_evt->evt.l2cap_evt.local_cid) + { + return; + } + ble_ots_l2cap_evt_t evt; + + evt.type = BLE_OTS_L2CAP_EVT_CH_DISCONNECTED; + + p_ots_l2cap->evt_handler(p_ots_l2cap, &evt); + + p_ots_l2cap->state = NOT_CONNECTED; + + p_ots_l2cap->local_cid = BLE_OTS_INVALID_CID; + +} + + +/**@brief This function ois called tx is completet. It continues to send if necessary. + * + * @param[in] p_ots_l2cap Object transfer service l2cap module structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static void on_tx_complete(ble_ots_l2cap_t * p_ots_l2cap, ble_evt_t const * p_ble_evt) +{ + if(p_ots_l2cap->local_cid != p_ble_evt->evt.l2cap_evt.local_cid) + { + return; + } + + p_ots_l2cap->remaining_bytes -= p_ble_evt->evt.l2cap_evt.params.tx.sdu_buf.len; + + if (p_ots_l2cap->remaining_bytes == 0) + { + ble_ots_l2cap_evt_t evt; + + evt.type = BLE_OTS_L2CAP_EVT_SEND_COMPLETE; + evt.param.len = p_ots_l2cap->transfer_len; + evt.param.p_data = p_ots_l2cap->tx_transfer_buffer.p_data; + evt.param.len = p_ots_l2cap->tx_transfer_buffer.len; + + p_ots_l2cap->evt_handler(p_ots_l2cap, &evt); + + p_ots_l2cap->state = CONNECTED; + + p_ots_l2cap->transfer_len = 0; + } + else + { + ble_ots_l2cap_resume_send(p_ots_l2cap); + } +} + + +static void on_l2cap_ch_rx(ble_ots_l2cap_t * p_ots_l2cap, ble_evt_t const * p_ble_evt) +{ + if(p_ots_l2cap->local_cid != p_ble_evt->evt.l2cap_evt.local_cid) + { + return; + } + + ble_ots_l2cap_evt_t evt; + + memcpy(&p_ots_l2cap->p_ots_oacp->p_ots->p_current_object->data[p_ots_l2cap->transfered_bytes], + p_ble_evt->evt.l2cap_evt.params.rx.sdu_buf.p_data, + p_ble_evt->evt.l2cap_evt.params.rx.sdu_len); + NRF_LOG_DEBUG("Object buffer dump"); + NRF_LOG_HEXDUMP_DEBUG(p_ots_l2cap->rx_params.sdu_buf.p_data , p_ots_l2cap->rx_params.sdu_buf.len); + p_ots_l2cap->transfered_bytes += p_ble_evt->evt.l2cap_evt.params.rx.sdu_len; + p_ots_l2cap->remaining_bytes -= p_ble_evt->evt.l2cap_evt.params.rx.sdu_len; + NRF_LOG_INFO("Bytes remaining to receive: %i", p_ots_l2cap->remaining_bytes); + p_ots_l2cap->state = CONNECTED; + + p_ots_l2cap->transfer_len = 0; + + if(p_ots_l2cap->remaining_bytes <= 0) + { + evt.type = BLE_OTS_L2CAP_EVT_RECV_COMPLETE; + evt.param.len = p_ots_l2cap->rx_params.sdu_buf.len; + evt.param.p_data = p_ots_l2cap->rx_params.sdu_buf.p_data; + p_ots_l2cap->evt_handler(p_ots_l2cap, &evt); + } + else + { + ret_code_t err_code; + + ble_data_t sdu_buf; + sdu_buf.p_data = &p_ots_l2cap->rx_params.sdu_buf.p_data[p_ots_l2cap->transfered_bytes]; + sdu_buf.len = p_ots_l2cap->rx_params.sdu_buf.len; + + err_code = sd_ble_l2cap_ch_rx(p_ots_l2cap->p_ots_oacp->p_ots->conn_handle, + p_ots_l2cap->local_cid, + &sdu_buf); + if (err_code == NRF_SUCCESS) + { + p_ots_l2cap->state = RECEIVING; + } + else + { + p_ots_l2cap->state = CONNECTED; + } + } +} + + + +void ble_ots_l2cap_on_ble_evt(ble_ots_l2cap_t * p_ots_l2cap, ble_evt_t const * p_ble_evt) +{ + if ((p_ots_l2cap == NULL) || (p_ble_evt == NULL)) + { + return; + } + + switch (p_ble_evt->header.evt_id) + { + case BLE_L2CAP_EVT_CH_SETUP_REQUEST: + on_l2cap_ch_setup_request(p_ots_l2cap, p_ble_evt); + break; + + case BLE_L2CAP_EVT_CH_SETUP_REFUSED: + // This should not happen because the client should be the initiator. + if (p_ots_l2cap->p_ots_oacp->p_ots->error_handler != NULL) + { + p_ots_l2cap->p_ots_oacp->p_ots->error_handler(NRF_ERROR_INVALID_STATE); + } + break; + + case BLE_L2CAP_EVT_CH_SETUP: + on_l2cap_ch_setup(p_ots_l2cap, p_ble_evt); + break; + + case BLE_L2CAP_EVT_CH_RELEASED: + on_l2cap_ch_released(p_ots_l2cap, p_ble_evt); + break; + case BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED: + break; + case BLE_L2CAP_EVT_CH_CREDIT: + break; + case BLE_L2CAP_EVT_CH_RX: + on_l2cap_ch_rx(p_ots_l2cap, p_ble_evt); + break; + + case BLE_L2CAP_EVT_CH_TX: + on_tx_complete(p_ots_l2cap, p_ble_evt); + break; + default: + // No implementation needed. + break; + } +} + + + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_l2cap.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_l2cap.h new file mode 100644 index 0000000..be0312a --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_l2cap.h @@ -0,0 +1,117 @@ +/** + * Copyright (c) 2017 - 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_sdk_srv_ots_l2cap Object Transfer Service, l2cap channel handling + * @{ + * @ingroup ble_ots + * @brief Object Transfer Service module + * + * @details This module is responsible for handling the l2cap connection oriented channels. + */ + +#ifndef BLE_OTS_L2CAP_H__ +#define BLE_OTS_L2CAP_H__ + +#include +#include "ble_ots.h" + +/**@brief Function for initializing the Object Transfer Service l2cap module. + * + * @param[out] p_ots_l2cap Object Transfer Service l2cap structure. This structure will have to be + * supplied by the application. It will be initialized by this function, * and will later be used to identify this particular instance. + * @param[in] p_ots_l2cap_init Information needed to initialize the service. + * + * @return NRF_SUCCESS on successful initialization, otherwise an error code. + */ +uint32_t ble_ots_l2cap_init(ble_ots_l2cap_t * p_ots_l2cap, ble_ots_l2cap_init_t * p_ots_l2cap_init); + +/**@brief Function for handling the Application's BLE Stack events. + * + * @details Handles all events from the BLE stack of interest to the l2cap module. + * + * @param[in] p_ots_l2cap Object transfer service l2cap module structure. + * @param[in] p_ble_evt Event received from the BLE stack. + */ +void ble_ots_l2cap_on_ble_evt(ble_ots_l2cap_t * p_ots_l2cap, ble_evt_t const * p_ble_evt); + +/**@brief Function starting to send the data in the transfer buffer. + * + * @param[in] p_ots_l2cap Object transfer service l2cap module structure. + * @param[in] p_data Pointer to the data to be sent. + * @param[in] data_len The length of the data to be sent. + * + * @return NRF_SUCCESS If the transmission was started. + * @return NRF_ERROR_INVALID_STATE When in an invalid state. Otherwise an other error code. + */ +uint32_t ble_ots_l2cap_start_send(ble_ots_l2cap_t * p_ots_l2cap, uint8_t * p_data, uint16_t data_len); + +/**@brief Function starting to receive data to the transfer buffer. + * + * @param[in] p_ots_l2cap Object transfer service l2cap module structure. + * @param[in] len The length of the data to be received. + * + * @return NRF_SUCCESS If the transmission was started. + * @return NRF_ERROR_INVALID_STATE When in an invalid state. Otherwise an other error code. + */ +uint32_t ble_ots_l2cap_start_recv(ble_ots_l2cap_t * p_ots_l2cap, uint16_t len); + +/**@brief Function that checks if the channel is available for transmission. + * + * @param[in] p_ots_l2cap Object transfer service l2cap module structure. + * + * @return true if the channel is available. + */ +bool ble_ots_l2cap_is_channel_available(ble_ots_l2cap_t * p_ots_l2cap); + +/**@brief Function starting to abort the current transmission. + * + * @param[in] p_ots_l2cap Object transfer service l2cap module structure. + * + * @return NRF_SUCCESS If the transmission was aborted. + * @return NRF_ERROR_INVALID_STATE When in an invalid state. Otherwise an other error code. + */ +uint32_t ble_ots_l2cap_abort_transmission(ble_ots_l2cap_t * p_ots_l2cap); + +#endif // BLE_OTS_L2CAP_H__ + +/** @} */ // End tag for the file. + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_oacp.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_oacp.c new file mode 100644 index 0000000..1357b29 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_oacp.c @@ -0,0 +1,606 @@ +/** + * Copyright (c) 2017 - 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. + * + */ +#include "ble_ots_oacp.h" + +#include +#include "fds.h" +#include "crc32.h" + +#include "ble_ots.h" +#include "ble_ots_l2cap.h" +#include "ble_ots_object.h" + +#define NRF_LOG_MODULE_NAME ble_ots_oacp +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define OTS_FILE_ID 1234 +#define OTS_FDS_KEY 4321 + + +/**@brief Checks if the cccd handle is configured for indication + * + * @param[in] cccd_handle The CCCD handle. + */ +bool is_cccd_configured(ble_ots_oacp_t * const p_ots_oacp) +{ + uint32_t err_code; + uint8_t cccd_value_buf[BLE_CCCD_VALUE_LEN]; + bool is_oacp_indic_enabled = false; + ble_gatts_value_t gatts_value; + + uint16_t cccd_handle = p_ots_oacp->oacp_handles.cccd_handle; + uint16_t conn_handle = p_ots_oacp->p_ots->conn_handle; + // Initialize value struct. + memset(&gatts_value, 0, sizeof(gatts_value)); + + gatts_value.len = BLE_CCCD_VALUE_LEN; + gatts_value.offset = 0; + gatts_value.p_value = cccd_value_buf; + + err_code = sd_ble_gatts_value_get(conn_handle, + cccd_handle, + &gatts_value); + if (err_code != NRF_SUCCESS) + { + // Report error to application + if (p_ots_oacp->p_ots->error_handler != NULL) + { + p_ots_oacp->p_ots->error_handler(err_code); + } + } + + is_oacp_indic_enabled = ble_srv_is_indication_enabled(cccd_value_buf); + + return is_oacp_indic_enabled; +} + + + +/** @brief This is the l2cap connection oriented channel event handler. + * + * @param[in] p_ots_l2cap Pointer to the l2cap module + * @param[in] p_evt The pointer to the event. + */ +static void ots_l2cap_evt_handler(ble_ots_l2cap_t * p_ots_l2cap, ble_ots_l2cap_evt_t * p_evt) +{ + uint32_t err_code; + + switch (p_evt->type) + { + case BLE_OTS_L2CAP_EVT_CH_CONNECTED: + NRF_LOG_INFO("BLE_OTS_L2CAP_EVT_CH_CONNECTED."); + break; + case BLE_OTS_L2CAP_EVT_CH_DISCONNECTED: + NRF_LOG_INFO("BLE_OTS_L2CAP_EVT_CH_DISCONNECTED."); + break; + case BLE_OTS_L2CAP_EVT_SEND_COMPLETE: + p_ots_l2cap->p_ots_oacp->p_ots->p_current_object->is_locked = false; + break; + case BLE_OTS_L2CAP_EVT_RECV_COMPLETE: + NRF_LOG_INFO("BLE_OTS_L2CAP_EVT_RECV_COMPLETE."); + memcpy(p_ots_l2cap->p_ots_oacp->p_ots->p_current_object->data, + p_ots_l2cap->rx_params.sdu_buf.p_data, + p_ots_l2cap->rx_params.sdu_buf.len); + err_code = ble_ots_object_set_current_size(&p_ots_l2cap->p_ots_oacp->p_ots->object_chars, + p_ots_l2cap->p_ots_oacp->p_ots->p_current_object, + p_ots_l2cap->p_ots_oacp->p_ots->p_current_object->current_size); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("ble_ots_object_set_current_size returned error 0x%x", err_code); + } + ble_ots_evt_t evt; + evt.type = BLE_OTS_EVT_OBJECT_RECEIVED; + p_ots_l2cap->p_ots_oacp->p_ots->evt_handler(p_ots_l2cap->p_ots_oacp->p_ots, &evt); + break; + } +} + + +/**@brief Adds the OACP characteristic + * + * @param[in] p_ots_oacp Pointer to the OACP structure. + * @param[in] service_handle The service handle to attach the characteristic to. + * @param[in] write_access The write security level for the OACP value handle. + * @param[in] cccd_write_access The write security level for the OACP cccd handle. + * + * @return NRF_SUCCESS When added successfully, else an error code from characteristic_add(). + */ +static uint32_t oacp_char_add(ble_ots_oacp_t * const p_ots_oacp, + uint16_t service_handle, + security_req_t write_access, + security_req_t cccd_write_access) +{ + ble_add_char_params_t add_char_params; + memset(&add_char_params, 0, sizeof(add_char_params)); + + add_char_params.uuid = BLE_UUID_OTS_OACP; + add_char_params.uuid_type = BLE_UUID_TYPE_BLE; + add_char_params.max_len = BLE_OTS_MAX_OACP_SIZE; + add_char_params.init_len = 0; + add_char_params.is_var_len = 1; + add_char_params.char_props.indicate = true; + add_char_params.char_props.write = true; + add_char_params.cccd_write_access = cccd_write_access; + //add_char_params.is_defered_write = true; + add_char_params.write_access = write_access; + + return characteristic_add(service_handle, + &add_char_params, + &p_ots_oacp->oacp_handles); +} + + +/**@brief Handling the OACP write procedure. + * + * @details The object is opened, and a l2cap transfer is started. + * + * @param[in] p_ots_oacp Pointer to the OACP structure. + * @param[in] offset The offset for where the read should start. + * @param[in] length The length of the read. + */ +static inline ble_ots_oacp_res_code_t oacp_write_proc(ble_ots_oacp_t * p_ots_oacp, + uint32_t offset, + uint32_t length, + uint8_t mode) +{ + uint32_t err_code; + + if (p_ots_oacp->p_ots->p_current_object == NULL) + { + return BLE_OTS_OACP_RES_INV_OBJ; + } + if (p_ots_oacp->p_ots->p_current_object->is_valid == false) + { + return BLE_OTS_OACP_RES_INV_OBJ; + } + + + if (p_ots_oacp->p_ots->p_current_object->properties.decoded.is_write_permitted == false) + { + return BLE_OTS_OACP_RES_NOT_PERMITTED; + } + + if (ble_ots_l2cap_is_channel_available(&p_ots_oacp->ots_l2cap) == false) + { + return BLE_OTS_OACP_RES_CHAN_UNAVAIL; + } + + if (length + offset > p_ots_oacp->p_ots->p_current_object->alloc_len) + { + return BLE_OTS_OACP_RES_INV_PARAM; + } + + if (p_ots_oacp->p_ots->p_current_object->is_locked) + { + return BLE_OTS_OACP_RES_OBJ_LOCKED; + } + + err_code = ble_ots_l2cap_start_recv(&p_ots_oacp->ots_l2cap, length); + if (err_code != NRF_SUCCESS) + { + return BLE_OTS_OACP_RES_OPER_FAILED; + } + + ble_ots_evt_t ble_ots_evt; + + ble_ots_evt.type = BLE_OTS_EVT_OACP; + + ble_ots_evt.evt.oacp_evt.type = BLE_OTS_OACP_EVT_REQ_WRITE; + ble_ots_evt.evt.oacp_evt.evt.p_object = p_ots_oacp->p_ots->p_current_object; + + p_ots_oacp->p_ots->p_current_object->current_size = length; + + p_ots_oacp->p_ots->evt_handler(p_ots_oacp->p_ots, &ble_ots_evt); + + return BLE_OTS_OACP_RES_SUCCESS; +} + + + +/**@brief Handling the OACP read procedure. + * + * @details The object is opened, and a l2cap transfer is started. + * + * @param[in] p_ots_oacp Pointer to the OACP structure. + * @param[in] offset The offset for where the read should start. + * @param[in] length The length of the read. + */ +static inline ble_ots_oacp_res_code_t oacp_read_proc(ble_ots_oacp_t * p_ots_oacp, + uint32_t offset, + uint32_t length) +{ + + if (p_ots_oacp->p_ots->p_current_object == NULL) + { + return BLE_OTS_OACP_RES_INV_OBJ; + } + if (p_ots_oacp->p_ots->p_current_object->is_valid == false) + { + return BLE_OTS_OACP_RES_INV_OBJ; + } + + + if (p_ots_oacp->p_ots->p_current_object->properties.decoded.is_read_permitted == false) + { + return BLE_OTS_OACP_RES_NOT_PERMITTED; + } + + if (ble_ots_l2cap_is_channel_available(&p_ots_oacp->ots_l2cap) == false) + { + return BLE_OTS_OACP_RES_CHAN_UNAVAIL; + } + + if (length + offset > p_ots_oacp->p_ots->p_current_object->current_size) + { + return BLE_OTS_OACP_RES_INV_PARAM; + } + + if (p_ots_oacp->p_ots->p_current_object->is_locked) + { + return BLE_OTS_OACP_RES_OBJ_LOCKED; + } + + ble_ots_evt_t ble_ots_evt; + + ble_ots_evt.type = BLE_OTS_EVT_OACP; + + ble_ots_evt.evt.oacp_evt.type = BLE_OTS_OACP_EVT_REQ_READ; + ble_ots_evt.evt.oacp_evt.evt.p_object = p_ots_oacp->p_ots->p_current_object; + + p_ots_oacp->p_ots->evt_handler(p_ots_oacp->p_ots, &ble_ots_evt); + + ret_code_t err_code = ble_ots_l2cap_start_send(&p_ots_oacp->ots_l2cap, + p_ots_oacp->p_ots->p_current_object->data, + p_ots_oacp->p_ots->p_current_object->current_size); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("ble_ots_l2cap_start_send returned error 0x%x", err_code); + } + return BLE_OTS_OACP_RES_SUCCESS; +} + + +/**@brief Handling the OACP abort procedure. + * + * @details The transmission is aborted. + * + * @param[in] p_ots_oacp Pointer to the OACP structure. + */ +static inline ble_ots_oacp_res_code_t oacp_abort_proc(ble_ots_oacp_t * p_ots_oacp) +{ + uint32_t err_code; + + err_code = ble_ots_l2cap_abort_transmission(&p_ots_oacp->ots_l2cap); + if (err_code != NRF_SUCCESS) + { + return BLE_OTS_OACP_RES_OPER_FAILED; + } + + p_ots_oacp->p_ots->p_current_object->is_locked = false; + + ble_ots_evt_t ble_ots_evt; + + ble_ots_evt.type = BLE_OTS_EVT_OACP; + + ble_ots_evt.evt.oacp_evt.type = BLE_OTS_OACP_EVT_ABORT; + ble_ots_evt.evt.oacp_evt.evt.p_object = p_ots_oacp->p_ots->p_current_object; + p_ots_oacp->p_ots->evt_handler(p_ots_oacp->p_ots, &ble_ots_evt); + + return BLE_OTS_OACP_RES_SUCCESS; +} + +/**@brief Sending the oacp procedure response back to the client. + * + * @details Encodes and sends the response. + * + * @param[in] p_ots_oacp Pointer to the OACP structure. + * @param[in] req_op_code The operation code of the procedure. + * @param[in] result_code The result of the procedure. + * @param[in] conn_handle The connection handle to send the result to. + */ +static uint32_t ble_ots_oacp_response_send(ble_ots_oacp_t * p_ots_oacp, + ble_ots_oacp_proc_type_t req_op_code, + ble_ots_oacp_res_code_t result_code, + uint16_t conn_handle) +{ + uint16_t index = 0; + uint8_t * p_data; + ble_gatts_hvx_params_t *p_hvx_params; + + ble_hvx_t * p_hvx = ble_hvx_get_p_to_next_hvx(&p_ots_oacp->p_ots->hvx_buf); + p_data = p_hvx->data; + p_hvx_params = &p_hvx->params; + + p_data[index++] = BLE_OTS_OACP_PROC_RESP; + + // Encode the Request Op code + p_data[index++] = (uint8_t)req_op_code; + + // Encode the Result code. + p_data[index++] = (uint8_t)result_code; + + + memset(p_hvx_params, 0, sizeof(ble_gatts_hvx_params_t)); + + p_hvx_params->handle = p_ots_oacp->oacp_handles.value_handle; + p_hvx_params->type = BLE_GATT_HVX_INDICATION; + p_hvx_params->offset = 0; + p_hvx_params->p_len = &index; + p_hvx_params->p_data = p_data; + + return ble_hvx_buffer_process(&p_ots_oacp->p_ots->hvx_buf); +} + +/**@brief Decode an OACP command, and extract its data. + * + * @param[in] p_ble_write_evt The write event from BLE stack. + * @param[out] p_proc The decoded OACP procedure is sent out. + * + * @return BLE_OTS_WRITE_SUCCESS If the filter was decoded correctly, else an error code. + */ +static inline ble_ots_oacp_res_code_t decode_oacp_command(ble_gatts_evt_write_t const * p_ble_write_evt, + ble_ots_oacp_proc_t * p_proc) +{ + uint32_t index = 0; + + p_proc->type = (ble_ots_oacp_proc_type_t)p_ble_write_evt->data[index++]; + + switch (p_proc->type) + { + case BLE_OTS_OACP_PROC_READ: + if (p_ble_write_evt->len != + sizeof(p_proc->params.read_params.offset) + + sizeof(p_proc->params.read_params.length) + + index) + { + return BLE_OTS_OACP_RES_INV_PARAM; + } +/*lint --e{415} --e{416} -save suppress Warning 415: Likely access of out-of-bounds pointer */ + p_proc->params.read_params.offset = uint32_decode(&(p_ble_write_evt->data[index])); + index += 4; + p_proc->params.read_params.length = uint32_decode(&(p_ble_write_evt->data[index])); +/*lint -restore*/ + break; + //return BLE_OTS_OACP_RES_SUCCESS; + case BLE_OTS_OACP_PROC_WRITE: + p_proc->params.write_params.offset = uint32_decode(&(p_ble_write_evt->data[index])); + index += sizeof(uint32_t); + p_proc->params.write_params.length = uint32_decode(&(p_ble_write_evt->data[index])); + index += sizeof(uint32_t); + p_proc->params.write_params.write_mode = p_ble_write_evt->data[index]; + break; + default: + // No implementation needed + break; + } + return BLE_OTS_OACP_RES_SUCCESS; +} + + +/**@brief Function for handling the BLE_GAP_EVT_DISCONNECTED event. + * + * @param[in] p_ots_oacp OTS OACP Structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static inline void on_disconnect(ble_ots_oacp_t * p_ots_oacp, ble_evt_t const * p_ble_evt) +{ + uint32_t err_code; + err_code = fds_gc(); + if (err_code != NRF_SUCCESS) + { + p_ots_oacp->p_ots->error_handler(err_code); + } + +} + + +/**@brief Function for handling the write events to the Blood Pressure Measurement characteristic. + * + * @param[in] p_bps Blood Pressure Service structure. + * @param[in] p_evt_write Write event received from the BLE stack. + */ +static void on_cccd_write(ble_ots_oacp_t * p_ots_oacp, ble_gatts_evt_write_t const * p_evt_write) +{ + if (p_evt_write->len == 2) + { + // CCCD written, update indication state + if (p_ots_oacp->p_ots->evt_handler != NULL) + { + ble_ots_evt_t evt; + + if (ble_srv_is_indication_enabled(p_evt_write->data)) + { + evt.type = BLE_OTS_EVT_INDICATION_ENABLED; + } + else + { + evt.type = BLE_OTS_EVT_INDICATION_DISABLED; + } + + p_ots_oacp->p_ots->evt_handler(p_ots_oacp->p_ots, &evt); + } + } +} + + +static void on_oacp_write(ble_ots_oacp_t * p_ots_oacp, ble_gatts_evt_write_t const * p_ble_evt_write) +{ + ret_code_t err_code; + ble_ots_oacp_res_code_t oacp_status; + ble_ots_oacp_proc_t oacp_proc; + + memset(&oacp_proc, 0, sizeof(oacp_proc)); + + oacp_status = decode_oacp_command(p_ble_evt_write, &oacp_proc); + + if (oacp_status == BLE_OTS_OACP_RES_SUCCESS) + { + oacp_status = ble_ots_oacp_do_proc(p_ots_oacp, &oacp_proc); + } + + err_code = ble_ots_oacp_response_send(p_ots_oacp, + oacp_proc.type, + oacp_status, + p_ots_oacp->p_ots->conn_handle); + + if (err_code != NRF_SUCCESS) + { + p_ots_oacp->p_ots->error_handler(err_code); + } +} + + + +/**@brief Function for handling the Write event. + * + * @param[in] p_bps Blood Pressure Service structure. + * @param[in] p_ble_evt Event received from the BLE stack. + */ +static void on_write(ble_ots_oacp_t * p_ots_oacp, ble_evt_t const * p_ble_evt) +{ + ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write; + + if (p_evt_write->handle == p_ots_oacp->p_ots->oacp_chars.oacp_handles.cccd_handle) + { + on_cccd_write(p_ots_oacp, p_evt_write); + } + if (p_evt_write->handle == p_ots_oacp->p_ots->oacp_chars.oacp_handles.value_handle) + { + on_oacp_write(p_ots_oacp, p_evt_write); + } +} + + +void ble_ots_oacp_on_ble_evt(ble_ots_oacp_t * p_ots_oacp, ble_evt_t const * p_ble_evt) +{ + if ((p_ots_oacp == NULL) || (p_ble_evt == NULL)) + { + return; + } + + ble_ots_l2cap_on_ble_evt(&p_ots_oacp->ots_l2cap, p_ble_evt); + + switch (p_ble_evt->header.evt_id) + { + + case BLE_GAP_EVT_DISCONNECTED: + on_disconnect(p_ots_oacp, p_ble_evt); + break; + + case BLE_GATTS_EVT_WRITE: + on_write(p_ots_oacp, p_ble_evt); + break; + default: + // No implementation needed. + break; + } +} + +uint32_t ble_ots_oacp_init(ble_ots_oacp_t * p_ots_oacp, ble_ots_oacp_init_t * p_ots_oacp_init) +{ + uint32_t err_code; + + if (p_ots_oacp == NULL || p_ots_oacp_init == NULL) + { + return NRF_ERROR_NULL; + } + p_ots_oacp->p_ots = p_ots_oacp_init->p_ots; + p_ots_oacp->on_create_obj_properties_raw = p_ots_oacp_init->on_create_obj_properties_raw; + + ble_ots_l2cap_init_t l2cap_init; + + l2cap_init.p_ots_oacp = p_ots_oacp; + l2cap_init.evt_handler = ots_l2cap_evt_handler; + l2cap_init.p_transfer_buffer = p_ots_oacp_init->p_l2cap_buffer; + l2cap_init.buffer_len = p_ots_oacp_init->l2cap_buffer_len; + + err_code = ble_ots_l2cap_init(&p_ots_oacp->ots_l2cap, &l2cap_init); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + + return oacp_char_add(p_ots_oacp, + p_ots_oacp->p_ots->service_handle, + p_ots_oacp_init->write_access, + p_ots_oacp_init->cccd_write_access); +} + + +ble_ots_oacp_res_code_t ble_ots_oacp_do_proc(ble_ots_oacp_t * p_ots_oacp, + ble_ots_oacp_proc_t * p_oacp_proc) +{ + if (p_ots_oacp == NULL || p_oacp_proc == NULL) + { + return BLE_OTS_OACP_RES_INV_PARAM; + } + + ble_ots_oacp_res_code_t oacp_status; + + switch (p_oacp_proc->type) + { + case BLE_OTS_OACP_PROC_WRITE: + oacp_status = oacp_write_proc(p_ots_oacp, + p_oacp_proc->params.write_params.offset, + p_oacp_proc->params.write_params.length, + p_oacp_proc->params.write_params.write_mode); + break; + case BLE_OTS_OACP_PROC_READ: + oacp_status = oacp_read_proc(p_ots_oacp, + p_oacp_proc->params.read_params.offset, + p_oacp_proc->params.read_params.length); + break; + + case BLE_OTS_OACP_PROC_ABORT: + oacp_status = oacp_abort_proc(p_ots_oacp); + break; + + default: + // Unsupported op code. + oacp_status = BLE_OTS_OACP_RES_OPCODE_NOT_SUP; + + } + return oacp_status; +} + + + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_oacp.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_oacp.h new file mode 100644 index 0000000..9f41204 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_oacp.h @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2017 - 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_sdk_srv_ots_oacp Object Transfer Service, OACP handling + * @{ + * @ingroup ble_ots + * @brief Object Transfer Service module + * + * @details This module is responsible for handling the Object Transfer Service + * Object Action Control Point. + */ +#ifndef BLE_OTS_OACP_H__ +#define BLE_OTS_OACP_H__ + +#include +#include "ble_ots.h" + +/**@brief Function for initializing the Object Transfer OACP characteristic. + * + * @param[out] p_ots_oacp Object Transfer Service OACP structure. This structure will have + * to be supplied by the application. It will be initialized by this function, + * and will later be used to identify this particular instance. + * @param[in] p_ots_oacp_init Information needed to initialize the module. + * + * @return NRF_SUCCESS on successful initialization, otherwise an error code. + */ +uint32_t ble_ots_oacp_init(ble_ots_oacp_t * p_ots_oacp, ble_ots_oacp_init_t * p_ots_oacp_init); + +/**@brief Function for handling the Application's BLE Stack events. + * + * @details Handles all events from the BLE stack of interest to the OACP module. + * + * @param[in] p_ots_oacp Object Transfer Service OACP structure + * @param[in] p_ble_evt Event received from the BLE stack. + */ +void ble_ots_oacp_on_ble_evt(ble_ots_oacp_t * p_ots_oacp, ble_evt_t const * p_ble_evt); + +/**@brief Execute an Object Action Control Point procedure + * + * @param[in] p_ots_oacp Object Transfer Service OACP structure. + * @param[in] p_oacp_proc Pointer to the procedure to be applied. + * + * @return BLE_OTS_WRITE_SUCCESS on success, otherwise an error. + */ +ble_ots_oacp_res_code_t ble_ots_oacp_do_proc(ble_ots_oacp_t * p_ots_oacp, + ble_ots_oacp_proc_t * p_oacp_proc); + + +#endif // BLE_OTS_OACP_H__ + +/** @} */ // End tag for the file. diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_object.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_object.c new file mode 100644 index 0000000..0abc39d --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_object.c @@ -0,0 +1,577 @@ +/** + * Copyright (c) 2017 - 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. + * + */ +#include "ble_ots_object.h" + +#include +#include "ble_srv_common.h" + +#include "ble_ots.h" + +#define BLE_OTS_WRITE_REQUEST_REJECTED 0x80 + +#define BLE_OTS_OBJECT_NOT_SELECTED 0x81 +#define BLE_OTS_CONCURRENCY_LIMIT_EXCEEDED 0x82 +#define BLE_OTS_OBJ_NAME_ALREADY_EXISTS 0x83 +#define BLE_SIZE_DATE_TIME 7 + + +uint32_t ble_ots_object_refresh_current(ble_ots_object_chars_t * p_ots_object_chars) +{ + uint32_t err_code; + ble_ots_object_t * p_obj; + + p_obj = p_ots_object_chars->p_ots->p_current_object; + + if (p_obj == NULL) + { + // Clear all characteristics + return NRF_SUCCESS; + } + + + // obtain the largest necessary buffer + typedef union { + uint8_t type_buf[sizeof(ble_ots_obj_type_t)+sizeof(uint8_t)]; + uint8_t size_buf[2*sizeof(uint32_t)]; + uint8_t prop_buf[sizeof(uint32_t)]; + } buffer_t; + + buffer_t buffer; + + ble_gatts_value_t gatts_value; + + memset(&gatts_value, 0, sizeof(gatts_value)); + + // name + gatts_value.len = strlen((const char *)p_obj->name) + 1; + gatts_value.p_value = p_obj->name; + err_code = sd_ble_gatts_value_set(p_ots_object_chars->p_ots->conn_handle, + p_ots_object_chars->obj_name_handles.value_handle, + &gatts_value); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + // type + if (p_obj->type.len == sizeof(uint16_t)) + { + gatts_value.len = uint16_encode(p_obj->type.param.type16, buffer.type_buf); + gatts_value.p_value = buffer.type_buf; + err_code = sd_ble_gatts_value_set(p_ots_object_chars->p_ots->conn_handle, + p_ots_object_chars->obj_type_handles.value_handle, + &gatts_value); + } + else + { + gatts_value.len = uint16_encode(p_obj->type.param.type16, buffer.type_buf); + gatts_value.p_value = p_obj->type.param.type128; + err_code = sd_ble_gatts_value_set(p_ots_object_chars->p_ots->conn_handle, + p_ots_object_chars->obj_type_handles.value_handle, + &gatts_value); + } + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + gatts_value.len = uint32_encode(p_obj->current_size, &buffer.size_buf[0]); + gatts_value.len += uint32_encode(p_obj->alloc_len, &buffer.size_buf[gatts_value.len]); + gatts_value.p_value = &buffer.size_buf[0]; + err_code = sd_ble_gatts_value_set(p_ots_object_chars->p_ots->conn_handle, + p_ots_object_chars->obj_size_handles.value_handle, + &gatts_value); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + gatts_value.len = uint32_encode(p_obj->properties.raw, buffer.prop_buf); + gatts_value.p_value = buffer.prop_buf; + err_code = sd_ble_gatts_value_set(p_ots_object_chars->p_ots->conn_handle, + p_ots_object_chars->obj_properties_handles.value_handle, + &gatts_value); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + return NRF_SUCCESS; +} + +/**@brief Function for adding the object name characteristic. + * + * @param[in] p_ots_object_chars Pointer the the object characteristics. + * @param[in] service_handle The service handle where the characteristic should be added. + * @param[in] read_access The read security level for the characteristic. + * @param[in] write_access The write security level for the characteristic. + * + * @return NRF_SUCCESS if the characteristic was successfully added, else a return code from + * characteristic_add(). + */ +static uint32_t obj_name_char_add(ble_ots_object_chars_t * const p_ots_object_chars, + uint16_t service_handle, + security_req_t read_access, + security_req_t write_access) +{ + ble_add_char_params_t add_char_params; + + memset(&add_char_params, 0, sizeof(add_char_params)); + + add_char_params.uuid = BLE_UUID_OTS_OBJECT_NAME; + add_char_params.uuid_type = BLE_UUID_TYPE_BLE; + add_char_params.max_len = BLE_OTS_NAME_MAX_SIZE; + add_char_params.is_var_len = 1; + add_char_params.char_props.read = 1; + add_char_params.read_access = read_access; + add_char_params.char_props.write = 0; + + return characteristic_add(service_handle, + &add_char_params, + &p_ots_object_chars->obj_name_handles); +} + +/**@brief Function for adding the object type characteristic. + * + * @param[in] p_ots_object_chars Pointer the the object characteristics. + * @param[in] service_handle The service handle where the characteristic should be added. + * @param[in] read_access The read security level for the characteristic. + * + * @return NRF_SUCCESS if the characteristic was successfully added, else a return code from + * characteristic_add(). + */ +static uint32_t obj_type_char_add(ble_ots_object_chars_t * const p_ots_object_chars, + uint16_t service_handle, + security_req_t read_access) +{ + ble_add_char_params_t add_char_params; + + memset(&add_char_params, 0, sizeof(add_char_params)); + + add_char_params.uuid = BLE_UUID_OTS_OBJECT_TYPE; + add_char_params.uuid_type = BLE_UUID_TYPE_BLE; + add_char_params.max_len = sizeof(ble_ots_obj_type_t); + add_char_params.is_var_len = 1; + add_char_params.char_props.read = 1; + add_char_params.read_access = read_access; + + return characteristic_add(service_handle, + &add_char_params, + &p_ots_object_chars->obj_type_handles); +} + +/**@brief Function for adding the object size characteristic. + * + * @param[in] p_ots_object_chars Pointer the the object characteristics. + * @param[in] service_handle The service handle where the characteristic should be added. + * @param[in] read_access The read security level for the characteristic. + * + * @return NRF_SUCCESS if the characteristic was successfully added, else a return code from + * characteristic_add(). + */ +static uint32_t obj_size_char_add(ble_ots_object_chars_t * const p_ots_object_chars, + uint16_t service_handle, + security_req_t read_access) +{ + ble_add_char_params_t add_char_params; + + memset(&add_char_params, 0, sizeof(add_char_params)); + + add_char_params.uuid = BLE_UUID_OTS_OBJECT_SIZE; + add_char_params.uuid_type = BLE_UUID_TYPE_BLE; + add_char_params.max_len = NRF_BLE_OTS_SIZE_CHAR_LEN; + add_char_params.is_var_len = 0; + add_char_params.char_props.read = 1; + add_char_params.read_access = read_access; + + return characteristic_add(service_handle, + &add_char_params, + &p_ots_object_chars->obj_size_handles); +} + +/**@brief Function for adding the object properties characteristic. + * + * @param[in] p_ots_object_chars Pointer the the object characteristics. + * @param[in] service_handle The service handle where the characteristic should be added. + * @param[in] read_access The read security level for the characteristic. + * @param[in] write_access The write security level for the characteristic. + * + * @return NRF_SUCCESS if the characteristic was successfully added, else a return code from + * characteristic_add(). + */ +static uint32_t obj_prop_char_add(ble_ots_object_chars_t * const p_ots_object_chars, + uint16_t service_handle, + security_req_t read_access, + security_req_t write_access) +{ + ble_add_char_params_t add_char_params; + + memset(&add_char_params, 0, sizeof(add_char_params)); + + add_char_params.uuid = BLE_UUID_OTS_OBJECT_PROPERTIES; + add_char_params.uuid_type = BLE_UUID_TYPE_BLE; + add_char_params.max_len = sizeof(uint32_t); + add_char_params.is_var_len = 0; + add_char_params.char_props.read = 1; + add_char_params.read_access = read_access; + + add_char_params.is_defered_write = 1; + add_char_params.write_access = write_access; + + return characteristic_add(service_handle, + &add_char_params, + &p_ots_object_chars->obj_properties_handles); +} + + + + + +uint32_t ble_ots_object_representation_init(ble_ots_object_chars_t * p_ots_object_chars, + ble_ots_object_chars_init_t * p_ots_object_chars_init) +{ + if (p_ots_object_chars == NULL || p_ots_object_chars_init == NULL) + { + return NRF_ERROR_NULL; + } + + uint32_t err_code; + + p_ots_object_chars->p_ots = p_ots_object_chars_init->p_ots; + + err_code = obj_name_char_add(p_ots_object_chars, + p_ots_object_chars_init->p_ots->service_handle, + p_ots_object_chars_init->name_read_access, + p_ots_object_chars_init->name_write_access); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + err_code = obj_type_char_add(p_ots_object_chars, + p_ots_object_chars_init->p_ots->service_handle, + p_ots_object_chars_init->type_read_access); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + err_code = obj_size_char_add(p_ots_object_chars, + p_ots_object_chars_init->p_ots->service_handle, + p_ots_object_chars_init->size_read_access); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + err_code = obj_prop_char_add(p_ots_object_chars, + p_ots_object_chars_init->p_ots->service_handle, + p_ots_object_chars_init->properties_read_access, + p_ots_object_chars_init->properties_write_access); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + return ble_ots_object_refresh_current(p_ots_object_chars); +} + + +uint32_t ble_ots_object_set_name(ble_ots_object_chars_t * p_ots_object_chars, + ble_ots_object_t * p_object, + const char * new_name) +{ + if (p_ots_object_chars == NULL || p_object == NULL || new_name == NULL) + { + return NRF_ERROR_NULL; + } + + + + strncpy((char *)p_object->name, new_name, BLE_OTS_NAME_MAX_SIZE); + + if (p_object == p_ots_object_chars->p_ots->p_current_object) + { + // update characteristic + uint32_t err_code; + ble_gatts_value_t gatts_value; + + memset(&gatts_value, 0, sizeof(gatts_value)); + + gatts_value.len = strlen((const char *)p_object->name) + 1; + gatts_value.p_value = p_object->name; + err_code = sd_ble_gatts_value_set(p_ots_object_chars->p_ots->conn_handle, + p_ots_object_chars->obj_name_handles.value_handle, + &gatts_value); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + } + + + return NRF_SUCCESS; +} + +uint32_t ble_ots_object_set_type(ble_ots_object_chars_t * p_ots_object_chars, + ble_ots_object_t * p_object, + ble_ots_obj_type_t * p_new_type) +{ + if (p_ots_object_chars == NULL || p_object == NULL || p_new_type == NULL) + { + return NRF_ERROR_NULL; + } + + if (p_new_type->len != sizeof(p_new_type->param.type16) && p_new_type->len != sizeof(p_new_type->param.type128)) + { + return NRF_ERROR_INVALID_PARAM; + } + + memcpy(&p_object->type, p_new_type, sizeof(ble_ots_obj_type_t)); + + if (p_object == p_ots_object_chars->p_ots->p_current_object) + { + // update characteristic + uint32_t err_code; + uint8_t buffer[sizeof(p_new_type->param.type16)]; + ble_gatts_value_t gatts_value; + + memset(&gatts_value, 0, sizeof(gatts_value)); + + if (p_object->type.len == sizeof(uint16_t)) + { + gatts_value.len = uint16_encode(p_object->type.param.type16, buffer); + gatts_value.p_value = buffer; + err_code = sd_ble_gatts_value_set(p_ots_object_chars->p_ots->conn_handle, + p_ots_object_chars->obj_type_handles.value_handle, + &gatts_value); + } + else + { + gatts_value.len = uint16_encode(p_object->type.param.type16, buffer); + gatts_value.p_value = p_object->type.param.type128; + err_code = sd_ble_gatts_value_set(p_ots_object_chars->p_ots->conn_handle, + p_ots_object_chars->obj_type_handles.value_handle, + &gatts_value); + } + if (err_code != NRF_SUCCESS) + { + return err_code; + } + } + + + return NRF_SUCCESS; + +} + +uint32_t ble_ots_object_set_current_size(ble_ots_object_chars_t * p_ots_object_chars, + ble_ots_object_t * p_object, + uint32_t new_current_size) +{ + if (p_ots_object_chars == NULL || p_object == NULL) + { + return NRF_ERROR_NULL; + } + + p_object->current_size = new_current_size; + + if (p_object == p_ots_object_chars->p_ots->p_current_object) + { + // update characteristic + uint32_t err_code; + uint8_t buffer[NRF_BLE_OTS_SIZE_CHAR_LEN]; + ble_gatts_value_t gatts_value; + + memset(&gatts_value, 0, sizeof(gatts_value)); + + gatts_value.len = 0; + gatts_value.len += uint32_encode(p_object->current_size, &buffer[gatts_value.len]); + gatts_value.len += uint32_encode(p_object->alloc_len, &buffer[gatts_value.len]); + gatts_value.p_value = &buffer[0]; + err_code = sd_ble_gatts_value_set(p_ots_object_chars->p_ots->conn_handle, + p_ots_object_chars->obj_size_handles.value_handle, + &gatts_value); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + } + + + return NRF_SUCCESS; + +} + + +/**@brief Function for handling write on object properties meta data. + * + * @param[in] p_ots_object_chars Pointer the the object characteristics. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static uint32_t on_obj_properties_write(ble_ots_object_chars_t * p_ots_object_chars, + ble_evt_t const * p_ble_evt) +{ +// uint32_t err_code; + ble_gatts_rw_authorize_reply_params_t write_authorize_reply; + ble_gatts_evt_write_t const * p_write_evt; + + p_write_evt = &p_ble_evt->evt.gatts_evt.params.authorize_request.request.write; + + write_authorize_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; + + uint32_t raw_prop = uint32_decode(p_write_evt->data); + if ((raw_prop & 0xFFFFFF80) != 0) + { + write_authorize_reply.params.write.gatt_status = BLE_OTS_WRITE_REQUEST_REJECTED; + } + else + { + p_ots_object_chars->p_ots->p_current_object->properties.raw = raw_prop; + write_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; + + ble_ots_evt_t ble_ots_evt; + + ble_ots_evt.type = BLE_OTS_EVT_OBJECT; + + ble_ots_evt.evt.object_evt.type = BLE_OTS_OBJECT_EVT_PROPERTIES_CHANGED; + ble_ots_evt.evt.object_evt.evt.p_object = p_ots_object_chars->p_ots->p_current_object; + p_ots_object_chars->p_ots->evt_handler(p_ots_object_chars->p_ots, &ble_ots_evt); + + } + return sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gatts_evt.conn_handle, &write_authorize_reply); +} + +uint32_t ble_ots_object_set_properties(ble_ots_object_chars_t * p_ots_object_chars, + ble_ots_object_t * p_object, + ble_ots_obj_properties_t * p_new_properties) +{ + if (p_ots_object_chars == NULL || p_object == NULL) + { + return NRF_ERROR_NULL; + } + + memcpy(&p_object->properties, p_new_properties, sizeof(ble_ots_obj_properties_t)); + + + if (p_object == p_ots_object_chars->p_ots->p_current_object) + { + // update characteristic + uint32_t err_code; + uint8_t buffer[sizeof(ble_ots_obj_properties_t)]; + ble_gatts_value_t gatts_value; + + memset(&gatts_value, 0, sizeof(gatts_value)); + + gatts_value.len = uint32_encode(p_object->properties.raw, buffer); + gatts_value.p_value = buffer; + err_code = sd_ble_gatts_value_set(p_ots_object_chars->p_ots->conn_handle, + p_ots_object_chars->obj_properties_handles.value_handle, + &gatts_value); + + if (err_code != NRF_SUCCESS) + { + return err_code; + } + } + + return NRF_SUCCESS; +} + + +/**@brief Function for handling the @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST event. + * + * @param[in] p_ots_object_chars Pointer the the object characteristics. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static void on_rw_auth_req(ble_ots_object_chars_t * p_ots_object_chars, ble_evt_t const * p_ble_evt) +{ + uint32_t err_code; + ble_gatts_evt_rw_authorize_request_t const * p_authorize_request; + + p_authorize_request = &(p_ble_evt->evt.gatts_evt.params.authorize_request); + + if (p_authorize_request->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) + { + if (p_authorize_request->request.write.handle == p_ots_object_chars->obj_name_handles.value_handle) + { + //err_code = on_name_prepare_write(p_ots_object_chars, p_ble_evt); + + // if (err_code != NRF_SUCCESS) + // { + // p_ots_object_chars->p_ots->error_handler(err_code); + // } + } + else + if (p_authorize_request->request.write.handle == p_ots_object_chars->obj_properties_handles.value_handle) + { + err_code = on_obj_properties_write(p_ots_object_chars, p_ble_evt); + if (err_code != NRF_SUCCESS) + { + p_ots_object_chars->p_ots->error_handler(err_code); + } + } + } +} + + +void ble_ots_object_on_ble_evt(ble_ots_object_chars_t * p_ots_chars, ble_evt_t const * p_ble_evt) +{ + if ((p_ots_chars == NULL) || (p_ble_evt == NULL)) + { + return; + } +// uint32_t err_code; + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: +// err_code = ble_ots_object_refresh_current(p_ots_chars); +// if (err_code != NRF_SUCCESS) +// { +// p_ots_chars->p_ots->error_handler(err_code); +// } + break; + + case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: + on_rw_auth_req(p_ots_chars, p_ble_evt); + break; + + default: + // No implementation needed. + break; + } +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_object.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_object.h new file mode 100644 index 0000000..b42a24d --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_ble_ots/ble_ots_object.h @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2017 - 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_sdk_srv_ots_obj Object Transfer Service, Object characteristics + * @{ + * @ingroup ble_ots + * @brief Object Transfer Service module + * + * @details This module is responsible for the object properties characteristics. + */ + +#ifndef BLE_OTS_OBJECT_H__ +#define BLE_OTS_OBJECT_H__ + +#include +#include "ble_ots.h" + +/**@brief Function for initializing the Object Transfer Object representation characteristics. + * + * @param[out] p_ots_object_chars Object Transfer Service object characteristics representation structure. * This structure will have to be supplied by the application. It * will be initialized by this function, and will later be used to * identify this particular instance. + * @param[in] p_ots_object_chars_init Information needed to initialize the module. + * + * @return NRF_SUCCESS on successful initialization, otherwise an error code. + */ +uint32_t ble_ots_object_representation_init(ble_ots_object_chars_t * p_ots_object_chars, + ble_ots_object_chars_init_t * p_ots_object_chars_init); + +/**@brief Refresh the characteristics of the current object. + * @param[in] p_ots_object_chars Pointer the the object characteristics. + * @return NRF_SUCCESS if everything was refreshed. + */ +uint32_t ble_ots_object_refresh_current(ble_ots_object_chars_t * p_ots_object_chars); + + +/**@brief Function for handling the Application's BLE Stack events. + * + * @details Handles all events from the BLE stack of interest to the list filter module. + * + * @param[in] p_ots_object_chars Pointer the the object characteristics. + * @param[in] p_ble_evt Event received from the BLE stack. + */ +void ble_ots_object_on_ble_evt(ble_ots_object_chars_t * p_ots_object_chars, + ble_evt_t const * p_ble_evt); + +#endif // BLE_OTS_OBJECT_H__ + +/** @} */ // End tag for the file. -- cgit v1.2.3