初始版本
This commit is contained in:
@@ -0,0 +1,476 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sdk_common.h"
|
||||
#if NRF_MODULE_ENABLED(BLE_OTS_C)
|
||||
#include <stdlib.h>
|
||||
#include "nrf_ble_ots_c.h"
|
||||
#include "nrf_ble_ots_c_oacp.h"
|
||||
#include "nrf_ble_ots_c_l2cap.h"
|
||||
#include "ble.h"
|
||||
|
||||
#define NRF_LOG_MODULE_NAME ble_ots_c
|
||||
#include "nrf_log.h"
|
||||
NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
#include "sdk_common.h"
|
||||
|
||||
|
||||
#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
|
||||
|
||||
#define MODULE_INITIALIZED (p_ots_c->initialized) /**< Macro designating whether the module was initialized properly. */
|
||||
|
||||
static const ble_uuid_t m_ots_uuid = {BLE_UUID_OTS_SERVICE, BLE_UUID_TYPE_BLE}; /**< Object Transfer Service UUID. */
|
||||
|
||||
|
||||
/**@brief Function for intercepting the errors of GATTC and the BLE GATT Queue.
|
||||
*
|
||||
* @param[in] nrf_error Error code.
|
||||
* @param[in] p_ctx Parameter from the event handler.
|
||||
* @param[in] conn_handle Connection handle.
|
||||
*/
|
||||
static void gatt_error_handler(uint32_t nrf_error,
|
||||
void * p_ctx,
|
||||
uint16_t conn_handle)
|
||||
{
|
||||
nrf_ble_ots_c_t * p_ots_c = (nrf_ble_ots_c_t *)p_ctx;
|
||||
|
||||
NRF_LOG_DEBUG("A GATT Client error has occurred on conn_handle: 0X%X", conn_handle);
|
||||
|
||||
if (p_ots_c->err_handler != NULL)
|
||||
{
|
||||
p_ots_c->err_handler(nrf_error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ret_code_t nrf_ble_ots_c_init(nrf_ble_ots_c_t * p_ots_c,
|
||||
nrf_ble_ots_c_init_t * p_ots_c_init)
|
||||
{
|
||||
ret_code_t err_code = NRF_SUCCESS;
|
||||
VERIFY_PARAM_NOT_NULL(p_ots_c);
|
||||
VERIFY_PARAM_NOT_NULL(p_ots_c_init);
|
||||
VERIFY_PARAM_NOT_NULL(p_ots_c_init->evt_handler);
|
||||
VERIFY_PARAM_NOT_NULL(p_ots_c_init->p_gatt_queue);
|
||||
|
||||
memset (p_ots_c, 0, sizeof(nrf_ble_ots_c_t));
|
||||
|
||||
p_ots_c->conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
p_ots_c->evt_handler = p_ots_c_init->evt_handler;
|
||||
p_ots_c->err_handler = p_ots_c_init->err_handler;
|
||||
p_ots_c->p_gatt_queue = p_ots_c_init->p_gatt_queue;
|
||||
p_ots_c->gatt_err_handler = gatt_error_handler;
|
||||
|
||||
err_code = ble_db_discovery_evt_register(&m_ots_uuid);
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
p_ots_c->initialized = true;
|
||||
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for checking whether the peer's Object Transfer Service instance has been discovered.
|
||||
|
||||
@param[in] p_ots_c Pointer to the GATT Service client structure instance.
|
||||
|
||||
@return True, if the Object Transfer service handles are valid.
|
||||
@return False, if the Object Transfer service handles are invalid.
|
||||
*/
|
||||
static bool ots_gatt_handles_are_valid(const nrf_ble_ots_c_t * const p_ots_c)
|
||||
{
|
||||
return (p_ots_c->service.object_prop_char.handle_value != BLE_GATT_HANDLE_INVALID
|
||||
&& p_ots_c->service.object_size_char.handle_value != BLE_GATT_HANDLE_INVALID
|
||||
&& p_ots_c->service.object_type_char.handle_value != BLE_GATT_HANDLE_INVALID
|
||||
&& p_ots_c->service.ots_feature_char.handle_value != BLE_GATT_HANDLE_INVALID);
|
||||
}
|
||||
|
||||
|
||||
ret_code_t nrf_ble_ots_c_feature_read(nrf_ble_ots_c_t * const p_ots_c)
|
||||
{
|
||||
VERIFY_MODULE_INITIALIZED();
|
||||
|
||||
nrf_ble_gq_req_t read_req;
|
||||
|
||||
memset(&read_req, 0, sizeof(nrf_ble_gq_req_t));
|
||||
|
||||
read_req.type = NRF_BLE_GQ_REQ_GATTC_READ;
|
||||
read_req.error_handler.cb = p_ots_c->gatt_err_handler;
|
||||
read_req.error_handler.p_ctx = (nrf_ble_ots_c_t *)p_ots_c;
|
||||
read_req.params.gattc_read.handle = p_ots_c->service.ots_feature_char.handle_value;
|
||||
read_req.params.gattc_read.offset = 0;
|
||||
|
||||
return nrf_ble_gq_item_add(p_ots_c->p_gatt_queue, &read_req, p_ots_c->conn_handle);
|
||||
}
|
||||
|
||||
|
||||
ret_code_t nrf_ble_ots_c_obj_size_read(nrf_ble_ots_c_t * const p_ots_c)
|
||||
{
|
||||
VERIFY_MODULE_INITIALIZED();
|
||||
|
||||
if( p_ots_c->service.object_size_char.handle_value == BLE_GATT_HANDLE_INVALID)
|
||||
{
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
nrf_ble_gq_req_t read_req;
|
||||
|
||||
memset(&read_req, 0, sizeof(nrf_ble_gq_req_t));
|
||||
|
||||
read_req.type = NRF_BLE_GQ_REQ_GATTC_READ;
|
||||
read_req.error_handler.cb = p_ots_c->gatt_err_handler;
|
||||
read_req.error_handler.p_ctx = (nrf_ble_ots_c_t *)p_ots_c;
|
||||
read_req.params.gattc_read.handle = p_ots_c->service.object_size_char.handle_value;
|
||||
read_req.params.gattc_read.offset = 0;
|
||||
|
||||
return nrf_ble_gq_item_add(p_ots_c->p_gatt_queue, &read_req, p_ots_c->conn_handle);
|
||||
}
|
||||
|
||||
|
||||
ret_code_t nrf_ble_ots_c_obj_properties_read(nrf_ble_ots_c_t * const p_ots_c)
|
||||
{
|
||||
VERIFY_MODULE_INITIALIZED();
|
||||
|
||||
if( p_ots_c->service.object_prop_char.handle_value == BLE_GATT_HANDLE_INVALID)
|
||||
{
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
nrf_ble_gq_req_t read_req;
|
||||
|
||||
memset(&read_req, 0, sizeof(nrf_ble_gq_req_t));
|
||||
|
||||
read_req.type = NRF_BLE_GQ_REQ_GATTC_READ;
|
||||
read_req.error_handler.cb = p_ots_c->gatt_err_handler;
|
||||
read_req.error_handler.p_ctx = (nrf_ble_ots_c_t *)p_ots_c;
|
||||
read_req.params.gattc_read.handle = p_ots_c->service.object_prop_char.handle_value;
|
||||
read_req.params.gattc_read.offset = 0;
|
||||
|
||||
return nrf_ble_gq_item_add(p_ots_c->p_gatt_queue, &read_req, p_ots_c->conn_handle);
|
||||
}
|
||||
|
||||
|
||||
static void prop_read_rsp_decode(nrf_ble_ots_c_t * p_ots_c, const ble_evt_t * p_ble_evt)
|
||||
{
|
||||
const ble_gattc_evt_read_rsp_t * p_response;
|
||||
p_response = &p_ble_evt->evt.gattc_evt.params.read_rsp;
|
||||
|
||||
uint32_t properties;
|
||||
properties = uint32_decode(&p_response->data[0]);
|
||||
|
||||
nrf_ble_ots_c_evt_t evt;
|
||||
evt.conn_handle = p_ble_evt->evt.gattc_evt.conn_handle;
|
||||
evt.params.prop.raw = properties;
|
||||
evt.evt_type = NRF_BLE_OTS_C_EVT_PROP_READ_RESP;
|
||||
p_ots_c->evt_handler(&evt);
|
||||
}
|
||||
|
||||
/**@brief Function for handling read response events.
|
||||
*
|
||||
* @details This function will validate the read response and raise the appropriate
|
||||
* event to the application.
|
||||
*
|
||||
* @param[in] p_ots_c Pointer to the Object Transfer instance.
|
||||
* @param[in] p_ble_evt Pointer to the SoftDevice event.
|
||||
*/
|
||||
static void on_read_rsp(nrf_ble_ots_c_t * p_ots_c, const ble_evt_t * p_ble_evt)
|
||||
{
|
||||
const ble_gattc_evt_read_rsp_t * p_response;
|
||||
|
||||
// Check if the event is on the link for this instance
|
||||
if (p_ots_c->conn_handle != p_ble_evt->evt.gattc_evt.conn_handle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
p_response = &p_ble_evt->evt.gattc_evt.params.read_rsp;
|
||||
|
||||
if (p_response->handle == p_ots_c->service.ots_feature_char.handle_value)
|
||||
{
|
||||
nrf_ble_ots_c_evt_t evt;
|
||||
|
||||
evt.conn_handle = p_ble_evt->evt.gattc_evt.conn_handle;
|
||||
evt.evt_type = NRF_BLE_OTS_C_EVT_FEATURE_READ_RESP;
|
||||
|
||||
uint32_t oacp_features;
|
||||
oacp_features = uint32_decode(&p_response->data[0]);
|
||||
evt.params.feature.oacp_create = oacp_features >> BLE_OTS_OACP_SUPPORT_FEATURE_CREATE_bp;
|
||||
evt.params.feature.oacp_delete = oacp_features >> BLE_OTS_OACP_SUPPORT_FEATURE_DELETE_bp;
|
||||
evt.params.feature.oacp_crc = oacp_features >> BLE_OTS_OACP_SUPPORT_FEATURE_CALC_CHECKSUM_bp;
|
||||
evt.params.feature.oacp_execute = oacp_features >> BLE_OTS_OACP_SUPPORT_FEATURE_EXECUTE_bp;
|
||||
evt.params.feature.oacp_read = oacp_features >> BLE_OTS_OACP_SUPPORT_FEATURE_READ_bp;
|
||||
evt.params.feature.oacp_write = oacp_features >> BLE_OTS_OACP_SUPPORT_FEATURE_WRITE_bp;
|
||||
evt.params.feature.oacp_append = oacp_features >> BLE_OTS_OACP_SUPPORT_FEATURE_APPEND_bp;
|
||||
evt.params.feature.oacp_truncate = oacp_features >> BLE_OTS_OACP_SUPPORT_FEATURE_TRUNCATE_bp;
|
||||
evt.params.feature.oacp_patch = oacp_features >> BLE_OTS_OACP_SUPPORT_FEATURE_PATCH_bp;
|
||||
evt.params.feature.oacp_abort = oacp_features >> BLE_OTS_OACP_SUPPORT_FEATURE_ABORT_bp;
|
||||
|
||||
uint32_t olcp_features;
|
||||
/*lint --e{415} --e{416} -save suppress Warning 415: Likely access of out-of-bounds pointer */
|
||||
olcp_features = uint32_decode(&p_response->data[sizeof(uint32_t)]);
|
||||
/*lint -restore*/
|
||||
evt.params.feature.olcp_goto = olcp_features >> BLE_OTS_OLCP_SUPPORT_FEATURE_GOTO_bp;
|
||||
evt.params.feature.olcp_order = olcp_features >> BLE_OTS_OLCP_SUPPORT_FEATURE_ORDER_bp;
|
||||
evt.params.feature.olcp_req_num = olcp_features >> BLE_OTS_OLCP_SUPPORT_FEATURE_REQ_NUM_OBJECTS_bp;
|
||||
evt.params.feature.olcp_clear = olcp_features >> BLE_OTS_OLCP_SUPPORT_FEATURE_CLEAR_MARKING_bp;
|
||||
|
||||
p_ots_c->evt_handler(&evt);
|
||||
}
|
||||
if (p_response->handle == p_ots_c->service.object_size_char.handle_value)
|
||||
{
|
||||
nrf_ble_ots_c_evt_t evt;
|
||||
|
||||
evt.conn_handle = p_ble_evt->evt.gattc_evt.conn_handle;
|
||||
evt.evt_type = NRF_BLE_OTS_C_EVT_SIZE_READ_RESP;
|
||||
|
||||
uint8_t len = 0;
|
||||
evt.params.size.current_size = uint32_decode(&p_response->data[len]);
|
||||
len += sizeof(uint32_t);
|
||||
/*lint --e{415} --e{416} -save suppress Warning 415: Likely access of out-of-bounds pointer */
|
||||
evt.params.size.allocated_size = uint32_decode(&p_response->data[len]);
|
||||
/*lint -restore*/
|
||||
|
||||
/*lint --e{438} -save */
|
||||
len += sizeof(uint32_t);
|
||||
/*lint -restore*/
|
||||
|
||||
p_ots_c->evt_handler(&evt);
|
||||
}
|
||||
if (p_response->handle == p_ots_c->service.object_prop_char.handle_value)
|
||||
{
|
||||
prop_read_rsp_decode(p_ots_c, p_ble_evt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void nrf_ble_ots_c_on_db_disc_evt(nrf_ble_ots_c_t const * const p_ots_c,
|
||||
ble_db_discovery_evt_t * const p_evt)
|
||||
{
|
||||
VERIFY_MODULE_INITIALIZED_VOID();
|
||||
|
||||
nrf_ble_ots_c_evt_t evt;
|
||||
ble_gatt_db_char_t* p_chars;
|
||||
|
||||
p_chars = p_evt->params.discovered_db.charateristics;
|
||||
evt.evt_type = NRF_BLE_OTS_C_EVT_DISCOVERY_FAILED;
|
||||
|
||||
if ((p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE) &&
|
||||
(p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_OTS_SERVICE) &&
|
||||
(p_evt->params.discovered_db.srv_uuid.type == BLE_UUID_TYPE_BLE))
|
||||
{
|
||||
// Find the handles of the OTS characteristics.
|
||||
for (uint32_t i = 0; i < p_evt->params.discovered_db.char_count; i++)
|
||||
{
|
||||
switch (p_chars[i].characteristic.uuid.uuid)
|
||||
{
|
||||
case BLE_UUID_OTS_FEATURES:
|
||||
NRF_LOG_DEBUG("OTS Feature Characteristic found.\r\n");
|
||||
memcpy(&evt.params.handles.ots_feature_char,
|
||||
&p_chars[i].characteristic,
|
||||
sizeof(ble_gattc_char_t));
|
||||
break;
|
||||
|
||||
case BLE_UUID_OTS_OBJECT_NAME:
|
||||
NRF_LOG_DEBUG("Object Name Characteristic found.\r\n");
|
||||
memcpy(&evt.params.handles.object_name_char,
|
||||
&p_chars[i].characteristic,
|
||||
sizeof(ble_gattc_char_t));
|
||||
break;
|
||||
|
||||
case BLE_UUID_OTS_OBJECT_TYPE:
|
||||
NRF_LOG_DEBUG("Object Type Characteristic found.\r\n");
|
||||
memcpy(&evt.params.handles.object_type_char,
|
||||
&p_chars[i].characteristic,
|
||||
sizeof(ble_gattc_char_t));
|
||||
break;
|
||||
|
||||
case BLE_UUID_OTS_OBJECT_SIZE:
|
||||
NRF_LOG_DEBUG("Object Size Characteristic found.\r\n");
|
||||
memcpy(&evt.params.handles.object_size_char,
|
||||
&p_chars[i].characteristic,
|
||||
sizeof(ble_gattc_char_t));
|
||||
break;
|
||||
|
||||
case BLE_UUID_OTS_OBJECT_PROPERTIES:
|
||||
NRF_LOG_DEBUG("Object Properties Characteristic found.\r\n");
|
||||
memcpy(&evt.params.handles.object_prop_char,
|
||||
&p_chars[i].characteristic,
|
||||
sizeof(ble_gattc_char_t));
|
||||
break;
|
||||
|
||||
case BLE_UUID_OTS_OACP:
|
||||
NRF_LOG_DEBUG("Object Action Control Point found. CCCD Handle %x\r\n", p_chars[i].cccd_handle);
|
||||
memcpy(&evt.params.handles.object_action_cp_char,
|
||||
&p_chars[i].characteristic,
|
||||
sizeof(ble_gattc_char_t));
|
||||
evt.params.handles.object_action_cp_cccd.handle = p_chars[i].cccd_handle;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
evt.evt_type = NRF_BLE_OTS_C_EVT_DISCOVERY_COMPLETE;
|
||||
evt.conn_handle = p_evt->conn_handle;
|
||||
}
|
||||
else if ((p_evt->evt_type == BLE_DB_DISCOVERY_SRV_NOT_FOUND) ||
|
||||
(p_evt->evt_type == BLE_DB_DISCOVERY_ERROR))
|
||||
{
|
||||
evt.evt_type = NRF_BLE_OTS_C_EVT_DISCOVERY_FAILED;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
p_ots_c->evt_handler(&evt);
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling the Disconnect event.
|
||||
|
||||
@param[in] p_cts Pointer to the GATT Service client structure instance.
|
||||
@param[in] p_ble_evt Event received from the BLE stack.
|
||||
*/
|
||||
static void on_disconnect(nrf_ble_ots_c_t * const p_ots_c, ble_evt_t const * const p_ble_evt)
|
||||
{
|
||||
if (p_ots_c->conn_handle == p_ble_evt->evt.gap_evt.conn_handle)
|
||||
{
|
||||
p_ots_c->conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
|
||||
if (ots_gatt_handles_are_valid(p_ots_c))
|
||||
{
|
||||
// There was a valid instance of ots on the peer. Send an event to the
|
||||
// application, so that it can do any clean up related to this module.
|
||||
nrf_ble_ots_c_evt_t evt;
|
||||
|
||||
evt.evt_type = NRF_BLE_OTS_C_EVT_DISCONN_COMPLETE;
|
||||
|
||||
p_ots_c->evt_handler(&evt);
|
||||
memset(&p_ots_c->service, 0, sizeof(nrf_ble_ots_c_service_t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void nrf_ble_ots_c_on_ble_evt(ble_evt_t const * const p_ble_evt,
|
||||
void * p_context)
|
||||
{
|
||||
nrf_ble_ots_c_t * p_ots_c;
|
||||
p_ots_c = (nrf_ble_ots_c_t*) p_context;
|
||||
|
||||
VERIFY_MODULE_INITIALIZED_VOID();
|
||||
VERIFY_PARAM_NOT_NULL_VOID(p_ots_c);
|
||||
VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt);
|
||||
|
||||
switch (p_ble_evt->header.evt_id)
|
||||
{
|
||||
case BLE_GAP_EVT_DISCONNECTED:
|
||||
on_disconnect(p_ots_c, p_ble_evt);
|
||||
break;
|
||||
|
||||
case BLE_GATTC_EVT_READ_RSP:
|
||||
on_read_rsp(p_ots_c, p_ble_evt);
|
||||
break;
|
||||
|
||||
case BLE_GATTC_EVT_WRITE_RSP:
|
||||
if ((p_ble_evt->evt.gattc_evt.error_handle != BLE_GATT_HANDLE_INVALID)
|
||||
&& (p_ble_evt->evt.gattc_evt.error_handle ==
|
||||
p_ots_c->service.object_action_cp_char.handle_value))
|
||||
{
|
||||
if (p_ble_evt->evt.gattc_evt.gatt_status == BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR)
|
||||
{
|
||||
NRF_LOG_INFO("write to OACP failed, CCCD improperly configured, enable indications on OACP and try again");
|
||||
}
|
||||
else
|
||||
{
|
||||
NRF_LOG_INFO("BLE_GATTC_EVT_WRITE_RSP error handle: %x error response %x\r\n",
|
||||
p_ble_evt->evt.gattc_evt.error_handle,
|
||||
p_ble_evt->evt.gattc_evt.gatt_status);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ots_c_l2cap_on_ble_evt(p_ots_c, p_ble_evt);
|
||||
ots_c_oacp_on_ble_evt(p_ots_c, p_ble_evt);
|
||||
}
|
||||
|
||||
|
||||
ret_code_t nrf_ble_ots_c_handles_assign(nrf_ble_ots_c_t * const p_ots_c,
|
||||
uint16_t const conn_handle,
|
||||
nrf_ble_ots_c_service_t const * const p_peer_handles)
|
||||
{
|
||||
VERIFY_MODULE_INITIALIZED();
|
||||
VERIFY_PARAM_NOT_NULL(p_ots_c);
|
||||
|
||||
p_ots_c->conn_handle = conn_handle;
|
||||
if (p_peer_handles != NULL)
|
||||
{
|
||||
p_ots_c->service.ots_feature_char.handle_value = p_peer_handles->ots_feature_char.handle_value;
|
||||
p_ots_c->service.object_type_char.handle_value = p_peer_handles->object_type_char.handle_value;
|
||||
p_ots_c->service.object_size_char.handle_value = p_peer_handles->object_size_char.handle_value;
|
||||
p_ots_c->service.object_prop_char.handle_value = p_peer_handles->object_prop_char.handle_value;
|
||||
p_ots_c->service.object_action_cp_char.handle_value = p_peer_handles->object_action_cp_char.handle_value;
|
||||
p_ots_c->service.object_action_cp_cccd.handle = p_peer_handles->object_action_cp_cccd.handle;
|
||||
|
||||
}
|
||||
|
||||
return nrf_ble_gq_conn_handle_register(p_ots_c->p_gatt_queue, conn_handle);
|
||||
}
|
||||
|
||||
|
||||
#endif // NRF_MODULE_ENABLED(BLE_OTS_C)
|
||||
@@ -0,0 +1,351 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**@file
|
||||
*
|
||||
* @defgroup nrf_ble_ots_c Object Transfer Service Client
|
||||
* @{
|
||||
* @ingroup ble_sdk_srv
|
||||
* @brief Object Transfer Service Client module
|
||||
*
|
||||
* @details This is the main module of the Object Transfer Service (OTS) Client.
|
||||
*/
|
||||
|
||||
#ifndef NRF_BLE_OTS_C_H__
|
||||
#define NRF_BLE_OTS_C_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "ble_gattc.h"
|
||||
#include "ble.h"
|
||||
#include "nrf_error.h"
|
||||
#include "ble_srv_common.h"
|
||||
#include "ble_db_discovery.h"
|
||||
#include "sdk_errors.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**@brief Macro for defining a ble_ots instance.
|
||||
*
|
||||
* @param _name Name of the instance.
|
||||
* @hideinitializer
|
||||
*/
|
||||
#define NRF_BLE_OTS_C_DEF(_name) \
|
||||
static nrf_ble_ots_c_t _name; \
|
||||
NRF_SDH_BLE_OBSERVER(_name ## _ble_obs, \
|
||||
BLE_OTS_C_BLE_OBSERVER_PRIO, \
|
||||
nrf_ble_ots_c_on_ble_evt, &_name) \
|
||||
|
||||
/** @brief Macro for defining multiple ble_ots instances.
|
||||
*
|
||||
* @param _name Name of the array of instances.
|
||||
* @param _cnt Number of instances to define.
|
||||
* @hideinitializer
|
||||
*/
|
||||
#define NRF_BLE_OTS_C_ARRAY_DEF(_name, _cnt) \
|
||||
static nrf_ble_ots_c_t _name[_cnt]; \
|
||||
NRF_SDH_BLE_OBSERVERS(_name ## _ble_obs, \
|
||||
BLE_OTS_C_BLE_OBSERVER_PRIO, \
|
||||
nrf_ble_ots_c_on_ble_evt, &_name, _cnt)
|
||||
|
||||
|
||||
/** @brief Types of Object Action Control Point Procedures. */
|
||||
typedef enum
|
||||
{
|
||||
NRF_BLE_OTS_C_OACP_PROC_CREATE = 0x01, //!< Create object.
|
||||
NRF_BLE_OTS_C_OACP_PROC_DELETE = 0x02, //!< Delete object.
|
||||
NRF_BLE_OTS_C_OACP_PROC_CALC_CHKSUM = 0x03, //!< Calculate checksum.
|
||||
NRF_BLE_OTS_C_OACP_PROC_EXECUTE = 0x04, //!< Execute object.
|
||||
NRF_BLE_OTS_C_OACP_PROC_READ = 0x05, //!< Read object.
|
||||
NRF_BLE_OTS_C_OACP_PROC_WRITE = 0x06, //!< Write object.
|
||||
NRF_BLE_OTS_C_OACP_PROC_ABORT = 0x07, //!< Abort object.
|
||||
NRF_BLE_OTS_C_OACP_PROC_RESP = 0x60 //!< Procedure response.
|
||||
} ble_ots_c_oacp_proc_type_t;
|
||||
|
||||
/** @brief Object Action Control Point return codes. */
|
||||
typedef enum
|
||||
{
|
||||
NRF_BLE_OTS_C_OACP_RES_SUCCESS = 0x01, //!< Success.
|
||||
NRF_BLE_OTS_C_OACP_RES_OPCODE_NOT_SUP = 0x02, //!< Not supported.
|
||||
NRF_BLE_OTS_C_OACP_RES_INV_PARAM = 0x03, //!< Invalid parameter.
|
||||
NRF_BLE_OTS_C_OACP_RES_INSUFF_RES = 0x04, //!< Insufficient resources.
|
||||
NRF_BLE_OTS_C_OACP_RES_INV_OBJ = 0x05, //!< Invalid object.
|
||||
NRF_BLE_OTS_C_OACP_RES_CHAN_UNAVAIL = 0x06, //!< Channel unavailable.
|
||||
NRF_BLE_OTS_C_OACP_RES_UNSUP_TYPE = 0x07, //!< Unsupported procedure.
|
||||
NRF_BLE_OTS_C_OACP_RES_NOT_PERMITTED = 0x08, //!< Procedure not permitted.
|
||||
NRF_BLE_OTS_C_OACP_RES_OBJ_LOCKED = 0x09, //!< Object locked.
|
||||
NRF_BLE_OTS_C_OACP_RES_OPER_FAILED = 0x0A //!< Operation failed.
|
||||
} ble_ots_c_oacp_res_code_t;
|
||||
|
||||
/**@brief Type of the Object Transfer Service Client event. */
|
||||
typedef enum
|
||||
{
|
||||
NRF_BLE_OTS_C_EVT_DISCOVERY_FAILED, //!< Event indicating that the Object Transfer Service has not been found on the peer.
|
||||
NRF_BLE_OTS_C_EVT_DISCOVERY_COMPLETE, //!< Event indicating that the Object Transfer Service is present on the peer device.
|
||||
NRF_BLE_OTS_C_EVT_DISCONN_COMPLETE, //!< Event indicating that the Object Transfer Service Client module finished processing the BLE_GAP_EVT_DISCONNECTED event. The application can use this event to do a cleanup related to the Object Transfer Service Client.
|
||||
NRF_BLE_OTS_C_EVT_FEATURE_READ_RESP, //!< Event indicating that the feature characteristic was read. The available features of the peer will be provided in the event.
|
||||
NRF_BLE_OTS_C_EVT_OACP_RESP, //!< Event indicating that a response was received (result of a write to the OACP).
|
||||
NRF_BLE_OTS_C_EVT_OBJ_READ, //!< Event indicating that the Object Transfer Service Client finished reading object from the peer.
|
||||
NRF_BLE_OTS_C_EVT_OBJ_WRITE, //!< Event indicating that the Object Transfer Service Client finished writing an object to the peer.
|
||||
NRF_BLE_OTS_C_EVT_CHANNEL_RELEASED, //!< Event indicating that the L2CAP Connection Oriented Channel was disconnected.
|
||||
NRF_BLE_OTS_C_EVT_SIZE_READ_RESP, //!< Event indicating that the object size characteristic was read.
|
||||
NRF_BLE_OTS_C_EVT_PROP_READ_RESP //!< Event indicating that the object properties characteristic was read.
|
||||
} nrf_ble_ots_c_evt_type_t;
|
||||
|
||||
/** @brief Structure to hold the features of a server. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t oacp_create : 1;
|
||||
uint8_t oacp_delete : 1;
|
||||
uint8_t oacp_crc : 1;
|
||||
uint8_t oacp_execute : 1;
|
||||
uint8_t oacp_read : 1;
|
||||
uint8_t oacp_write : 1;
|
||||
uint8_t oacp_append : 1;
|
||||
uint8_t oacp_truncate : 1;
|
||||
uint8_t oacp_patch : 1;
|
||||
uint8_t oacp_abort : 1;
|
||||
uint8_t olcp_goto : 1;
|
||||
uint8_t olcp_order : 1;
|
||||
uint8_t olcp_req_num : 1;
|
||||
uint8_t olcp_clear : 1;
|
||||
} nrf_ble_ots_c_feature_t;
|
||||
|
||||
|
||||
/**@brief Properties of an Object Transfer Service object. */
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
bool is_delete_permitted :1; /**< Object can be deleted. */
|
||||
bool is_execute_permitted :1; /**< Object can be executed. */
|
||||
bool is_read_permitted :1; /**< Object can be read. */
|
||||
bool is_write_permitted :1; /**< Object can be written. */
|
||||
bool is_append_permitted :1; /**< Object can be appended. */
|
||||
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; /**< Boolean to keep track whether the object is marked or not. */
|
||||
} decoded;
|
||||
uint32_t raw;
|
||||
} nrf_ble_ots_c_obj_properties_t;
|
||||
|
||||
|
||||
/**@brief Structure for holding the Object Transfer Service found during the
|
||||
discovery process.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ble_gattc_service_t service; //!< The Object Transfer Service holding the discovered Object Transfer Service (0x1825).
|
||||
ble_gattc_char_t ots_feature_char; //!< OTS Feature (0x2ABD).
|
||||
ble_gattc_char_t object_name_char; //!< Object name (0x2ABE).
|
||||
ble_gattc_char_t object_type_char; //!< Object type (0x2ABF).
|
||||
ble_gattc_char_t object_size_char; //!< Object size (0x2AC0).
|
||||
ble_gattc_char_t object_prop_char; //!< Object properties (0x2AC4).
|
||||
ble_gattc_char_t object_action_cp_char; //!< Object action control point (0x2AC5).
|
||||
ble_gattc_desc_t object_action_cp_cccd; //!< Object action control point descriptor. Enables or disables Object Transfer notifications.
|
||||
} nrf_ble_ots_c_service_t;
|
||||
|
||||
/** @brief Structure to hold responses received when writing to the Object Action Control Point on the server. */
|
||||
typedef struct
|
||||
{
|
||||
ble_ots_c_oacp_proc_type_t request_op_code;
|
||||
ble_ots_c_oacp_res_code_t result_code;
|
||||
} nrf_ble_ots_c_oacp_response_t;
|
||||
|
||||
/** @brief Structure to hold the size of the object on the server when read from the Object Size characteristic on the server. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t current_size;
|
||||
uint32_t allocated_size;
|
||||
} nrf_ble_ots_c_obj_size;
|
||||
|
||||
/**@brief Structure containing the event from the Object Transfer client module to the application.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
nrf_ble_ots_c_evt_type_t evt_type; /**< Type of event. See @ref nrf_ble_ots_c_evt_type_t. */
|
||||
uint16_t conn_handle; /**< Handle of the connection for which this event has occurred. */
|
||||
union
|
||||
{
|
||||
nrf_ble_ots_c_feature_t feature; /**< Will be provided if the event type is @ref NRF_BLE_OTS_C_EVT_FEATURE_READ_RESP.*/
|
||||
nrf_ble_ots_c_service_t handles; /**< Handles that the Object Transfer service occupies in the peer device. Will be filled if the event type is @ref NRF_BLE_OTS_C_EVT_DISCOVERY_COMPLETE.*/
|
||||
nrf_ble_ots_c_oacp_response_t response; /**< Will be provided if the event type is @ref NRF_BLE_OTS_C_EVT_OACP_RESP. */
|
||||
ble_data_t object; /**< Will be provided if the event type is @ref NRF_BLE_OTS_C_EVT_OBJ_READ. */
|
||||
nrf_ble_ots_c_obj_size size; /**< Will be provided if the event type is @ref NRF_BLE_OTS_C_EVT_SIZE_READ_RESP. */
|
||||
nrf_ble_ots_c_obj_properties_t prop; /**< Will be provided if the eevnt type is @ref NRF_BLE_OTS_C_EVT_PROP_READ_RESP. */
|
||||
} params;
|
||||
} nrf_ble_ots_c_evt_t;
|
||||
|
||||
|
||||
/**@brief Object Transfer handler type. */
|
||||
typedef void (* nrf_ble_ots_c_evt_handler_t)(nrf_ble_ots_c_evt_t * p_evt);
|
||||
|
||||
|
||||
/**@brief Structure for holding the information related to the Object Transfer Service.
|
||||
|
||||
@warning This structure must be zero-initialized.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bool initialized; /**< Boolean telling whether the context was initialized or not. */
|
||||
uint16_t conn_handle; /**< Active connection handle. */
|
||||
nrf_ble_ots_c_service_t service; /**< Structure to store the different handles and UUIDs related to the service. */
|
||||
nrf_ble_ots_c_evt_handler_t evt_handler; /**< Pointer to event handler function. */
|
||||
ble_srv_error_handler_t err_handler; /**< Pointer to error handler function. */
|
||||
nrf_ble_gq_req_error_cb_t gatt_err_handler; /**< Error handler to be called in case of an error from the SoftDevice. */
|
||||
uint16_t local_cid; /**< Connection ID of the current connection. */
|
||||
ble_l2cap_evt_ch_setup_t ch_setup; /**< Parameters of the L2CAP Channel Setup Completed event. */
|
||||
uint32_t transmitted_bytes; /**< Variable used when transferring an object to the peer. */
|
||||
uint32_t received_bytes; /**< Variable used when transferring an object from the peer. */
|
||||
ble_data_t * current_obj; /**< Pointer to the current object to be transferred. */
|
||||
nrf_ble_gq_t * p_gatt_queue; /**< Pointer to the BLE GATT Queue instance. */
|
||||
} nrf_ble_ots_c_t;
|
||||
|
||||
|
||||
/**@brief Initialization parameters. These must be supplied when calling @ref nrf_ble_ots_c_init. */
|
||||
typedef struct
|
||||
{
|
||||
nrf_ble_ots_c_evt_handler_t evt_handler; /**< The event handler that is called by the Object Transfer client module when any related event occurs. */
|
||||
ble_srv_error_handler_t err_handler; /**< The error handler that is called by the Object Transfer client module if any error occurs. */
|
||||
nrf_ble_gq_t * p_gatt_queue; /**< Pointer to the BLE GATT Queue instance. */
|
||||
} nrf_ble_ots_c_init_t;
|
||||
|
||||
/**@brief Function for initializing the Object Transfer client module.
|
||||
|
||||
@param[in,out] p_ots_c Pointer to the Object Transfer Service client structure instance.
|
||||
@param[in] p_ots_c_init Init parameters that contain the event handler that is called
|
||||
by the Object Transfer client module when any related event occurs.
|
||||
|
||||
@retval NRF_SUCCESS If the service was initialized successfully.
|
||||
@retval NRF_ERROR_NULL If any of the input parameters are NULL.
|
||||
@retval err_code If functions from other modules return errors to this function,
|
||||
the @ref nrf_error are propagated.
|
||||
*/
|
||||
ret_code_t nrf_ble_ots_c_init(nrf_ble_ots_c_t * p_ots_c,
|
||||
nrf_ble_ots_c_init_t * p_ots_c_init);
|
||||
|
||||
|
||||
/**@brief Function for handling events from the Database Discovery module.
|
||||
|
||||
@details This function handles an event from the Database Discovery module, and determines
|
||||
whether it relates to the discovery of Object Transfer Service at the peer. If it does,
|
||||
the function calls the application's event handler to indicate that Object Transfer Service
|
||||
has been discovered at the peer.
|
||||
|
||||
@param[in,out] p_ots_c Pointer to the Object Transfer Service client structure instance.
|
||||
@param[in] p_evt Pointer to the event received from the Database Discovery module.
|
||||
*/
|
||||
void nrf_ble_ots_c_on_db_disc_evt(nrf_ble_ots_c_t const * const p_ots_c,
|
||||
ble_db_discovery_evt_t * const p_evt);
|
||||
|
||||
|
||||
/**@brief Function for reading the features characteristic (@ref BLE_UUID_OTS_FEATURES) on the server.
|
||||
|
||||
@param[in,out] p_ots_c Pointer to Object Transfer Client structure.
|
||||
|
||||
@retval NRF_SUCCESS Operation success.
|
||||
@retval err_code Otherwise, this API propagates the error code returned by function @ref nrf_ble_gq_item_add.
|
||||
*/
|
||||
ret_code_t nrf_ble_ots_c_feature_read(nrf_ble_ots_c_t * const p_ots_c);
|
||||
|
||||
|
||||
/**@brief Function for reading the Object Size characteristic (@ref BLE_UUID_OTS_FEATURES) on the server.
|
||||
|
||||
@param[in,out] p_ots_c Pointer to Object Transfer Client structure.
|
||||
|
||||
@retval NRF_SUCCESS Operation success.
|
||||
@retval NRF_ERROR_INVALID_STATE If the Object Size characteristic has not been discovered.
|
||||
@retval err_code Otherwise, this API propagates the error code returned by function @ref nrf_ble_gq_item_add.
|
||||
*/
|
||||
ret_code_t nrf_ble_ots_c_obj_size_read(nrf_ble_ots_c_t * const p_ots_c);
|
||||
|
||||
|
||||
/**@brief Function for reading the Object properties (@ref BLE_UUID_OTS_OBJECT_PROPERTIES) on the server.
|
||||
|
||||
@param[in,out] p_ots_c Pointer to Object Transfer Client structure.
|
||||
|
||||
@retval NRF_SUCCESS Operation success.
|
||||
@retval NRF_ERROR_INVALID_STATE If the Object Properties characteristic has not been discovered.
|
||||
@retval err_code Otherwise, this API propagates the error code returned by function @ref nrf_ble_gq_item_add.
|
||||
*/
|
||||
ret_code_t nrf_ble_ots_c_obj_properties_read(nrf_ble_ots_c_t * const p_ots_c);
|
||||
|
||||
|
||||
/**@brief Function for handling the Application's BLE Stack events.
|
||||
|
||||
@param[in] p_ble_evt Pointer to the BLE event received.
|
||||
@param[in,out] p_context Pointer to the Object Transfer Service client structure instance.
|
||||
*/
|
||||
void nrf_ble_ots_c_on_ble_evt(const ble_evt_t * const p_ble_evt, void * p_context);
|
||||
|
||||
|
||||
ret_code_t nrf_ble_ots_c_obj_name_read(nrf_ble_ots_c_t * const p_ots_c, ble_data_t * p_obj);
|
||||
ret_code_t nrf_ble_ots_c_obj_name_write(nrf_ble_ots_c_t * const p_ots_c, ble_data_t * p_obj);
|
||||
ret_code_t nrf_ble_ots_c_obj_type_read(nrf_ble_ots_c_t * const p_ots_c);
|
||||
|
||||
|
||||
/**@brief Function for assigning handles to an Object Transfer Service Client instance.
|
||||
|
||||
@details Call this function when a link has been established with a peer to
|
||||
associate the link to an instance of the module. This makes it
|
||||
possible to handle several links and associate each link to a particular
|
||||
instance of the Object Transfer Service Client module. The connection handle and
|
||||
attribute handles are provided from the discovery event
|
||||
@ref NRF_BLE_OTS_C_EVT_DISCOVERY_COMPLETE.
|
||||
|
||||
@param[in,out] p_ots_c Pointer to the Object Transfer Service Client structure instance for associating the link.
|
||||
@param[in] conn_handle Connection handle to be associated with the given Object Transfer Service Client
|
||||
instance.
|
||||
@param[in] p_peer_handles Attribute handles on the Object Transfer Service server that you want this
|
||||
Object Transfer Service client to interact with.
|
||||
|
||||
@retval NRF_SUCCESS If the connection handle was successfully stored in the Object Transfer Service instance.
|
||||
@retval NRF_ERROR_NULL If any of the input parameters are NULL.
|
||||
@retval err_code Otherwise, this API propagates the error code returned by function
|
||||
@ref nrf_ble_gq_conn_handle_register.
|
||||
*/
|
||||
ret_code_t nrf_ble_ots_c_handles_assign(nrf_ble_ots_c_t * const p_ots_c,
|
||||
uint16_t const conn_handle,
|
||||
nrf_ble_ots_c_service_t const * const p_peer_handles);
|
||||
|
||||
#endif // NRF_BLE_OTS_C_H__
|
||||
|
||||
/** @} */
|
||||
@@ -0,0 +1,302 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sdk_common.h"
|
||||
#if NRF_MODULE_ENABLED(BLE_OTS_C_L2CAP)
|
||||
#include <stdlib.h>
|
||||
#include "nrf_ble_ots_c.h"
|
||||
#include "nrf_ble_ots_c_oacp.h"
|
||||
#include "nrf_ble_ots_c_l2cap.h"
|
||||
#include "ble.h"
|
||||
|
||||
#define NRF_LOG_MODULE_NAME ble_ots_c_l2cap
|
||||
#include "nrf_log.h"
|
||||
NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
#include "sdk_common.h"
|
||||
|
||||
#define MODULE_INITIALIZED (p_ots_c->initialized) /**< Macro designating whether the module has been initialized properly. */
|
||||
|
||||
|
||||
/**@brief Function for handling the BLE_L2CAP_EVT_CH_SETUP event.
|
||||
*
|
||||
* @param[in] p_ots_c Object Transfer Service Instance.
|
||||
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
|
||||
*/
|
||||
static void on_l2cap_ch_setup_complete(nrf_ble_ots_c_t * const p_ots_c,
|
||||
ble_evt_t const * const p_ble_evt)
|
||||
{
|
||||
p_ots_c->local_cid = p_ble_evt->evt.l2cap_evt.local_cid;
|
||||
p_ots_c->ch_setup.tx_params.peer_mps = p_ble_evt->evt.l2cap_evt.params.ch_setup.tx_params.peer_mps;
|
||||
p_ots_c->ch_setup.tx_params.tx_mtu = p_ble_evt->evt.l2cap_evt.params.ch_setup.tx_params.tx_mtu;
|
||||
p_ots_c->ch_setup.tx_params.credits = p_ble_evt->evt.l2cap_evt.params.ch_setup.tx_params.credits;
|
||||
}
|
||||
|
||||
|
||||
/**@brief This function sends the next MTU of the object.
|
||||
*
|
||||
* @param[in] p_ots_c Object Transfer Service Instance.
|
||||
*/
|
||||
static void send_resume(nrf_ble_ots_c_t * const p_ots_c)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
uint16_t tx_size;
|
||||
|
||||
tx_size = MIN((p_ots_c->current_obj->len - p_ots_c->transmitted_bytes),
|
||||
p_ots_c->ch_setup.tx_params.tx_mtu);
|
||||
|
||||
ble_data_t obj;
|
||||
obj.len = tx_size;
|
||||
obj.p_data = &p_ots_c->current_obj->p_data[p_ots_c->transmitted_bytes];
|
||||
|
||||
err_code = sd_ble_l2cap_ch_tx(p_ots_c->conn_handle, p_ots_c->local_cid, &obj);
|
||||
|
||||
if (err_code == NRF_ERROR_RESOURCES)
|
||||
{
|
||||
return; // Too many SDUs queued for transmission, the transmission will be tried again on the next BLE_L2CAP_EVT_CH_TX event.
|
||||
}
|
||||
if(err_code != NRF_SUCCESS && p_ots_c->err_handler != NULL)
|
||||
{
|
||||
p_ots_c->err_handler(err_code);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief This function receives the next of the object.
|
||||
*
|
||||
* @param[in] p_ots_c Object Transfer Service Instance.
|
||||
*/
|
||||
static void receive_resume(nrf_ble_ots_c_t * const p_ots_c)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
ble_data_t sdu_buf;
|
||||
|
||||
sdu_buf.p_data = &p_ots_c->current_obj->p_data[p_ots_c->received_bytes];
|
||||
sdu_buf.len = p_ots_c->current_obj->len - p_ots_c->received_bytes;
|
||||
|
||||
err_code = sd_ble_l2cap_ch_rx(p_ots_c->conn_handle,
|
||||
p_ots_c->local_cid,
|
||||
&sdu_buf);
|
||||
|
||||
if (err_code == NRF_ERROR_RESOURCES)
|
||||
{
|
||||
return; // Too many SDUs queued for transmission, the transmission will be tried again on the next BLE_L2CAP_EVT_CH_RX event.
|
||||
}
|
||||
|
||||
if(err_code != NRF_SUCCESS && p_ots_c->err_handler != NULL)
|
||||
{
|
||||
p_ots_c->err_handler(err_code);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling the BLE_L2CAP_EVT_CH_TX event.
|
||||
*
|
||||
* @param[in] p_ots_c Object Transfer Service Instance.
|
||||
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
|
||||
*/
|
||||
static void on_l2cap_ch_tx(nrf_ble_ots_c_t * const p_ots_c, ble_evt_t const * const p_ble_evt)
|
||||
{
|
||||
if(p_ots_c->local_cid != p_ble_evt->evt.l2cap_evt.local_cid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NRF_LOG_DEBUG("Bytes sent in the previous PDU: %i",
|
||||
p_ble_evt->evt.l2cap_evt.params.tx.sdu_buf.len);
|
||||
NRF_LOG_HEXDUMP_DEBUG(p_ble_evt->evt.l2cap_evt.params.tx.sdu_buf.p_data,
|
||||
p_ble_evt->evt.l2cap_evt.params.tx.sdu_buf.len);
|
||||
|
||||
p_ots_c->transmitted_bytes += p_ble_evt->evt.l2cap_evt.params.tx.sdu_buf.len;
|
||||
uint16_t remaining_tx_bytes = p_ots_c->current_obj->len - p_ots_c->transmitted_bytes;
|
||||
|
||||
NRF_LOG_DEBUG("Total bytes transmitted: %i ",
|
||||
(p_ots_c->transmitted_bytes));
|
||||
NRF_LOG_DEBUG("Total bytes remaining: %i",
|
||||
(remaining_tx_bytes));
|
||||
|
||||
if (remaining_tx_bytes == 0)
|
||||
{
|
||||
nrf_ble_ots_c_evt_t evt;
|
||||
|
||||
evt.evt_type = NRF_BLE_OTS_C_EVT_OBJ_WRITE;
|
||||
evt.params.object.len = p_ots_c->current_obj->len;
|
||||
evt.params.object.p_data = p_ots_c->current_obj->p_data;
|
||||
p_ots_c->evt_handler(&evt);
|
||||
}
|
||||
else
|
||||
{
|
||||
send_resume(p_ots_c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling the BLE_L2CAP_EVT_CH_TR event.
|
||||
*
|
||||
* @param[in] p_ots_c Object Transfer Service Instance.
|
||||
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
|
||||
*/
|
||||
static void on_l2cap_ch_rx(nrf_ble_ots_c_t * const p_ots_c,
|
||||
ble_evt_t const * const p_ble_evt)
|
||||
{
|
||||
if(p_ots_c->local_cid != p_ble_evt->evt.l2cap_evt.local_cid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NRF_LOG_DEBUG("Bytes received: %i", p_ble_evt->evt.l2cap_evt.params.rx.sdu_len);
|
||||
NRF_LOG_HEXDUMP_DEBUG(p_ble_evt->evt.l2cap_evt.params.rx.sdu_buf.p_data,
|
||||
p_ble_evt->evt.l2cap_evt.params.rx.sdu_len);
|
||||
|
||||
memcpy(&p_ots_c->current_obj->p_data[p_ots_c->received_bytes], //Not needed`? buffer provied
|
||||
p_ble_evt->evt.l2cap_evt.params.rx.sdu_buf.p_data,
|
||||
p_ble_evt->evt.l2cap_evt.params.rx.sdu_len);
|
||||
|
||||
p_ots_c->received_bytes += p_ble_evt->evt.l2cap_evt.params.rx.sdu_len;
|
||||
uint16_t remaining_bytes = (p_ots_c->current_obj->len - p_ots_c->received_bytes);
|
||||
|
||||
if(remaining_bytes == 0)
|
||||
{
|
||||
nrf_ble_ots_c_evt_t evt;
|
||||
|
||||
evt.evt_type = NRF_BLE_OTS_C_EVT_OBJ_READ;
|
||||
evt.params.object.len = p_ots_c->current_obj->len;
|
||||
evt.params.object.p_data = p_ots_c->current_obj->p_data;
|
||||
p_ots_c->evt_handler(&evt);
|
||||
}
|
||||
else
|
||||
{
|
||||
receive_resume(p_ots_c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling the BLE_L2CAP_EVT_CH_RELEASED event.
|
||||
*
|
||||
* @param[in] p_ots_c Object Transfer Service Instance.
|
||||
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
|
||||
*/
|
||||
static void on_l2cap_ch_released(nrf_ble_ots_c_t * const p_ots_c,
|
||||
ble_evt_t const * const p_ble_evt)
|
||||
{
|
||||
nrf_ble_ots_c_evt_t evt;
|
||||
|
||||
evt.evt_type = NRF_BLE_OTS_C_EVT_CHANNEL_RELEASED;
|
||||
p_ots_c->evt_handler(&evt);
|
||||
}
|
||||
|
||||
|
||||
ret_code_t nrf_ble_ots_c_l2cap_obj_send(nrf_ble_ots_c_t * const p_ots_c, ble_data_t * p_obj)
|
||||
{
|
||||
VERIFY_MODULE_INITIALIZED();
|
||||
VERIFY_PARAM_NOT_NULL(p_ots_c);
|
||||
VERIFY_PARAM_NOT_NULL(p_obj);
|
||||
|
||||
ret_code_t err_code;
|
||||
uint16_t tx_size;
|
||||
|
||||
p_ots_c->transmitted_bytes = 0;
|
||||
tx_size = MIN(p_obj->len, p_ots_c->ch_setup.tx_params.tx_mtu);
|
||||
p_ots_c->current_obj = p_obj;
|
||||
|
||||
ble_data_t obj;
|
||||
obj.len = tx_size;
|
||||
obj.p_data = p_obj->p_data;
|
||||
err_code = sd_ble_l2cap_ch_tx(p_ots_c->conn_handle, p_ots_c->local_cid, &obj);
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
ret_code_t nrf_ble_ots_c_l2cap_obj_receive(nrf_ble_ots_c_t * const p_ots_c, ble_data_t * p_obj)
|
||||
{
|
||||
uint32_t err_code;
|
||||
p_ots_c->received_bytes = 0;
|
||||
p_ots_c->current_obj = p_obj;
|
||||
|
||||
err_code = sd_ble_l2cap_ch_rx(p_ots_c->conn_handle,
|
||||
p_ots_c->local_cid,
|
||||
p_ots_c->current_obj);
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
void ots_c_l2cap_on_ble_evt(nrf_ble_ots_c_t * const p_ots_c,
|
||||
ble_evt_t const * const p_ble_evt)
|
||||
{
|
||||
VERIFY_MODULE_INITIALIZED_VOID();
|
||||
VERIFY_PARAM_NOT_NULL_VOID(p_ots_c);
|
||||
VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt);
|
||||
|
||||
if (p_ble_evt->evt.l2cap_evt.local_cid != p_ots_c->local_cid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (p_ble_evt->header.evt_id)
|
||||
{
|
||||
case BLE_L2CAP_EVT_CH_SETUP:
|
||||
NRF_LOG_DEBUG("BLE_L2CAP_EVT_CH_SETUP");
|
||||
on_l2cap_ch_setup_complete(p_ots_c, p_ble_evt);
|
||||
break;
|
||||
|
||||
case BLE_L2CAP_EVT_CH_TX:
|
||||
NRF_LOG_DEBUG("BLE_L2CAP_EVT_CH_TX");
|
||||
on_l2cap_ch_tx(p_ots_c, p_ble_evt);
|
||||
break;
|
||||
|
||||
case BLE_L2CAP_EVT_CH_RX:
|
||||
NRF_LOG_DEBUG("BLE_L2CAP_EVT_CH_RX");
|
||||
on_l2cap_ch_rx(p_ots_c, p_ble_evt);
|
||||
break;
|
||||
|
||||
case BLE_L2CAP_EVT_CH_CREDIT:
|
||||
NRF_LOG_DEBUG("BLE_L2CAP_EVT_CH_CREDIT");
|
||||
break;
|
||||
|
||||
case BLE_L2CAP_EVT_CH_RELEASED:
|
||||
NRF_LOG_DEBUG("BLE_L2CAP_EVT_CH_RELEASED");
|
||||
on_l2cap_ch_released(p_ots_c, p_ble_evt);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif // NRF_MODULE_ENABLED(BLE_OTS_C_L2CAP)
|
||||
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**@file
|
||||
*
|
||||
* @defgroup nrf_ble_ots_c_l2cap Object Transfer Service Client
|
||||
* @{
|
||||
* @ingroup nrf_ble_ots_c
|
||||
* @brief Object Transfer Service client module
|
||||
*
|
||||
* @details This is the main module of the Object Transfer Service (OTS) client.
|
||||
*/
|
||||
|
||||
#ifndef NRF_BLE_OTS_C_L2CAP_H__
|
||||
#define NRF_BLE_OTS_C_L2CAP_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "ble_gattc.h"
|
||||
#include "ble.h"
|
||||
#include "nrf_error.h"
|
||||
#include "ble_srv_common.h"
|
||||
#include "ble_db_discovery.h"
|
||||
#include "sdk_errors.h"
|
||||
#include "nrf_ble_ots_c.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**@brief Function for handling the Application's BLE Stack events.
|
||||
|
||||
@param[in,out] p_ots_c Pointer to Object Transfer client structure.
|
||||
@param[in] p_ble_evt Pointer to the BLE event received.
|
||||
*/
|
||||
void ots_c_l2cap_on_ble_evt(nrf_ble_ots_c_t * const p_ots_c,
|
||||
ble_evt_t const * const p_ble_evt);
|
||||
|
||||
|
||||
/**@brief Function sending an object.
|
||||
|
||||
@details This Function will only succeed in sending an object if the peer is in a state to
|
||||
receive it. call @ref nrf_ble_ots_c_oacp_write_object before this function.
|
||||
|
||||
@param[in,out] p_ots_c Pointer to Object Transfer client structure.
|
||||
@param[in,out] p_obj Pointer to object that will be sent to the peer.
|
||||
|
||||
@retval NRF_ERROR_INVALID_STATE if the Object Transfer module is not initialized.
|
||||
@retval NRF_ERROR_NULL if any of the input parameters are NULL.
|
||||
*/
|
||||
ret_code_t nrf_ble_ots_c_l2cap_obj_send(nrf_ble_ots_c_t * const p_ots_c, ble_data_t * p_obj);
|
||||
|
||||
|
||||
/**@brief Function for receiving an object.
|
||||
|
||||
@details This Function will only succeed in receiving an object if the peer is in a state to
|
||||
send it. call @ref nrf_ble_ots_c_oacp_read_object before this function.
|
||||
|
||||
@param[in,out] p_ots_c Pointer to Object Transfer client structure.
|
||||
@param[in,out] p_obj Pointer to buffer where the received data will be stored.
|
||||
*/
|
||||
ret_code_t nrf_ble_ots_c_l2cap_obj_receive(nrf_ble_ots_c_t * const p_ots_c, ble_data_t * p_obj);
|
||||
|
||||
|
||||
#endif // NRF_BLE_OTS_C_L2CAP_H__
|
||||
|
||||
/** @} */
|
||||
@@ -0,0 +1,264 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sdk_common.h"
|
||||
#if NRF_MODULE_ENABLED(BLE_OTS_C_OACP)
|
||||
#include <stdlib.h>
|
||||
#include "nrf_ble_ots_c_oacp.h"
|
||||
#include "ble.h"
|
||||
|
||||
#define NRF_LOG_MODULE_NAME ble_ots_c_oacp
|
||||
#include "nrf_log.h"
|
||||
NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
#include "sdk_common.h"
|
||||
|
||||
#define BLE_OTS_OACP_WRITE_OP_SIZE 10
|
||||
#define BLE_OTS_OACP_READ_OP_SIZE 9
|
||||
|
||||
#define MODULE_INITIALIZED (p_ots_c->initialized)
|
||||
|
||||
static void oacp_response(nrf_ble_ots_c_t const * const p_ots_c,
|
||||
ble_gattc_evt_t const * const p_ble_gattc_evt)
|
||||
{
|
||||
nrf_ble_ots_c_evt_t evt;
|
||||
nrf_ble_ots_c_evt_handler_t evt_handler = p_ots_c->evt_handler;
|
||||
|
||||
/*lint --e{415} --e{416} -save suppress Warning 415: Likely access of out-of-bounds pointer */
|
||||
evt.params.response.request_op_code = (ble_ots_c_oacp_proc_type_t) p_ble_gattc_evt->params.hvx.data[sizeof(uint8_t)];
|
||||
evt.params.response.result_code = (ble_ots_c_oacp_res_code_t) p_ble_gattc_evt->params.hvx.data[2*sizeof(uint8_t)];
|
||||
/*lint -restore*/
|
||||
evt.evt_type = NRF_BLE_OTS_C_EVT_OACP_RESP;
|
||||
evt.conn_handle = p_ble_gattc_evt->conn_handle;
|
||||
evt_handler(&evt);
|
||||
}
|
||||
|
||||
/**@brief Function for handling the indication and notifications from the GATT Service Server.
|
||||
|
||||
@param[in] p_ots_c Pointer to Object Transfer client structure.
|
||||
@param[in] p_ble_gattc_evt Pointer to a GATTC event.
|
||||
*/
|
||||
static void on_hvx(nrf_ble_ots_c_t const * const p_ots_c,
|
||||
ble_gattc_evt_t const * const p_ble_gattc_evt)
|
||||
{
|
||||
|
||||
|
||||
uint16_t oacp_handle = p_ots_c->service.object_action_cp_char.handle_value;
|
||||
|
||||
if ((p_ble_gattc_evt->params.hvx.handle == oacp_handle)
|
||||
&& (p_ots_c->evt_handler != NULL))
|
||||
{
|
||||
ret_code_t err_code = sd_ble_gattc_hv_confirm(p_ble_gattc_evt->conn_handle,
|
||||
oacp_handle);
|
||||
|
||||
if ((err_code != NRF_SUCCESS) && (p_ots_c->err_handler != NULL))
|
||||
{
|
||||
p_ots_c->err_handler(err_code);
|
||||
}
|
||||
uint8_t op_code = p_ble_gattc_evt->params.hvx.data[0];
|
||||
|
||||
if(op_code == NRF_BLE_OTS_C_OACP_PROC_RESP)
|
||||
{
|
||||
oacp_response(p_ots_c, p_ble_gattc_evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**@brief Function for checking whether the peer's Object Transfer Service instance has been discovered.
|
||||
|
||||
@param[in] p_ots_c Pointer to the GATT Service Client structure instance.
|
||||
|
||||
@return True if the Object Transfer Service handles are valid.
|
||||
@return False if the Object Transfer Service handles are invalid.
|
||||
*/
|
||||
static bool ots_gatt_handles_are_valid(const nrf_ble_ots_c_t * const p_ots_c)
|
||||
{
|
||||
return (p_ots_c->service.object_prop_char.handle_value != BLE_GATT_HANDLE_INVALID
|
||||
&& p_ots_c->service.object_size_char.handle_value != BLE_GATT_HANDLE_INVALID
|
||||
&& p_ots_c->service.object_type_char.handle_value != BLE_GATT_HANDLE_INVALID
|
||||
&& p_ots_c->service.ots_feature_char.handle_value != BLE_GATT_HANDLE_INVALID);
|
||||
}
|
||||
|
||||
|
||||
ret_code_t nrf_ble_ots_c_indication_enable(nrf_ble_ots_c_t * const p_ots_c,
|
||||
bool const indication_enable)
|
||||
{
|
||||
VERIFY_MODULE_INITIALIZED();
|
||||
VERIFY_TRUE(ots_gatt_handles_are_valid(p_ots_c), NRF_ERROR_INVALID_STATE);
|
||||
|
||||
if (p_ots_c->conn_handle == BLE_CONN_HANDLE_INVALID)
|
||||
{
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
uint8_t cccd[BLE_CCCD_VALUE_LEN];
|
||||
nrf_ble_gq_req_t cccd_req;
|
||||
uint16_t cccd_val = (indication_enable) ? BLE_GATT_HVX_INDICATION : 0;
|
||||
|
||||
cccd[0] = LSB_16(cccd_val);
|
||||
cccd[1] = MSB_16(cccd_val);
|
||||
|
||||
memset(&cccd_req, 0, sizeof(nrf_ble_gq_req_t));
|
||||
|
||||
cccd_req.type = NRF_BLE_GQ_REQ_GATTC_WRITE;
|
||||
cccd_req.error_handler.cb = p_ots_c->gatt_err_handler;
|
||||
cccd_req.error_handler.p_ctx = (nrf_ble_ots_c_t *)p_ots_c;
|
||||
cccd_req.params.gattc_write.handle = p_ots_c->service.object_action_cp_cccd.handle;
|
||||
cccd_req.params.gattc_write.len = BLE_CCCD_VALUE_LEN;
|
||||
cccd_req.params.gattc_write.offset = 0;
|
||||
cccd_req.params.gattc_write.p_value = cccd;
|
||||
cccd_req.params.gattc_write.write_op = BLE_GATT_OP_WRITE_REQ;
|
||||
|
||||
return nrf_ble_gq_item_add(p_ots_c->p_gatt_queue, &cccd_req, p_ots_c->conn_handle);
|
||||
}
|
||||
|
||||
|
||||
ret_code_t nrf_ble_ots_c_oacp_write_object(nrf_ble_ots_c_t * const p_ots_c, uint32_t offset, uint32_t len, bool truncate)
|
||||
{
|
||||
VERIFY_MODULE_INITIALIZED();
|
||||
VERIFY_TRUE(ots_gatt_handles_are_valid(p_ots_c), NRF_ERROR_INVALID_STATE);
|
||||
|
||||
if (p_ots_c->conn_handle == BLE_CONN_HANDLE_INVALID)
|
||||
{
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
ret_code_t err_code = NRF_SUCCESS;
|
||||
|
||||
uint8_t val[BLE_OTS_OACP_WRITE_OP_SIZE];
|
||||
memset(val, 0, sizeof(val));
|
||||
|
||||
uint32_t i = 0;
|
||||
|
||||
// OP Code
|
||||
val[i++] = NRF_BLE_OTS_C_OACP_PROC_WRITE;
|
||||
|
||||
//Offset
|
||||
i += uint32_encode(offset, &val[i]);
|
||||
|
||||
//Len
|
||||
i += uint32_encode(len, &val[i]);
|
||||
|
||||
val[i] |= (truncate << 0);
|
||||
|
||||
nrf_ble_gq_req_t write_req;
|
||||
|
||||
memset(&write_req, 0, sizeof(nrf_ble_gq_req_t));
|
||||
|
||||
write_req.type = NRF_BLE_GQ_REQ_GATTC_WRITE;
|
||||
write_req.error_handler.cb = p_ots_c->gatt_err_handler;
|
||||
write_req.error_handler.p_ctx = (nrf_ble_ots_c_t *)p_ots_c;
|
||||
write_req.params.gattc_write.handle = p_ots_c->service.object_action_cp_char.handle_value;
|
||||
write_req.params.gattc_write.len = i;
|
||||
write_req.params.gattc_write.offset = 0;
|
||||
write_req.params.gattc_write.p_value = val;
|
||||
write_req.params.gattc_write.write_op = BLE_GATT_OP_WRITE_REQ;
|
||||
|
||||
err_code = nrf_ble_gq_item_add(p_ots_c->p_gatt_queue, &write_req, p_ots_c->conn_handle);
|
||||
|
||||
if(err_code != NRF_SUCCESS)
|
||||
{
|
||||
p_ots_c->err_handler(err_code);
|
||||
}
|
||||
return err_code;
|
||||
}
|
||||
|
||||
ret_code_t nrf_ble_ots_c_oacp_read_object(nrf_ble_ots_c_t * const p_ots_c, uint32_t offset, uint32_t len)
|
||||
{
|
||||
VERIFY_MODULE_INITIALIZED();
|
||||
VERIFY_TRUE(ots_gatt_handles_are_valid(p_ots_c), NRF_ERROR_INVALID_STATE);
|
||||
|
||||
if (p_ots_c->conn_handle == BLE_CONN_HANDLE_INVALID)
|
||||
{
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
uint8_t val[BLE_OTS_OACP_READ_OP_SIZE];
|
||||
memset(val, 0, sizeof(val));
|
||||
|
||||
uint32_t i = 0;
|
||||
|
||||
// OP Code
|
||||
val[i++] = NRF_BLE_OTS_C_OACP_PROC_READ;
|
||||
|
||||
//Offset
|
||||
i += uint32_encode(offset, &val[i]);
|
||||
|
||||
//Len
|
||||
i += uint32_encode(len, &val[i]);
|
||||
|
||||
nrf_ble_gq_req_t write_req;
|
||||
|
||||
memset(&write_req, 0, sizeof(nrf_ble_gq_req_t));
|
||||
|
||||
write_req.type = NRF_BLE_GQ_REQ_GATTC_WRITE;
|
||||
write_req.error_handler.cb = p_ots_c->gatt_err_handler;
|
||||
write_req.error_handler.p_ctx = (nrf_ble_ots_c_t *)p_ots_c;
|
||||
write_req.params.gattc_write.handle = p_ots_c->service.object_action_cp_char.handle_value;
|
||||
write_req.params.gattc_write.len = sizeof(val);
|
||||
write_req.params.gattc_write.offset = 0;
|
||||
write_req.params.gattc_write.p_value = val;
|
||||
write_req.params.gattc_write.write_op = BLE_GATT_OP_WRITE_REQ;
|
||||
|
||||
return nrf_ble_gq_item_add(p_ots_c->p_gatt_queue, &write_req, p_ots_c->conn_handle);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ots_c_oacp_on_ble_evt(nrf_ble_ots_c_t * const p_ots_c,
|
||||
ble_evt_t const * const p_ble_evt)
|
||||
{
|
||||
VERIFY_MODULE_INITIALIZED_VOID();
|
||||
VERIFY_PARAM_NOT_NULL_VOID(p_ots_c);
|
||||
VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt);
|
||||
|
||||
switch (p_ble_evt->header.evt_id)
|
||||
{
|
||||
|
||||
case BLE_GATTC_EVT_HVX:
|
||||
on_hvx(p_ots_c, &(p_ble_evt->evt.gattc_evt));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // NRF_MODULE_ENABLED(BLE_OTS_C)
|
||||
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**@file
|
||||
*
|
||||
* @defgroup nrf_ble_ots_c_oacp Object Transfer Service Client Object Action Control Point
|
||||
* @{
|
||||
* @ingroup nrf_ble_ots_c
|
||||
* @brief Object Action Control Point module
|
||||
*
|
||||
* @details This is the Object Action Control Point module of the Object Transfer Service (OTS) Client.
|
||||
*/
|
||||
|
||||
#ifndef NRF_BLE_OTS_C_OACP_H__
|
||||
#define NRF_BLE_OTS_C_OACP_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "ble_gattc.h"
|
||||
#include "ble.h"
|
||||
#include "nrf_error.h"
|
||||
#include "ble_srv_common.h"
|
||||
#include "ble_db_discovery.h"
|
||||
#include "sdk_errors.h"
|
||||
#include "nrf_ble_ots_c.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**@brief Function for enabling remote indication.
|
||||
|
||||
@param[in,out] p_ots_c Pointer to Object Transfer Client structure.
|
||||
@param[in] enable True to enable Object Action Control Point (OACP) indication; false to disable.
|
||||
|
||||
@retval NRF_SUCCESS Operation success.
|
||||
@retval err_code If functions from other modules return errors to this function,
|
||||
the @ref nrf_error are propagated.
|
||||
*/
|
||||
ret_code_t nrf_ble_ots_c_indication_enable(nrf_ble_ots_c_t * const p_ots_c,
|
||||
bool const enable);
|
||||
|
||||
|
||||
/**@brief Function for requesting a write of an object.
|
||||
|
||||
@details This function informs the peer about the length of the object to write.
|
||||
(The object itself is not written by this function.)
|
||||
The peer indicates a response on the Object Action Control Point.
|
||||
If the write is accepted (the event NRF_BLE_OTS_C_OACP_RES_SUCCESS ), an object can be
|
||||
transfered with @ref nrf_ble_ots_c_l2cap_obj_send.
|
||||
|
||||
@param[in,out] p_ots_c Pointer to Object Transfer Client structure.
|
||||
@param[in] offset Offset of the write.
|
||||
@param[in] len Length of the object to write.
|
||||
@param[in] truncate True to let the write truncate on the object.
|
||||
|
||||
@retval NRF_SUCCESS Operation success.
|
||||
@retval NRF_ERROR_INVALID_STATE Module is not initialized, or the handles of the peer OACP
|
||||
are invalid.
|
||||
@retval err_code Otherwise, this API propagates the error code returned by functions: @ref nrf_ble_gq_item_add.
|
||||
*/
|
||||
ret_code_t nrf_ble_ots_c_oacp_write_object(nrf_ble_ots_c_t * const p_ots_c, uint32_t offset, uint32_t len, bool truncate);
|
||||
|
||||
/**@brief Function for requesting a read of an object.
|
||||
|
||||
@param[in,out] p_ots_c Pointer to Object Transfer Client structure.
|
||||
@param[in] offset Offset of the read.
|
||||
@param[in] len Length of the read.
|
||||
|
||||
@retval NRF_SUCCESS Operation success.
|
||||
@return Otherwise this API propagates the error code returned by functions: @ref nrf_ble_gq_item_add.
|
||||
*/
|
||||
ret_code_t nrf_ble_ots_c_oacp_read_object(nrf_ble_ots_c_t * const p_ots_c, uint32_t offset, uint32_t len);
|
||||
|
||||
|
||||
/**@brief Function for handling the Application's BLE Stack events.
|
||||
|
||||
@param[in,out] p_ots_c Pointer to Object Transfer client structure.
|
||||
@param[in] p_ble_evt Pointer to the BLE event received.
|
||||
*/
|
||||
void ots_c_oacp_on_ble_evt(nrf_ble_ots_c_t * const p_ots_c,
|
||||
ble_evt_t const * const p_ble_evt);
|
||||
|
||||
|
||||
#endif // NRF_BLE_OTS_C_OACP_H__
|
||||
|
||||
/** @} */
|
||||
Reference in New Issue
Block a user