Bluetooth: Mesh: Introduce acknowledged message API

The implementation of blocking calls is common for all the client
models.

This change reduces the code duplication by introducing new API that
helps to manage acknowledged messages.

Signed-off-by: Pavel Vasilyev <pavel.vasilyev@nordicsemi.no>
This commit is contained in:
Pavel Vasilyev 2021-03-24 17:38:03 +01:00 committed by Carles Cufí
commit a94c7e3a23
12 changed files with 494 additions and 361 deletions

View file

@ -14,6 +14,7 @@
#include <stddef.h>
#include <net/buf.h>
#include <bluetooth/mesh/msg.h>
#include <bluetooth/mesh/access.h>
#include <bluetooth/mesh/main.h>
#include <bluetooth/mesh/cfg.h>

View file

@ -160,33 +160,6 @@ struct bt_mesh_elem {
#define BT_MESH_MODEL_ID_LIGHT_LC_SETUPSRV 0x1310
#define BT_MESH_MODEL_ID_LIGHT_LC_CLI 0x1311
/** Message sending context. */
struct bt_mesh_msg_ctx {
/** NetKey Index of the subnet to send the message on. */
uint16_t net_idx;
/** AppKey Index to encrypt the message with. */
uint16_t app_idx;
/** Remote address. */
uint16_t addr;
/** Destination address of a received message. Not used for sending. */
uint16_t recv_dst;
/** RSSI of received packet. Not used for sending. */
int8_t recv_rssi;
/** Received TTL value. Not used for sending. */
uint8_t recv_ttl;
/** Force sending reliably by using segment acknowledgement */
bool send_rel;
/** TTL, or BT_MESH_TTL_DEFAULT for default TTL. */
uint8_t send_ttl;
};
/** Model opcode handler. */
struct bt_mesh_model_op {
/** OpCode encoded using the BT_MESH_MODEL_OP_* macros */
@ -220,56 +193,6 @@ struct bt_mesh_model_op {
/** Helper to define an empty model array */
#define BT_MESH_MODEL_NONE ((struct bt_mesh_model []){})
/** Length of a short Mesh MIC. */
#define BT_MESH_MIC_SHORT 4
/** Length of a long Mesh MIC. */
#define BT_MESH_MIC_LONG 8
/** @def BT_MESH_MODEL_OP_LEN
*
* @brief Helper to determine the length of an opcode.
*
* @param _op Opcode.
*/
#define BT_MESH_MODEL_OP_LEN(_op) ((_op) <= 0xff ? 1 : (_op) <= 0xffff ? 2 : 3)
/** @def BT_MESH_MODEL_BUF_LEN
*
* @brief Helper for model message buffer length.
*
* Returns the length of a Mesh model message buffer, including the opcode
* length and a short MIC.
*
* @param _op Opcode of the message.
* @param _payload_len Length of the model payload.
*/
#define BT_MESH_MODEL_BUF_LEN(_op, _payload_len) \
(BT_MESH_MODEL_OP_LEN(_op) + (_payload_len) + BT_MESH_MIC_SHORT)
/** @def BT_MESH_MODEL_BUF_LEN_LONG_MIC
*
* @brief Helper for model message buffer length.
*
* Returns the length of a Mesh model message buffer, including the opcode
* length and a long MIC.
*
* @param _op Opcode of the message.
* @param _payload_len Length of the model payload.
*/
#define BT_MESH_MODEL_BUF_LEN_LONG_MIC(_op, _payload_len) \
(BT_MESH_MODEL_OP_LEN(_op) + (_payload_len) + BT_MESH_MIC_LONG)
/** @def BT_MESH_MODEL_BUF_DEFINE
*
* @brief Define a Mesh model message buffer using @ref NET_BUF_SIMPLE_DEFINE.
*
* @param _buf Buffer name.
* @param _op Opcode of the message.
* @param _payload_len Length of the model message payload.
*/
#define BT_MESH_MODEL_BUF_DEFINE(_buf, _op, _payload_len) \
NET_BUF_SIMPLE_DEFINE(_buf, BT_MESH_MODEL_BUF_LEN(_op, (_payload_len)))
/** @def BT_MESH_MODEL_CB
*
* @brief Composition data SIG model entry with callback functions.
@ -600,16 +523,6 @@ struct bt_mesh_send_cb {
};
/** @brief Initialize a model message.
*
* Clears the message buffer contents, and encodes the given opcode.
* The message buffer will be ready for filling in payload data.
*
* @param msg Message buffer.
* @param opcode Opcode to encode.
*/
void bt_mesh_model_msg_init(struct net_buf_simple *msg, uint32_t opcode);
/** Special TTL value to request using configured default TTL */
#define BT_MESH_TTL_DEFAULT 0xff

View file

@ -27,10 +27,7 @@ struct bt_mesh_cfg_cli {
struct bt_mesh_model *model;
/* Internal parameters for tracking message responses. */
struct k_sem op_sync;
uint32_t op_pending;
void *op_param;
uint16_t op_addr;
struct bt_mesh_msg_ack_ctx ack_ctx;
};
/** @def BT_MESH_MODEL_CFG_CLI

View file

@ -46,9 +46,7 @@ struct bt_mesh_health_cli {
size_t fault_count);
/* Internal parameters for tracking message responses. */
struct k_sem op_sync;
uint32_t op_pending;
void *op_param;
struct bt_mesh_msg_ack_ctx ack_ctx;
};

View file

@ -0,0 +1,226 @@
/** @file
* @brief Bluetooth Mesh Message APIs.
*/
/*
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_MSG_H_
#define ZEPHYR_INCLUDE_BLUETOOTH_MESH_MSG_H_
/**
* @brief Bluetooth Mesh Message API
* @defgroup bt_mesh_msg Bluetooth Mesh Message API
* @ingroup bt_mesh
* @{
*/
#include <zephyr.h>
#include <net/buf.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Length of a short Mesh MIC. */
#define BT_MESH_MIC_SHORT 4
/** Length of a long Mesh MIC. */
#define BT_MESH_MIC_LONG 8
/** @def BT_MESH_MODEL_OP_LEN
*
* @brief Helper to determine the length of an opcode.
*
* @param _op Opcode.
*/
#define BT_MESH_MODEL_OP_LEN(_op) ((_op) <= 0xff ? 1 : (_op) <= 0xffff ? 2 : 3)
/** @def BT_MESH_MODEL_BUF_LEN
*
* @brief Helper for model message buffer length.
*
* Returns the length of a Mesh model message buffer, including the opcode
* length and a short MIC.
*
* @param _op Opcode of the message.
* @param _payload_len Length of the model payload.
*/
#define BT_MESH_MODEL_BUF_LEN(_op, _payload_len) \
(BT_MESH_MODEL_OP_LEN(_op) + (_payload_len) + BT_MESH_MIC_SHORT)
/** @def BT_MESH_MODEL_BUF_LEN_LONG_MIC
*
* @brief Helper for model message buffer length.
*
* Returns the length of a Mesh model message buffer, including the opcode
* length and a long MIC.
*
* @param _op Opcode of the message.
* @param _payload_len Length of the model payload.
*/
#define BT_MESH_MODEL_BUF_LEN_LONG_MIC(_op, _payload_len) \
(BT_MESH_MODEL_OP_LEN(_op) + (_payload_len) + BT_MESH_MIC_LONG)
/** @def BT_MESH_MODEL_BUF_DEFINE
*
* @brief Define a Mesh model message buffer using @ref NET_BUF_SIMPLE_DEFINE.
*
* @param _buf Buffer name.
* @param _op Opcode of the message.
* @param _payload_len Length of the model message payload.
*/
#define BT_MESH_MODEL_BUF_DEFINE(_buf, _op, _payload_len) \
NET_BUF_SIMPLE_DEFINE(_buf, BT_MESH_MODEL_BUF_LEN(_op, (_payload_len)))
/** Message sending context. */
struct bt_mesh_msg_ctx {
/** NetKey Index of the subnet to send the message on. */
uint16_t net_idx;
/** AppKey Index to encrypt the message with. */
uint16_t app_idx;
/** Remote address. */
uint16_t addr;
/** Destination address of a received message. Not used for sending. */
uint16_t recv_dst;
/** RSSI of received packet. Not used for sending. */
int8_t recv_rssi;
/** Received TTL value. Not used for sending. */
uint8_t recv_ttl;
/** Force sending reliably by using segment acknowledgment */
bool send_rel;
/** TTL, or BT_MESH_TTL_DEFAULT for default TTL. */
uint8_t send_ttl;
};
/** @brief Initialize a model message.
*
* Clears the message buffer contents, and encodes the given opcode.
* The message buffer will be ready for filling in payload data.
*
* @param msg Message buffer.
* @param opcode Opcode to encode.
*/
void bt_mesh_model_msg_init(struct net_buf_simple *msg, uint32_t opcode);
/**
* Acknowledged message context for tracking the status of model messages pending a response.
*/
struct bt_mesh_msg_ack_ctx {
struct k_sem sem; /**< Sync semaphore. */
uint32_t op; /**< Opcode we're waiting for. */
uint16_t dst; /**< Address of the node that should respond. */
void *user_data; /**< User specific parameter. */
};
/** @brief Initialize an acknowledged message context.
*
* Initializes semaphore used for synchronization between @ref bt_mesh_msg_ack_ctx_wait and
* @ref bt_mesh_msg_ack_ctx_rx calls. Call this function before using @ref bt_mesh_msg_ack_ctx.
*
* @param ack Acknowledged message context to initialize.
*/
static inline void bt_mesh_msg_ack_ctx_init(struct bt_mesh_msg_ack_ctx *ack)
{
k_sem_init(&ack->sem, 0, 1);
}
/** @brief Reset the synchronization semaphore in an acknowledged message context.
*
* This function aborts call to @ref bt_mesh_msg_ack_ctx_wait.
*
* @param ack Acknowledged message context to be reset.
*/
static inline void bt_mesh_msg_ack_ctx_reset(struct bt_mesh_msg_ack_ctx *ack)
{
k_sem_reset(&ack->sem);
}
/** @brief Clear parameters of an acknowledged message context.
*
* This function clears the opcode, remote address and user data set
* by @ref bt_mesh_msg_ack_ctx_prepare.
*
* @param ack Acknowledged message context to be cleared.
*/
void bt_mesh_msg_ack_ctx_clear(struct bt_mesh_msg_ack_ctx *ack);
/** @brief Prepare an acknowledged message context for the incoming message to wait.
*
* This function sets the opcode, remote address of the incoming message and stores the user data.
* Use this function before calling @ref bt_mesh_msg_ack_ctx_wait.
*
* @param ack Acknowledged message context to prepare.
* @param op The message OpCode.
* @param dst Destination address of the message.
* @param user_data User data for the acknowledged message context.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_msg_ack_ctx_prepare(struct bt_mesh_msg_ack_ctx *ack,
uint32_t op, uint16_t dst, void *user_data);
/** @brief Check if the acknowledged message context is initialized with an opcode.
*
* @param ack Acknowledged message context.
*
* @return true if the acknowledged message context is initialized with an opcode,
* false otherwise.
*/
static inline bool bt_mesh_msg_ack_ctx_busy(struct bt_mesh_msg_ack_ctx *ack)
{
return (ack->op != 0);
}
/** @brief Wait for a message acknowledge.
*
* This function blocks execution until @ref bt_mesh_msg_ack_ctx_rx is called or by timeout.
*
* @param ack Acknowledged message context of the message to wait for.
* @param timeout Wait timeout.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_msg_ack_ctx_wait(struct bt_mesh_msg_ack_ctx *ack, k_timeout_t timeout);
/** @brief Mark a message as acknowledged.
*
* This function unblocks call to @ref bt_mesh_msg_ack_ctx_wait.
*
* @param ack Context of a message to be acknowledged.
*/
static inline void bt_mesh_msg_ack_ctx_rx(struct bt_mesh_msg_ack_ctx *ack)
{
k_sem_give(&ack->sem);
}
/** @brief Check if an opcode and address of a message matches the expected one.
*
* @param ack Acknowledged message context to be checked.
* @param op OpCode of the incoming message.
* @param addr Source address of the incoming message.
* @param user_data If not NULL, returns a user data stored in the acknowledged message context
* by @ref bt_mesh_msg_ack_ctx_prepare.
*
* @return true if the incoming message matches the expected one, false otherwise.
*/
bool bt_mesh_msg_ack_ctx_match(const struct bt_mesh_msg_ack_ctx *ack,
uint32_t op, uint16_t addr, void **user_data);
#ifdef __cplusplus
}
#endif
/**
* @}
*/
#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_MSG_H_ */