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