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