1 /*
2 * Copyright (C) 2019 BlueKitchen GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the copyright holders nor the names of
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * 4. Any redistribution, use, or modification is done solely for
17 * personal benefit and not for any commercial purpose or for
18 * monetary gain.
19 *
20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24 * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * Please inquire about commercial licensing options at
34 * [email protected]
35 *
36 */
37
38 #define BTSTACK_FILE__ "mesh_configuration_client.c"
39
40 #include <string.h>
41 #include <stdio.h>
42
43 #include "mesh/mesh_configuration_client.h"
44
45 #include "bluetooth_company_id.h"
46 #include "btstack_debug.h"
47 #include "btstack_memory.h"
48 #include "btstack_util.h"
49
50 #include "mesh/mesh_access.h"
51 #include "mesh/mesh_foundation.h"
52 #include "mesh/mesh_generic_model.h"
53 #include "mesh/mesh_keys.h"
54 #include "mesh/mesh_network.h"
55 #include "mesh/mesh_upper_transport.h"
56
57
58 // Mesh Composition Data Element iterator
59 #define MESH_VENDOR_MODEL_SIZE 4
60 #define MESH_SIG_MODEL_SIZE 2
61 #define MESH_COMPOSITION_DATA_ELEMENT_DESCRIPTION_OFFSET 17
62 #define MESH_COMPOSITION_DATA_ELEMENT_LOCATION_DESCRIPTOR_LEN 2
63 #define MESH_COMPOSITION_DATA_ELEMENT_MODEL_SIZE_LEN 1
64
mesh_composition_data_iterator_sig_model_list_size(mesh_composite_data_iterator_t * it)65 static inline uint16_t mesh_composition_data_iterator_sig_model_list_size(mesh_composite_data_iterator_t * it){
66 return it->elements[it->offset + 2] * MESH_SIG_MODEL_SIZE;
67 }
68
mesh_composition_data_iterator_vendor_model_list_size(mesh_composite_data_iterator_t * it)69 static inline uint16_t mesh_composition_data_iterator_vendor_model_list_size(mesh_composite_data_iterator_t * it){
70 return it->elements[it->offset + 3] * MESH_VENDOR_MODEL_SIZE;
71 }
72
mesh_composition_data_iterator_element_len(mesh_composite_data_iterator_t * it)73 static inline uint16_t mesh_composition_data_iterator_element_len(mesh_composite_data_iterator_t * it){
74 uint16_t sig_model_list_size = mesh_composition_data_iterator_sig_model_list_size(it);
75 uint16_t vendor_model_list_size = mesh_composition_data_iterator_vendor_model_list_size(it);
76 uint16_t previous_fields_len = MESH_COMPOSITION_DATA_ELEMENT_LOCATION_DESCRIPTOR_LEN + 2 * MESH_COMPOSITION_DATA_ELEMENT_MODEL_SIZE_LEN;
77
78 return previous_fields_len + sig_model_list_size + vendor_model_list_size;;
79 }
80
mesh_subevent_configuration_composition_data_get_num_elements(const uint8_t * event,uint16_t size)81 uint16_t mesh_subevent_configuration_composition_data_get_num_elements(const uint8_t * event, uint16_t size){
82 uint16_t pos = MESH_COMPOSITION_DATA_ELEMENT_DESCRIPTION_OFFSET;
83 uint16_t num_elements = 0;
84
85 while ((pos + 4) <= size){
86 // location descriptor
87 pos += 2;
88 uint8_t num_sig_model_ids = event[pos++];
89 uint8_t num_vendor_model_ids = event[pos++];
90 pos += (num_sig_model_ids + num_vendor_model_ids) * 2;
91 num_elements++;
92 }
93 return num_elements;
94 }
95
mesh_composition_data_iterator_init(mesh_composite_data_iterator_t * it,const uint8_t * elements,uint16_t size)96 void mesh_composition_data_iterator_init(mesh_composite_data_iterator_t * it, const uint8_t * elements, uint16_t size){
97 it->elements = elements;
98 it->size = size;
99 it->offset = MESH_COMPOSITION_DATA_ELEMENT_DESCRIPTION_OFFSET;
100 }
101
mesh_composition_data_iterator_has_next_element(mesh_composite_data_iterator_t * it)102 bool mesh_composition_data_iterator_has_next_element(mesh_composite_data_iterator_t * it){
103 if ((it->offset + 3) >= it->size) return false;
104 return (it->offset + mesh_composition_data_iterator_element_len(it)) <= it->size;
105 }
106
mesh_composition_data_iterator_next_element(mesh_composite_data_iterator_t * it)107 void mesh_composition_data_iterator_next_element(mesh_composite_data_iterator_t * it){
108 it->sig_model_iterator.models = &it->elements[it->offset + 4];
109 it->sig_model_iterator.size = mesh_composition_data_iterator_sig_model_list_size(it);
110 it->sig_model_iterator.offset = 0;
111
112 it->vendor_model_iterator.models = &it->elements[it->offset + 4 + it->sig_model_iterator.size];
113 it->vendor_model_iterator.size = mesh_composition_data_iterator_vendor_model_list_size(it);
114 it->vendor_model_iterator.offset = 0;
115
116 it->loc = little_endian_read_16(it->elements, it->offset);
117 it->offset += mesh_composition_data_iterator_element_len(it);
118 }
119
mesh_composition_data_iterator_element_loc(mesh_composite_data_iterator_t * it)120 uint16_t mesh_composition_data_iterator_element_loc(mesh_composite_data_iterator_t * it){
121 return it->loc;
122 }
123
mesh_composition_data_iterator_has_next_sig_model(mesh_composite_data_iterator_t * it)124 bool mesh_composition_data_iterator_has_next_sig_model(mesh_composite_data_iterator_t * it){
125 return (it->sig_model_iterator.offset + MESH_SIG_MODEL_SIZE) <= it->sig_model_iterator.size;
126 }
127
mesh_composition_data_iterator_next_sig_model(mesh_composite_data_iterator_t * it)128 void mesh_composition_data_iterator_next_sig_model(mesh_composite_data_iterator_t * it){
129 it->sig_model_iterator.id = little_endian_read_16(it->sig_model_iterator.models, it->sig_model_iterator.offset);
130 it->sig_model_iterator.offset += 2;
131 }
132
mesh_composition_data_iterator_sig_model_id(mesh_composite_data_iterator_t * it)133 uint16_t mesh_composition_data_iterator_sig_model_id(mesh_composite_data_iterator_t * it){
134 return (uint16_t)it->sig_model_iterator.id;
135 }
136
mesh_composition_data_iterator_has_next_vendor_model(mesh_composite_data_iterator_t * it)137 bool mesh_composition_data_iterator_has_next_vendor_model(mesh_composite_data_iterator_t * it){
138 return (it->vendor_model_iterator.offset + MESH_VENDOR_MODEL_SIZE) <= it->vendor_model_iterator.size;
139 }
140
mesh_composition_data_iterator_next_vendor_model(mesh_composite_data_iterator_t * it)141 void mesh_composition_data_iterator_next_vendor_model(mesh_composite_data_iterator_t * it){
142 uint16_t vendor_id = little_endian_read_16(it->vendor_model_iterator.models, it->vendor_model_iterator.offset);
143 it->vendor_model_iterator.offset += 2;
144 uint16_t model_id = little_endian_read_16(it->vendor_model_iterator.models, it->vendor_model_iterator.offset);
145 it->vendor_model_iterator.offset += 2;
146 it->vendor_model_iterator.id = mesh_model_get_model_identifier(vendor_id, model_id);
147 }
148
mesh_composition_data_iterator_vendor_model_id(mesh_composite_data_iterator_t * it)149 uint32_t mesh_composition_data_iterator_vendor_model_id(mesh_composite_data_iterator_t * it){
150 return it->vendor_model_iterator.id;
151 }
152
153 // Configuration client messages
154
155 static const mesh_access_message_t mesh_configuration_client_beacon_get = {
156 MESH_FOUNDATION_OPERATION_BEACON_GET, ""
157 };
158 static const mesh_access_message_t mesh_configuration_client_beacon_set = {
159 MESH_FOUNDATION_OPERATION_BEACON_SET, "1"
160 };
161
162
163 static const mesh_access_message_t mesh_configuration_client_composition_data_get = {
164 MESH_FOUNDATION_OPERATION_COMPOSITION_DATA_GET, "1"
165 };
166
167
168 static const mesh_access_message_t mesh_configuration_client_default_ttl_get = {
169 MESH_FOUNDATION_OPERATION_DEFAULT_TTL_GET, ""
170 };
171 static const mesh_access_message_t mesh_configuration_client_default_ttl_set = {
172 MESH_FOUNDATION_OPERATION_DEFAULT_TTL_SET, "1"
173 };
174
175
176 static const mesh_access_message_t mesh_configuration_client_gatt_proxy_get = {
177 MESH_FOUNDATION_OPERATION_GATT_PROXY_GET, ""
178 };
179 static const mesh_access_message_t mesh_configuration_client_gatt_proxy_set = {
180 MESH_FOUNDATION_OPERATION_GATT_PROXY_SET, "1"
181 };
182
183
184 static const mesh_access_message_t mesh_configuration_client_relay_get = {
185 MESH_FOUNDATION_OPERATION_RELAY_GET, ""
186 };
187 static const mesh_access_message_t mesh_configuration_client_relay_set = {
188 MESH_FOUNDATION_OPERATION_RELAY_SET, "11"
189 };
190
191 static const mesh_access_message_t mesh_configuration_client_model_publication_get = {
192 MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_GET, "2m"
193 };
194 static const mesh_access_message_t mesh_configuration_client_model_publication_set = {
195 MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_SET, "222111m"
196 };
197 static const mesh_access_message_t mesh_configuration_client_model_publication_virtual_address_set = {
198 MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_VIRTUAL_ADDRESS_SET, "2P2111m"
199 };
200
201
202 static const mesh_access_message_t mesh_configuration_client_model_subscription_add = {
203 MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_ADD, "22m"
204 };
205 static const mesh_access_message_t mesh_configuration_client_model_subscription_virtual_address_add = {
206 MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_VIRTUAL_ADDRESS_ADD, "2Pm"
207 };
208 static const mesh_access_message_t mesh_configuration_client_model_subscription_delete = {
209 MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_DELETE, "22m"
210 };
211 static const mesh_access_message_t mesh_configuration_client_model_subscription_virtual_address_delete = {
212 MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_VIRTUAL_ADDRESS_DELETE, "2Pm"
213 };
214 static const mesh_access_message_t mesh_configuration_client_model_subscription_overwrite = {
215 MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_OVERWRITE, "22m"
216 };
217 static const mesh_access_message_t mesh_configuration_client_model_subscription_virtual_address_overwrite = {
218 MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_VIRTUAL_ADDRESS_OVERWRITE, "2Pm"
219 };
220 static const mesh_access_message_t mesh_configuration_client_model_subscription_delete_all = {
221 MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_DELETE_ALL, "22m"
222 };
223
224
225 static const mesh_access_message_t mesh_configuration_client_sig_model_subscription_get = {
226 MESH_FOUNDATION_OPERATION_SIG_MODEL_SUBSCRIPTION_GET, "22"
227 };
228
229 static const mesh_access_message_t mesh_configuration_client_vendor_model_subscription_get = {
230 MESH_FOUNDATION_OPERATION_VENDOR_MODEL_SUBSCRIPTION_GET, "24"
231 };
232
233 static const mesh_access_message_t mesh_configuration_client_netkey_add = {
234 MESH_FOUNDATION_OPERATION_NETKEY_ADD, "2P"
235 };
236 static const mesh_access_message_t mesh_configuration_client_netkey_update = {
237 MESH_FOUNDATION_OPERATION_NETKEY_UPDATE, "2P"
238 };
239 static const mesh_access_message_t mesh_configuration_client_netkey_delete = {
240 MESH_FOUNDATION_OPERATION_NETKEY_DELETE, "2"
241 };
242 static const mesh_access_message_t mesh_configuration_client_netkey_get = {
243 MESH_FOUNDATION_OPERATION_NETKEY_GET, ""
244 };
245
246
247 static const mesh_access_message_t mesh_configuration_client_appkey_add = {
248 MESH_FOUNDATION_OPERATION_APPKEY_ADD, "3P"
249 };
250 static const mesh_access_message_t mesh_configuration_client_appkey_update = {
251 MESH_FOUNDATION_OPERATION_APPKEY_UPDATE, "3P"
252 };
253 static const mesh_access_message_t mesh_configuration_client_appkey_delete = {
254 MESH_FOUNDATION_OPERATION_APPKEY_DELETE, "3"
255 };
256 static const mesh_access_message_t mesh_configuration_client_appkey_get = {
257 MESH_FOUNDATION_OPERATION_APPKEY_GET, "2"
258 };
259
260 static const mesh_access_message_t mesh_configuration_client_node_identity_get = {
261 MESH_FOUNDATION_OPERATION_NODE_IDENTITY_GET, "2"
262 };
263 static const mesh_access_message_t mesh_configuration_client_node_identity_set = {
264 MESH_FOUNDATION_OPERATION_NODE_IDENTITY_SET, "21"
265 };
266
267 static const mesh_access_message_t mesh_configuration_client_model_app_bind = {
268 MESH_FOUNDATION_OPERATION_MODEL_APP_BIND, "22m"
269 };
270 static const mesh_access_message_t mesh_configuration_client_model_app_unbind = {
271 MESH_FOUNDATION_OPERATION_MODEL_APP_UNBIND, "22m"
272 };
273
274 static const mesh_access_message_t mesh_configuration_client_sig_model_app_get = {
275 MESH_FOUNDATION_OPERATION_SIG_MODEL_APP_GET, "2m"
276 };
277 static const mesh_access_message_t mesh_configuration_client_vendor_model_app_get = {
278 MESH_FOUNDATION_OPERATION_VENDOR_MODEL_APP_GET, "2m"
279 };
280
281 static const mesh_access_message_t mesh_configuration_client_node_reset = {
282 MESH_FOUNDATION_OPERATION_NODE_RESET, ""
283 };
284
285 static const mesh_access_message_t mesh_configuration_client_friend_get = {
286 MESH_FOUNDATION_OPERATION_FRIEND_GET, ""
287 };
288 static const mesh_access_message_t mesh_configuration_client_friend_set = {
289 MESH_FOUNDATION_OPERATION_FRIEND_SET, "1"
290 };
291
292 static const mesh_access_message_t mesh_configuration_client_key_refresh_phase_get = {
293 MESH_FOUNDATION_OPERATION_KEY_REFRESH_PHASE_GET, "2"
294 };
295 static const mesh_access_message_t mesh_configuration_client_key_refresh_phase_set = {
296 MESH_FOUNDATION_OPERATION_KEY_REFRESH_PHASE_SET, "21"
297 };
298
299 static const mesh_access_message_t mesh_configuration_client_heartbeat_publication_get = {
300 MESH_FOUNDATION_OPERATION_HEARTBEAT_PUBLICATION_GET, ""
301 };
302 static const mesh_access_message_t mesh_configuration_client_heartbeat_publication_set = {
303 MESH_FOUNDATION_OPERATION_HEARTBEAT_PUBLICATION_SET, "211122"
304 };
305
306 static const mesh_access_message_t mesh_configuration_client_heartbeat_subscription_get = {
307 MESH_FOUNDATION_OPERATION_HEARTBEAT_SUBSCRIPTION_GET, ""
308 };
309 static const mesh_access_message_t mesh_configuration_client_heartbeat_subscription_set = {
310 MESH_FOUNDATION_OPERATION_HEARTBEAT_SUBSCRIPTION_SET, "221"
311 };
312
313 static const mesh_access_message_t mesh_configuration_client_low_power_node_poll_timeout_get = {
314 MESH_FOUNDATION_OPERATION_LOW_POWER_NODE_POLL_TIMEOUT_GET, ""
315 };
316
317
318 static const mesh_access_message_t mesh_configuration_network_transmit_get = {
319 MESH_FOUNDATION_OPERATION_NETWORK_TRANSMIT_GET, ""
320 };
321 static const mesh_access_message_t mesh_configuration_network_transmit_set = {
322 MESH_FOUNDATION_OPERATION_NETWORK_TRANSMIT_SET, "1"
323 };
324
mesh_configuration_client_send_acknowledged(uint16_t src,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,mesh_pdu_t * pdu,uint32_t ack_opcode)325 static void mesh_configuration_client_send_acknowledged(uint16_t src, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, mesh_pdu_t *pdu, uint32_t ack_opcode){
326 uint8_t ttl = mesh_foundation_default_ttl_get();
327 mesh_upper_transport_setup_access_pdu_header(pdu, netkey_index, appkey_index, ttl, src, dest, 0);
328 mesh_access_send_acknowledged_pdu(pdu, mesh_access_acknowledged_message_retransmissions(), ack_opcode);
329 }
330
mesh_access_validate_envelop_params(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index)331 static uint8_t mesh_access_validate_envelop_params(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index){
332 btstack_assert(mesh_model != NULL);
333 // TODO: validate other params
334 UNUSED(mesh_model);
335 UNUSED(dest);
336 UNUSED(netkey_index);
337 UNUSED(appkey_index);
338
339 return ERROR_CODE_SUCCESS;
340 }
341
mesh_configuration_client_send_beacon_get(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index)342 uint8_t mesh_configuration_client_send_beacon_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index){
343 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
344 if (status != ERROR_CODE_SUCCESS) return status;
345
346 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_beacon_get);
347 if (!upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
348
349 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_BEACON_STATUS);
350 return ERROR_CODE_SUCCESS;
351 }
352
mesh_configuration_client_send_beacon_set(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint8_t beacon)353 uint8_t mesh_configuration_client_send_beacon_set(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint8_t beacon){
354 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
355 if (status != ERROR_CODE_SUCCESS) return status;
356
357 if (beacon > 1) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE;
358
359 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_beacon_set, beacon);
360 if (!upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
361
362 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_BEACON_STATUS);
363 return ERROR_CODE_SUCCESS;
364 }
365
mesh_configuration_client_send_composition_data_get(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint8_t page)366 uint8_t mesh_configuration_client_send_composition_data_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint8_t page){
367 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
368 if (status != ERROR_CODE_SUCCESS) return status;
369
370 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_composition_data_get, page);
371 if (!upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
372
373 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_COMPOSITION_DATA_STATUS);
374 return ERROR_CODE_SUCCESS;
375 }
376
mesh_configuration_client_send_default_ttl_get(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index)377 uint8_t mesh_configuration_client_send_default_ttl_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index){
378 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
379 if (status != ERROR_CODE_SUCCESS) return status;
380
381 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_default_ttl_get);
382 if (!upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
383
384 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_DEFAULT_TTL_STATUS);
385 return ERROR_CODE_SUCCESS;
386 }
387
mesh_configuration_client_send_default_ttl_set(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint8_t ttl)388 uint8_t mesh_configuration_client_send_default_ttl_set(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint8_t ttl){
389 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
390 if (status != ERROR_CODE_SUCCESS) return status;
391
392 if (ttl == 0x01 || ttl >= 0x80) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE;
393
394 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_default_ttl_set, ttl);
395 if (!upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
396
397 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_DEFAULT_TTL_STATUS);
398 return ERROR_CODE_SUCCESS;
399 }
400
mesh_configuration_client_send_gatt_proxy_get(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index)401 uint8_t mesh_configuration_client_send_gatt_proxy_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index){
402 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
403 if (status != ERROR_CODE_SUCCESS) return status;
404
405 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_gatt_proxy_get);
406 if (!upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
407
408 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_GATT_PROXY_STATUS);
409 return ERROR_CODE_SUCCESS;
410 }
411
mesh_configuration_client_send_gatt_proxy_set(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint8_t gatt_proxy_state)412 uint8_t mesh_configuration_client_send_gatt_proxy_set(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint8_t gatt_proxy_state){
413 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
414 if (status != ERROR_CODE_SUCCESS) return status;
415
416 if (gatt_proxy_state > 2) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE;
417
418 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_gatt_proxy_set, gatt_proxy_state);
419 if (!upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
420
421 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_GATT_PROXY_STATUS);
422 return ERROR_CODE_SUCCESS;
423 }
424
mesh_configuration_client_send_relay_get(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index)425 uint8_t mesh_configuration_client_send_relay_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index){
426 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
427 if (status != ERROR_CODE_SUCCESS) return status;
428
429 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_relay_get);
430 if (!upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
431
432 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_RELAY_STATUS);
433 return ERROR_CODE_SUCCESS;
434 }
435
mesh_configuration_client_send_relay_set(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint8_t relay,uint8_t relay_retransmit_count,uint8_t relay_retransmit_interval_steps)436 uint8_t mesh_configuration_client_send_relay_set(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint8_t relay, uint8_t relay_retransmit_count, uint8_t relay_retransmit_interval_steps){
437 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
438 if (status != ERROR_CODE_SUCCESS) return status;
439
440 if (relay_retransmit_count > 0x07) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE;
441 if (relay_retransmit_interval_steps > 0x1F) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE;
442
443 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_relay_set, relay, (relay_retransmit_count << 5) | relay_retransmit_interval_steps);
444 if (!upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
445
446 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_RELAY_SET);
447 return ERROR_CODE_SUCCESS;
448 }
449
mesh_configuration_client_send_model_publication_get(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint32_t model_id)450 uint8_t mesh_configuration_client_send_model_publication_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint32_t model_id){
451 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
452 if (status != ERROR_CODE_SUCCESS) return status;
453
454 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_model_publication_get, dest, model_id);
455 if (!upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
456
457 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_STATUS);
458 return ERROR_CODE_SUCCESS;
459 }
460
mesh_validate_publication_model_config_parameters(mesh_publication_model_config_t * publication_config,bool use_unicast_address)461 static uint8_t mesh_validate_publication_model_config_parameters(mesh_publication_model_config_t * publication_config, bool use_unicast_address){
462 if (publication_config->appkey_index > 0xFFF) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE;
463 if (publication_config->credential_flag > 1) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE;
464 if (publication_config->publish_retransmit_count > 0x07) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE;
465 if (publication_config->publish_retransmit_interval_steps > 0x1F) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE;
466 if (use_unicast_address && mesh_network_address_virtual(publication_config->publish_address_unicast)) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE;
467 return ERROR_CODE_SUCCESS;
468 }
469
mesh_configuration_client_send_model_publication_set(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint32_t model_id,mesh_publication_model_config_t * publication_config)470 uint8_t mesh_configuration_client_send_model_publication_set(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint32_t model_id, mesh_publication_model_config_t * publication_config){
471 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
472 if (status != ERROR_CODE_SUCCESS) return status;
473
474 if (!mesh_network_address_unicast(dest) ||
475 mesh_validate_publication_model_config_parameters(publication_config, true) != ERROR_CODE_SUCCESS){
476 return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE;
477 }
478
479 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_model_publication_set,
480 dest,
481 publication_config->publish_address_unicast,
482 (publication_config->credential_flag << 12) | publication_config->appkey_index,
483 publication_config->publish_ttl,
484 publication_config->publish_period,
485 (publication_config->publish_retransmit_interval_steps << 3) | publication_config->publish_retransmit_count,
486 model_id);
487 if (!upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
488
489 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_STATUS);
490 return ERROR_CODE_SUCCESS;
491
492 }
493
mesh_configuration_client_send_model_publication_virtual_address_set(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint32_t model_id,mesh_publication_model_config_t * publication_config)494 uint8_t mesh_configuration_client_send_model_publication_virtual_address_set(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint32_t model_id, mesh_publication_model_config_t * publication_config){
495 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
496 if (status != ERROR_CODE_SUCCESS) return status;
497
498 if (!mesh_network_address_unicast(dest) ||
499 mesh_validate_publication_model_config_parameters(publication_config, false) != ERROR_CODE_SUCCESS){
500 return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE;
501 }
502
503 mesh_upper_transport_pdu_t * transport_pdu = mesh_access_setup_message(&mesh_configuration_client_model_publication_virtual_address_set,
504 dest,
505 publication_config->publish_address_virtual,
506 (publication_config->credential_flag << 12) | publication_config->appkey_index,
507 publication_config->publish_ttl,
508 publication_config->publish_period,
509 (publication_config->publish_retransmit_interval_steps << 3) | publication_config->publish_retransmit_count,
510 model_id);
511 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
512
513 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_STATUS);
514 return ERROR_CODE_SUCCESS;
515 }
516
517
mesh_configuration_client_send_model_subscription_add(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint16_t address,uint32_t model_id)518 uint8_t mesh_configuration_client_send_model_subscription_add(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint16_t address, uint32_t model_id){
519 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
520 if (status != ERROR_CODE_SUCCESS) return status;
521
522 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_model_subscription_add, dest, address, model_id);
523 if (!upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
524
525 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_STATUS);
526 return ERROR_CODE_SUCCESS;
527 }
528
mesh_configuration_client_send_model_subscription_virtual_address_add(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint8_t * address,uint32_t model_id)529 uint8_t mesh_configuration_client_send_model_subscription_virtual_address_add(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint8_t * address, uint32_t model_id){
530 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
531 if (status != ERROR_CODE_SUCCESS) return status;
532
533 mesh_upper_transport_pdu_t * transport_pdu = mesh_access_setup_message(&mesh_configuration_client_model_subscription_virtual_address_add, dest, address, model_id);
534 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
535
536 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_STATUS);
537 return ERROR_CODE_SUCCESS;
538 }
539
mesh_configuration_client_send_model_subscription_delete(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint16_t address,uint32_t model_id)540 uint8_t mesh_configuration_client_send_model_subscription_delete(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint16_t address, uint32_t model_id){
541 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
542 if (status != ERROR_CODE_SUCCESS) return status;
543
544 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_model_subscription_delete, dest, address, model_id);
545 if (!upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
546
547 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_STATUS);
548 return ERROR_CODE_SUCCESS;
549 }
550
mesh_configuration_client_send_model_subscription_virtual_address_delete(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint8_t * address,uint32_t model_id)551 uint8_t mesh_configuration_client_send_model_subscription_virtual_address_delete(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint8_t * address, uint32_t model_id){
552 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
553 if (status != ERROR_CODE_SUCCESS) return status;
554
555 mesh_upper_transport_pdu_t * transport_pdu = mesh_access_setup_message(&mesh_configuration_client_model_subscription_virtual_address_delete, dest, address, model_id);
556 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
557
558 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_STATUS);
559 return ERROR_CODE_SUCCESS;
560 }
561
mesh_configuration_client_send_model_subscription_overwrite(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint16_t address,uint32_t model_id)562 uint8_t mesh_configuration_client_send_model_subscription_overwrite(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint16_t address, uint32_t model_id){
563 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
564 if (status != ERROR_CODE_SUCCESS) return status;
565
566 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_model_subscription_overwrite, dest, address, model_id);
567 if (!upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
568
569 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_STATUS);
570 return ERROR_CODE_SUCCESS;
571 }
572
mesh_configuration_client_send_model_subscription_virtual_address_overwrite(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint8_t * address,uint32_t model_id)573 uint8_t mesh_configuration_client_send_model_subscription_virtual_address_overwrite(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint8_t * address, uint32_t model_id){
574 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
575 if (status != ERROR_CODE_SUCCESS) return status;
576
577 mesh_upper_transport_pdu_t * transport_pdu = mesh_access_setup_message(&mesh_configuration_client_model_subscription_virtual_address_overwrite, dest, address, model_id);
578 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
579
580 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_STATUS);
581 return ERROR_CODE_SUCCESS;
582 }
583
mesh_configuration_client_send_model_subscription_delete_all(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint16_t address,uint32_t model_id)584 uint8_t mesh_configuration_client_send_model_subscription_delete_all(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint16_t address, uint32_t model_id){
585 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
586 if (status != ERROR_CODE_SUCCESS) return status;
587
588 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_model_subscription_delete_all, dest, address, model_id);
589 if (!upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
590
591 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_STATUS);
592 return ERROR_CODE_SUCCESS;
593 }
594
mesh_configuration_client_send_model_subscription_get(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint32_t model_id)595 uint8_t mesh_configuration_client_send_model_subscription_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint32_t model_id){
596 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
597 if (status != ERROR_CODE_SUCCESS) return status;
598
599 mesh_upper_transport_pdu_t * upper_pdu = NULL;
600 uint32_t ack_opcode = MESH_FOUNDATION_OPERATION_SIG_MODEL_SUBSCRIPTION_LIST;
601
602 if (mesh_model_is_bluetooth_sig(model_id)){
603 upper_pdu = mesh_access_setup_message(&mesh_configuration_client_sig_model_subscription_get, dest, model_id);
604 } else {
605 upper_pdu = mesh_access_setup_message(&mesh_configuration_client_vendor_model_subscription_get, dest, model_id);
606 ack_opcode = MESH_FOUNDATION_OPERATION_VENDOR_MODEL_SUBSCRIPTION_LIST;
607 }
608
609 if (!upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
610
611 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, ack_opcode);
612 return ERROR_CODE_SUCCESS;
613 }
614
mesh_configuration_client_send_netkey_add(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint16_t index,uint8_t * netkey)615 uint8_t mesh_configuration_client_send_netkey_add(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint16_t index, uint8_t * netkey){
616 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
617 if (status != ERROR_CODE_SUCCESS) return status;
618
619 mesh_upper_transport_pdu_t * transport_pdu = mesh_access_setup_message(&mesh_configuration_client_netkey_add, index, netkey);
620 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
621
622 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_NETKEY_STATUS);
623 return ERROR_CODE_SUCCESS;
624 }
625
mesh_configuration_client_send_netkey_update(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint16_t index,uint8_t * netkey)626 uint8_t mesh_configuration_client_send_netkey_update(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint16_t index, uint8_t * netkey){
627 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
628 if (status != ERROR_CODE_SUCCESS) return status;
629
630 mesh_upper_transport_pdu_t * transport_pdu = mesh_access_setup_message(&mesh_configuration_client_netkey_update, index, netkey);
631 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
632
633 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_NETKEY_STATUS);
634 return ERROR_CODE_SUCCESS;
635 }
636
mesh_configuration_client_send_netkey_delete(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint16_t index)637 uint8_t mesh_configuration_client_send_netkey_delete(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint16_t index){
638 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
639 if (status != ERROR_CODE_SUCCESS) return status;
640
641 mesh_upper_transport_pdu_t * transport_pdu = mesh_access_setup_message(&mesh_configuration_client_netkey_delete, index);
642 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
643
644 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_NETKEY_STATUS);
645 return ERROR_CODE_SUCCESS;
646 }
647
mesh_configuration_client_send_netkey_get(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index)648 uint8_t mesh_configuration_client_send_netkey_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index){
649 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
650 if (status != ERROR_CODE_SUCCESS) return status;
651
652 mesh_upper_transport_pdu_t * transport_pdu = mesh_access_setup_message(&mesh_configuration_client_netkey_get);
653 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
654
655 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_NETKEY_LIST);
656 return ERROR_CODE_SUCCESS;
657 }
658
mesh_configuration_client_send_appkey_add(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint16_t netk_index,uint16_t appk_index,uint8_t * appkey)659 uint8_t mesh_configuration_client_send_appkey_add(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint16_t netk_index, uint16_t appk_index, uint8_t * appkey){
660 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
661 if (status != ERROR_CODE_SUCCESS) return status;
662
663 mesh_upper_transport_pdu_t * transport_pdu = mesh_access_setup_message(&mesh_configuration_client_appkey_add, netk_index << 12 | appk_index, appkey);
664 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
665
666 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_APPKEY_STATUS);
667 return ERROR_CODE_SUCCESS;
668 }
669
mesh_configuration_client_send_appkey_update(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint16_t netk_index,uint16_t appk_index,uint8_t * appkey)670 uint8_t mesh_configuration_client_send_appkey_update(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint16_t netk_index, uint16_t appk_index, uint8_t * appkey){
671 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
672 if (status != ERROR_CODE_SUCCESS) return status;
673
674 mesh_upper_transport_pdu_t * transport_pdu = mesh_access_setup_message(&mesh_configuration_client_appkey_update, netk_index << 12 | appk_index, appkey);
675 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
676
677 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_APPKEY_STATUS);
678 return ERROR_CODE_SUCCESS;
679 }
680
mesh_configuration_client_send_appkey_delete(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint16_t netk_index,uint16_t appk_index)681 uint8_t mesh_configuration_client_send_appkey_delete(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint16_t netk_index, uint16_t appk_index){
682 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
683 if (status != ERROR_CODE_SUCCESS) return status;
684
685 mesh_upper_transport_pdu_t * transport_pdu = mesh_access_setup_message(&mesh_configuration_client_appkey_delete, netk_index << 12 | appk_index);
686 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
687
688 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_APPKEY_STATUS);
689 return ERROR_CODE_SUCCESS;
690 }
691
mesh_configuration_client_send_appkey_get(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint16_t netk_index)692 uint8_t mesh_configuration_client_send_appkey_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint16_t netk_index){
693 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
694 if (status != ERROR_CODE_SUCCESS) return status;
695
696 mesh_upper_transport_pdu_t * transport_pdu = mesh_access_setup_message(&mesh_configuration_client_appkey_get, netk_index);
697 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
698
699 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_APPKEY_LIST);
700 return ERROR_CODE_SUCCESS;
701 }
702
mesh_configuration_client_send_node_identity_get(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint16_t netk_index)703 uint8_t mesh_configuration_client_send_node_identity_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint16_t netk_index){
704 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
705 if (status != ERROR_CODE_SUCCESS) return status;
706
707 mesh_upper_transport_pdu_t * transport_pdu = mesh_access_setup_message(&mesh_configuration_client_node_identity_get, netk_index);
708 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
709
710 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_NODE_IDENTITY_STATUS);
711 return ERROR_CODE_SUCCESS;
712 }
713
mesh_configuration_client_send_node_identity_set(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint16_t netk_index,mesh_node_identity_state_t node_identity_state)714 uint8_t mesh_configuration_client_send_node_identity_set(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint16_t netk_index, mesh_node_identity_state_t node_identity_state){
715 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
716 if (status != ERROR_CODE_SUCCESS) return status;
717
718 mesh_upper_transport_pdu_t * transport_pdu = mesh_access_setup_message(&mesh_configuration_client_node_identity_set, netk_index, node_identity_state);
719 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
720
721 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_NODE_IDENTITY_STATUS);
722 return ERROR_CODE_SUCCESS;
723 }
724
mesh_configuration_client_send_model_app_bind_get(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint16_t appk_index,uint32_t model_identifier)725 uint8_t mesh_configuration_client_send_model_app_bind_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint16_t appk_index, uint32_t model_identifier){
726 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
727 if (status != ERROR_CODE_SUCCESS) return status;
728
729 mesh_upper_transport_pdu_t * transport_pdu = mesh_access_setup_message(&mesh_configuration_client_model_app_bind, dest, appk_index, model_identifier);
730 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
731
732 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_MODEL_APP_STATUS);
733 return ERROR_CODE_SUCCESS;
734 }
735
mesh_configuration_client_send_model_app_unbind_set(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint16_t appk_index,uint32_t model_identifier)736 uint8_t mesh_configuration_client_send_model_app_unbind_set(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint16_t appk_index, uint32_t model_identifier){
737 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
738 if (status != ERROR_CODE_SUCCESS) return status;
739
740 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_model_app_unbind, dest, appk_index, model_identifier);
741 if (!upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
742
743 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_MODEL_APP_STATUS);
744 return ERROR_CODE_SUCCESS;
745 }
746
mesh_configuration_client_send_model_app_get(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint32_t model_identifier)747 uint8_t mesh_configuration_client_send_model_app_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint32_t model_identifier){
748 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
749 if (status != ERROR_CODE_SUCCESS) return status;
750
751 mesh_upper_transport_pdu_t * upper_pdu;
752 uint32_t ack_opcode = MESH_FOUNDATION_OPERATION_SIG_MODEL_APP_LIST;
753
754 if (mesh_model_is_bluetooth_sig(model_identifier)){
755 upper_pdu = mesh_access_setup_message(&mesh_configuration_client_sig_model_app_get, dest, model_identifier);
756 } else {
757 upper_pdu = mesh_access_setup_message(&mesh_configuration_client_vendor_model_app_get, dest, model_identifier);
758 ack_opcode = MESH_FOUNDATION_OPERATION_VENDOR_MODEL_APP_LIST;
759 }
760
761 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, ack_opcode);
762 return ERROR_CODE_SUCCESS;
763 }
764
mesh_configuration_client_send_node_reset(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index)765 uint8_t mesh_configuration_client_send_node_reset(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index){
766 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
767 if (status != ERROR_CODE_SUCCESS) return status;
768
769 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_node_reset);
770 if (upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
771
772 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_NODE_RESET_STATUS);
773 return ERROR_CODE_SUCCESS;
774 }
775
mesh_configuration_client_send_friend_get(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index)776 uint8_t mesh_configuration_client_send_friend_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index){
777 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
778 if (status != ERROR_CODE_SUCCESS) return status;
779
780 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_friend_get);
781 if (upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
782
783 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_FRIEND_STATUS);
784 return ERROR_CODE_SUCCESS;
785 }
786
mesh_configuration_client_send_friend_set(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,mesh_friend_state_t friend_state)787 uint8_t mesh_configuration_client_send_friend_set(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, mesh_friend_state_t friend_state){
788 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
789 if (status != ERROR_CODE_SUCCESS) return status;
790
791 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_friend_set, friend_state);
792 if (upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
793
794 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_FRIEND_STATUS);
795 return ERROR_CODE_SUCCESS;
796 }
797
mesh_configuration_client_send_key_refresh_phase_get(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint16_t netk_index)798 uint8_t mesh_configuration_client_send_key_refresh_phase_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint16_t netk_index){
799 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
800 if (status != ERROR_CODE_SUCCESS) return status;
801
802 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_key_refresh_phase_get, netk_index);
803 if (upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
804
805 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_KEY_REFRESH_PHASE_STATUS);
806 return ERROR_CODE_SUCCESS;
807 }
808
mesh_configuration_client_send_key_refresh_phase_set(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint16_t netk_index,uint8_t transition)809 uint8_t mesh_configuration_client_send_key_refresh_phase_set(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint16_t netk_index, uint8_t transition){
810 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
811 if (status != ERROR_CODE_SUCCESS) return status;
812
813 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_key_refresh_phase_set, netk_index, transition);
814 if (upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
815
816 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_KEY_REFRESH_PHASE_STATUS);
817 return ERROR_CODE_SUCCESS;
818 }
819
mesh_configuration_client_send_heartbeat_publication_get(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index)820 uint8_t mesh_configuration_client_send_heartbeat_publication_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index){
821 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
822 if (status != ERROR_CODE_SUCCESS) return status;
823
824 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_heartbeat_publication_get);
825 if (upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
826
827 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_HEARTBEAT_PUBLICATION_STATUS);
828 return ERROR_CODE_SUCCESS;
829 }
830
mesh_configuration_client_send_heartbeat_publication_set(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,mesh_heartbeat_publication_state_t publication_state)831 uint8_t mesh_configuration_client_send_heartbeat_publication_set(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, mesh_heartbeat_publication_state_t publication_state){
832 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
833 if (status != ERROR_CODE_SUCCESS) return status;
834
835 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_heartbeat_publication_set,
836 publication_state.destination,
837 mesh_heartbeat_period_log(publication_state.count),
838 mesh_heartbeat_period_log(publication_state.period_s),
839 publication_state.ttl,
840 publication_state.features,
841 publication_state.netkey_index);
842
843 if (upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
844
845 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_HEARTBEAT_PUBLICATION_STATUS);
846 return ERROR_CODE_SUCCESS;
847 }
848
mesh_configuration_client_send_heartbeat_subscription_get(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index)849 uint8_t mesh_configuration_client_send_heartbeat_subscription_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index){
850 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
851 if (status != ERROR_CODE_SUCCESS) return status;
852
853 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_heartbeat_subscription_get);
854 if (upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
855
856 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_HEARTBEAT_SUBSCRIPTION_STATUS);
857 return ERROR_CODE_SUCCESS;
858 }
859
mesh_configuration_client_send_heartbeat_subscription_set(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint16_t heartbeat_source,uint16_t heartbeat_destination,uint16_t period_s)860 uint8_t mesh_configuration_client_send_heartbeat_subscription_set(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint16_t heartbeat_source, uint16_t heartbeat_destination, uint16_t period_s){
861 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
862 if (status != ERROR_CODE_SUCCESS) return status;
863
864 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_heartbeat_subscription_set, heartbeat_source, heartbeat_destination, mesh_heartbeat_period_log(period_s));
865 if (upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
866
867 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_HEARTBEAT_SUBSCRIPTION_STATUS);
868 return ERROR_CODE_SUCCESS;
869 }
870
mesh_configuration_client_send_low_power_node_poll_timeout_get(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index)871 uint8_t mesh_configuration_client_send_low_power_node_poll_timeout_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index){
872 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
873 if (status != ERROR_CODE_SUCCESS) return status;
874
875 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_client_low_power_node_poll_timeout_get);
876 if (upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
877
878 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_LOW_POWER_NODE_POLL_TIMEOUT_STATUS);
879 return ERROR_CODE_SUCCESS;
880 }
881
mesh_configuration_client_send_network_transmit_get(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index)882 uint8_t mesh_configuration_client_send_network_transmit_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index){
883 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
884 if (status != ERROR_CODE_SUCCESS) return status;
885
886 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_network_transmit_get);
887 if (upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
888
889 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_NETWORK_TRANSMIT_STATUS);
890 return ERROR_CODE_SUCCESS;
891 }
892
mesh_configuration_client_send_network_transmit_set(mesh_model_t * mesh_model,uint16_t dest,uint16_t netkey_index,uint16_t appkey_index,uint8_t transmit_count,uint16_t transmit_interval_steps_ms)893 uint8_t mesh_configuration_client_send_network_transmit_set(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint8_t transmit_count, uint16_t transmit_interval_steps_ms){
894 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index);
895 if (status != ERROR_CODE_SUCCESS) return status;
896
897 uint8_t transmit_interval_steps_10ms = (uint8_t) (transmit_interval_steps_ms/10);
898 if (transmit_interval_steps_10ms > 0){
899 transmit_interval_steps_10ms -= 1;
900 }
901
902 mesh_upper_transport_pdu_t * upper_pdu = mesh_access_setup_message(&mesh_configuration_network_transmit_set, (transmit_count << 5) | (transmit_interval_steps_10ms & 0x1F));
903 if (upper_pdu) return BTSTACK_MEMORY_ALLOC_FAILED;
904
905 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) upper_pdu, MESH_FOUNDATION_OPERATION_NETWORK_TRANSMIT_STATUS);
906 return ERROR_CODE_SUCCESS;
907 }
908
909 // Model Operations
mesh_configuration_client_composition_data_status_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)910 static void mesh_configuration_client_composition_data_status_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
911 // Composition Data has variable of element descriptions, with two lists of model lists
912 // Pass raw data to application but provide convenient setters instead of parsing pdu here
913
914 // reuse part of the mesh_network_t / mesh_transport_t struct to create event without memcpy or allocation
915 uint8_t * data = mesh_pdu_data(pdu);
916 uint8_t * event = &data[-6];
917
918 int pos = 0;
919 event[pos++] = HCI_EVENT_MESH_META;
920 // Composite Data might be larger than 251 bytes - in this case only lower 8 bit are stored here. packet size is correct
921 event[pos++] = (uint8_t) (6 + mesh_pdu_len(pdu));
922 event[pos++] = MESH_SUBEVENT_CONFIGURATION_COMPOSITION_DATA;
923 // dest
924 little_endian_store_16(event, pos, mesh_pdu_src(pdu));
925 pos += 2;
926 event[pos++] = ERROR_CODE_SUCCESS;
927
928 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos);
929 mesh_access_message_processed(pdu);
930 }
931
mesh_subevent_configuration_composition_data_get_page(const uint8_t * event)932 uint8_t mesh_subevent_configuration_composition_data_get_page(const uint8_t * event){
933 return event[6];
934 }
935
mesh_subevent_configuration_composition_data_get_cid(const uint8_t * event)936 uint16_t mesh_subevent_configuration_composition_data_get_cid(const uint8_t * event){
937 return little_endian_read_16(event, 7);
938 }
939
mesh_subevent_configuration_composition_data_get_pid(const uint8_t * event)940 uint16_t mesh_subevent_configuration_composition_data_get_pid(const uint8_t * event){
941 return little_endian_read_16(event, 9);
942 }
943
mesh_subevent_configuration_composition_data_get_vid(const uint8_t * event)944 uint16_t mesh_subevent_configuration_composition_data_get_vid(const uint8_t * event){
945 return little_endian_read_16(event, 11);
946 }
947
mesh_subevent_configuration_composition_data_get_crpl(const uint8_t * event)948 uint16_t mesh_subevent_configuration_composition_data_get_crpl(const uint8_t * event){
949 return little_endian_read_16(event, 13);
950 }
951
mesh_subevent_configuration_composition_data_get_features(const uint8_t * event)952 uint16_t mesh_subevent_configuration_composition_data_get_features(const uint8_t * event){
953 return little_endian_read_16(event, 15);
954 }
955
956
mesh_configuration_client_handle_uint8_value(mesh_model_t * mesh_model,mesh_pdu_t * pdu,uint8_t subevent_type)957 static inline void mesh_configuration_client_handle_uint8_value(mesh_model_t *mesh_model, mesh_pdu_t * pdu, uint8_t subevent_type){
958 mesh_access_parser_state_t parser;
959 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu);
960
961 uint8_t value = mesh_access_parser_get_uint8(&parser);
962
963 uint8_t event[7];
964 int pos = 0;
965
966 event[pos++] = HCI_EVENT_MESH_META;
967 event[pos++] = sizeof(event) - 2;
968 event[pos++] = subevent_type;
969 // dest
970 little_endian_store_16(event, pos, mesh_pdu_src(pdu));
971 pos += 2;
972 event[pos++] = ERROR_CODE_SUCCESS;
973 event[pos++] = value;
974
975 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos);
976 mesh_access_message_processed(pdu);
977 }
978
mesh_configuration_client_beacon_status_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)979 static void mesh_configuration_client_beacon_status_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
980 mesh_configuration_client_handle_uint8_value(mesh_model, pdu, MESH_SUBEVENT_CONFIGURATION_BEACON);
981 }
982
mesh_configuration_client_default_ttl_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)983 static void mesh_configuration_client_default_ttl_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
984 mesh_configuration_client_handle_uint8_value(mesh_model, pdu, MESH_SUBEVENT_CONFIGURATION_DEFAULT_TTL);
985 }
986
mesh_configuration_client_gatt_proxy_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)987 static void mesh_configuration_client_gatt_proxy_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
988 mesh_configuration_client_handle_uint8_value(mesh_model, pdu, MESH_SUBEVENT_CONFIGURATION_GATT_PROXY);
989 }
990
mesh_configuration_client_relay_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)991 static void mesh_configuration_client_relay_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
992 mesh_access_parser_state_t parser;
993 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu);
994
995 uint8_t relay = mesh_access_parser_get_uint8(&parser);
996 uint8_t retransmition = mesh_access_parser_get_uint8(&parser);
997
998 uint8_t event[9];
999
1000 int pos = 0;
1001 event[pos++] = HCI_EVENT_MESH_META;
1002 event[pos++] = sizeof(event) - 2;
1003 event[pos++] = MESH_SUBEVENT_CONFIGURATION_RELAY;
1004 // dest
1005 little_endian_store_16(event, pos, mesh_pdu_src(pdu));
1006 pos += 2;
1007 event[pos++] = ERROR_CODE_SUCCESS;
1008 event[pos++] = relay;
1009 event[pos++] = (retransmition >> 5) + 1;
1010 event[pos++] = ((retransmition & 0x07) + 1) * 10;
1011
1012 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos);
1013 mesh_access_message_processed(pdu);
1014 }
1015
mesh_configuration_client_model_publication_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)1016 static void mesh_configuration_client_model_publication_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
1017 mesh_access_parser_state_t parser;
1018 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu);
1019 uint8_t status = mesh_access_parser_get_uint8(&parser);
1020 uint16_t publish_addres = mesh_access_parser_get_uint16(&parser);
1021
1022 uint16_t value = mesh_access_parser_get_uint16(&parser);
1023 uint16_t appkey_index = value & 0xFFF;
1024 uint8_t credential_flag = (value & 0x1000) >> 12;
1025
1026 uint8_t publish_ttl = mesh_access_parser_get_uint8(&parser);
1027 uint8_t publish_period = mesh_access_parser_get_uint8(&parser);
1028
1029 uint8_t retransmit = mesh_access_parser_get_uint8(&parser);
1030 uint8_t publish_retransmit_count = retransmit & 0x111;
1031 uint8_t publish_retransmit_interval_steps = retransmit >> 5;
1032 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser);
1033
1034 uint8_t event[19];
1035 int pos = 0;
1036 event[pos++] = HCI_EVENT_MESH_META;
1037 event[pos++] = sizeof(event) - 2;
1038 event[pos++] = MESH_SUBEVENT_CONFIGURATION_MODEL_PUBLICATION;
1039 // dest
1040 little_endian_store_16(event, pos, mesh_pdu_src(pdu));
1041 pos += 2;
1042 event[pos++] = status;
1043
1044 little_endian_store_16(event, pos, publish_addres);
1045 pos += 2;
1046
1047 little_endian_store_16(event, pos, appkey_index);
1048 pos += 2;
1049
1050 event[pos++] = credential_flag;
1051 event[pos++] = publish_ttl;
1052 event[pos++] = publish_period;
1053 event[pos++] = publish_retransmit_count;
1054 event[pos++] = publish_retransmit_interval_steps;
1055
1056 little_endian_store_32(event, pos, model_identifier);
1057 pos += 4;
1058
1059 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos);
1060 mesh_access_message_processed(pdu);
1061 }
1062
mesh_configuration_client_model_subscription_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)1063 static void mesh_configuration_client_model_subscription_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
1064 mesh_access_parser_state_t parser;
1065 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu);
1066 uint8_t status = mesh_access_parser_get_uint8(&parser);
1067 uint16_t address = mesh_access_parser_get_uint16(&parser);
1068 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser);
1069
1070 uint8_t event[12];
1071 int pos = 0;
1072 event[pos++] = HCI_EVENT_MESH_META;
1073 event[pos++] = sizeof(event) - 2;
1074 event[pos++] = MESH_SUBEVENT_CONFIGURATION_MODEL_SUBSCRIPTION;
1075 // dest
1076 little_endian_store_16(event, pos, mesh_pdu_src(pdu));
1077 pos += 2;
1078 event[pos++] = status;
1079
1080 little_endian_store_16(event, pos, address);
1081 pos += 2;
1082
1083 little_endian_store_32(event, pos, model_identifier);
1084 pos += 4;
1085
1086 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos);
1087 mesh_access_message_processed(pdu);
1088 }
1089
mesh_configuration_client_model_subscription_event(mesh_model_t * mesh_model,mesh_pdu_t * pdu,bool is_sig_model)1090 static void mesh_configuration_client_model_subscription_event(mesh_model_t *mesh_model, mesh_pdu_t * pdu, bool is_sig_model){
1091 mesh_access_parser_state_t parser;
1092 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu);
1093 uint8_t status = mesh_access_parser_get_uint8(&parser);
1094 uint16_t element_address = mesh_access_parser_get_uint16(&parser);
1095 uint32_t model_identifier;
1096
1097 if (element_address != mesh_pdu_src(pdu)){
1098 log_info("MESH_SUBEVENT_CONFIGURATION_MODEL_SUBSCRIPTION_LIST_ITEM event, element_address differs from mesh_pdu_src");
1099 }
1100
1101 if (is_sig_model == true) {
1102 model_identifier = mesh_access_parser_get_sig_model_identifier(&parser);
1103 } else {
1104 model_identifier = mesh_access_parser_get_vendor_model_identifier(&parser);
1105 }
1106 uint8_t list_size = mesh_access_parser_available(&parser)/2;
1107
1108 uint8_t event[14];
1109 int pos = 0;
1110 event[pos++] = HCI_EVENT_MESH_META;
1111 event[pos++] = sizeof(event) - 2;
1112 event[pos++] = MESH_SUBEVENT_CONFIGURATION_MODEL_SUBSCRIPTION_LIST_ITEM;
1113 // dest
1114 little_endian_store_16(event, pos, mesh_pdu_src(pdu));
1115 pos += 2;
1116 event[pos++] = status;
1117
1118 little_endian_store_32(event, pos, model_identifier);
1119 pos += 4;
1120
1121 event[pos++] = list_size;
1122 uint8_t i;
1123 for (i = 0; i < list_size; i++){
1124 event[pos++] = i;
1125 little_endian_store_16(event, pos, mesh_access_parser_get_uint16(&parser));
1126 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos + 2);
1127 }
1128 mesh_access_message_processed(pdu);
1129 }
1130
mesh_configuration_client_sig_model_subscription_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)1131 static void mesh_configuration_client_sig_model_subscription_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
1132 mesh_configuration_client_model_subscription_event(mesh_model, pdu, true);
1133 }
1134
mesh_configuration_client_vendor_model_subscription_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)1135 static void mesh_configuration_client_vendor_model_subscription_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
1136 mesh_configuration_client_model_subscription_event(mesh_model, pdu, false);
1137 }
1138
mesh_configuration_client_netkey_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)1139 static void mesh_configuration_client_netkey_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
1140 mesh_access_parser_state_t parser;
1141 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu);
1142 uint8_t status = mesh_access_parser_get_uint8(&parser);
1143
1144 uint8_t event[6];
1145 int pos = 0;
1146 event[pos++] = HCI_EVENT_MESH_META;
1147 event[pos++] = sizeof(event) - 2;
1148 event[pos++] = MESH_SUBEVENT_CONFIGURATION_NETKEY_INDEX;
1149 // dest
1150 little_endian_store_16(event, pos, mesh_pdu_src(pdu));
1151 pos += 2;
1152 event[pos++] = status;
1153 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos);
1154 mesh_access_message_processed(pdu);
1155 }
1156
mesh_configuration_client_netkey_list_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)1157 static void mesh_configuration_client_netkey_list_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
1158 mesh_access_parser_state_t parser;
1159 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu);
1160 uint8_t status = 0;
1161 uint8_t list_size = mesh_access_parser_available(&parser)/2;
1162
1163 uint8_t event[10];
1164 int pos = 0;
1165 event[pos++] = HCI_EVENT_MESH_META;
1166 event[pos++] = sizeof(event) - 2;
1167 event[pos++] = MESH_SUBEVENT_CONFIGURATION_NETKEY_INDEX_LIST_ITEM;
1168 // dest
1169 little_endian_store_16(event, pos, mesh_pdu_src(pdu));
1170 pos += 2;
1171 event[pos++] = status;
1172
1173 event[pos++] = list_size;
1174 uint8_t i;
1175 for (i = 0; i < list_size; i++){
1176 event[pos++] = i;
1177 little_endian_store_16(event, pos, mesh_access_parser_get_uint16(&parser));
1178 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos + 2);
1179 }
1180 mesh_access_message_processed(pdu);
1181 }
1182
mesh_configuration_client_appkey_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)1183 static void mesh_configuration_client_appkey_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
1184 mesh_access_parser_state_t parser;
1185 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu);
1186 uint8_t status = mesh_access_parser_get_uint8(&parser);
1187 uint32_t netappkey_index = mesh_access_parser_get_uint24(&parser);
1188 uint16_t netkey_index = netappkey_index >> 12;
1189 uint16_t appkey_index = netappkey_index & 0xFFF;
1190
1191 uint8_t event[10];
1192 int pos = 0;
1193 event[pos++] = HCI_EVENT_MESH_META;
1194 event[pos++] = sizeof(event) - 2;
1195 event[pos++] = MESH_SUBEVENT_CONFIGURATION_APPKEY_INDEX;
1196 // dest
1197 little_endian_store_16(event, pos, mesh_pdu_src(pdu));
1198 pos += 2;
1199 event[pos++] = status;
1200 little_endian_store_16(event, pos, netkey_index);
1201 pos += 2;
1202 little_endian_store_16(event, pos, appkey_index);
1203 pos += 2;
1204
1205 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos);
1206 mesh_access_message_processed(pdu);
1207 }
1208
mesh_configuration_client_appkey_list_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)1209 static void mesh_configuration_client_appkey_list_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
1210 mesh_access_parser_state_t parser;
1211 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu);
1212 uint8_t status = 0;
1213 uint8_t list_size = mesh_access_parser_available(&parser)/2;
1214
1215 uint8_t event[12];
1216 int pos = 0;
1217 event[pos++] = HCI_EVENT_MESH_META;
1218 event[pos++] = sizeof(event) - 2;
1219 event[pos++] = MESH_SUBEVENT_CONFIGURATION_APPKEY_INDEX_LIST_ITEM;
1220 // dest
1221 little_endian_store_16(event, pos, mesh_pdu_src(pdu));
1222 pos += 2;
1223 event[pos++] = status;
1224
1225 event[pos++] = list_size;
1226 uint8_t i;
1227 for (i = 0; i < list_size; i++){
1228 event[pos++] = i;
1229 uint32_t netappkey_index = mesh_access_parser_get_uint24(&parser);
1230 little_endian_store_16(event, pos, netappkey_index >> 12);
1231 little_endian_store_16(event, pos + 2, netappkey_index & 0xFFF);
1232 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos + 4);
1233 }
1234 mesh_access_message_processed(pdu);
1235 }
1236
mesh_configuration_client_node_identity_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)1237 static void mesh_configuration_client_node_identity_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
1238 mesh_access_parser_state_t parser;
1239 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu);
1240 uint8_t status = mesh_access_parser_get_uint8(&parser);
1241 uint16_t netkey_index = mesh_access_parser_get_uint16(&parser);
1242 uint8_t identity_status = mesh_access_parser_get_uint8(&parser);
1243
1244 uint8_t event[9];
1245 int pos = 0;
1246 event[pos++] = HCI_EVENT_MESH_META;
1247 event[pos++] = sizeof(event) - 2;
1248 event[pos++] = MESH_SUBEVENT_CONFIGURATION_NODE_IDENTITY;
1249 // dest
1250 little_endian_store_16(event, pos, mesh_pdu_src(pdu));
1251 pos += 2;
1252 event[pos++] = status;
1253 little_endian_store_16(event, pos, netkey_index);
1254 pos += 2;
1255 event[pos++] = identity_status;
1256
1257 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos);
1258 mesh_access_message_processed(pdu);
1259 }
1260
mesh_configuration_client_model_app_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)1261 static void mesh_configuration_client_model_app_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
1262 mesh_access_parser_state_t parser;
1263 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu);
1264 uint8_t status = mesh_access_parser_get_uint8(&parser);
1265 uint16_t element_address = mesh_access_parser_get_uint16(&parser);
1266 uint16_t appkey_index = mesh_access_parser_get_uint16(&parser);
1267 uint32_t model_id = 0;
1268
1269 if (element_address != mesh_pdu_src(pdu)){
1270 log_info("MESH_SUBEVENT_CONFIGURATION_MODEL_APP event, element_address differs from mesh_pdu_src");
1271 }
1272
1273 if (mesh_access_parser_available(&parser) == 4){
1274 model_id = mesh_access_parser_get_uint32(&parser);
1275 } else {
1276 model_id = mesh_access_parser_get_uint16(&parser);
1277 }
1278
1279 uint8_t event[12];
1280 int pos = 0;
1281 event[pos++] = HCI_EVENT_MESH_META;
1282 event[pos++] = sizeof(event) - 2;
1283 event[pos++] = MESH_SUBEVENT_CONFIGURATION_MODEL_APP;
1284 // dest
1285 little_endian_store_16(event, pos, mesh_pdu_src(pdu));
1286 pos += 2;
1287 event[pos++] = status;
1288
1289 little_endian_store_16(event, pos, appkey_index);
1290 pos += 2;
1291 little_endian_store_32(event, pos, model_id);
1292 pos += 4;
1293
1294 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos);
1295 mesh_access_message_processed(pdu);
1296 }
1297
1298
mesh_configuration_client_model_app_list_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu,bool is_sig_model)1299 static void mesh_configuration_client_model_app_list_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu, bool is_sig_model){
1300 mesh_access_parser_state_t parser;
1301 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu);
1302
1303 uint8_t status = mesh_access_parser_get_uint8(&parser);
1304 uint16_t element_address = mesh_access_parser_get_uint16(&parser);
1305 uint32_t model_identifier;
1306
1307 if (element_address != mesh_pdu_src(pdu)){
1308 log_info("MESH_SUBEVENT_CONFIGURATION_MODEL_APP_LIST_ITEM event, element_address differs from mesh_pdu_src");
1309 }
1310
1311 if (is_sig_model == true) {
1312 model_identifier = mesh_access_parser_get_sig_model_identifier(&parser);
1313 } else {
1314 model_identifier = mesh_access_parser_get_vendor_model_identifier(&parser);
1315 }
1316
1317 uint8_t list_size = mesh_access_parser_available(&parser)/2;
1318
1319 uint8_t event[14];
1320 int pos = 0;
1321 event[pos++] = HCI_EVENT_MESH_META;
1322 event[pos++] = sizeof(event) - 2;
1323 event[pos++] = MESH_SUBEVENT_CONFIGURATION_MODEL_APP_LIST_ITEM;
1324 // dest
1325 little_endian_store_16(event, pos, mesh_pdu_src(pdu));
1326 pos += 2;
1327 event[pos++] = status;
1328
1329 little_endian_store_32(event, pos, model_identifier);
1330 pos += 4;
1331
1332 event[pos++] = list_size;
1333 uint8_t i;
1334 for (i = 0; i < list_size; i++){
1335 event[pos++] = i;
1336 uint16_t appkey_index = mesh_access_parser_get_uint16(&parser);
1337 little_endian_store_16(event, pos, appkey_index);
1338 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos + 2);
1339 }
1340 mesh_access_message_processed(pdu);
1341 }
1342
mesh_configuration_client_sig_model_app_list_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)1343 static void mesh_configuration_client_sig_model_app_list_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
1344 mesh_configuration_client_model_app_list_handler(mesh_model, pdu, true);
1345 }
1346
mesh_configuration_client_vendor_model_app_list_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)1347 static void mesh_configuration_client_vendor_model_app_list_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
1348 mesh_configuration_client_model_app_list_handler(mesh_model, pdu, false);
1349 }
1350
mesh_configuration_client_node_reset_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)1351 static void mesh_configuration_client_node_reset_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
1352 uint8_t event[6];
1353 int pos = 0;
1354 event[pos++] = HCI_EVENT_MESH_META;
1355 event[pos++] = sizeof(event) - 2;
1356 event[pos++] = MESH_SUBEVENT_CONFIGURATION_NODE_RESET;
1357 // dest
1358 little_endian_store_16(event, pos, mesh_pdu_src(pdu));
1359 pos += 2;
1360 event[pos++] = ERROR_CODE_SUCCESS;
1361
1362 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos);
1363 mesh_access_message_processed(pdu);
1364 }
1365
mesh_configuration_client_friend_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)1366 static void mesh_configuration_client_friend_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
1367 mesh_access_parser_state_t parser;
1368 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu);
1369 uint8_t friend_state = mesh_access_parser_get_uint8(&parser);
1370
1371 uint8_t event[7];
1372 int pos = 0;
1373 event[pos++] = HCI_EVENT_MESH_META;
1374 event[pos++] = sizeof(event) - 2;
1375 event[pos++] = MESH_SUBEVENT_CONFIGURATION_FRIEND;
1376 // dest
1377 little_endian_store_16(event, pos, mesh_pdu_src(pdu));
1378 pos += 2;
1379 event[pos++] = ERROR_CODE_SUCCESS;
1380 event[pos++] = friend_state;
1381
1382 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos);
1383 mesh_access_message_processed(pdu);
1384 }
1385
mesh_configuration_client_key_refresh_phase_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)1386 static void mesh_configuration_client_key_refresh_phase_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
1387 mesh_access_parser_state_t parser;
1388 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu);
1389 uint8_t status = mesh_access_parser_get_uint8(&parser);
1390 uint16_t netkey_index = mesh_access_parser_get_uint16(&parser);
1391 uint8_t phase = mesh_access_parser_get_uint8(&parser);
1392
1393 uint8_t event[9];
1394 int pos = 0;
1395 event[pos++] = HCI_EVENT_MESH_META;
1396 event[pos++] = sizeof(event) - 2;
1397 event[pos++] = MESH_SUBEVENT_CONFIGURATION_KEY_REFRESH_PHASE;
1398 // dest
1399 little_endian_store_16(event, pos, mesh_pdu_src(pdu));
1400 pos += 2;
1401 event[pos++] = status;
1402 little_endian_store_16(event, pos, netkey_index);
1403 pos += 2;
1404 event[pos++] = phase;
1405
1406 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos);
1407 mesh_access_message_processed(pdu);
1408 }
1409
mesh_configuration_client_heartbeat_publication_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)1410 static void mesh_configuration_client_heartbeat_publication_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
1411 mesh_access_parser_state_t parser;
1412 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu);
1413 uint8_t status = mesh_access_parser_get_uint8(&parser);
1414 uint16_t dest = mesh_access_parser_get_uint16(&parser);
1415 uint8_t count = mesh_heartbeat_pwr2(mesh_access_parser_get_uint8(&parser));
1416 uint16_t period_s = mesh_heartbeat_pwr2(mesh_access_parser_get_uint8(&parser));
1417 uint8_t ttl = mesh_access_parser_get_uint8(&parser);
1418 uint16_t features = mesh_access_parser_get_uint16(&parser);
1419 uint16_t netkey_index = mesh_access_parser_get_uint16(&parser);
1420
1421 uint8_t event[17];
1422 int pos = 0;
1423 event[pos++] = HCI_EVENT_MESH_META;
1424 event[pos++] = sizeof(event) - 2;
1425 event[pos++] = MESH_SUBEVENT_CONFIGURATION_HEARTBEAT_PUBLICATION;
1426 // dest
1427 little_endian_store_16(event, pos, mesh_pdu_src(pdu));
1428 pos += 2;
1429 event[pos++] = status;
1430 little_endian_store_16(event, pos, dest);
1431 pos += 2;
1432 little_endian_store_16(event, pos, count);
1433 pos += 2;
1434 little_endian_store_16(event, pos, period_s);
1435 pos += 2;
1436 event[pos++] = ttl;
1437 little_endian_store_16(event, pos, features);
1438 pos += 2;
1439 little_endian_store_16(event, pos, netkey_index);
1440 pos += 2;
1441 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos);
1442 mesh_access_message_processed(pdu);
1443 }
1444
mesh_configuration_client_heartbeat_subscription_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)1445 static void mesh_configuration_client_heartbeat_subscription_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
1446 mesh_access_parser_state_t parser;
1447 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu);
1448 uint8_t status = mesh_access_parser_get_uint8(&parser);
1449 uint16_t source = mesh_access_parser_get_uint16(&parser);
1450 uint16_t dest = mesh_access_parser_get_uint16(&parser);
1451 uint16_t period_s = mesh_heartbeat_pwr2(mesh_access_parser_get_uint8(&parser));
1452 uint16_t count = mesh_heartbeat_pwr2(mesh_access_parser_get_uint8(&parser));
1453 uint8_t min_hops = mesh_access_parser_get_uint8(&parser);
1454 uint8_t max_hops = mesh_access_parser_get_uint8(&parser);
1455
1456 uint8_t event[16];
1457 int pos = 0;
1458 event[pos++] = HCI_EVENT_MESH_META;
1459 event[pos++] = sizeof(event) - 2;
1460 event[pos++] = MESH_SUBEVENT_CONFIGURATION_HEARTBEAT_SUBSCRIPTION;
1461 // dest
1462 little_endian_store_16(event, pos, mesh_pdu_src(pdu));
1463 pos += 2;
1464 event[pos++] = status;
1465 little_endian_store_16(event, pos, dest);
1466 pos += 2;
1467 little_endian_store_16(event, pos, source);
1468 pos += 2;
1469 little_endian_store_16(event, pos, count);
1470 pos += 2;
1471 little_endian_store_16(event, pos, period_s);
1472 pos += 2;
1473 event[pos++] = min_hops;
1474 event[pos++] = max_hops;
1475
1476 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos);
1477 mesh_access_message_processed(pdu);
1478 }
1479
mesh_configuration_client_low_power_node_poll_timeout_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)1480 static void mesh_configuration_client_low_power_node_poll_timeout_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
1481 mesh_access_parser_state_t parser;
1482 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu);
1483 uint16_t lpn_address = mesh_access_parser_get_uint16(&parser);
1484 uint32_t poll_timeout = mesh_access_parser_get_uint24(&parser);
1485
1486 uint8_t event[11];
1487 int pos = 0;
1488 event[pos++] = HCI_EVENT_MESH_META;
1489 event[pos++] = sizeof(event) - 2;
1490 event[pos++] = MESH_SUBEVENT_CONFIGURATION_LOW_POWER_NODE_POLL_TIMEOUT;
1491 // dest
1492 little_endian_store_16(event, pos, mesh_pdu_src(pdu));
1493 pos += 2;
1494 event[pos++] = ERROR_CODE_SUCCESS;
1495
1496 little_endian_store_16(event, pos, lpn_address);
1497 pos += 2;
1498
1499 little_endian_store_24(event, pos, poll_timeout);
1500 pos += 3;
1501
1502 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos);
1503 mesh_access_message_processed(pdu);
1504 }
1505
mesh_configuration_client_network_transmit_handler(mesh_model_t * mesh_model,mesh_pdu_t * pdu)1506 static void mesh_configuration_client_network_transmit_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){
1507 mesh_access_parser_state_t parser;
1508 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu);
1509 uint8_t value = mesh_access_parser_get_uint8(&parser);
1510 uint8_t transmit_count = value >> 5;
1511 uint8_t transmit_interval_steps_10ms = value & 0x1F;
1512
1513 uint8_t event[9];
1514 int pos = 0;
1515 event[pos++] = HCI_EVENT_MESH_META;
1516 event[pos++] = sizeof(event) - 2;
1517 event[pos++] = MESH_SUBEVENT_CONFIGURATION_NETWORK_TRANSMIT;
1518 // dest
1519 little_endian_store_16(event, pos, mesh_pdu_src(pdu));
1520 pos += 2;
1521 event[pos++] = ERROR_CODE_SUCCESS;
1522
1523 event[pos++] = transmit_count;
1524 little_endian_store_16(event, pos, (transmit_interval_steps_10ms + 1) * 10);
1525 pos += 2;
1526
1527 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos);
1528 mesh_access_message_processed(pdu);
1529 }
1530
1531 static const mesh_operation_t mesh_configuration_client_model_operations[] = {
1532 { MESH_FOUNDATION_OPERATION_BEACON_STATUS, 1, mesh_configuration_client_beacon_status_handler },
1533 { MESH_FOUNDATION_OPERATION_COMPOSITION_DATA_STATUS, 10, mesh_configuration_client_composition_data_status_handler },
1534 { MESH_FOUNDATION_OPERATION_DEFAULT_TTL_STATUS, 1, mesh_configuration_client_default_ttl_handler },
1535 { MESH_FOUNDATION_OPERATION_GATT_PROXY_STATUS, 1, mesh_configuration_client_gatt_proxy_handler },
1536 { MESH_FOUNDATION_OPERATION_RELAY_STATUS, 2, mesh_configuration_client_relay_handler },
1537 { MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_STATUS, 12, mesh_configuration_client_model_publication_handler },
1538 { MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_STATUS, 7, mesh_configuration_client_model_subscription_handler },
1539 { MESH_FOUNDATION_OPERATION_SIG_MODEL_SUBSCRIPTION_LIST, 5, mesh_configuration_client_sig_model_subscription_handler},
1540 { MESH_FOUNDATION_OPERATION_VENDOR_MODEL_SUBSCRIPTION_LIST, 7, mesh_configuration_client_vendor_model_subscription_handler},
1541 { MESH_FOUNDATION_OPERATION_NETKEY_STATUS, 3, mesh_configuration_client_netkey_handler },
1542 { MESH_FOUNDATION_OPERATION_NETKEY_LIST, 0, mesh_configuration_client_netkey_list_handler },
1543 { MESH_FOUNDATION_OPERATION_APPKEY_STATUS, 4, mesh_configuration_client_appkey_handler },
1544 { MESH_FOUNDATION_OPERATION_APPKEY_LIST, 3, mesh_configuration_client_appkey_list_handler },
1545 { MESH_FOUNDATION_OPERATION_NODE_IDENTITY_STATUS, 4, mesh_configuration_client_node_identity_handler },
1546 { MESH_FOUNDATION_OPERATION_MODEL_APP_STATUS, 7, mesh_configuration_client_model_app_handler },
1547 { MESH_FOUNDATION_OPERATION_SIG_MODEL_APP_LIST, 5, mesh_configuration_client_sig_model_app_list_handler },
1548 { MESH_FOUNDATION_OPERATION_VENDOR_MODEL_APP_LIST, 7, mesh_configuration_client_vendor_model_app_list_handler },
1549 { MESH_FOUNDATION_OPERATION_NODE_RESET_STATUS, 0, mesh_configuration_client_node_reset_handler },
1550 { MESH_FOUNDATION_OPERATION_FRIEND_STATUS, 1, mesh_configuration_client_friend_handler },
1551 { MESH_FOUNDATION_OPERATION_KEY_REFRESH_PHASE_STATUS, 4, mesh_configuration_client_key_refresh_phase_handler },
1552 { MESH_FOUNDATION_OPERATION_HEARTBEAT_PUBLICATION_STATUS, 12, mesh_configuration_client_heartbeat_publication_handler },
1553 { MESH_FOUNDATION_OPERATION_HEARTBEAT_SUBSCRIPTION_STATUS, 11, mesh_configuration_client_heartbeat_subscription_handler },
1554 { MESH_FOUNDATION_OPERATION_LOW_POWER_NODE_POLL_TIMEOUT_STATUS, 5, mesh_configuration_client_low_power_node_poll_timeout_handler},
1555 { MESH_FOUNDATION_OPERATION_NETWORK_TRANSMIT_STATUS, 1, mesh_configuration_client_network_transmit_handler},
1556 { 0, 0, NULL }
1557 };
1558
mesh_configuration_client_get_operations(void)1559 const mesh_operation_t * mesh_configuration_client_get_operations(void){
1560 return mesh_configuration_client_model_operations;
1561 }
1562
mesh_configuration_client_register_packet_handler(mesh_model_t * configuration_client_model,btstack_packet_handler_t events_packet_handler)1563 void mesh_configuration_client_register_packet_handler(mesh_model_t *configuration_client_model, btstack_packet_handler_t events_packet_handler){
1564 btstack_assert(events_packet_handler != NULL);
1565 btstack_assert(configuration_client_model != NULL);
1566
1567 configuration_client_model->model_packet_handler = events_packet_handler;
1568 }
1569
1570