380 lines
16 KiB
C
380 lines
16 KiB
C
/*
|
|
* Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA
|
|
* Copyright (c) 2021-2022 Espressif Systems (Shanghai) PTE LTD
|
|
* 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 Espressif Systems
|
|
* 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 the copyright holder nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software without
|
|
* specific prior written permission.
|
|
*
|
|
* 4. Any software provided in binary form under this license must not be reverse
|
|
* engineered, decompiled, modified and/or disassembled.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
|
*/
|
|
/* PURPOSE: ZBOSS specific Tunnel cluster, purpose: general data tunneling.
|
|
*/
|
|
#ifndef ZB_ZCL_TUNNEL_H
|
|
#define ZB_ZCL_TUNNEL_H 1
|
|
|
|
/** @cond (DOXYGEN_ZCL_SECTION && DOXYGEN_CUSTOM_TUNNEL_CLUSTER) */
|
|
|
|
/** @addtogroup ZB_ZCL_TUNNEL
|
|
* @{
|
|
* @details
|
|
* Manufacture specific cluster for transmit custom data between peers
|
|
* Model: One (client) to More (servers)
|
|
* Usually a device has MIXED role
|
|
*/
|
|
|
|
/*! @name Tunnel cluster commands
|
|
@{
|
|
*/
|
|
|
|
/**
|
|
* @brief Tunnel cluster commands
|
|
*/
|
|
enum zb_zcl_tunnel_cmd_e
|
|
{
|
|
ZB_ZCL_CMD_TUNNEL_TRANSFER_DATA_REQ = 0x00, /**< Request to transfer data. */
|
|
ZB_ZCL_CMD_TUNNEL_TRANSFER_DATA_RESP = 0x01, /**< Response on received data */
|
|
};
|
|
|
|
|
|
/* Tunnel manufacturer specific cluster commands list : only for information - do not modify */
|
|
#define ZB_ZCL_CLUSTER_ID_TUNNEL_FC00_SERVER_ROLE_GENERATED_CMD_LIST ZB_ZCL_CMD_TUNNEL_TRANSFER_DATA_RESP
|
|
|
|
#define ZB_ZCL_CLUSTER_ID_TUNNEL_FC00_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_TUNNEL_FC00_SERVER_ROLE_GENERATED_CMD_LIST
|
|
|
|
#define ZB_ZCL_CLUSTER_ID_TUNNEL_FC00_CLIENT_ROLE_GENERATED_CMD_LIST ZB_ZCL_CMD_TUNNEL_TRANSFER_DATA_REQ
|
|
|
|
#define ZB_ZCL_CLUSTER_ID_TUNNEL_FC00_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_TUNNEL_FC00_CLIENT_ROLE_GENERATED_CMD_LIST
|
|
|
|
|
|
/** Tunnel status; range: 0x00 - 0x3F (6-bit value) */
|
|
typedef enum zb_zcl_tunnel_status_e
|
|
{
|
|
ZB_ZCL_TUNNEL_STATUS_OK = 0, /**< Data is sent or received. Use for inform User App about success current command */
|
|
ZB_ZCL_TUNNEL_STATUS_ERROR = 1, /**< General Error. Current operation has error: unexpected message etc. */
|
|
ZB_ZCL_TUNNEL_STATUS_ERROR_NO_MEMORY = 2, /**< No memory */
|
|
ZB_ZCL_TUNNEL_STATUS_ERROR_TIMEOUT = 3, /**< Timeout. Use for inform User App about when wait answer */
|
|
}
|
|
zb_zcl_tunnel_status_t;
|
|
|
|
/** Tunnel i/o operation type, range: 0x00 - 0x03 (2-bit value) */
|
|
enum zb_zcl_tunnel_operation_code_e
|
|
{
|
|
ZB_ZCL_TUNNEL_OPERATION_TX = 1 << 0, /**< Current command - send data */
|
|
ZB_ZCL_TUNNEL_OPERATION_RX = 1 << 1 /**< Current command - receive data */
|
|
};
|
|
|
|
/************* Tunnel cluster command structures **************/
|
|
|
|
/**
|
|
* @brief Tunnel Transfer Data Request command payload
|
|
*/
|
|
typedef ZB_PACKED_PRE struct zb_zcl_tunnel_transfer_data_req_s
|
|
{
|
|
zb_uint8_t tx_flag; /**< see @ref zb_zcl_tunnel_tx_flags_e */
|
|
/**< byte_num value:
|
|
- if ZB_ZCL_TUNNEL_TX_START is on => total data size to be sent is specified
|
|
- if ZB_ZCL_TUNNEL_TX_CONTINUE is on => current data offset is specified
|
|
*/
|
|
zb_uint16_t byte_num;
|
|
/**< length data - size of data */
|
|
zb_uint8_t data_size;
|
|
/**< data - part of transfer data */
|
|
}
|
|
ZB_PACKED_STRUCT
|
|
zb_zcl_tunnel_transfer_data_req_t;
|
|
|
|
/**
|
|
* @brief Tunnel Transfer Data Request command internal payload
|
|
*/
|
|
typedef ZB_PACKED_PRE struct zb_zcl_tunnel_transfer_data_req_internal_s
|
|
{
|
|
zb_zcl_tunnel_transfer_data_req_t req_header;
|
|
zb_uint8_t *tun_data;
|
|
}
|
|
ZB_PACKED_STRUCT
|
|
zb_zcl_tunnel_transfer_data_req_data_internal_t;
|
|
|
|
/**
|
|
* @brief Tunnel Transfer Data Request flags
|
|
*/
|
|
enum zb_zcl_tunnel_tx_flags_e
|
|
{
|
|
ZB_ZCL_TUNNEL_TX_START = 1 << 0, /**< first block - if set then contains total length of transferring data
|
|
else - contains current offset of transferring data */
|
|
};
|
|
|
|
/*! @brief Send Transfer Data command
|
|
@param _buffer - to put packet to
|
|
@param _addr - address to send packet to
|
|
@param _dst_addr_mode - addressing mode
|
|
@param _dst_ep - destination endpoint
|
|
@param _ep - sending endpoint
|
|
@param _prfl_id - profile identifier
|
|
@param _def_resp - enable or disable default response
|
|
@param _cb - callback for getting command send status
|
|
@param _manufacturer_id - Manufacturer code
|
|
@param _flag - command flag, see @ref zb_zcl_tunnel_tx_flags_e
|
|
@param _byte_num - all transfer length or current offset, see @ref zb_zcl_tunnel_transfer_data_req_t
|
|
@param _data_size - data size
|
|
@param _image_data - image data
|
|
*/
|
|
#define ZB_ZCL_TUNNEL_SEND_TRANSFER_REQ( \
|
|
_buffer, _addr, _dst_addr_mode, _dst_ep, _ep, _prfl_id, _def_resp, _cb, \
|
|
_manufacturer_id, _flag, _byte_num, _data_size, _image_data) \
|
|
{ \
|
|
zb_uint8_t* __ptr = ZB_ZCL_START_PACKET((_buffer)); \
|
|
ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(__ptr, \
|
|
ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, (_def_resp));\
|
|
ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(__ptr, ZB_ZCL_GET_SEQ_NUM(), \
|
|
ZB_ZCL_MANUFACTURER_SPECIFIC, (_manufacturer_id), \
|
|
ZB_ZCL_CMD_TUNNEL_TRANSFER_DATA_REQ); \
|
|
ZB_ZCL_PACKET_PUT_DATA8(__ptr, (_flag)); \
|
|
ZB_ZCL_PACKET_PUT_DATA16_VAL(__ptr, (_byte_num)); \
|
|
ZB_ZCL_PACKET_PUT_DATA8(__ptr, (_data_size)); \
|
|
if((_data_size)>0) \
|
|
{ \
|
|
ZB_ZCL_PACKET_PUT_DATA_N(__ptr, (_image_data), (_data_size)); \
|
|
} \
|
|
ZB_ZCL_FINISH_PACKET((_buffer), __ptr) \
|
|
ZB_ZCL_SEND_COMMAND_SHORT( \
|
|
(_buffer), (_addr), (_dst_addr_mode), (_dst_ep), (_ep), (_prfl_id), \
|
|
ZB_ZCL_CLUSTER_ID_TUNNEL, (_cb)); \
|
|
}
|
|
|
|
/** @brief Macro for getting Send Transfer Data command
|
|
* @attention Assumes that ZCL header already cut.
|
|
* @param _data_ptr - pointer to a variable of type @ref
|
|
* zb_zcl_tunnel_transfer_data_req_data_internal_t.
|
|
* @param _buffer containing the packet (by pointer).
|
|
* @param _status - variable to put parse status to (see @ref zb_zcl_parse_status_t).
|
|
*
|
|
* @note File data place is placed in buffer, payload saves pointer to data only!
|
|
*/
|
|
#define ZB_ZCL_TUNNEL_GET_TRANSFER_REQ(_data_ptr, _buffer, _status) \
|
|
{ \
|
|
zb_zcl_tunnel_transfer_data_req_t *src_ptr = \
|
|
(zb_zcl_tunnel_transfer_data_req_t*)zb_buf_begin((_buffer)); \
|
|
\
|
|
if (zb_buf_len((_buffer)) != sizeof(zb_zcl_tunnel_transfer_data_req_t) \
|
|
+ src_ptr->data_size * sizeof(zb_uint8_t) ) \
|
|
{ \
|
|
(_status) = ZB_ZCL_PARSE_STATUS_FAILURE; \
|
|
} \
|
|
else \
|
|
{ \
|
|
(_status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \
|
|
(_data_ptr)->req_header.tx_flag = src_ptr->tx_flag; \
|
|
ZB_HTOLE16(&((_data_ptr)->req_header.byte_num), &(src_ptr->byte_num)); \
|
|
(_data_ptr)->req_header.data_size = src_ptr->data_size; \
|
|
(_data_ptr)->tun_data = (zb_uint8_t*)(src_ptr+1); \
|
|
} \
|
|
}
|
|
|
|
/**
|
|
* @brief Tunnel Transfer Data Response command payload
|
|
*/
|
|
typedef ZB_PACKED_PRE struct zb_zcl_tunnel_transfer_data_resp_s
|
|
{
|
|
zb_uint8_t tun_status; /**< enum @ref zb_zcl_tunnel_status_e */
|
|
}
|
|
ZB_PACKED_STRUCT
|
|
zb_zcl_tunnel_transfer_data_resp_t;
|
|
|
|
/*! @brief Send Transfer Data response command
|
|
@param _buffer - to put packet to
|
|
@param _addr - address to send packet to
|
|
@param _dst_addr_mode - addressing mode
|
|
@param _dst_ep - destination endpoint
|
|
@param _ep - sending endpoint
|
|
@param _prfl_id - profile identifier
|
|
@param _seq - request sequence
|
|
@param _cb - callback for getting command send status
|
|
@param _manufacturer_id - Manufacturer code
|
|
@param _tun_status - command status, see @ref zb_zcl_tunnel_status_e
|
|
*/
|
|
#define ZB_ZCL_TUNNEL_SEND_TRANSFER_RESP( \
|
|
_buffer, _addr, _dst_addr_mode, _dst_ep, _ep, _prfl_id, _seq, _cb, \
|
|
_manufacturer_id, _tun_status) \
|
|
{ \
|
|
zb_uint8_t* __ptr = ZB_ZCL_START_PACKET((_buffer)); \
|
|
ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RESP_FRAME_CONTROL_A(__ptr, \
|
|
ZB_ZCL_FRAME_DIRECTION_TO_CLI, ZB_ZCL_MANUFACTURER_SPECIFIC); \
|
|
ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(__ptr, (_seq), ZB_ZCL_MANUFACTURER_SPECIFIC,\
|
|
(_manufacturer_id), ZB_ZCL_CMD_TUNNEL_TRANSFER_DATA_RESP); \
|
|
ZB_ZCL_PACKET_PUT_DATA8(__ptr, (_tun_status)); \
|
|
ZB_ZCL_FINISH_PACKET((_buffer), __ptr) \
|
|
ZB_ZCL_SEND_COMMAND_SHORT( \
|
|
(_buffer), (_addr), (_dst_addr_mode), (_dst_ep), (_ep), (_prfl_id), \
|
|
ZB_ZCL_CLUSTER_ID_TUNNEL, (_cb)); \
|
|
}
|
|
|
|
/** @brief Macro for getting Send Transfer Data response command
|
|
* @attention Assumes that ZCL header already cut.
|
|
* @param _data_ptr - pointer to a variable of type @ref
|
|
* zb_zcl_tunnel_transfer_data_resp_t.
|
|
* @param _buffer containing the packet (by pointer).
|
|
* @param _status - variable to put parse status to (see @ref zb_zcl_parse_status_t).
|
|
*/
|
|
#define ZB_ZCL_TUNNEL_GET_TRANSFER_RESP(_data_ptr, _buffer, _status) \
|
|
{ \
|
|
zb_zcl_tunnel_transfer_data_resp_t *src_ptr = \
|
|
(zb_zcl_tunnel_transfer_data_resp_t*)zb_buf_begin((_buffer)); \
|
|
\
|
|
if (zb_buf_len((_buffer)) != sizeof(zb_zcl_tunnel_transfer_data_resp_t) ) \
|
|
{ \
|
|
(_status) = ZB_ZCL_PARSE_STATUS_FAILURE; \
|
|
} \
|
|
else \
|
|
{ \
|
|
(_status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \
|
|
(_data_ptr)->tun_status = src_ptr->tun_status; \
|
|
} \
|
|
}
|
|
|
|
/*! @} */ /* Tunnel cluster commands */
|
|
|
|
|
|
/*********************** Tunnel API **************************/
|
|
|
|
/*! @name Tunnel cluster commands
|
|
@{
|
|
*/
|
|
|
|
/** Callback to inform user about tx operation status or rx data;
|
|
* @param param - param is reference to a buffer;
|
|
* zb_zcl_tunnel_io_param_t is stored as buffer parameter */
|
|
typedef void (ZB_CODE * zb_zcl_tunnel_cb_t)(zb_uint8_t param);
|
|
|
|
/** Tunnel operation status
|
|
*/
|
|
typedef ZB_PACKED_PRE struct zb_zcl_tunnel_op_status_s
|
|
{
|
|
zb_bitfield_t status :6; /**< zb_zcl_tunnel_status_e value */
|
|
zb_bitfield_t op_code :2; /**< zb_zcl_tunnel_operation_code_e value */
|
|
}
|
|
ZB_PACKED_STRUCT
|
|
zb_zcl_tunnel_op_status_t;
|
|
|
|
/** structure to pass parameters for data i/o
|
|
* Save in first of each buffer
|
|
* */
|
|
typedef ZB_PACKED_PRE struct zb_zcl_tunnel_io_param_s
|
|
{
|
|
zb_uint16_t length; /* total data size*/
|
|
zb_uint16_t peer_addr;
|
|
zb_uint8_t peer_ep;
|
|
zb_uint8_t src_ep;
|
|
zb_uint8_t next_buf; /* pointer to the next buf for fragmented data */
|
|
zb_zcl_tunnel_op_status_t op_status;
|
|
zb_uint8_t seq;
|
|
}
|
|
ZB_PACKED_STRUCT
|
|
zb_zcl_tunnel_io_param_t;
|
|
|
|
/** Init CTX data table
|
|
* @param manuf_id - manufacturer ID */
|
|
void zb_zcl_tunnel_init(zb_uint16_t manuf_id);
|
|
|
|
/** Register user callback */
|
|
void zb_zcl_tunnel_register_cb(zb_zcl_tunnel_cb_t tunnel_cb);
|
|
|
|
/** Start user data transmit. buf_param is a reference to a buffer;
|
|
* zb_zcl_tunnel_io_param_t is stored as a buffer parameter;
|
|
* data to be transmitted is stored as buffer data */
|
|
zb_ret_t zb_zcl_tunnel_transmit_data(zb_uint8_t buf_param);
|
|
|
|
/** Default user application
|
|
* Contain default handle (usually free buffer) for different Tunnel Status command */
|
|
void zb_zcl_tunnel_default_user_app(zb_uint8_t param);
|
|
|
|
/*! @} */ /* Tunnel cluster commands */
|
|
|
|
/**************************** Tunnel internal **********************************/
|
|
|
|
#define ZB_ZCL_TUNNEL_TIMEOUT (10*ZB_TIME_ONE_SECOND)
|
|
|
|
/** @brief Maximum slots for send/receive data */
|
|
#define ZB_ZCL_TUNNEL_MAX_IO_SLOT_NUMBER 16
|
|
|
|
/** @brief Not slots index*/
|
|
#define ZB_ZCL_TUNNEL_IO_SLOT_UNKNOWN 0xff
|
|
|
|
typedef ZB_PACKED_PRE struct zb_zcl_tunnel_io_slot_s
|
|
{
|
|
zb_zcl_tunnel_io_param_t io_param;
|
|
zb_uint16_t offset; /* length of current sent/received data */
|
|
zb_uint8_t seq;
|
|
}
|
|
ZB_PACKED_STRUCT
|
|
zb_zcl_tunnel_io_slot_t;
|
|
|
|
/** struct for next buffer in multi-buffer chain*/
|
|
typedef ZB_PACKED_PRE struct zb_zcl_tunnel_io_slot_continue_s
|
|
{
|
|
zb_uint8_t next_buf;
|
|
}
|
|
ZB_PACKED_STRUCT
|
|
zb_zcl_tunnel_io_slot_continue_t;
|
|
|
|
|
|
/* internal cluster data - context info */
|
|
typedef struct zb_zcl_tunnel_context_s
|
|
{
|
|
zb_uint16_t manufacturer_id; /* manufacturer ID - should be initialized */
|
|
zb_zcl_tunnel_cb_t tunnel_cb; /* user callback - should be registered */
|
|
/* store reference to i/o buffer: tx or rx;
|
|
* zb_zcl_tunnel_io_param_t is stored as buffer parameter to keep status info */
|
|
zb_uint8_t tunnel_io_slot[ZB_ZCL_TUNNEL_MAX_IO_SLOT_NUMBER];
|
|
}
|
|
zb_zcl_tunnel_context_t;
|
|
|
|
zb_ret_t zb_zcl_tunnel_transfer_data_req_handler(zb_uint8_t buf_param);
|
|
zb_ret_t zb_zcl_tunnel_transfer_data_resp_handler(zb_uint8_t buf_param);
|
|
void zb_zcl_tunnel_transfer_data_resp_send(zb_uint8_t param, zb_uint16_t endpoint16);
|
|
|
|
void zb_zcl_tunnel_send_fist_block(zb_uint8_t param, zb_uint16_t index16);
|
|
void zb_zcl_tunnel_timeout(zb_uint8_t index);
|
|
void zb_zcl_tunnel_invoke_user_app(zb_uint8_t param);
|
|
|
|
zb_ret_t zb_zcl_process_tunnel_default_response_commands(zb_uint8_t param);
|
|
|
|
zb_bool_t zb_zcl_process_tunnel_specific_commands(zb_uint8_t param);
|
|
|
|
/*! @} */ /* addtogroup */
|
|
|
|
/** @endcond */ /* DOXYGEN_ZCL_SECTION */
|
|
|
|
void zb_zcl_tunnel_init_server(void);
|
|
void zb_zcl_tunnel_init_client(void);
|
|
#define ZB_ZCL_CLUSTER_ID_TUNNEL_SERVER_ROLE_INIT zb_zcl_tunnel_init_server
|
|
#define ZB_ZCL_CLUSTER_ID_TUNNEL_CLIENT_ROLE_INIT zb_zcl_tunnel_init_client
|
|
|
|
#endif /* ZB_ZCL_TUNNEL_H */
|