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_server.c" 39 40 #include <string.h> 41 #include <stdio.h> 42 43 #include "mesh/mesh_configuration_server.h" 44 45 #include "bluetooth_company_id.h" 46 #include "btstack_debug.h" 47 #include "btstack_memory.h" 48 #include "btstack_tlv.h" 49 #include "btstack_util.h" 50 51 #include "mesh/beacon.h" 52 #include "mesh/gatt_bearer.h" 53 #include "mesh/mesh.h" 54 #include "mesh/mesh_access.h" 55 #include "mesh/mesh_crypto.h" 56 #include "mesh/mesh_foundation.h" 57 #include "mesh/mesh_iv_index_seq_number.h" 58 #include "mesh/mesh_keys.h" 59 #include "mesh/mesh_network.h" 60 #include "mesh/mesh_node.h" 61 #include "mesh/mesh_proxy.h" 62 #include "mesh/mesh_upper_transport.h" 63 #include "mesh/mesh_virtual_addresses.h" 64 65 #define MESH_HEARTBEAT_FEATURES_SUPPORTED_MASK 0x000f 66 67 // current access pdu 68 static mesh_pdu_t * access_pdu_in_process; 69 70 // data from current pdu 71 static uint16_t configuration_server_element_address; 72 static uint32_t configuration_server_model_identifier; 73 static mesh_model_t * configuration_server_target_model; 74 static mesh_publication_model_t configuration_server_publication_model; 75 76 // cmac for virtual address hash and netkey derive 77 static btstack_crypto_aes128_cmac_t configuration_server_cmac_request; 78 79 // used to setup virtual addresses 80 static uint8_t configuration_server_label_uuid[16]; 81 static uint16_t configuration_server_hash; 82 83 // heartbeat publication and subscription state for all Configuration Server models - there is only one 84 // static mesh_heartbeat_subscription_t mesh_heartbeat_subscription; 85 86 // for PTS testing 87 static int config_netkey_list_max = 0; 88 89 90 // Heartbeat (helper) 91 static uint16_t heartbeat_pwr2(uint8_t value){ 92 if (!value) return 0x0000; 93 if (value == 0xff || value == 0x11) return 0xffff; 94 return 1 << (value-1); 95 } 96 97 static uint8_t heartbeat_count_log(uint16_t value){ 98 if (!value) return 0x00; 99 if (value == 0x01) return 0x01; 100 if (value == 0xffff) return 0xff; 101 // count leading zeros, supported by clang and gcc 102 return 32 - __builtin_clz(value - 1) + 1; 103 } 104 105 // TLV 106 107 static const btstack_tlv_t * btstack_tlv_singleton_impl; 108 static void * btstack_tlv_singleton_context; 109 110 111 static void mesh_configuration_server_setup_tlv(void){ 112 if (btstack_tlv_singleton_impl) return; 113 btstack_tlv_get_instance(&btstack_tlv_singleton_impl, &btstack_tlv_singleton_context); 114 } 115 116 117 static int mesh_model_is_configuration_server(uint32_t model_identifier){ 118 return mesh_model_is_bluetooth_sig(model_identifier) && (mesh_model_get_model_id(model_identifier) == MESH_SIG_MODEL_ID_CONFIGURATION_SERVER); 119 } 120 121 // Configuration Model Subscriptions (helper) 122 123 // Model to Appkey List 124 125 static uint8_t mesh_model_add_subscription(mesh_model_t * mesh_model, uint16_t address){ 126 uint16_t i; 127 for (i=0;i<MAX_NR_MESH_SUBSCRIPTION_PER_MODEL;i++){ 128 if (mesh_model->subscriptions[i] == address) return MESH_FOUNDATION_STATUS_SUCCESS; 129 } 130 for (i=0;i<MAX_NR_MESH_SUBSCRIPTION_PER_MODEL;i++){ 131 if (mesh_model->subscriptions[i] == MESH_ADDRESS_UNSASSIGNED) { 132 mesh_model->subscriptions[i] = address; 133 return MESH_FOUNDATION_STATUS_SUCCESS; 134 } 135 } 136 return MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES; 137 } 138 139 static void mesh_model_delete_subscription(mesh_model_t * mesh_model, uint16_t address){ 140 uint16_t i; 141 for (i=0;i<MAX_NR_MESH_SUBSCRIPTION_PER_MODEL;i++){ 142 if (mesh_model->subscriptions[i] == address) { 143 mesh_model->subscriptions[i] = MESH_ADDRESS_UNSASSIGNED; 144 } 145 } 146 } 147 148 static void mesh_model_delete_all_subscriptions(mesh_model_t * mesh_model){ 149 uint16_t i; 150 for (i=0;i<MAX_NR_MESH_SUBSCRIPTION_PER_MODEL;i++){ 151 mesh_model->subscriptions[i] = MESH_ADDRESS_UNSASSIGNED; 152 } 153 } 154 155 static void mesh_subcription_decrease_virtual_address_ref_count(mesh_model_t *mesh_model){ 156 // decrease ref counts for current virtual subscriptions 157 uint16_t i; 158 for (i = 0; i<MAX_NR_MESH_SUBSCRIPTION_PER_MODEL ; i++){ 159 uint16_t src = mesh_model->subscriptions[i]; 160 if (mesh_network_address_virtual(src)){ 161 mesh_virtual_address_t * virtual_address = mesh_virtual_address_for_pseudo_dst(src); 162 mesh_virtual_address_decrease_refcount(virtual_address); 163 } 164 } 165 } 166 167 // AppKeys Helper 168 static void mesh_configuration_server_delete_appkey(mesh_transport_key_t * transport_key){ 169 uint16_t appkey_index = transport_key->appkey_index; 170 171 // iterate over elements and models 172 mesh_element_iterator_t element_it; 173 mesh_element_iterator_init(&element_it); 174 while (mesh_element_iterator_has_next(&element_it)){ 175 mesh_element_t * element = mesh_element_iterator_next(&element_it); 176 mesh_model_iterator_t model_it; 177 mesh_model_iterator_init(&model_it, element); 178 while (mesh_model_iterator_has_next(&model_it)){ 179 mesh_model_t * mesh_model = mesh_model_iterator_next(&model_it); 180 181 // remove from Model to AppKey List 182 mesh_model_unbind_appkey(mesh_model, appkey_index); 183 184 // stop publishing if this AppKey was used 185 if (mesh_model->publication_model != NULL){ 186 mesh_publication_model_t * publication_model = mesh_model->publication_model; 187 if (publication_model->appkey_index == appkey_index){ 188 publication_model->address = MESH_ADDRESS_UNSASSIGNED; 189 publication_model->appkey_index = MESH_APPKEY_INVALID; 190 mesh_model_store_publication(mesh_model); 191 } 192 } 193 } 194 } 195 196 mesh_access_appkey_finalize(transport_key); 197 } 198 199 // Foundatiopn Message 200 201 const mesh_access_message_t mesh_foundation_config_beacon_status = { 202 MESH_FOUNDATION_OPERATION_BEACON_STATUS, "1" 203 }; 204 const mesh_access_message_t mesh_foundation_config_default_ttl_status = { 205 MESH_FOUNDATION_OPERATION_DEFAULT_TTL_STATUS, "1" 206 }; 207 const mesh_access_message_t mesh_foundation_config_friend_status = { 208 MESH_FOUNDATION_OPERATION_FRIEND_STATUS, "1" 209 }; 210 const mesh_access_message_t mesh_foundation_config_gatt_proxy_status = { 211 MESH_FOUNDATION_OPERATION_GATT_PROXY_STATUS, "1" 212 }; 213 const mesh_access_message_t mesh_foundation_config_relay_status = { 214 MESH_FOUNDATION_OPERATION_RELAY_STATUS, "11" 215 }; 216 const mesh_access_message_t mesh_foundation_config_model_publication_status = { 217 MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_STATUS, "1222111m" 218 }; 219 const mesh_access_message_t mesh_foundation_config_model_subscription_status = { 220 MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_STATUS, "122m" 221 }; 222 const mesh_access_message_t mesh_foundation_config_netkey_status = { 223 MESH_FOUNDATION_OPERATION_NETKEY_STATUS, "12" 224 }; 225 const mesh_access_message_t mesh_foundation_config_appkey_status = { 226 MESH_FOUNDATION_OPERATION_APPKEY_STATUS, "13" 227 }; 228 const mesh_access_message_t mesh_foundation_config_model_app_status = { 229 MESH_FOUNDATION_OPERATION_MODEL_APP_STATUS, "122m" 230 }; 231 const mesh_access_message_t mesh_foundation_node_reset_status = { 232 MESH_FOUNDATION_OPERATION_NODE_RESET_STATUS, "" 233 }; 234 const mesh_access_message_t mesh_foundation_config_heartbeat_publication_status = { 235 MESH_FOUNDATION_OPERATION_HEARTBEAT_PUBLICATION_STATUS, "1211122" 236 }; 237 const mesh_access_message_t mesh_foundation_config_network_transmit_status = { 238 MESH_FOUNDATION_OPERATION_NETWORK_TRANSMIT_STATUS, "11" 239 }; 240 const mesh_access_message_t mesh_foundation_node_identity_status = { 241 MESH_FOUNDATION_OPERATION_NODE_IDENTITY_STATUS, "121" 242 }; 243 const mesh_access_message_t mesh_key_refresh_phase_status = { 244 MESH_FOUNDATION_OPERATION_KEY_REFRESH_PHASE_STATUS, "121" 245 }; 246 const mesh_access_message_t mesh_foundation_low_power_node_poll_timeout_status = { 247 MESH_FOUNDATION_OPERATION_LOW_POWER_NODE_POLL_TIMEOUT_STATUS, "23" 248 }; 249 const mesh_access_message_t mesh_foundation_config_heartbeat_subscription_status = { 250 MESH_FOUNDATION_OPERATION_HEARTBEAT_SUBSCRIPTION_STATUS, "1221111" 251 }; 252 253 static void config_server_send_message(uint16_t netkey_index, uint16_t dest, mesh_pdu_t *pdu){ 254 // Configuration Server is on primary element and can only use DeviceKey 255 uint16_t appkey_index = MESH_DEVICE_KEY_INDEX; 256 uint16_t src = mesh_node_get_primary_element_address(); 257 uint8_t ttl = mesh_foundation_default_ttl_get(); 258 mesh_upper_transport_setup_access_pdu_header(pdu, netkey_index, appkey_index, ttl, src, dest, 0); 259 mesh_access_send_unacknowledged_pdu(pdu); 260 } 261 262 static void config_composition_data_status(uint16_t netkey_index, uint16_t dest){ 263 264 printf("Received Config Composition Data Get -> send Config Composition Data Status\n"); 265 266 mesh_transport_pdu_t * transport_pdu = mesh_access_transport_init(MESH_FOUNDATION_OPERATION_COMPOSITION_DATA_STATUS); 267 if (!transport_pdu) return; 268 269 // page 0 270 mesh_access_transport_add_uint8(transport_pdu, 0); 271 272 // CID 273 mesh_access_transport_add_uint16(transport_pdu, BLUETOOTH_COMPANY_ID_BLUEKITCHEN_GMBH); 274 // PID 275 mesh_access_transport_add_uint16(transport_pdu, 0); 276 // VID 277 mesh_access_transport_add_uint16(transport_pdu, 0); 278 // CRPL - number of protection list entries 279 mesh_access_transport_add_uint16(transport_pdu, 1); 280 // Features - Relay, Proxy, Friend, Lower Power, ... 281 mesh_access_transport_add_uint16(transport_pdu, 0); 282 283 mesh_element_iterator_t element_it; 284 mesh_element_iterator_init(&element_it); 285 while (mesh_element_iterator_has_next(&element_it)){ 286 mesh_element_t * element = mesh_element_iterator_next(&element_it); 287 288 // Loc 289 mesh_access_transport_add_uint16(transport_pdu, element->loc); 290 // NumS 291 mesh_access_transport_add_uint8( transport_pdu, element->models_count_sig); 292 // NumV 293 mesh_access_transport_add_uint8( transport_pdu, element->models_count_vendor); 294 295 mesh_model_iterator_t model_it; 296 297 // SIG Models 298 mesh_model_iterator_init(&model_it, element); 299 while (mesh_model_iterator_has_next(&model_it)){ 300 mesh_model_t * model = mesh_model_iterator_next(&model_it); 301 if (!mesh_model_is_bluetooth_sig(model->model_identifier)) continue; 302 mesh_access_transport_add_uint16(transport_pdu, model->model_identifier); 303 } 304 // Vendor Models 305 mesh_model_iterator_init(&model_it, element); 306 while (mesh_model_iterator_has_next(&model_it)){ 307 mesh_model_t * model = mesh_model_iterator_next(&model_it); 308 if (mesh_model_is_bluetooth_sig(model->model_identifier)) continue; 309 mesh_access_transport_add_uint32(transport_pdu, model->model_identifier); 310 } 311 } 312 313 // send as segmented access pdu 314 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 315 } 316 317 static void config_composition_data_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 318 UNUSED(mesh_model); 319 config_composition_data_status(mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 320 321 mesh_access_message_processed(pdu); 322 } 323 324 static void config_model_beacon_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest){ 325 UNUSED(mesh_model); 326 // setup message 327 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_foundation_config_beacon_status, 328 mesh_foundation_beacon_get()); 329 if (!transport_pdu) return; 330 331 // send as segmented access pdu 332 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 333 } 334 335 static void config_beacon_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 336 config_model_beacon_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 337 338 mesh_access_message_processed(pdu); 339 } 340 341 static void config_beacon_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 342 mesh_access_parser_state_t parser; 343 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 344 345 uint8_t beacon_enabled = mesh_access_parser_get_u8(&parser); 346 347 // beacon valid 348 if (beacon_enabled >= MESH_FOUNDATION_STATE_NOT_SUPPORTED) return; 349 350 // store 351 mesh_foundation_beacon_set(beacon_enabled); 352 mesh_foundation_state_store(); 353 354 // 355 config_model_beacon_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 356 357 mesh_access_message_processed(pdu); 358 } 359 360 static void config_model_default_ttl_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest){ 361 UNUSED(mesh_model); 362 // setup message 363 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 364 &mesh_foundation_config_default_ttl_status, mesh_foundation_default_ttl_get()); 365 if (!transport_pdu) return; 366 367 // send as segmented access pdu 368 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 369 } 370 371 static void config_default_ttl_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 372 config_model_default_ttl_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 373 374 mesh_access_message_processed(pdu); 375 } 376 377 static void config_default_ttl_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 378 mesh_access_parser_state_t parser; 379 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 380 381 uint8_t new_ttl = mesh_access_parser_get_u8(&parser); 382 383 // ttl valid 384 if (new_ttl > 0x7f || new_ttl == 0x01) return; 385 // store 386 mesh_foundation_default_ttl_set(new_ttl); 387 mesh_foundation_state_store(); 388 389 // 390 config_model_default_ttl_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 391 392 mesh_access_message_processed(pdu); 393 } 394 395 static void config_friend_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest){ 396 UNUSED(mesh_model); 397 398 // setup message 399 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 400 &mesh_foundation_config_friend_status, mesh_foundation_friend_get()); 401 if (!transport_pdu) return; 402 403 // send as segmented access pdu 404 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 405 } 406 407 static void config_friend_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 408 config_friend_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 409 410 mesh_access_message_processed(pdu); 411 } 412 413 static void config_friend_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 414 mesh_access_parser_state_t parser; 415 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 416 417 uint8_t new_friend_state = mesh_access_parser_get_u8(&parser); 418 419 // validate 420 if (new_friend_state >= MESH_FOUNDATION_STATE_NOT_SUPPORTED) return; 421 422 // store if supported 423 if (mesh_foundation_friend_get() != MESH_FOUNDATION_STATE_NOT_SUPPORTED){ 424 mesh_foundation_friend_set(new_friend_state); 425 mesh_foundation_state_store(); 426 } 427 428 // 429 config_friend_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 430 431 mesh_access_message_processed(pdu); 432 } 433 434 static void config_model_gatt_proxy_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest){ 435 UNUSED(mesh_model); 436 // setup message 437 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 438 &mesh_foundation_config_gatt_proxy_status, mesh_foundation_gatt_proxy_get()); 439 if (!transport_pdu) return; 440 441 // send as segmented access pdu 442 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 443 } 444 445 static void config_gatt_proxy_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 446 config_model_gatt_proxy_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 447 448 mesh_access_message_processed(pdu); 449 } 450 451 static void config_gatt_proxy_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 452 mesh_access_parser_state_t parser; 453 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 454 455 uint8_t enabled = mesh_access_parser_get_u8(&parser); 456 457 // ttl valid 458 if (enabled > 1) return; 459 // store 460 mesh_foundation_gatt_proxy_set(enabled); 461 mesh_foundation_state_store(); 462 463 // 464 config_model_gatt_proxy_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 465 466 mesh_access_message_processed(pdu); 467 468 // trigger heartbeat emit on change 469 mesh_configuration_server_feature_changed(); 470 } 471 472 static void config_model_relay_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest){ 473 UNUSED(mesh_model); 474 475 // setup message 476 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_foundation_config_relay_status, 477 mesh_foundation_relay_get(), 478 mesh_foundation_relay_retransmit_get()); 479 if (!transport_pdu) return; 480 481 // send as segmented access pdu 482 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 483 } 484 485 static void config_relay_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 486 config_model_relay_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 487 488 mesh_access_message_processed(pdu); 489 } 490 491 static void config_relay_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 492 493 mesh_access_parser_state_t parser; 494 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 495 496 // check if valid 497 uint8_t relay = mesh_access_parser_get_u8(&parser); 498 uint8_t relay_retransmit = mesh_access_parser_get_u8(&parser); 499 500 // check if valid 501 if (relay > 1) return; 502 503 // only update if supported 504 if (mesh_foundation_relay_get() != MESH_FOUNDATION_STATE_NOT_SUPPORTED){ 505 mesh_foundation_relay_set(relay); 506 mesh_foundation_relay_retransmit_set(relay_retransmit); 507 mesh_foundation_state_store(); 508 } 509 510 // 511 config_model_relay_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 512 513 mesh_access_message_processed(pdu); 514 515 // trigger heartbeat emit on change 516 mesh_configuration_server_feature_changed(); 517 } 518 519 static void config_model_network_transmit_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest){ 520 UNUSED(mesh_model); 521 522 // setup message 523 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 524 &mesh_foundation_config_network_transmit_status, mesh_foundation_network_transmit_get()); 525 if (!transport_pdu) return; 526 527 // send as segmented access pdu 528 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 529 } 530 531 static void config_model_network_transmit_get_handler(mesh_model_t * mesh_model, mesh_pdu_t * pdu){ 532 config_model_network_transmit_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 533 534 mesh_access_message_processed(pdu); 535 } 536 537 static void config_model_network_transmit_set_handler(mesh_model_t * mesh_model, mesh_pdu_t * pdu){ 538 mesh_access_parser_state_t parser; 539 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 540 541 uint8_t new_ttl = mesh_access_parser_get_u8(&parser); 542 543 // store 544 mesh_foundation_network_transmit_set(new_ttl); 545 mesh_foundation_state_store(); 546 547 // 548 config_model_network_transmit_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 549 550 mesh_access_message_processed(pdu); 551 } 552 553 // NetKey List 554 555 void config_nekey_list_set_max(uint16_t max){ 556 config_netkey_list_max = max; 557 } 558 559 static void config_netkey_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest, uint8_t status, uint16_t new_netkey_index){ 560 UNUSED(mesh_model); 561 562 // setup message 563 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 564 &mesh_foundation_config_netkey_status, status, new_netkey_index); 565 if (!transport_pdu) return; 566 567 // send as segmented access pdu 568 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 569 } 570 571 static void config_netkey_list(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest) { 572 UNUSED(mesh_model); 573 574 mesh_transport_pdu_t * transport_pdu = mesh_access_transport_init(MESH_FOUNDATION_OPERATION_NETKEY_LIST); 575 if (!transport_pdu) return; 576 577 // add list of netkey indexes 578 mesh_network_key_iterator_t it; 579 mesh_network_key_iterator_init(&it); 580 while (mesh_network_key_iterator_has_more(&it)){ 581 mesh_network_key_t * network_key = mesh_network_key_iterator_get_next(&it); 582 mesh_access_transport_add_uint16(transport_pdu, network_key->netkey_index); 583 } 584 585 // send as segmented access pdu 586 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 587 } 588 589 static void config_netkey_add_derived(void * arg){ 590 mesh_subnet_t * subnet = (mesh_subnet_t *) arg; 591 592 // store network key 593 mesh_store_network_key(subnet->old_key); 594 595 // add key to NetKey List 596 mesh_network_key_add(subnet->old_key); 597 598 // add subnet 599 mesh_subnet_add(subnet); 600 601 #ifdef ENABLE_MESH_PROXY_SERVER 602 mesh_proxy_start_advertising_with_network_id(); 603 #endif 604 605 config_netkey_status(mesh_model_get_configuration_server(), mesh_pdu_netkey_index(access_pdu_in_process), mesh_pdu_src(access_pdu_in_process), MESH_FOUNDATION_STATUS_SUCCESS, subnet->netkey_index); 606 mesh_access_message_processed(access_pdu_in_process); 607 } 608 609 static void config_netkey_add_handler(mesh_model_t * mesh_model, mesh_pdu_t * pdu){ 610 mesh_access_parser_state_t parser; 611 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 612 613 // get params 614 uint8_t new_netkey[16]; 615 uint16_t new_netkey_index = mesh_access_parser_get_u16(&parser); 616 mesh_access_parser_get_key(&parser, new_netkey); 617 618 uint8_t status; 619 620 const mesh_subnet_t * existing_subnet = mesh_subnet_get_by_netkey_index(new_netkey_index); 621 if (existing_subnet == NULL){ 622 623 // check limit for pts 624 uint16_t internal_index = mesh_network_key_get_free_index(); 625 if (internal_index == 0 || (config_netkey_list_max && mesh_network_key_list_count() >= config_netkey_list_max)){ 626 status = MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES; 627 } else { 628 629 // allocate new key and subnet 630 mesh_network_key_t * new_network_key = btstack_memory_mesh_network_key_get(); 631 mesh_subnet_t * new_subnet = btstack_memory_mesh_subnet_get(); 632 633 if (new_network_key == NULL || new_subnet == NULL){ 634 if (new_network_key != NULL){ 635 btstack_memory_mesh_network_key_free(new_network_key); 636 } 637 if (new_subnet != NULL){ 638 btstack_memory_mesh_subnet_free(new_subnet); 639 } 640 status = MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES; 641 642 } else { 643 644 // setup key 645 new_network_key->internal_index = internal_index; 646 new_network_key->netkey_index = new_netkey_index; 647 memcpy(new_network_key->net_key, new_netkey, 16); 648 649 // setup subnet 650 new_subnet->old_key = new_network_key; 651 new_subnet->netkey_index = new_netkey_index; 652 new_subnet->key_refresh = MESH_KEY_REFRESH_NOT_ACTIVE; 653 654 // derive other keys 655 access_pdu_in_process = pdu; 656 mesh_network_key_derive(&configuration_server_cmac_request, new_network_key, config_netkey_add_derived, new_network_key); 657 return; 658 } 659 } 660 661 } else { 662 // network key for netkey index already exists 663 if (memcmp(existing_subnet->old_key->net_key, new_netkey, 16) == 0){ 664 // same netkey 665 status = MESH_FOUNDATION_STATUS_SUCCESS; 666 } else { 667 // different netkey 668 status = MESH_FOUNDATION_STATUS_KEY_INDEX_ALREADY_STORED; 669 } 670 } 671 672 // report status 673 config_netkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, new_netkey_index); 674 mesh_access_message_processed(access_pdu_in_process); 675 } 676 677 static void config_netkey_update_derived(void * arg){ 678 mesh_subnet_t * subnet = (mesh_subnet_t *) arg; 679 680 // store network key 681 mesh_store_network_key(subnet->new_key); 682 683 // add key to NetKey List 684 mesh_network_key_add(subnet->new_key); 685 686 // update subnet - Key Refresh Phase 1 687 subnet->key_refresh = MESH_KEY_REFRESH_FIRST_PHASE; 688 689 // report status 690 config_netkey_status(mesh_model_get_configuration_server(), mesh_pdu_netkey_index(access_pdu_in_process), mesh_pdu_src(access_pdu_in_process), MESH_FOUNDATION_STATUS_SUCCESS, subnet->netkey_index); 691 mesh_access_message_processed(access_pdu_in_process); 692 } 693 694 static void config_netkey_update_handler(mesh_model_t * mesh_model, mesh_pdu_t * pdu) { 695 mesh_access_parser_state_t parser; 696 mesh_access_parser_init(&parser, (mesh_pdu_t *) pdu); 697 698 // get params 699 uint8_t new_netkey[16]; 700 uint16_t netkey_index = mesh_access_parser_get_u16(&parser); 701 mesh_access_parser_get_key(&parser, new_netkey); 702 703 // get existing subnet 704 mesh_subnet_t * subnet = mesh_subnet_get_by_netkey_index(netkey_index); 705 if (subnet == NULL){ 706 config_netkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX, netkey_index); 707 mesh_access_message_processed(access_pdu_in_process); 708 return; 709 } 710 711 // setup new key 712 uint16_t internal_index = mesh_network_key_get_free_index(); 713 mesh_network_key_t * new_network_key = btstack_memory_mesh_network_key_get(); 714 if (internal_index == 0 || new_network_key == NULL){ 715 config_netkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES, netkey_index); 716 mesh_access_message_processed(access_pdu_in_process); 717 return; 718 } 719 720 // setup new key 721 new_network_key->internal_index = internal_index; 722 new_network_key->netkey_index = netkey_index; 723 new_network_key->version = (uint8_t)(subnet->old_key->version + 1); 724 memcpy(new_network_key->net_key, new_netkey, 16); 725 726 // store in subnet (not active yet) 727 subnet->new_key = new_network_key; 728 729 // derive other keys 730 access_pdu_in_process = pdu; 731 mesh_network_key_derive(&configuration_server_cmac_request, new_network_key, config_netkey_update_derived, subnet); 732 } 733 734 static void config_netkey_delete_handler(mesh_model_t * mesh_model, mesh_pdu_t * pdu) { 735 mesh_access_parser_state_t parser; 736 mesh_access_parser_init(&parser, (mesh_pdu_t *) pdu); 737 738 // get params 739 uint16_t netkey_index = mesh_access_parser_get_u16(&parser); 740 741 // get existing network_key 742 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 743 744 // remove subnet 745 mesh_subnet_t * subnet = mesh_subnet_get_by_netkey_index(netkey_index); 746 if (subnet != NULL){ 747 // A NetKey shall not be deleted from the NetKey List using a message secured with this NetKey. 748 if (mesh_subnet_list_count() > 1 && subnet->netkey_index != netkey_index){ 749 750 // remove all appkeys for this netkey 751 mesh_transport_key_iterator_t it; 752 mesh_transport_key_iterator_init(&it, netkey_index); 753 while (mesh_transport_key_iterator_has_more(&it)){ 754 mesh_transport_key_t * transport_key = mesh_transport_key_iterator_get_next(&it); 755 mesh_configuration_server_delete_appkey(transport_key); 756 } 757 758 // delete old/current key 759 mesh_access_netkey_finalize(subnet->old_key); 760 subnet->old_key = NULL; 761 762 // delete new key 763 if (subnet->new_key != NULL){ 764 mesh_access_netkey_finalize(subnet->new_key); 765 subnet->new_key = NULL; 766 } 767 768 // remove subnet 769 mesh_subnet_remove(subnet); 770 btstack_memory_mesh_subnet_free(subnet); 771 772 } else { 773 // we cannot remove the last network key 774 status = MESH_FOUNDATION_STATUS_CANNOT_REMOVE; 775 } 776 } 777 config_netkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, netkey_index); 778 } 779 780 static void config_netkey_get_handler(mesh_model_t * mesh_model, mesh_pdu_t * pdu){ 781 config_netkey_list(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 782 mesh_access_message_processed(pdu); 783 } 784 785 // AppKey List 786 787 static void config_appkey_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest, uint32_t netkey_and_appkey_index, uint8_t status){ 788 UNUSED(mesh_model); 789 790 // setup message 791 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_foundation_config_appkey_status, 792 status, netkey_and_appkey_index); 793 if (!transport_pdu) return; 794 795 // send as segmented access pdu 796 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 797 } 798 799 static void config_appkey_list(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest, uint32_t netkey_index_of_list){ 800 UNUSED(mesh_model); 801 802 mesh_transport_pdu_t * transport_pdu = mesh_access_transport_init(MESH_FOUNDATION_OPERATION_APPKEY_LIST); 803 if (!transport_pdu) return; 804 805 // check netkey_index is valid 806 mesh_network_key_t * network_key = mesh_network_key_list_get(netkey_index_of_list); 807 uint8_t status; 808 if (network_key == NULL){ 809 status = MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX; 810 } else { 811 status = MESH_FOUNDATION_STATUS_SUCCESS; 812 } 813 mesh_access_transport_add_uint8(transport_pdu, status); 814 mesh_access_transport_add_uint16(transport_pdu, netkey_index_of_list); 815 816 // add list of appkey indexes 817 mesh_transport_key_iterator_t it; 818 mesh_transport_key_iterator_init(&it, netkey_index_of_list); 819 while (mesh_transport_key_iterator_has_more(&it)){ 820 mesh_transport_key_t * transport_key = mesh_transport_key_iterator_get_next(&it); 821 mesh_access_transport_add_uint16(transport_pdu, transport_key->appkey_index); 822 } 823 824 // send as segmented access pdu 825 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 826 } 827 828 static void config_appkey_add_or_update_aid(void *arg){ 829 mesh_transport_key_t * transport_key = (mesh_transport_key_t *) arg; 830 831 printf("Config Appkey Add/Update: NetKey Index 0x%04x, AppKey Index 0x%04x, AID %02x: ", transport_key->netkey_index, transport_key->appkey_index, transport_key->aid); 832 printf_hexdump(transport_key->key, 16); 833 834 // store in TLV 835 mesh_store_app_key(transport_key); 836 837 // add app key 838 mesh_transport_key_add(transport_key); 839 840 uint32_t netkey_and_appkey_index = (transport_key->appkey_index << 12) | transport_key->netkey_index; 841 config_appkey_status(mesh_model_get_configuration_server(), mesh_pdu_netkey_index(access_pdu_in_process), mesh_pdu_src(access_pdu_in_process), netkey_and_appkey_index, MESH_FOUNDATION_STATUS_SUCCESS); 842 843 mesh_access_message_processed(access_pdu_in_process); 844 } 845 846 static void config_appkey_add_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 847 848 mesh_access_parser_state_t parser; 849 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 850 851 // netkey and appkey index 852 uint32_t netkey_and_appkey_index = mesh_access_parser_get_u24(&parser); 853 uint16_t netkey_index = netkey_and_appkey_index & 0xfff; 854 uint16_t appkey_index = netkey_and_appkey_index >> 12; 855 856 // actual key 857 uint8_t appkey[16]; 858 mesh_access_parser_get_key(&parser, appkey); 859 860 // check netkey_index is valid 861 mesh_network_key_t * network_key = mesh_network_key_list_get(netkey_index); 862 if (network_key == NULL){ 863 config_appkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_and_appkey_index, MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX); 864 mesh_access_message_processed(pdu); 865 return; 866 } 867 868 // check if appkey already exists 869 mesh_transport_key_t * transport_key = mesh_transport_key_get(appkey_index); 870 if (transport_key){ 871 uint8_t status; 872 if (transport_key->netkey_index != netkey_index){ 873 // already stored but with different netkey 874 status = MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX; 875 } else if (memcmp(transport_key->key, appkey, 16) == 0){ 876 // key identical 877 status = MESH_FOUNDATION_STATUS_SUCCESS; 878 } else { 879 // key differs 880 status = MESH_FOUNDATION_STATUS_KEY_INDEX_ALREADY_STORED; 881 } 882 config_appkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_and_appkey_index, status); 883 mesh_access_message_processed(pdu); 884 return; 885 } 886 887 // create app key (first get free slot in transport key table) 888 mesh_transport_key_t * app_key = NULL; 889 uint16_t internal_index = mesh_transport_key_get_free_index(); 890 if (internal_index > 0){ 891 app_key = btstack_memory_mesh_transport_key_get(); 892 } 893 if (app_key == NULL) { 894 config_appkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_and_appkey_index, MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES); 895 mesh_access_message_processed(pdu); 896 return; 897 } 898 899 // store data 900 app_key->internal_index = internal_index; 901 app_key->akf = 1; 902 app_key->appkey_index = appkey_index; 903 app_key->netkey_index = netkey_index; 904 app_key->version = 0; 905 app_key->old_key = 0; 906 907 memcpy(app_key->key, appkey, 16); 908 909 // calculate AID 910 access_pdu_in_process = pdu; 911 mesh_transport_key_calc_aid(&configuration_server_cmac_request, app_key, config_appkey_add_or_update_aid, app_key); 912 } 913 914 static void config_appkey_update_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 915 916 mesh_access_parser_state_t parser; 917 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 918 919 // netkey and appkey index 920 uint32_t netkey_and_appkey_index = mesh_access_parser_get_u24(&parser); 921 uint16_t netkey_index = netkey_and_appkey_index & 0xfff; 922 uint16_t appkey_index = netkey_and_appkey_index >> 12; 923 924 // actual key 925 uint8_t appkey[16]; 926 mesh_access_parser_get_key(&parser, appkey); 927 928 929 // for PTS testing 930 // check netkey_index is valid 931 mesh_network_key_t * network_key = mesh_network_key_list_get(netkey_index); 932 if (network_key == NULL){ 933 config_appkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_and_appkey_index, MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX); 934 mesh_access_message_processed(pdu); 935 return; 936 } 937 938 // check if appkey already exists 939 mesh_transport_key_t * existing_app_key = mesh_transport_key_get(appkey_index); 940 if (!existing_app_key) { 941 config_appkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_and_appkey_index, MESH_FOUNDATION_STATUS_INVALID_APPKEY_INDEX); 942 mesh_access_message_processed(pdu); 943 return; 944 } 945 946 if (existing_app_key->netkey_index != netkey_index){ 947 // already stored but with different netkey 948 config_appkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_and_appkey_index, MESH_FOUNDATION_STATUS_INVALID_BINDING); 949 mesh_access_message_processed(pdu); 950 return; 951 } 952 953 if (memcmp(existing_app_key->key, appkey, 16) == 0){ 954 // key identical 955 config_appkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_and_appkey_index, MESH_FOUNDATION_STATUS_SUCCESS); 956 mesh_access_message_processed(pdu); 957 return; 958 } 959 960 // create app key 961 mesh_transport_key_t * new_app_key = NULL; 962 uint16_t internal_index = mesh_transport_key_get_free_index(); 963 if (internal_index > 0){ 964 new_app_key = btstack_memory_mesh_transport_key_get(); 965 } 966 if (new_app_key == NULL) { 967 config_appkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_and_appkey_index, MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES); 968 mesh_access_message_processed(pdu); 969 return; 970 } 971 972 // store data 973 new_app_key->internal_index = internal_index; 974 new_app_key->appkey_index = appkey_index; 975 new_app_key->netkey_index = netkey_index; 976 new_app_key->key_refresh = 1; 977 new_app_key->version = (uint8_t)(existing_app_key->version + 1); 978 memcpy(new_app_key->key, appkey, 16); 979 980 // mark old key 981 existing_app_key->old_key = 1; 982 983 // calculate AID 984 access_pdu_in_process = pdu; 985 mesh_transport_key_calc_aid(&configuration_server_cmac_request, new_app_key, config_appkey_add_or_update_aid, new_app_key); 986 } 987 988 static void config_appkey_delete_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 989 mesh_access_parser_state_t parser; 990 mesh_access_parser_init(&parser, (mesh_pdu_t *) pdu); 991 992 // netkey and appkey index 993 uint32_t netkey_and_appkey_index = mesh_access_parser_get_u24(&parser); 994 uint16_t netkey_index = netkey_and_appkey_index & 0xfff; 995 uint16_t appkey_index = netkey_and_appkey_index >> 12; 996 997 // check netkey_index is valid 998 mesh_network_key_t * network_key = mesh_network_key_list_get(netkey_index); 999 if (network_key == NULL){ 1000 config_appkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_and_appkey_index, MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX); 1001 mesh_access_message_processed(pdu); 1002 return; 1003 } 1004 1005 // check if appkey already exists 1006 mesh_transport_key_t * transport_key = mesh_transport_key_get(appkey_index); 1007 if (transport_key){ 1008 mesh_configuration_server_delete_appkey(transport_key); 1009 } 1010 1011 config_appkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_and_appkey_index, MESH_FOUNDATION_STATUS_SUCCESS); 1012 mesh_access_message_processed(pdu); 1013 } 1014 1015 static void config_appkey_get_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 uint16_t netkey_index = mesh_access_parser_get_u16(&parser); 1019 1020 config_appkey_list(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_index); 1021 mesh_access_message_processed(pdu); 1022 } 1023 1024 // Configuration Model Subscriptions (messages) 1025 1026 static void config_model_subscription_list_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest, uint8_t status, uint16_t element_address, uint32_t model_identifier, mesh_model_t * target_model){ 1027 UNUSED(mesh_model); 1028 1029 uint16_t opcode; 1030 if (mesh_model_is_bluetooth_sig(model_identifier)){ 1031 opcode = MESH_FOUNDATION_OPERATION_SIG_MODEL_SUBSCRIPTION_LIST; 1032 } else { 1033 opcode = MESH_FOUNDATION_OPERATION_VENDOR_MODEL_SUBSCRIPTION_LIST; 1034 } 1035 1036 mesh_transport_pdu_t * transport_pdu = mesh_access_transport_init(opcode); 1037 if (!transport_pdu) return; 1038 1039 // setup segmented message 1040 mesh_access_transport_add_uint8(transport_pdu, status); 1041 mesh_access_transport_add_uint16(transport_pdu, element_address); 1042 mesh_access_transport_add_model_identifier(transport_pdu, model_identifier); 1043 1044 if (target_model != NULL){ 1045 uint16_t i; 1046 for (i = 0; i < MAX_NR_MESH_SUBSCRIPTION_PER_MODEL; i++){ 1047 if (target_model->subscriptions[i] == MESH_ADDRESS_UNSASSIGNED) continue; 1048 if (mesh_network_address_virtual(target_model->subscriptions[i])) continue; 1049 mesh_access_transport_add_uint16(transport_pdu, target_model->subscriptions[i]); 1050 } 1051 } 1052 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 1053 } 1054 1055 static void config_model_subscription_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 1056 mesh_access_parser_state_t parser; 1057 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1058 1059 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1060 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1061 1062 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1063 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1064 1065 config_model_subscription_list_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, element_address, model_identifier, target_model); 1066 mesh_access_message_processed(pdu); 1067 } 1068 1069 static void config_model_subscription_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest, uint8_t status, uint16_t element_address, uint16_t address, uint32_t model_identifier){ 1070 UNUSED(mesh_model); 1071 1072 // setup message 1073 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_foundation_config_model_subscription_status, 1074 status, element_address, address, model_identifier); 1075 if (!transport_pdu) return; 1076 // send as segmented access pdu 1077 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 1078 } 1079 1080 static void config_model_subscription_add_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 1081 mesh_access_parser_state_t parser; 1082 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1083 1084 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1085 uint16_t address = mesh_access_parser_get_u16(&parser); 1086 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1087 1088 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1089 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1090 1091 if (target_model != NULL){ 1092 if (mesh_network_address_group(address) && !mesh_network_address_all_nodes(address)){ 1093 status = mesh_model_add_subscription(target_model, address); 1094 if (status == MESH_FOUNDATION_STATUS_SUCCESS){ 1095 mesh_model_store_subscriptions(target_model); 1096 } 1097 } else { 1098 status = MESH_FOUNDATION_STATUS_INVALID_ADDRESS; 1099 } 1100 } 1101 1102 config_model_subscription_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, element_address, address, model_identifier); 1103 mesh_access_message_processed(pdu); 1104 } 1105 1106 static void config_model_subscription_virtual_address_add_hash(void *arg){ 1107 mesh_model_t * target_model = (mesh_model_t*) arg; 1108 mesh_model_t * mesh_model = mesh_model_get_configuration_server(); 1109 1110 // add if not exists 1111 mesh_virtual_address_t * virtual_address = mesh_virtual_address_for_label_uuid(configuration_server_label_uuid); 1112 if (virtual_address == NULL){ 1113 virtual_address = mesh_virtual_address_register(configuration_server_label_uuid, configuration_server_hash); 1114 } 1115 1116 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1117 uint16_t pseudo_dst = MESH_ADDRESS_UNSASSIGNED; 1118 if (virtual_address == NULL){ 1119 status = MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES; 1120 } else { 1121 pseudo_dst = virtual_address->pseudo_dst; 1122 if (!mesh_model_contains_subscription(target_model, pseudo_dst)){ 1123 status = mesh_model_add_subscription(target_model, pseudo_dst); 1124 if (status == MESH_FOUNDATION_STATUS_SUCCESS){ 1125 mesh_virtual_address_increase_refcount(virtual_address); 1126 mesh_model_store_subscriptions(target_model); 1127 } 1128 } 1129 } 1130 1131 config_model_subscription_status(mesh_model, mesh_pdu_netkey_index(access_pdu_in_process), mesh_pdu_src(access_pdu_in_process), status, configuration_server_element_address, pseudo_dst, target_model->model_identifier); 1132 mesh_access_message_processed(access_pdu_in_process); 1133 return; 1134 } 1135 1136 static void config_model_subscription_virtual_address_add_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 1137 mesh_access_parser_state_t parser; 1138 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1139 1140 // ElementAddress - Address of the element - should be us 1141 configuration_server_element_address = mesh_access_parser_get_u16(&parser); 1142 1143 // store label uuid 1144 mesh_access_parser_get_label_uuid(&parser, configuration_server_label_uuid); 1145 1146 // Model Identifier 1147 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1148 1149 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1150 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(configuration_server_element_address, model_identifier, &status); 1151 1152 if (target_model == NULL){ 1153 config_model_subscription_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, configuration_server_element_address, MESH_ADDRESS_UNSASSIGNED, model_identifier); 1154 mesh_access_message_processed(pdu); 1155 return; 1156 } 1157 1158 access_pdu_in_process = pdu; 1159 mesh_virtual_address(&configuration_server_cmac_request, configuration_server_label_uuid, &configuration_server_hash, &config_model_subscription_virtual_address_add_hash, target_model); 1160 } 1161 1162 static void config_model_subscription_overwrite_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 1163 mesh_access_parser_state_t parser; 1164 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1165 1166 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1167 uint16_t address = mesh_access_parser_get_u16(&parser); 1168 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1169 1170 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1171 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1172 1173 if (target_model != NULL){ 1174 if (mesh_network_address_group(address) && !mesh_network_address_all_nodes(address)){ 1175 mesh_subcription_decrease_virtual_address_ref_count(target_model); 1176 mesh_model_delete_all_subscriptions(mesh_model); 1177 mesh_model_add_subscription(mesh_model, address); 1178 mesh_model_store_subscriptions(target_model); 1179 } else { 1180 status = MESH_FOUNDATION_STATUS_INVALID_ADDRESS; 1181 } 1182 } 1183 1184 config_model_subscription_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, element_address, address, model_identifier); 1185 mesh_access_message_processed(pdu); 1186 } 1187 1188 static void config_model_subscription_virtual_address_overwrite_hash(void *arg){ 1189 mesh_model_t * target_model = (mesh_model_t*) arg; 1190 mesh_model_t * mesh_model = mesh_model_get_configuration_server(); 1191 1192 // add if not exists 1193 mesh_virtual_address_t * virtual_address = mesh_virtual_address_for_label_uuid(configuration_server_label_uuid); 1194 if (virtual_address == NULL){ 1195 virtual_address = mesh_virtual_address_register(configuration_server_label_uuid, configuration_server_hash); 1196 } 1197 1198 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1199 uint16_t pseudo_dst = MESH_ADDRESS_UNSASSIGNED; 1200 if (virtual_address == NULL){ 1201 status = MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES; 1202 } else { 1203 1204 // increase refcount first to avoid flash delete + add in a row 1205 mesh_virtual_address_increase_refcount(virtual_address); 1206 1207 // decrease ref counts for virtual addresses in subscription 1208 mesh_subcription_decrease_virtual_address_ref_count(target_model); 1209 1210 // clear subscriptions 1211 mesh_model_delete_all_subscriptions(target_model); 1212 1213 // add new subscription (successfull if MAX_NR_MESH_SUBSCRIPTION_PER_MODEL > 0) 1214 pseudo_dst = virtual_address->pseudo_dst; 1215 mesh_model_add_subscription(target_model, pseudo_dst); 1216 1217 mesh_model_store_subscriptions(target_model); 1218 } 1219 1220 config_model_subscription_status(mesh_model, mesh_pdu_netkey_index(access_pdu_in_process), mesh_pdu_src(access_pdu_in_process), status, configuration_server_element_address, pseudo_dst, target_model->model_identifier); 1221 mesh_access_message_processed(access_pdu_in_process); 1222 return; 1223 } 1224 1225 static void config_model_subscription_virtual_address_overwrite_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 1226 mesh_access_parser_state_t parser; 1227 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1228 1229 // ElementAddress - Address of the element - should be us 1230 configuration_server_element_address = mesh_access_parser_get_u16(&parser); 1231 1232 // store label uuid 1233 mesh_access_parser_get_label_uuid(&parser, configuration_server_label_uuid); 1234 1235 // Model Identifier 1236 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1237 1238 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1239 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(configuration_server_element_address, model_identifier, &status); 1240 1241 if (target_model == NULL){ 1242 config_model_subscription_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, configuration_server_element_address, MESH_ADDRESS_UNSASSIGNED, model_identifier); 1243 mesh_access_message_processed(pdu); 1244 return; 1245 } 1246 access_pdu_in_process = pdu; 1247 mesh_virtual_address(&configuration_server_cmac_request, configuration_server_label_uuid, &configuration_server_hash, &config_model_subscription_virtual_address_overwrite_hash, target_model); 1248 } 1249 1250 static void config_model_subscription_delete_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 1251 mesh_access_parser_state_t parser; 1252 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1253 1254 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1255 uint16_t address = mesh_access_parser_get_u16(&parser); 1256 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1257 1258 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1259 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1260 1261 if (target_model != NULL){ 1262 if (mesh_network_address_group(address) && !mesh_network_address_all_nodes(address)){ 1263 mesh_model_delete_subscription(target_model, address); 1264 mesh_model_store_subscriptions(target_model); 1265 } else { 1266 status = MESH_FOUNDATION_STATUS_INVALID_ADDRESS; 1267 } 1268 } 1269 1270 config_model_subscription_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, element_address, address, model_identifier); 1271 mesh_access_message_processed(pdu); 1272 } 1273 1274 static void config_model_subscription_virtual_address_delete_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 1275 mesh_access_parser_state_t parser; 1276 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1277 1278 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1279 mesh_access_parser_get_label_uuid(&parser, configuration_server_label_uuid); 1280 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1281 1282 mesh_virtual_address_t * virtual_address = mesh_virtual_address_for_label_uuid(configuration_server_label_uuid); 1283 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1284 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1285 1286 if ((target_model != NULL) && (virtual_address != NULL) && mesh_model_contains_subscription(target_model, virtual_address->pseudo_dst)){ 1287 mesh_virtual_address_decrease_refcount(virtual_address); 1288 mesh_model_delete_subscription(target_model, virtual_address->pseudo_dst); 1289 mesh_model_store_subscriptions(target_model); 1290 } 1291 1292 config_model_subscription_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, element_address, virtual_address->hash, model_identifier); 1293 mesh_access_message_processed(pdu); 1294 } 1295 1296 static void config_model_subscription_delete_all_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 1297 mesh_access_parser_state_t parser; 1298 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1299 1300 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1301 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1302 1303 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1304 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1305 1306 if (target_model != NULL){ 1307 mesh_subcription_decrease_virtual_address_ref_count(target_model); 1308 mesh_model_delete_all_subscriptions(target_model); 1309 mesh_model_store_subscriptions(target_model); 1310 } 1311 1312 config_model_subscription_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, element_address, MESH_ADDRESS_UNSASSIGNED, model_identifier); 1313 mesh_access_message_processed(pdu); 1314 } 1315 1316 // Configuration Model to AppKey List 1317 1318 static void config_model_app_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest, uint8_t status, uint16_t element_address, uint16_t appkey_index, uint32_t model_identifier){ 1319 UNUSED(mesh_model); 1320 1321 // setup message 1322 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_foundation_config_model_app_status, 1323 status, element_address, appkey_index, model_identifier); 1324 if (!transport_pdu) return; 1325 1326 // send as segmented access pdu 1327 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 1328 } 1329 1330 static void config_model_app_list(mesh_model_t * config_server_model, uint16_t netkey_index, uint16_t dest, uint8_t status, uint16_t element_address, uint32_t model_identifier, mesh_model_t * mesh_model){ 1331 UNUSED(config_server_model); 1332 1333 uint16_t opcode; 1334 if (mesh_model_is_bluetooth_sig(model_identifier)){ 1335 opcode = MESH_FOUNDATION_OPERATION_SIG_MODEL_APP_LIST; 1336 } else { 1337 opcode = MESH_FOUNDATION_OPERATION_VENDOR_MODEL_APP_LIST; 1338 } 1339 mesh_transport_pdu_t * transport_pdu = mesh_access_transport_init(opcode); 1340 if (!transport_pdu) return; 1341 1342 mesh_access_transport_add_uint8(transport_pdu, status); 1343 mesh_access_transport_add_uint16(transport_pdu, element_address); 1344 if (mesh_model_is_bluetooth_sig(model_identifier)) { 1345 mesh_access_transport_add_uint16(transport_pdu, mesh_model_get_model_id(model_identifier)); 1346 } else { 1347 mesh_access_transport_add_uint32(transport_pdu, model_identifier); 1348 } 1349 1350 // add list of appkey indexes 1351 if (mesh_model){ 1352 uint16_t i; 1353 for (i=0;i<MAX_NR_MESH_APPKEYS_PER_MODEL;i++){ 1354 uint16_t appkey_index = mesh_model->appkey_indices[i]; 1355 if (appkey_index == MESH_APPKEY_INVALID) continue; 1356 mesh_access_transport_add_uint16(transport_pdu, appkey_index); 1357 } 1358 } 1359 1360 // send as segmented access pdu 1361 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 1362 } 1363 1364 static void config_model_app_bind_handler(mesh_model_t *config_server_model, mesh_pdu_t * pdu) { 1365 mesh_access_parser_state_t parser; 1366 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1367 1368 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1369 uint16_t appkey_index = mesh_access_parser_get_u16(&parser); 1370 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1371 1372 uint8_t status; 1373 do { 1374 // validate address and look up model 1375 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1376 if (target_model == NULL) break; 1377 1378 // validate app key exists 1379 mesh_transport_key_t * app_key = mesh_transport_key_get(appkey_index); 1380 if (!app_key){ 1381 status = MESH_FOUNDATION_STATUS_INVALID_APPKEY_INDEX; 1382 break; 1383 } 1384 1385 // Configuration Server only allows device keys 1386 if (mesh_model_is_configuration_server(model_identifier)){ 1387 status = MESH_FOUNDATION_STATUS_CANNOT_BIND; 1388 break; 1389 } 1390 status = mesh_model_bind_appkey(target_model, appkey_index); 1391 1392 } while (0); 1393 1394 config_model_app_status(config_server_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, element_address, appkey_index, model_identifier); 1395 mesh_access_message_processed(pdu); 1396 } 1397 1398 static void config_model_app_unbind_handler(mesh_model_t *config_server_model, mesh_pdu_t * pdu) { 1399 mesh_access_parser_state_t parser; 1400 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1401 1402 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1403 uint16_t appkey_index = mesh_access_parser_get_u16(&parser); 1404 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1405 1406 uint8_t status; 1407 do { 1408 // validate address and look up model 1409 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1410 if (target_model == NULL) break; 1411 1412 // validate app key exists 1413 mesh_transport_key_t * app_key = mesh_transport_key_get(appkey_index); 1414 if (!app_key){ 1415 status = MESH_FOUNDATION_STATUS_INVALID_APPKEY_INDEX; 1416 break; 1417 } 1418 mesh_model_unbind_appkey(target_model, appkey_index); 1419 status = MESH_FOUNDATION_STATUS_SUCCESS; 1420 } while (0); 1421 1422 config_model_app_status(config_server_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, element_address, appkey_index, model_identifier); 1423 mesh_access_message_processed(pdu); 1424 } 1425 1426 static void config_model_app_get_handler(mesh_model_t *config_server_model, mesh_pdu_t * pdu){ 1427 mesh_access_parser_state_t parser; 1428 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1429 1430 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1431 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1432 1433 uint8_t status; 1434 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1435 config_model_app_list(config_server_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, element_address, model_identifier, target_model); 1436 mesh_access_message_processed(pdu); 1437 } 1438 1439 // Model Publication 1440 1441 static void config_model_publication_changed(mesh_model_t *mesh_model, mesh_publication_model_t * new_publication_model){ 1442 1443 // stop publication 1444 mesh_model_publication_stop(mesh_model); 1445 1446 // update model publication state 1447 memcpy(mesh_model->publication_model, &configuration_server_publication_model, sizeof(mesh_publication_model_t)); 1448 1449 // store 1450 mesh_model_store_publication(mesh_model); 1451 1452 // start publication if address is set (nothing happens if period = 0 and retransmit = 0) 1453 if (new_publication_model->address == MESH_ADDRESS_UNSASSIGNED) return; 1454 1455 // start to publish 1456 mesh_model_publication_start(mesh_model); 1457 } 1458 1459 1460 static void 1461 config_model_publication_status(mesh_model_t *mesh_model, uint16_t netkey_index, uint16_t dest, uint8_t status, 1462 uint16_t element_address, uint32_t model_identifier, mesh_publication_model_t *publication_model) { 1463 UNUSED(mesh_model); 1464 1465 // setup message 1466 uint16_t app_key_index_and_credential_flag = (publication_model->friendship_credential_flag << 12) | publication_model->appkey_index; 1467 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 1468 &mesh_foundation_config_model_app_status, status, element_address, publication_model->address, 1469 app_key_index_and_credential_flag, 1470 publication_model->ttl, publication_model->period, publication_model->retransmit, model_identifier); 1471 if (!transport_pdu) return; 1472 1473 // send as segmented access pdu 1474 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 1475 } 1476 1477 static void 1478 config_model_publication_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 1479 1480 // set defaults 1481 memset(&configuration_server_publication_model, 0, sizeof(mesh_publication_model_t)); 1482 1483 mesh_access_parser_state_t parser; 1484 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1485 1486 // ElementAddress - Address of the element - should be us 1487 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1488 1489 // PublishAddress, 16 bit 1490 configuration_server_publication_model.address = mesh_access_parser_get_u16(&parser); 1491 1492 // AppKeyIndex (12), CredentialFlag (1), RFU (3) 1493 uint16_t temp = mesh_access_parser_get_u16(&parser); 1494 configuration_server_publication_model.appkey_index = temp & 0x0fff; 1495 configuration_server_publication_model.friendship_credential_flag = (temp >> 12) & 1; 1496 1497 // TTL 1498 configuration_server_publication_model.ttl = mesh_access_parser_get_u8(&parser); 1499 1500 // Period 1501 configuration_server_publication_model.period = mesh_access_parser_get_u8(&parser); 1502 1503 // Retransmit 1504 configuration_server_publication_model.retransmit = mesh_access_parser_get_u8(&parser); 1505 1506 // Model Identifier 1507 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1508 uint8_t status; 1509 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1510 1511 // TODO validate params 1512 1513 if (target_model){ 1514 if (target_model->publication_model == NULL){ 1515 status = MESH_FOUNDATION_STATUS_CANNOT_SET; 1516 } else { 1517 1518 // decrease ref count if old virtual address 1519 if (mesh_network_address_virtual(configuration_server_publication_model.address)) { 1520 mesh_virtual_address_t * current_virtual_address = mesh_virtual_address_for_pseudo_dst(configuration_server_publication_model.address); 1521 mesh_virtual_address_decrease_refcount(current_virtual_address); 1522 } 1523 1524 // restart publication 1525 config_model_publication_changed(target_model, &configuration_server_publication_model); 1526 } 1527 } 1528 1529 // send status 1530 config_model_publication_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, element_address, model_identifier, &configuration_server_publication_model); 1531 mesh_access_message_processed(pdu); 1532 } 1533 1534 static void config_model_publication_virtual_address_set_hash(void *arg){ 1535 mesh_model_t *mesh_model = (mesh_model_t*) arg; 1536 1537 // add if not exist 1538 mesh_virtual_address_t * virtual_address = mesh_virtual_address_for_label_uuid(configuration_server_label_uuid); 1539 if (virtual_address == NULL){ 1540 virtual_address = mesh_virtual_address_register(configuration_server_label_uuid, configuration_server_hash); 1541 } 1542 1543 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1544 if (virtual_address == NULL){ 1545 status = MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES; 1546 } else { 1547 1548 // increase ref count if new virtual address 1549 mesh_virtual_address_increase_refcount(virtual_address); 1550 1551 // decrease ref count if old virtual address 1552 if (mesh_network_address_virtual(configuration_server_publication_model.address)) { 1553 mesh_virtual_address_t * current_virtual_address = mesh_virtual_address_for_pseudo_dst(configuration_server_publication_model.address); 1554 mesh_virtual_address_decrease_refcount(current_virtual_address); 1555 } 1556 1557 configuration_server_publication_model.address = virtual_address->pseudo_dst; 1558 mesh_virtual_address_increase_refcount(virtual_address); 1559 1560 // restart publication 1561 config_model_publication_changed(configuration_server_target_model, &configuration_server_publication_model); 1562 } 1563 1564 // send status 1565 config_model_publication_status(mesh_model, mesh_pdu_netkey_index(access_pdu_in_process), mesh_pdu_src(access_pdu_in_process), status, configuration_server_element_address, configuration_server_model_identifier, &configuration_server_publication_model); 1566 1567 mesh_access_message_processed(access_pdu_in_process); 1568 } 1569 1570 static void 1571 config_model_publication_virtual_address_set_handler(mesh_model_t *mesh_model, 1572 mesh_pdu_t * pdu) { 1573 1574 // set defaults 1575 memset(&configuration_server_publication_model, 0, sizeof(mesh_publication_model_t)); 1576 1577 mesh_access_parser_state_t parser; 1578 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1579 1580 // ElementAddress - Address of the element 1581 configuration_server_element_address = mesh_access_parser_get_u16(&parser); 1582 1583 // store label uuid 1584 mesh_access_parser_get_label_uuid(&parser, configuration_server_label_uuid); 1585 1586 // AppKeyIndex (12), CredentialFlag (1), RFU (3) 1587 uint16_t temp = mesh_access_parser_get_u16(&parser); 1588 configuration_server_publication_model.appkey_index = temp & 0x0fff; 1589 configuration_server_publication_model.friendship_credential_flag = (temp >> 12) & 1; 1590 configuration_server_publication_model.ttl = mesh_access_parser_get_u8(&parser); 1591 configuration_server_publication_model.period = mesh_access_parser_get_u8(&parser); 1592 configuration_server_publication_model.retransmit = mesh_access_parser_get_u8(&parser); 1593 1594 // Model Identifier 1595 configuration_server_model_identifier = mesh_access_parser_get_model_identifier(&parser); 1596 1597 uint8_t status; 1598 configuration_server_target_model = mesh_access_model_for_address_and_model_identifier(configuration_server_element_address, configuration_server_model_identifier, &status); 1599 1600 // model exists, but no publication model 1601 if (configuration_server_target_model != NULL && configuration_server_target_model->publication_model == NULL){ 1602 status = MESH_FOUNDATION_STATUS_CANNOT_SET; 1603 } 1604 1605 // on error, no need to calculate virtual address hash 1606 if (status != MESH_FOUNDATION_STATUS_SUCCESS){ 1607 config_model_publication_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, configuration_server_element_address, configuration_server_model_identifier, &configuration_server_publication_model); 1608 mesh_access_message_processed(pdu); 1609 return; 1610 } 1611 1612 access_pdu_in_process = pdu; 1613 mesh_virtual_address(&configuration_server_cmac_request, configuration_server_label_uuid, &configuration_server_publication_model.address, &config_model_publication_virtual_address_set_hash, mesh_model); 1614 } 1615 1616 static void 1617 config_model_publication_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 1618 1619 1620 mesh_access_parser_state_t parser; 1621 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1622 1623 // ElementAddress - Address of the element - should be us 1624 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1625 1626 // Model Identifier 1627 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1628 1629 uint8_t status; 1630 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1631 1632 mesh_publication_model_t * publication_model; 1633 1634 if (target_model == NULL){ 1635 // use defaults 1636 memset(&configuration_server_publication_model, 0, sizeof(mesh_publication_model_t)); 1637 publication_model = &configuration_server_publication_model; 1638 } else { 1639 publication_model = target_model->publication_model; 1640 } 1641 1642 config_model_publication_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, configuration_server_element_address, model_identifier, publication_model); 1643 mesh_access_message_processed(pdu); 1644 } 1645 1646 // Heartbeat Publication 1647 1648 static void config_heartbeat_publication_emit(mesh_heartbeat_publication_t * mesh_heartbeat_publication){ 1649 1650 printf("CONFIG_SERVER_HEARTBEAT: Emit (dest %04x, count %u, period %u ms)\n", 1651 mesh_heartbeat_publication->destination, 1652 mesh_heartbeat_publication->count, 1653 mesh_heartbeat_publication->period_ms); 1654 1655 // active features 1656 mesh_heartbeat_publication->active_features = mesh_foundation_get_features(); 1657 1658 mesh_network_pdu_t * network_pdu = mesh_network_pdu_get(); 1659 if (network_pdu){ 1660 uint8_t data[3]; 1661 data[0] = mesh_heartbeat_publication->ttl; 1662 big_endian_store_16(data, 1, mesh_heartbeat_publication->active_features); 1663 mesh_upper_transport_setup_control_pdu((mesh_pdu_t *) network_pdu, mesh_heartbeat_publication->netkey_index, 1664 mesh_heartbeat_publication->ttl, mesh_node_get_primary_element_address(), mesh_heartbeat_publication->destination, 1665 MESH_TRANSPORT_OPCODE_HEARTBEAT, data, sizeof(data)); 1666 mesh_upper_transport_send_control_pdu((mesh_pdu_t *) network_pdu); 1667 } 1668 1669 // forever 1670 if (mesh_heartbeat_publication->count < 0xffffu) { 1671 mesh_heartbeat_publication->count--; 1672 } 1673 } 1674 void mesh_configuration_server_feature_changed(void){ 1675 mesh_model_t * mesh_model = mesh_model_get_configuration_server(); 1676 mesh_heartbeat_publication_t * mesh_heartbeat_publication = &((mesh_configuration_server_model_context_t*) mesh_model->model_data)->heartbeat_publication; 1677 1678 // active features 1679 uint16_t active_features = mesh_foundation_get_features(); 1680 if (mesh_heartbeat_publication->active_features == active_features) return; 1681 config_heartbeat_publication_emit(mesh_heartbeat_publication); 1682 } 1683 1684 static void config_heartbeat_publication_timeout_handler(btstack_timer_source_t * ts){ 1685 1686 mesh_heartbeat_publication_t * mesh_heartbeat_publication = (mesh_heartbeat_publication_t*) ts; 1687 1688 // emit beat 1689 config_heartbeat_publication_emit(mesh_heartbeat_publication); 1690 1691 // all sent? 1692 if (mesh_heartbeat_publication->count == 0) return; 1693 1694 // periodic publication? 1695 if (mesh_heartbeat_publication->period_ms == 0) return; 1696 1697 btstack_run_loop_set_timer(ts, mesh_heartbeat_publication->period_ms); 1698 btstack_run_loop_add_timer(ts); 1699 } 1700 1701 static void config_heartbeat_publication_status(mesh_model_t *mesh_model, uint16_t netkey_index, uint16_t dest, uint8_t status, mesh_heartbeat_publication_t * mesh_heartbeat_publication){ 1702 UNUSED(mesh_model); 1703 1704 // setup message 1705 uint8_t count_log = heartbeat_count_log(mesh_heartbeat_publication->count); 1706 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 1707 &mesh_foundation_config_heartbeat_publication_status, 1708 status, 1709 mesh_heartbeat_publication->destination, 1710 count_log, 1711 mesh_heartbeat_publication->period_log, 1712 mesh_heartbeat_publication->ttl, 1713 mesh_heartbeat_publication->features, 1714 mesh_heartbeat_publication->netkey_index); 1715 if (!transport_pdu) return; 1716 printf("MESH config_heartbeat_publication_status count = %u => count_log = %u\n", mesh_heartbeat_publication->count, count_log); 1717 1718 // send as segmented access pdu 1719 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 1720 } 1721 1722 static void config_heartbeat_publication_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 1723 1724 mesh_heartbeat_publication_t requested_publication; 1725 1726 mesh_access_parser_state_t parser; 1727 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1728 1729 // Destination address for Heartbeat messages 1730 requested_publication.destination = mesh_access_parser_get_u16(&parser); 1731 // Number of Heartbeat messages to be sent 1732 requested_publication.count = heartbeat_pwr2(mesh_access_parser_get_u8(&parser)); 1733 // Period for sending Heartbeat messages 1734 requested_publication.period_log = mesh_access_parser_get_u8(&parser); 1735 // TTL to be used when sending Heartbeat messages 1736 requested_publication.ttl = mesh_access_parser_get_u8(&parser); 1737 // Bit field indicating features that trigger Heartbeat messages when changed 1738 requested_publication.features = mesh_access_parser_get_u16(&parser) & MESH_HEARTBEAT_FEATURES_SUPPORTED_MASK; 1739 // NetKey Index 1740 requested_publication.netkey_index = mesh_access_parser_get_u16(&parser); 1741 1742 // store period as ms 1743 requested_publication.period_ms = heartbeat_pwr2(requested_publication.period_log) * 1000; 1744 1745 mesh_heartbeat_publication_t * mesh_heartbeat_publication = &((mesh_configuration_server_model_context_t*) mesh_model->model_data)->heartbeat_publication; 1746 1747 // validate fields 1748 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1749 mesh_network_key_t * network_key = mesh_network_key_list_get(requested_publication.netkey_index); 1750 if (network_key == NULL){ 1751 status = MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX; 1752 } else { 1753 printf("MESH config_heartbeat_publication_set, destination %x, count = %x, period = %u s\n", 1754 requested_publication.destination, requested_publication.count, requested_publication.period_ms); 1755 1756 // accept update 1757 memcpy(mesh_heartbeat_publication, &requested_publication, sizeof(mesh_heartbeat_publication_t)); 1758 } 1759 1760 config_heartbeat_publication_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, mesh_heartbeat_publication); 1761 1762 mesh_access_message_processed(pdu); 1763 1764 if (status != MESH_FOUNDATION_STATUS_SUCCESS) return; 1765 1766 // check if heartbeats should be disabled 1767 if (mesh_heartbeat_publication->destination == MESH_ADDRESS_UNSASSIGNED || mesh_heartbeat_publication->period_log == 0) { 1768 btstack_run_loop_remove_timer(&mesh_heartbeat_publication->timer); 1769 printf("MESH config_heartbeat_publication_set, disable\n"); 1770 return; 1771 } 1772 1773 // NOTE: defer first heartbeat to allow config status getting sent first 1774 btstack_run_loop_set_timer_handler(&mesh_heartbeat_publication->timer, config_heartbeat_publication_timeout_handler); 1775 btstack_run_loop_set_timer_context(&mesh_heartbeat_publication->timer, mesh_heartbeat_publication); 1776 btstack_run_loop_set_timer(&mesh_heartbeat_publication->timer, 2000); 1777 btstack_run_loop_add_timer(&mesh_heartbeat_publication->timer); 1778 } 1779 1780 static void config_heartbeat_publication_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 1781 mesh_heartbeat_publication_t * mesh_heartbeat_publication = &((mesh_configuration_server_model_context_t*) mesh_model->model_data)->heartbeat_publication; 1782 config_heartbeat_publication_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), MESH_FOUNDATION_STATUS_SUCCESS, mesh_heartbeat_publication); 1783 mesh_access_message_processed(pdu); 1784 } 1785 1786 // Heartbeat Subscription 1787 1788 static void config_heartbeat_subscription_status(mesh_model_t *mesh_model, uint16_t netkey_index, uint16_t dest, uint8_t status, mesh_heartbeat_subscription_t * mesh_heartbeat_subscription){ 1789 UNUSED(mesh_model); 1790 1791 // setup message 1792 uint8_t count_log = heartbeat_count_log(mesh_heartbeat_subscription->count_log); 1793 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 1794 &mesh_foundation_config_heartbeat_subscription_status, 1795 status, 1796 mesh_heartbeat_subscription->source, 1797 mesh_heartbeat_subscription->destination, 1798 mesh_heartbeat_subscription->period_log, 1799 count_log, 1800 mesh_heartbeat_subscription->min_hops, 1801 mesh_heartbeat_subscription->max_hops); 1802 if (!transport_pdu) return; 1803 printf("MESH config_heartbeat_subscription_status count = %u => count_log = %u\n", mesh_heartbeat_subscription->count_log, count_log); 1804 1805 // send as segmented access pdu 1806 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 1807 } 1808 static int config_heartbeat_subscription_enabled(mesh_heartbeat_subscription_t * mesh_heartbeat_subscription){ 1809 return mesh_network_address_unicast(mesh_heartbeat_subscription->source) && mesh_heartbeat_subscription->period_log > 0 && 1810 (mesh_network_address_unicast(mesh_heartbeat_subscription->destination) || mesh_network_address_group(mesh_heartbeat_subscription->destination)); 1811 } 1812 1813 static void config_heartbeat_subscription_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 1814 mesh_access_parser_state_t parser; 1815 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1816 1817 mesh_heartbeat_subscription_t requested_subscription; 1818 1819 // Destination address for Heartbeat messages 1820 requested_subscription.source = mesh_access_parser_get_u16(&parser); 1821 // Destination address for Heartbeat messages 1822 requested_subscription.destination = mesh_access_parser_get_u16(&parser); 1823 // Period for sending Heartbeat messages 1824 requested_subscription.period_log = mesh_access_parser_get_u8(&parser); 1825 1826 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1827 if (requested_subscription.period_log > 0x11u){ 1828 status = MESH_FOUNDATION_STATUS_CANNOT_SET; 1829 } else if ((requested_subscription.source != MESH_ADDRESS_UNSASSIGNED) && 1830 !mesh_network_address_unicast(requested_subscription.source)){ 1831 status = MESH_FOUNDATION_STATUS_INVALID_ADDRESS; 1832 } else if ((requested_subscription.destination != MESH_ADDRESS_UNSASSIGNED) && 1833 !mesh_network_address_unicast(requested_subscription.destination) && 1834 !mesh_network_address_group(requested_subscription.destination)){ 1835 status = MESH_FOUNDATION_STATUS_INVALID_ADDRESS; 1836 } 1837 1838 if (status != MESH_FOUNDATION_STATUS_SUCCESS){ 1839 config_heartbeat_subscription_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, &requested_subscription); 1840 mesh_access_message_processed(pdu); 1841 return; 1842 } 1843 1844 mesh_heartbeat_subscription_t * mesh_heartbeat_subscription = &((mesh_configuration_server_model_context_t*) mesh_model->model_data)->heartbeat_subscription; 1845 1846 if (config_heartbeat_subscription_enabled(mesh_heartbeat_subscription)){ 1847 requested_subscription.count_log = 0u; 1848 requested_subscription.min_hops = 0x7Fu; 1849 requested_subscription.max_hops = 0u; 1850 } else { 1851 requested_subscription.source = MESH_ADDRESS_UNSASSIGNED; 1852 requested_subscription.destination = MESH_ADDRESS_UNSASSIGNED; 1853 requested_subscription.period_log = 0u; 1854 requested_subscription.count_log = 0u; 1855 requested_subscription.min_hops = 0u; 1856 requested_subscription.max_hops = 0u; 1857 } 1858 1859 // accept request 1860 memcpy(mesh_heartbeat_subscription, &requested_subscription, sizeof(mesh_heartbeat_subscription_t)); 1861 1862 printf("MESH config_heartbeat_subscription_set, destination %x, count = %x, period = %u s\n", 1863 mesh_heartbeat_subscription->destination, mesh_heartbeat_subscription->count_log, heartbeat_pwr2(mesh_heartbeat_subscription->period_log)); 1864 1865 config_heartbeat_subscription_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, mesh_heartbeat_subscription); 1866 mesh_access_message_processed(pdu); 1867 } 1868 1869 1870 static void config_heartbeat_subscription_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 1871 mesh_heartbeat_subscription_t * mesh_heartbeat_subscription = &((mesh_configuration_server_model_context_t*) mesh_model->model_data)->heartbeat_subscription; 1872 config_heartbeat_subscription_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), MESH_FOUNDATION_STATUS_SUCCESS, mesh_heartbeat_subscription); 1873 mesh_access_message_processed(pdu); 1874 } 1875 1876 // KeyRefresh Phase 1877 1878 static void config_key_refresh_phase_status(mesh_model_t *mesh_model, uint16_t netkey_index_dest, uint16_t dest, uint8_t status, uint16_t netkey_index, 1879 mesh_key_refresh_state_t key_refresh_state){ 1880 UNUSED(mesh_model); 1881 1882 // setup message 1883 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 1884 &mesh_key_refresh_phase_status, 1885 status, 1886 netkey_index, 1887 key_refresh_state); 1888 if (!transport_pdu) return; 1889 1890 // send as segmented access pdu 1891 config_server_send_message(netkey_index_dest, dest, (mesh_pdu_t *) transport_pdu); 1892 } 1893 1894 static void config_key_refresh_phase_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 1895 mesh_access_parser_state_t parser; 1896 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1897 uint16_t netkey_index = mesh_access_parser_get_u16(&parser); 1898 mesh_subnet_t * subnet = mesh_subnet_get_by_netkey_index(netkey_index); 1899 1900 uint8_t status = MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX; 1901 mesh_key_refresh_state_t key_refresh_state = MESH_KEY_REFRESH_NOT_ACTIVE; 1902 1903 if (subnet != NULL){ 1904 status = MESH_FOUNDATION_STATUS_SUCCESS; 1905 key_refresh_state = subnet->key_refresh; 1906 } 1907 1908 config_key_refresh_phase_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, netkey_index, key_refresh_state); 1909 mesh_access_message_processed(pdu); 1910 } 1911 1912 static void config_key_refresh_phase_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 1913 mesh_access_parser_state_t parser; 1914 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1915 uint16_t netkey_index = mesh_access_parser_get_u16(&parser); 1916 uint8_t key_refresh_phase_transition = mesh_access_parser_get_u8(&parser); 1917 mesh_subnet_t * subnet = mesh_subnet_get_by_netkey_index(netkey_index); 1918 1919 uint8_t status = MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX; 1920 1921 if (subnet != NULL){ 1922 status = MESH_FOUNDATION_STATUS_SUCCESS; 1923 1924 switch (key_refresh_phase_transition){ 1925 case 0x02: 1926 switch (subnet->key_refresh){ 1927 case MESH_KEY_REFRESH_FIRST_PHASE: 1928 case MESH_KEY_REFRESH_SECOND_PHASE: 1929 subnet->key_refresh = MESH_KEY_REFRESH_SECOND_PHASE; 1930 break; 1931 default: 1932 break; 1933 } 1934 break; 1935 case 0x03: 1936 switch (subnet->key_refresh){ 1937 case MESH_KEY_REFRESH_FIRST_PHASE: 1938 case MESH_KEY_REFRESH_SECOND_PHASE: 1939 // key refresh phase 3 entered 1940 mesh_access_key_refresh_revoke_keys(subnet); 1941 subnet->key_refresh = MESH_KEY_REFRESH_NOT_ACTIVE; 1942 break; 1943 default: 1944 break; 1945 } 1946 break; 1947 default: 1948 status = MESH_FOUNDATION_STATUS_CANNOT_SET; 1949 break; 1950 } 1951 } 1952 1953 config_key_refresh_phase_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, netkey_index, subnet->key_refresh); 1954 mesh_access_message_processed(pdu); 1955 } 1956 1957 1958 static void config_node_reset_status(mesh_model_t *mesh_model, uint16_t netkey_index, uint16_t dest){ 1959 UNUSED(mesh_model); 1960 1961 // setup message 1962 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_foundation_node_reset_status); 1963 if (!transport_pdu) return; 1964 1965 // send as segmented access pdu 1966 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 1967 } 1968 1969 static void config_node_reset_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 1970 mesh_node_reset(); 1971 config_node_reset_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 1972 mesh_access_message_processed(pdu); 1973 } 1974 1975 static void low_power_node_poll_timeout_status(mesh_model_t *mesh_model, uint16_t netkey_index_dest, uint16_t dest, uint8_t status){ 1976 UNUSED(mesh_model); 1977 1978 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 1979 &mesh_foundation_low_power_node_poll_timeout_status, 1980 status, 1981 0, // The unicast address of the Low Power node 1982 0); // The current value of the PollTimeout timer of the Low Power node 1983 if (!transport_pdu) return; 1984 printf("TODO: send unicast address of the Low Power node and the current value of the PollTimeout timer, instead of 0s\n"); 1985 // send as segmented access pdu 1986 config_server_send_message(netkey_index_dest, dest, (mesh_pdu_t *) transport_pdu); 1987 } 1988 1989 static void config_low_power_node_poll_timeout_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 1990 mesh_access_parser_state_t parser; 1991 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1992 printf("TODO: implement get the current value of PollTimeout timer of the Low Power node within a Friend node\n"); 1993 low_power_node_poll_timeout_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), MESH_FOUNDATION_STATUS_SUCCESS); 1994 mesh_access_message_processed(pdu); 1995 } 1996 1997 static void config_node_identity_status(mesh_model_t *mesh_model, uint16_t netkey_index_dest, uint16_t dest, uint8_t status, uint16_t netkey_index, 1998 mesh_node_identity_state_t node_identity_state){ 1999 UNUSED(mesh_model); 2000 2001 // setup message 2002 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 2003 &mesh_foundation_node_identity_status, 2004 status, 2005 netkey_index, 2006 node_identity_state); 2007 if (!transport_pdu) return; 2008 2009 // send as segmented access pdu 2010 config_server_send_message(netkey_index_dest, dest, (mesh_pdu_t *) transport_pdu); 2011 } 2012 2013 static void config_node_identity_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 2014 mesh_access_parser_state_t parser; 2015 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 2016 uint16_t netkey_index = mesh_access_parser_get_u16(&parser); 2017 2018 mesh_node_identity_state_t node_identity_state = MESH_NODE_IDENTITY_STATE_ADVERTISING_NOT_SUPPORTED; 2019 uint8_t status = mesh_proxy_get_advertising_with_node_id_status(netkey_index, &node_identity_state); 2020 2021 config_node_identity_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, netkey_index, node_identity_state); 2022 mesh_access_message_processed(pdu); 2023 } 2024 2025 static void config_node_identity_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 2026 mesh_access_parser_state_t parser; 2027 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 2028 uint16_t netkey_index = mesh_access_parser_get_u16(&parser); 2029 mesh_node_identity_state_t node_identity_state = (mesh_node_identity_state_t) mesh_access_parser_get_u8(&parser); 2030 2031 uint8_t status = mesh_proxy_set_advertising_with_node_id(netkey_index, node_identity_state); 2032 2033 config_node_identity_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, netkey_index, node_identity_state); 2034 mesh_access_message_processed(pdu); 2035 } 2036 2037 // 2038 2039 const static mesh_operation_t mesh_configuration_server_model_operations[] = { 2040 { MESH_FOUNDATION_OPERATION_APPKEY_ADD, 19, config_appkey_add_handler }, 2041 { MESH_FOUNDATION_OPERATION_APPKEY_DELETE, 3, config_appkey_delete_handler }, 2042 { MESH_FOUNDATION_OPERATION_APPKEY_GET, 2, config_appkey_get_handler }, 2043 { MESH_FOUNDATION_OPERATION_APPKEY_UPDATE, 19, config_appkey_update_handler }, 2044 { MESH_FOUNDATION_OPERATION_NETKEY_ADD, 18, config_netkey_add_handler }, 2045 { MESH_FOUNDATION_OPERATION_NETKEY_UPDATE, 18, config_netkey_update_handler }, 2046 { MESH_FOUNDATION_OPERATION_NETKEY_DELETE, 2, config_netkey_delete_handler }, 2047 { MESH_FOUNDATION_OPERATION_NETKEY_GET, 0, config_netkey_get_handler }, 2048 { MESH_FOUNDATION_OPERATION_COMPOSITION_DATA_GET, 1, config_composition_data_get_handler }, 2049 { MESH_FOUNDATION_OPERATION_BEACON_GET, 0, config_beacon_get_handler }, 2050 { MESH_FOUNDATION_OPERATION_BEACON_SET, 1, config_beacon_set_handler }, 2051 { MESH_FOUNDATION_OPERATION_DEFAULT_TTL_GET, 0, config_default_ttl_get_handler }, 2052 { MESH_FOUNDATION_OPERATION_DEFAULT_TTL_SET, 1, config_default_ttl_set_handler }, 2053 { MESH_FOUNDATION_OPERATION_FRIEND_GET, 0, config_friend_get_handler }, 2054 { MESH_FOUNDATION_OPERATION_FRIEND_SET, 1, config_friend_set_handler }, 2055 { MESH_FOUNDATION_OPERATION_NETWORK_TRANSMIT_GET, 0, config_model_network_transmit_get_handler }, 2056 { MESH_FOUNDATION_OPERATION_NETWORK_TRANSMIT_SET, 1, config_model_network_transmit_set_handler }, 2057 { MESH_FOUNDATION_OPERATION_GATT_PROXY_GET, 0, config_gatt_proxy_get_handler }, 2058 { MESH_FOUNDATION_OPERATION_GATT_PROXY_SET, 1, config_gatt_proxy_set_handler }, 2059 { MESH_FOUNDATION_OPERATION_RELAY_GET, 0, config_relay_get_handler }, 2060 { MESH_FOUNDATION_OPERATION_RELAY_SET, 1, config_relay_set_handler }, 2061 { MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_ADD, 6, config_model_subscription_add_handler }, 2062 { MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_VIRTUAL_ADDRESS_ADD, 20, config_model_subscription_virtual_address_add_handler }, 2063 { MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_DELETE, 6, config_model_subscription_delete_handler }, 2064 { MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_VIRTUAL_ADDRESS_DELETE, 20, config_model_subscription_virtual_address_delete_handler }, 2065 { MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_OVERWRITE, 6, config_model_subscription_overwrite_handler }, 2066 { MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_VIRTUAL_ADDRESS_OVERWRITE,20, config_model_subscription_virtual_address_overwrite_handler }, 2067 { MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_DELETE_ALL, 4, config_model_subscription_delete_all_handler }, 2068 { MESH_FOUNDATION_OPERATION_SIG_MODEL_SUBSCRIPTION_GET, 4, config_model_subscription_get_handler }, 2069 { MESH_FOUNDATION_OPERATION_VENDOR_MODEL_SUBSCRIPTION_GET, 6, config_model_subscription_get_handler }, 2070 { MESH_FOUNDATION_OPERATION_SIG_MODEL_APP_GET, 4, config_model_app_get_handler }, 2071 { MESH_FOUNDATION_OPERATION_VENDOR_MODEL_APP_GET, 6, config_model_app_get_handler }, 2072 { MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_SET, 11, config_model_publication_set_handler }, 2073 { MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_VIRTUAL_ADDRESS_SET, 25, config_model_publication_virtual_address_set_handler }, 2074 { MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_GET, 4, config_model_publication_get_handler }, 2075 { MESH_FOUNDATION_OPERATION_MODEL_APP_BIND, 6, config_model_app_bind_handler }, 2076 { MESH_FOUNDATION_OPERATION_MODEL_APP_UNBIND, 6, config_model_app_unbind_handler }, 2077 { MESH_FOUNDATION_OPERATION_HEARTBEAT_PUBLICATION_GET, 0, config_heartbeat_publication_get_handler }, 2078 { MESH_FOUNDATION_OPERATION_HEARTBEAT_PUBLICATION_SET, 9, config_heartbeat_publication_set_handler }, 2079 { MESH_FOUNDATION_OPERATION_HEARTBEAT_SUBSCRIPTION_GET, 0, config_heartbeat_subscription_get_handler}, 2080 { MESH_FOUNDATION_OPERATION_HEARTBEAT_SUBSCRIPTION_SET, 5, config_heartbeat_subscription_set_handler}, 2081 { MESH_FOUNDATION_OPERATION_KEY_REFRESH_PHASE_GET, 2, config_key_refresh_phase_get_handler }, 2082 { MESH_FOUNDATION_OPERATION_KEY_REFRESH_PHASE_SET, 3, config_key_refresh_phase_set_handler }, 2083 { MESH_FOUNDATION_OPERATION_NODE_RESET, 0, config_node_reset_handler }, 2084 { MESH_FOUNDATION_OPERATION_LOW_POWER_NODE_POLL_TIMEOUT_GET, 2, config_low_power_node_poll_timeout_get_handler }, 2085 { MESH_FOUNDATION_OPERATION_NODE_IDENTITY_GET, 2, config_node_identity_get_handler }, 2086 { MESH_FOUNDATION_OPERATION_NODE_IDENTITY_SET, 3, config_node_identity_set_handler }, 2087 { 0, 0, NULL } 2088 }; 2089 2090 const mesh_operation_t * mesh_configuration_server_get_operations(void){ 2091 return mesh_configuration_server_model_operations; 2092 } 2093 2094 static uint32_t mesh_tag_for_prov_data(void){ 2095 return ((uint32_t) 'P' << 24) | ((uint32_t) 'R' << 16) | ((uint32_t) 'O' << 8) | (uint32_t)'V'; 2096 } 2097 2098 void mesh_node_reset(void){ 2099 mesh_configuration_server_setup_tlv(); 2100 2101 // PROV 2102 btstack_tlv_singleton_impl->delete_tag(btstack_tlv_singleton_context, mesh_tag_for_prov_data()); 2103 // everything else 2104 mesh_delete_network_keys(); 2105 mesh_delete_app_keys(); 2106 mesh_delete_appkey_lists(); 2107 mesh_delete_virtual_addresses(); 2108 mesh_delete_subscriptions(); 2109 mesh_delete_publications(); 2110 } 2111 2112 typedef struct { 2113 uint16_t unicast_address; 2114 uint8_t flags; 2115 uint8_t device_key[16]; 2116 2117 } mesh_persistent_provisioning_data_t; 2118 2119 void mesh_node_store_provisioning_data(mesh_provisioning_data_t * provisioning_data){ 2120 2121 // fill persistent prov data 2122 mesh_persistent_provisioning_data_t persistent_provisioning_data; 2123 2124 persistent_provisioning_data.unicast_address = provisioning_data->unicast_address; 2125 memcpy(persistent_provisioning_data.device_key, provisioning_data->device_key, 16); 2126 2127 // store in tlv 2128 btstack_tlv_get_instance(&btstack_tlv_singleton_impl, &btstack_tlv_singleton_context); 2129 btstack_tlv_singleton_impl->store_tag(btstack_tlv_singleton_context, mesh_tag_for_prov_data(), (uint8_t *) &persistent_provisioning_data, sizeof(mesh_persistent_provisioning_data_t)); 2130 2131 // store IV Index and sequence number 2132 mesh_store_iv_index_after_provisioning(provisioning_data->iv_index); 2133 2134 // store primary network key 2135 mesh_store_network_key(provisioning_data->network_key); 2136 } 2137 2138 int mesh_node_startup_from_tlv(void){ 2139 2140 mesh_persistent_provisioning_data_t persistent_provisioning_data; 2141 btstack_tlv_get_instance(&btstack_tlv_singleton_impl, &btstack_tlv_singleton_context); 2142 2143 // load provisioning data 2144 uint32_t prov_len = btstack_tlv_singleton_impl->get_tag(btstack_tlv_singleton_context, mesh_tag_for_prov_data(), (uint8_t *) &persistent_provisioning_data, sizeof(mesh_persistent_provisioning_data_t)); 2145 printf("Provisioning data available: %u\n", prov_len ? 1 : 0); 2146 if (prov_len){ 2147 2148 // copy into mesh_provisioning_data 2149 mesh_provisioning_data_t provisioning_data; 2150 memcpy(provisioning_data.device_key, persistent_provisioning_data.device_key, 16); 2151 provisioning_data.unicast_address = persistent_provisioning_data.unicast_address; 2152 provisioning_data.flags = persistent_provisioning_data.flags; 2153 provisioning_data.network_key = NULL; 2154 2155 // load iv index 2156 uint32_t iv_index; 2157 uint32_t sequence_number; 2158 int ok = mesh_load_iv_index_and_sequence_number(&iv_index, &sequence_number); 2159 if (ok){ 2160 // bump sequence number to account for interval updates 2161 sequence_number += MESH_SEQUENCE_NUMBER_STORAGE_INTERVAL; 2162 mesh_sequence_number_set(sequence_number); 2163 mesh_store_iv_index_and_sequence_number(); 2164 log_info("IV Index: %08x, Sequence Number %08x", (int) iv_index, (int) sequence_number); 2165 provisioning_data.iv_index = iv_index; 2166 } 2167 2168 // load network keys 2169 mesh_load_network_keys(); 2170 // load app keys 2171 mesh_load_app_keys(); 2172 // load model to appkey bindings 2173 mesh_load_appkey_lists(); 2174 // load virtual addresses 2175 mesh_load_virtual_addresses(); 2176 // load model subscriptions 2177 mesh_load_subscriptions(); 2178 // load model publications 2179 mesh_load_publications(); 2180 // load foundation state 2181 mesh_foundation_state_load(); 2182 2183 mesh_access_setup_from_provisioning_data(&provisioning_data); 2184 2185 #if defined(ENABLE_MESH_ADV_BEARER) || defined(ENABLE_MESH_PB_ADV) 2186 // start sending Secure Network Beacon 2187 mesh_subnet_t * subnet = mesh_subnet_get_by_netkey_index(0); 2188 if (subnet){ 2189 beacon_secure_network_start(subnet); 2190 } 2191 #endif 2192 return 1; 2193 } else { 2194 mesh_access_setup_without_provisiong_data(); 2195 return 0; 2196 } 2197 } 2198 2199