Line data Source code
1 1 : /** @file
2 : * @brief Message APIs.
3 : */
4 :
5 : /*
6 : * Copyright (c) 2021 Nordic Semiconductor ASA
7 : *
8 : * SPDX-License-Identifier: Apache-2.0
9 : */
10 : #ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_MSG_H_
11 : #define ZEPHYR_INCLUDE_BLUETOOTH_MESH_MSG_H_
12 :
13 : /**
14 : * @brief Message
15 : * @defgroup bt_mesh_msg Message
16 : * @ingroup bt_mesh
17 : * @{
18 : */
19 :
20 : #include <zephyr/kernel.h>
21 : #include <zephyr/net_buf.h>
22 :
23 : #ifdef __cplusplus
24 : extern "C" {
25 : #endif
26 :
27 : struct bt_mesh_model;
28 :
29 : /** Length of a short Mesh MIC. */
30 1 : #define BT_MESH_MIC_SHORT 4
31 : /** Length of a long Mesh MIC. */
32 1 : #define BT_MESH_MIC_LONG 8
33 :
34 : /**
35 : * @brief Helper to determine the length of an opcode.
36 : *
37 : * @param _op Opcode.
38 : */
39 1 : #define BT_MESH_MODEL_OP_LEN(_op) ((_op) <= 0xff ? 1 : (_op) <= 0xffff ? 2 : 3)
40 :
41 : /**
42 : * @brief Helper for model message buffer length.
43 : *
44 : * Returns the length of a Mesh model message buffer, including the opcode
45 : * length and a short MIC.
46 : *
47 : * @param _op Opcode of the message.
48 : * @param _payload_len Length of the model payload.
49 : */
50 1 : #define BT_MESH_MODEL_BUF_LEN(_op, _payload_len) \
51 : (BT_MESH_MODEL_OP_LEN(_op) + (_payload_len) + BT_MESH_MIC_SHORT)
52 :
53 : /**
54 : * @brief Helper for model message buffer length.
55 : *
56 : * Returns the length of a Mesh model message buffer, including the opcode
57 : * length and a long MIC.
58 : *
59 : * @param _op Opcode of the message.
60 : * @param _payload_len Length of the model payload.
61 : */
62 1 : #define BT_MESH_MODEL_BUF_LEN_LONG_MIC(_op, _payload_len) \
63 : (BT_MESH_MODEL_OP_LEN(_op) + (_payload_len) + BT_MESH_MIC_LONG)
64 :
65 : /**
66 : * @brief Define a Mesh model message buffer using @ref NET_BUF_SIMPLE_DEFINE.
67 : *
68 : * @param _buf Buffer name.
69 : * @param _op Opcode of the message.
70 : * @param _payload_len Length of the model message payload.
71 : */
72 1 : #define BT_MESH_MODEL_BUF_DEFINE(_buf, _op, _payload_len) \
73 : NET_BUF_SIMPLE_DEFINE(_buf, BT_MESH_MODEL_BUF_LEN(_op, (_payload_len)))
74 :
75 : /** Message sending context. */
76 1 : struct bt_mesh_msg_ctx {
77 : /** NetKey Index of the subnet to send the message on. */
78 1 : uint16_t net_idx;
79 :
80 : /** AppKey Index to encrypt the message with. */
81 1 : uint16_t app_idx;
82 :
83 : /** Remote address. */
84 1 : uint16_t addr;
85 :
86 : /** Destination address of a received message. Not used for sending. */
87 1 : uint16_t recv_dst;
88 :
89 : /** Label UUID if Remote address is Virtual address, or NULL otherwise. */
90 1 : const uint8_t *uuid;
91 :
92 : /** RSSI of received packet. Not used for sending. */
93 1 : int8_t recv_rssi;
94 :
95 : /** Received TTL value. Not used for sending. */
96 1 : uint8_t recv_ttl;
97 :
98 : /** Force sending reliably by using segment acknowledgment */
99 1 : bool send_rel;
100 :
101 : /** Send message with a random delay according to the Access layer transmitting rules. */
102 1 : bool rnd_delay;
103 :
104 : /** TTL, or BT_MESH_TTL_DEFAULT for default TTL. */
105 1 : uint8_t send_ttl;
106 : };
107 :
108 : /**
109 : * @brief Helper for bt_mesh_msg_ctx structure initialization.
110 : *
111 : * @note If @c dst is a Virtual Address, Label UUID shall be initialized separately.
112 : *
113 : * @param net_key_idx NetKey Index of the subnet to send the message on. Only used if
114 : * @c app_key_idx points to devkey.
115 : * @param app_key_idx AppKey Index to encrypt the message with.
116 : * @param dst Remote addr.
117 : * @param ttl Time To Live.
118 : */
119 1 : #define BT_MESH_MSG_CTX_INIT(net_key_idx, app_key_idx, dst, ttl) \
120 : { \
121 : .net_idx = (net_key_idx), \
122 : .app_idx = (app_key_idx), \
123 : .addr = (dst), \
124 : .send_ttl = (ttl), \
125 : }
126 :
127 : /**
128 : * @brief Helper for bt_mesh_msg_ctx structure initialization secured with Application Key.
129 : *
130 : * @param app_key_idx AppKey Index to encrypt the message with.
131 : * @param dst Remote addr.
132 : */
133 1 : #define BT_MESH_MSG_CTX_INIT_APP(app_key_idx, dst) \
134 : BT_MESH_MSG_CTX_INIT(0, app_key_idx, dst, BT_MESH_TTL_DEFAULT)
135 :
136 : /**
137 : * @brief Helper for bt_mesh_msg_ctx structure initialization secured with Device Key of a remote
138 : * device.
139 : *
140 : * @param net_key_idx NetKey Index of the subnet to send the message on.
141 : * @param dst Remote addr.
142 : */
143 1 : #define BT_MESH_MSG_CTX_INIT_DEV(net_key_idx, dst) \
144 : BT_MESH_MSG_CTX_INIT(net_key_idx, BT_MESH_KEY_DEV_REMOTE, dst, BT_MESH_TTL_DEFAULT)
145 :
146 : /**
147 : * @brief Helper for bt_mesh_msg_ctx structure initialization using Model Publication context.
148 : *
149 : * @param pub Pointer to a model publication context.
150 : */
151 1 : #define BT_MESH_MSG_CTX_INIT_PUB(pub) \
152 : { \
153 : .app_idx = (pub)->key, \
154 : .addr = (pub)->addr, \
155 : .send_ttl = (pub)->ttl, \
156 : .uuid = (pub)->uuid, \
157 : }
158 :
159 : /** @brief Initialize a model message.
160 : *
161 : * Clears the message buffer contents, and encodes the given opcode.
162 : * The message buffer will be ready for filling in payload data.
163 : *
164 : * @param msg Message buffer.
165 : * @param opcode Opcode to encode.
166 : */
167 1 : void bt_mesh_model_msg_init(struct net_buf_simple *msg, uint32_t opcode);
168 :
169 : /**
170 : * Acknowledged message context for tracking the status of model messages pending a response.
171 : */
172 1 : struct bt_mesh_msg_ack_ctx {
173 1 : struct k_sem sem; /**< Sync semaphore. */
174 1 : uint32_t op; /**< Opcode we're waiting for. */
175 1 : uint16_t dst; /**< Address of the node that should respond. */
176 1 : void *user_data; /**< User specific parameter. */
177 : };
178 :
179 : /** @brief Initialize an acknowledged message context.
180 : *
181 : * Initializes semaphore used for synchronization between @ref bt_mesh_msg_ack_ctx_wait and
182 : * @ref bt_mesh_msg_ack_ctx_rx calls. Call this function before using @ref bt_mesh_msg_ack_ctx.
183 : *
184 : * @param ack Acknowledged message context to initialize.
185 : */
186 1 : static inline void bt_mesh_msg_ack_ctx_init(struct bt_mesh_msg_ack_ctx *ack)
187 : {
188 : k_sem_init(&ack->sem, 0, 1);
189 : }
190 :
191 : /** @brief Reset the synchronization semaphore in an acknowledged message context.
192 : *
193 : * This function aborts call to @ref bt_mesh_msg_ack_ctx_wait.
194 : *
195 : * @param ack Acknowledged message context to be reset.
196 : */
197 1 : static inline void bt_mesh_msg_ack_ctx_reset(struct bt_mesh_msg_ack_ctx *ack)
198 : {
199 : k_sem_reset(&ack->sem);
200 : }
201 :
202 : /** @brief Clear parameters of an acknowledged message context.
203 : *
204 : * This function clears the opcode, remote address and user data set
205 : * by @ref bt_mesh_msg_ack_ctx_prepare.
206 : *
207 : * @param ack Acknowledged message context to be cleared.
208 : */
209 1 : void bt_mesh_msg_ack_ctx_clear(struct bt_mesh_msg_ack_ctx *ack);
210 :
211 : /** @brief Prepare an acknowledged message context for the incoming message to wait.
212 : *
213 : * This function sets the opcode, remote address of the incoming message and stores the user data.
214 : * Use this function before calling @ref bt_mesh_msg_ack_ctx_wait.
215 : *
216 : * @param ack Acknowledged message context to prepare.
217 : * @param op The message OpCode.
218 : * @param dst Destination address of the message.
219 : * @param user_data User data for the acknowledged message context.
220 : *
221 : * @return 0 on success, or (negative) error code on failure.
222 : */
223 1 : int bt_mesh_msg_ack_ctx_prepare(struct bt_mesh_msg_ack_ctx *ack,
224 : uint32_t op, uint16_t dst, void *user_data);
225 :
226 : /** @brief Check if the acknowledged message context is initialized with an opcode.
227 : *
228 : * @param ack Acknowledged message context.
229 : *
230 : * @return true if the acknowledged message context is initialized with an opcode,
231 : * false otherwise.
232 : */
233 1 : static inline bool bt_mesh_msg_ack_ctx_busy(struct bt_mesh_msg_ack_ctx *ack)
234 : {
235 : return (ack->op != 0);
236 : }
237 :
238 : /** @brief Wait for a message acknowledge.
239 : *
240 : * This function blocks execution until @ref bt_mesh_msg_ack_ctx_rx is called or by timeout.
241 : *
242 : * @param ack Acknowledged message context of the message to wait for.
243 : * @param timeout Wait timeout.
244 : *
245 : * @return 0 on success, or (negative) error code on failure.
246 : */
247 1 : int bt_mesh_msg_ack_ctx_wait(struct bt_mesh_msg_ack_ctx *ack, k_timeout_t timeout);
248 :
249 : /** @brief Mark a message as acknowledged.
250 : *
251 : * This function unblocks call to @ref bt_mesh_msg_ack_ctx_wait.
252 : *
253 : * @param ack Context of a message to be acknowledged.
254 : */
255 1 : static inline void bt_mesh_msg_ack_ctx_rx(struct bt_mesh_msg_ack_ctx *ack)
256 : {
257 : k_sem_give(&ack->sem);
258 : }
259 :
260 : /** @brief Check if an opcode and address of a message matches the expected one.
261 : *
262 : * @param ack Acknowledged message context to be checked.
263 : * @param op OpCode of the incoming message.
264 : * @param addr Source address of the incoming message.
265 : * @param user_data If not NULL, returns a user data stored in the acknowledged message context
266 : * by @ref bt_mesh_msg_ack_ctx_prepare.
267 : *
268 : * @return true if the incoming message matches the expected one, false otherwise.
269 : */
270 1 : bool bt_mesh_msg_ack_ctx_match(const struct bt_mesh_msg_ack_ctx *ack,
271 : uint32_t op, uint16_t addr, void **user_data);
272 :
273 : #ifdef __cplusplus
274 : }
275 : #endif
276 :
277 : /**
278 : * @}
279 : */
280 :
281 : #endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_MSG_H_ */
|