zephyr/subsys/bluetooth/mesh/msg.c
Pavel Vasilyev a94c7e3a23 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>
2021-04-08 13:44:24 +02:00

84 lines
1.8 KiB
C

/* Bluetooth Mesh */
/*
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <bluetooth/mesh.h>
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_ACCESS)
#define LOG_MODULE_NAME bt_mesh_msg
#include "common/log.h"
void bt_mesh_model_msg_init(struct net_buf_simple *msg, uint32_t opcode)
{
net_buf_simple_init(msg, 0);
switch (BT_MESH_MODEL_OP_LEN(opcode)) {
case 1:
net_buf_simple_add_u8(msg, opcode);
break;
case 2:
net_buf_simple_add_be16(msg, opcode);
break;
case 3:
net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff));
/* Using LE for the CID since the model layer is defined as
* little-endian in the mesh spec and using BT_MESH_MODEL_OP_3
* will declare the opcode in this way.
*/
net_buf_simple_add_le16(msg, opcode & 0xffff);
break;
default:
BT_WARN("Unknown opcode format");
break;
}
}
void bt_mesh_msg_ack_ctx_clear(struct bt_mesh_msg_ack_ctx *ack)
{
ack->op = 0U;
ack->user_data = NULL;
ack->dst = BT_MESH_ADDR_UNASSIGNED;
}
int bt_mesh_msg_ack_ctx_prepare(struct bt_mesh_msg_ack_ctx *ack,
uint32_t op, uint16_t dst, void *user_data)
{
if (ack->op) {
BT_WARN("Another synchronous operation pending");
return -EBUSY;
}
ack->op = op;
ack->user_data = user_data;
ack->dst = dst;
return 0;
}
int bt_mesh_msg_ack_ctx_wait(struct bt_mesh_msg_ack_ctx *ack, k_timeout_t timeout)
{
int err;
err = k_sem_take(&ack->sem, timeout);
bt_mesh_msg_ack_ctx_clear(ack);
return err;
}
bool bt_mesh_msg_ack_ctx_match(const struct bt_mesh_msg_ack_ctx *ack,
uint32_t op, uint16_t addr, void **user_data)
{
if (ack->op != op || (BT_MESH_ADDR_IS_UNICAST(ack->dst) && ack->dst != addr)) {
return false;
}
if (user_data != NULL) {
*user_data = ack->user_data;
}
return true;
}