1 /* 2 * Copyright (C) 2019 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 #define BTSTACK_FILE__ "mesh_configuration_client.c" 39 40 #include <string.h> 41 #include <stdio.h> 42 43 #include "mesh/mesh_configuration_client.h" 44 45 #include "bluetooth_company_id.h" 46 #include "btstack_debug.h" 47 #include "btstack_memory.h" 48 #include "btstack_util.h" 49 50 #include "mesh/mesh_access.h" 51 #include "mesh/mesh_foundation.h" 52 #include "mesh/mesh_generic_model.h" 53 #include "mesh/mesh_keys.h" 54 #include "mesh/mesh_network.h" 55 #include "mesh/mesh_upper_transport.h" 56 57 58 // Mesh Composition Data Element iterator 59 #define MESH_VENDOR_MODEL_SIZE 4 60 #define MESH_SIG_MODEL_SIZE 2 61 #define MESH_COMPOSITION_DATA_ELEMENT_DESCRIPTION_OFFSET 17 62 #define MESH_COMPOSITION_DATA_ELEMENT_LOCATION_DESCRIPTOR_LEN 2 63 #define MESH_COMPOSITION_DATA_ELEMENT_MODEL_SIZE_LEN 1 64 65 static inline uint16_t mesh_composition_data_iterator_sig_model_list_size(mesh_composite_data_iterator_t * it){ 66 return it->elements[it->offset + 2] * MESH_SIG_MODEL_SIZE; 67 } 68 69 static inline uint16_t mesh_composition_data_iterator_vendor_model_list_size(mesh_composite_data_iterator_t * it){ 70 return it->elements[it->offset + 3] * MESH_VENDOR_MODEL_SIZE; 71 } 72 73 static inline uint16_t mesh_composition_data_iterator_element_len(mesh_composite_data_iterator_t * it){ 74 uint16_t sig_model_list_size = mesh_composition_data_iterator_sig_model_list_size(it); 75 uint16_t vendor_model_list_size = mesh_composition_data_iterator_vendor_model_list_size(it); 76 uint16_t previous_fields_len = MESH_COMPOSITION_DATA_ELEMENT_LOCATION_DESCRIPTOR_LEN + 2 * MESH_COMPOSITION_DATA_ELEMENT_MODEL_SIZE_LEN; 77 78 return previous_fields_len + sig_model_list_size + vendor_model_list_size;; 79 } 80 81 uint16_t mesh_subevent_configuration_composition_data_get_num_elements(const uint8_t * event, uint16_t size){ 82 uint16_t pos = MESH_COMPOSITION_DATA_ELEMENT_DESCRIPTION_OFFSET; 83 uint16_t num_elements = 0; 84 85 while ((pos + 4) <= size){ 86 // location descriptor 87 pos += 2; 88 uint8_t num_sig_model_ids = event[pos++]; 89 uint8_t num_vendor_model_ids = event[pos++]; 90 pos += (num_sig_model_ids + num_vendor_model_ids) * 2; 91 num_elements++; 92 } 93 return num_elements; 94 } 95 96 void mesh_composition_data_iterator_init(mesh_composite_data_iterator_t * it, const uint8_t * elements, uint16_t size){ 97 it->elements = elements; 98 it->size = size; 99 it->offset = MESH_COMPOSITION_DATA_ELEMENT_DESCRIPTION_OFFSET; 100 } 101 102 bool mesh_composition_data_iterator_has_next_element(mesh_composite_data_iterator_t * it){ 103 return (it->offset + mesh_composition_data_iterator_element_len(it)) <= it->size; 104 } 105 106 void mesh_composition_data_iterator_next_element(mesh_composite_data_iterator_t * it){ 107 it->sig_model_iterator.models = &it->elements[it->offset + 4]; 108 it->sig_model_iterator.size = mesh_composition_data_iterator_sig_model_list_size(it); 109 it->sig_model_iterator.offset = 0; 110 111 it->vendor_model_iterator.models = &it->elements[it->offset + 4 + it->sig_model_iterator.size]; 112 it->vendor_model_iterator.size = mesh_composition_data_iterator_vendor_model_list_size(it); 113 it->vendor_model_iterator.offset = 0; 114 115 it->loc = little_endian_read_16(it->elements, it->offset); 116 it->offset += mesh_composition_data_iterator_element_len(it); 117 } 118 119 uint16_t mesh_composition_data_iterator_element_loc(mesh_composite_data_iterator_t * it){ 120 return it->loc; 121 } 122 123 bool mesh_composition_data_iterator_has_next_sig_model(mesh_composite_data_iterator_t * it){ 124 return (it->sig_model_iterator.offset + MESH_SIG_MODEL_SIZE) <= it->sig_model_iterator.size; 125 } 126 127 void mesh_composition_data_iterator_next_sig_model(mesh_composite_data_iterator_t * it){ 128 it->sig_model_iterator.id = little_endian_read_16(it->sig_model_iterator.models, it->sig_model_iterator.offset); 129 it->sig_model_iterator.offset += 2; 130 } 131 132 uint16_t mesh_composition_data_iterator_sig_model_id(mesh_composite_data_iterator_t * it){ 133 return (uint16_t)it->sig_model_iterator.id; 134 } 135 136 bool mesh_composition_data_iterator_has_next_vendor_model(mesh_composite_data_iterator_t * it){ 137 return (it->vendor_model_iterator.offset + MESH_VENDOR_MODEL_SIZE) <= it->vendor_model_iterator.size; 138 } 139 140 void mesh_composition_data_iterator_next_vendor_model(mesh_composite_data_iterator_t * it){ 141 uint16_t vendor_id = little_endian_read_16(it->vendor_model_iterator.models, it->vendor_model_iterator.offset); 142 it->vendor_model_iterator.offset += 2; 143 uint16_t model_id = little_endian_read_16(it->vendor_model_iterator.models, it->vendor_model_iterator.offset); 144 it->vendor_model_iterator.offset += 2; 145 it->vendor_model_iterator.id = mesh_model_get_model_identifier(vendor_id, model_id); 146 } 147 148 uint32_t mesh_composition_data_iterator_vendor_model_id(mesh_composite_data_iterator_t * it){ 149 return it->vendor_model_iterator.id; 150 } 151 152 // Configuration client messages 153 154 static const mesh_access_message_t mesh_configuration_client_beacon_get = { 155 MESH_FOUNDATION_OPERATION_BEACON_GET, "" 156 }; 157 static const mesh_access_message_t mesh_configuration_client_beacon_set = { 158 MESH_FOUNDATION_OPERATION_BEACON_SET, "1" 159 }; 160 161 162 static const mesh_access_message_t mesh_configuration_client_composition_data_get = { 163 MESH_FOUNDATION_OPERATION_COMPOSITION_DATA_GET, "1" 164 }; 165 166 167 static const mesh_access_message_t mesh_configuration_client_default_ttl_get = { 168 MESH_FOUNDATION_OPERATION_DEFAULT_TTL_GET, "" 169 }; 170 static const mesh_access_message_t mesh_configuration_client_default_ttl_set = { 171 MESH_FOUNDATION_OPERATION_DEFAULT_TTL_SET, "1" 172 }; 173 174 175 static const mesh_access_message_t mesh_configuration_client_gatt_proxy_get = { 176 MESH_FOUNDATION_OPERATION_GATT_PROXY_GET, "" 177 }; 178 static const mesh_access_message_t mesh_configuration_client_gatt_proxy_set = { 179 MESH_FOUNDATION_OPERATION_GATT_PROXY_SET, "1" 180 }; 181 182 183 static const mesh_access_message_t mesh_configuration_client_relay_get = { 184 MESH_FOUNDATION_OPERATION_RELAY_GET, "" 185 }; 186 static const mesh_access_message_t mesh_configuration_client_relay_set = { 187 MESH_FOUNDATION_OPERATION_RELAY_SET, "11" 188 }; 189 190 static const mesh_access_message_t mesh_configuration_client_model_publication_get = { 191 MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_GET, "2m" 192 }; 193 static const mesh_access_message_t mesh_configuration_client_model_publication_set = { 194 MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_SET, "222111m" 195 }; 196 static const mesh_access_message_t mesh_configuration_client_model_publication_virtual_address_set = { 197 MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_VIRTUAL_ADDRESS_SET, "2P2111m" 198 }; 199 200 201 static const mesh_access_message_t mesh_configuration_client_model_subscription_add = { 202 MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_ADD, "22m" 203 }; 204 static const mesh_access_message_t mesh_configuration_client_model_subscription_virtual_address_add = { 205 MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_VIRTUAL_ADDRESS_ADD, "2Pm" 206 }; 207 static const mesh_access_message_t mesh_configuration_client_model_subscription_delete = { 208 MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_DELETE, "22m" 209 }; 210 static const mesh_access_message_t mesh_configuration_client_model_subscription_virtual_address_delete = { 211 MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_VIRTUAL_ADDRESS_DELETE, "2Pm" 212 }; 213 static const mesh_access_message_t mesh_configuration_client_model_subscription_overwrite = { 214 MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_OVERWRITE, "22m" 215 }; 216 static const mesh_access_message_t mesh_configuration_client_model_subscription_virtual_address_overwrite = { 217 MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_VIRTUAL_ADDRESS_OVERWRITE, "2Pm" 218 }; 219 static const mesh_access_message_t mesh_configuration_client_model_subscription_delete_all = { 220 MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_DELETE_ALL, "22m" 221 }; 222 223 224 static const mesh_access_message_t mesh_configuration_client_sig_model_subscription_get = { 225 MESH_FOUNDATION_OPERATION_SIG_MODEL_SUBSCRIPTION_GET, "22" 226 }; 227 228 static const mesh_access_message_t mesh_configuration_client_vendor_model_subscription_get = { 229 MESH_FOUNDATION_OPERATION_VENDOR_MODEL_SUBSCRIPTION_GET, "24" 230 }; 231 232 static const mesh_access_message_t mesh_configuration_client_netkey_add = { 233 MESH_FOUNDATION_OPERATION_NETKEY_ADD, "2P" 234 }; 235 static const mesh_access_message_t mesh_configuration_client_netkey_update = { 236 MESH_FOUNDATION_OPERATION_NETKEY_UPDATE, "2P" 237 }; 238 static const mesh_access_message_t mesh_configuration_client_netkey_delete = { 239 MESH_FOUNDATION_OPERATION_NETKEY_DELETE, "2" 240 }; 241 static const mesh_access_message_t mesh_configuration_client_netkey_get = { 242 MESH_FOUNDATION_OPERATION_NETKEY_GET, "" 243 }; 244 245 246 static const mesh_access_message_t mesh_configuration_client_appkey_add = { 247 MESH_FOUNDATION_OPERATION_APPKEY_ADD, "3P" 248 }; 249 static const mesh_access_message_t mesh_configuration_client_appkey_update = { 250 MESH_FOUNDATION_OPERATION_APPKEY_UPDATE, "3P" 251 }; 252 static const mesh_access_message_t mesh_configuration_client_appkey_delete = { 253 MESH_FOUNDATION_OPERATION_APPKEY_DELETE, "3" 254 }; 255 static const mesh_access_message_t mesh_configuration_client_appkey_get = { 256 MESH_FOUNDATION_OPERATION_APPKEY_GET, "2" 257 }; 258 259 static const mesh_access_message_t mesh_configuration_client_node_identity_get = { 260 MESH_FOUNDATION_OPERATION_NODE_IDENTITY_GET, "2" 261 }; 262 static const mesh_access_message_t mesh_configuration_client_node_identity_set = { 263 MESH_FOUNDATION_OPERATION_NODE_IDENTITY_SET, "21" 264 }; 265 266 static const mesh_access_message_t mesh_configuration_client_model_app_bind = { 267 MESH_FOUNDATION_OPERATION_MODEL_APP_BIND, "22m" 268 }; 269 static const mesh_access_message_t mesh_configuration_client_model_app_unbind = { 270 MESH_FOUNDATION_OPERATION_MODEL_APP_UNBIND, "22m" 271 }; 272 273 static const mesh_access_message_t mesh_configuration_client_sig_model_app_get = { 274 MESH_FOUNDATION_OPERATION_SIG_MODEL_APP_GET, "2m" 275 }; 276 static const mesh_access_message_t mesh_configuration_client_vendor_model_app_get = { 277 MESH_FOUNDATION_OPERATION_VENDOR_MODEL_APP_GET, "2m" 278 }; 279 280 static 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){ 281 uint8_t ttl = mesh_foundation_default_ttl_get(); 282 mesh_upper_transport_setup_access_pdu_header(pdu, netkey_index, appkey_index, ttl, src, dest, 0); 283 mesh_access_send_acknowledged_pdu(pdu, mesh_access_acknowledged_message_retransmissions(), ack_opcode); 284 } 285 286 static uint8_t mesh_access_validate_envelop_params(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index){ 287 btstack_assert(mesh_model != NULL); 288 // TODO: validate other params 289 UNUSED(mesh_model); 290 UNUSED(dest); 291 UNUSED(netkey_index); 292 UNUSED(appkey_index); 293 294 return ERROR_CODE_SUCCESS; 295 } 296 297 uint8_t mesh_configuration_client_send_beacon_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index){ 298 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 299 if (status != ERROR_CODE_SUCCESS) return status; 300 301 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_beacon_get); 302 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 303 304 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) network_pdu, MESH_FOUNDATION_OPERATION_BEACON_STATUS); 305 return ERROR_CODE_SUCCESS; 306 } 307 308 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){ 309 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 310 if (status != ERROR_CODE_SUCCESS) return status; 311 312 if (beacon > 1) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 313 314 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_beacon_set, beacon); 315 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 316 317 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) network_pdu, MESH_FOUNDATION_OPERATION_BEACON_STATUS); 318 return ERROR_CODE_SUCCESS; 319 } 320 321 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){ 322 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 323 if (status != ERROR_CODE_SUCCESS) return status; 324 325 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_composition_data_get, page); 326 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 327 328 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) network_pdu, MESH_FOUNDATION_OPERATION_COMPOSITION_DATA_STATUS); 329 return ERROR_CODE_SUCCESS; 330 } 331 332 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){ 333 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 334 if (status != ERROR_CODE_SUCCESS) return status; 335 336 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_default_ttl_get); 337 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 338 339 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) network_pdu, MESH_FOUNDATION_OPERATION_DEFAULT_TTL_STATUS); 340 return ERROR_CODE_SUCCESS; 341 } 342 343 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){ 344 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 345 if (status != ERROR_CODE_SUCCESS) return status; 346 347 if (ttl == 0x01 || ttl >= 0x80) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 348 349 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_default_ttl_set, ttl); 350 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 351 352 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) network_pdu, MESH_FOUNDATION_OPERATION_DEFAULT_TTL_STATUS); 353 return ERROR_CODE_SUCCESS; 354 } 355 356 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){ 357 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 358 if (status != ERROR_CODE_SUCCESS) return status; 359 360 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_gatt_proxy_get); 361 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 362 363 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) network_pdu, MESH_FOUNDATION_OPERATION_GATT_PROXY_STATUS); 364 return ERROR_CODE_SUCCESS; 365 } 366 367 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){ 368 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 369 if (status != ERROR_CODE_SUCCESS) return status; 370 371 if (gatt_proxy_state > 2) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 372 373 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_gatt_proxy_set, gatt_proxy_state); 374 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 375 376 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) network_pdu, MESH_FOUNDATION_OPERATION_GATT_PROXY_STATUS); 377 return ERROR_CODE_SUCCESS; 378 } 379 380 uint8_t mesh_configuration_client_send_relay_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index){ 381 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 382 if (status != ERROR_CODE_SUCCESS) return status; 383 384 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_relay_get); 385 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 386 387 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) network_pdu, MESH_FOUNDATION_OPERATION_RELAY_STATUS); 388 return ERROR_CODE_SUCCESS; 389 } 390 391 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){ 392 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 393 if (status != ERROR_CODE_SUCCESS) return status; 394 395 if (relay_retransmit_count > 0x07) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 396 if (relay_retransmit_interval_steps > 0x1F) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 397 398 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_relay_set, relay, (relay_retransmit_count << 5) | relay_retransmit_interval_steps); 399 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 400 401 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) network_pdu, MESH_FOUNDATION_OPERATION_RELAY_SET); 402 return ERROR_CODE_SUCCESS; 403 } 404 405 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){ 406 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 407 if (status != ERROR_CODE_SUCCESS) return status; 408 409 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_model_publication_get, dest, model_id); 410 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 411 412 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) network_pdu, MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_STATUS); 413 return ERROR_CODE_SUCCESS; 414 } 415 416 static uint8_t mesh_validate_publication_model_config_parameters(mesh_publication_model_config_t * publication_config, bool use_unicast_address){ 417 if (publication_config->appkey_index > 0xFFF) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 418 if (publication_config->credential_flag > 1) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 419 if (publication_config->publish_retransmit_count > 0x07) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 420 if (publication_config->publish_retransmit_interval_steps > 0x1F) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 421 if (use_unicast_address && mesh_network_address_virtual(publication_config->publish_address_unicast)) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 422 return ERROR_CODE_SUCCESS; 423 } 424 425 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){ 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 if (!mesh_network_address_unicast(dest) || 430 mesh_validate_publication_model_config_parameters(publication_config, true) != ERROR_CODE_SUCCESS){ 431 return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 432 } 433 434 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_model_publication_set, 435 dest, 436 publication_config->publish_address_unicast, 437 (publication_config->credential_flag << 12) | publication_config->appkey_index, 438 publication_config->publish_ttl, 439 publication_config->publish_period, 440 (publication_config->publish_retransmit_interval_steps << 3) | publication_config->publish_retransmit_count, 441 model_id); 442 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 443 444 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) network_pdu, MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_STATUS); 445 return ERROR_CODE_SUCCESS; 446 447 } 448 449 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){ 450 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 451 if (status != ERROR_CODE_SUCCESS) return status; 452 453 if (!mesh_network_address_unicast(dest) || 454 mesh_validate_publication_model_config_parameters(publication_config, false) != ERROR_CODE_SUCCESS){ 455 return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 456 } 457 458 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_model_publication_virtual_address_set, 459 dest, 460 publication_config->publish_address_virtual, 461 (publication_config->credential_flag << 12) | publication_config->appkey_index, 462 publication_config->publish_ttl, 463 publication_config->publish_period, 464 (publication_config->publish_retransmit_interval_steps << 3) | publication_config->publish_retransmit_count, 465 model_id); 466 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 467 468 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); 469 return ERROR_CODE_SUCCESS; 470 } 471 472 473 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){ 474 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 475 if (status != ERROR_CODE_SUCCESS) return status; 476 477 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_model_subscription_add, dest, address, model_id); 478 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 479 480 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) network_pdu, MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_STATUS); 481 return ERROR_CODE_SUCCESS; 482 } 483 484 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){ 485 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 486 if (status != ERROR_CODE_SUCCESS) return status; 487 488 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_model_subscription_virtual_address_add, dest, address, model_id); 489 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 490 491 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); 492 return ERROR_CODE_SUCCESS; 493 } 494 495 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){ 496 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 497 if (status != ERROR_CODE_SUCCESS) return status; 498 499 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_model_subscription_delete, dest, address, model_id); 500 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 501 502 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) network_pdu, MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_STATUS); 503 return ERROR_CODE_SUCCESS; 504 } 505 506 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){ 507 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 508 if (status != ERROR_CODE_SUCCESS) return status; 509 510 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_model_subscription_virtual_address_delete, dest, address, 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_SUBSCRIPTION_STATUS); 514 return ERROR_CODE_SUCCESS; 515 } 516 517 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){ 518 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 519 if (status != ERROR_CODE_SUCCESS) return status; 520 521 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_model_subscription_overwrite, dest, address, model_id); 522 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 523 524 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) network_pdu, MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_STATUS); 525 return ERROR_CODE_SUCCESS; 526 } 527 528 uint8_t mesh_configuration_client_send_model_subscription_virtual_address_overwrite(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint8_t * address, uint32_t model_id){ 529 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 530 if (status != ERROR_CODE_SUCCESS) return status; 531 532 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_model_subscription_virtual_address_overwrite, dest, address, model_id); 533 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 534 535 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_STATUS); 536 return ERROR_CODE_SUCCESS; 537 } 538 539 uint8_t mesh_configuration_client_send_model_subscription_delete_all(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint16_t address, uint32_t model_id){ 540 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 541 if (status != ERROR_CODE_SUCCESS) return status; 542 543 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_model_subscription_delete_all, dest, address, model_id); 544 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 545 546 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) network_pdu, MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_STATUS); 547 return ERROR_CODE_SUCCESS; 548 } 549 550 uint8_t mesh_configuration_client_send_model_subscription_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint32_t model_id){ 551 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 552 if (status != ERROR_CODE_SUCCESS) return status; 553 554 mesh_network_pdu_t * network_pdu = NULL; 555 uint32_t ack_opcode = MESH_FOUNDATION_OPERATION_SIG_MODEL_SUBSCRIPTION_LIST; 556 557 if (mesh_model_is_bluetooth_sig(model_id)){ 558 network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_sig_model_subscription_get, dest, model_id); 559 } else { 560 network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_vendor_model_subscription_get, dest, model_id); 561 ack_opcode = MESH_FOUNDATION_OPERATION_VENDOR_MODEL_SUBSCRIPTION_LIST; 562 } 563 564 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 565 566 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) network_pdu, ack_opcode); 567 return ERROR_CODE_SUCCESS; 568 } 569 570 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){ 571 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 572 if (status != ERROR_CODE_SUCCESS) return status; 573 574 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_netkey_add, index, netkey); 575 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 576 577 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); 578 return ERROR_CODE_SUCCESS; 579 } 580 581 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){ 582 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 583 if (status != ERROR_CODE_SUCCESS) return status; 584 585 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_netkey_update, index, netkey); 586 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 587 588 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); 589 return ERROR_CODE_SUCCESS; 590 } 591 592 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){ 593 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 594 if (status != ERROR_CODE_SUCCESS) return status; 595 596 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_netkey_delete, index); 597 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 598 599 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); 600 return ERROR_CODE_SUCCESS; 601 } 602 603 uint8_t mesh_configuration_client_send_netkey_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index){ 604 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 605 if (status != ERROR_CODE_SUCCESS) return status; 606 607 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_netkey_get); 608 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 609 610 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_NETKEY_LIST); 611 return ERROR_CODE_SUCCESS; 612 } 613 614 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){ 615 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 616 if (status != ERROR_CODE_SUCCESS) return status; 617 618 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_appkey_add, netk_index << 12 | appk_index, appkey); 619 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 620 621 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_APPKEY_STATUS); 622 return ERROR_CODE_SUCCESS; 623 } 624 625 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){ 626 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 627 if (status != ERROR_CODE_SUCCESS) return status; 628 629 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_appkey_update, netk_index << 12 | appk_index, appkey); 630 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 631 632 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_APPKEY_STATUS); 633 return ERROR_CODE_SUCCESS; 634 } 635 636 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){ 637 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 638 if (status != ERROR_CODE_SUCCESS) return status; 639 640 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_appkey_delete, netk_index << 12 | appk_index); 641 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 642 643 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_APPKEY_STATUS); 644 return ERROR_CODE_SUCCESS; 645 } 646 647 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){ 648 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 649 if (status != ERROR_CODE_SUCCESS) return status; 650 651 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_appkey_get, netk_index); 652 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 653 654 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_APPKEY_LIST); 655 return ERROR_CODE_SUCCESS; 656 } 657 658 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){ 659 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 660 if (status != ERROR_CODE_SUCCESS) return status; 661 662 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_node_identity_get, netk_index); 663 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 664 665 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_NODE_IDENTITY_STATUS); 666 return ERROR_CODE_SUCCESS; 667 } 668 669 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){ 670 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 671 if (status != ERROR_CODE_SUCCESS) return status; 672 673 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_node_identity_set, netk_index, node_identity_state); 674 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 675 676 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_NODE_IDENTITY_STATUS); 677 return ERROR_CODE_SUCCESS; 678 } 679 680 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){ 681 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 682 if (status != ERROR_CODE_SUCCESS) return status; 683 684 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_model_app_bind, dest, appk_index, model_identifier); 685 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 686 687 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_MODEL_APP_STATUS); 688 return ERROR_CODE_SUCCESS; 689 } 690 691 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){ 692 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 693 if (status != ERROR_CODE_SUCCESS) return status; 694 695 mesh_network_pdu_t * transport_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_model_app_unbind, dest, appk_index, model_identifier); 696 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 697 698 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, MESH_FOUNDATION_OPERATION_MODEL_APP_STATUS); 699 return ERROR_CODE_SUCCESS; 700 } 701 702 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){ 703 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 704 if (status != ERROR_CODE_SUCCESS) return status; 705 706 mesh_network_pdu_t * transport_pdu; 707 uint32_t ack_opcode = MESH_FOUNDATION_OPERATION_SIG_MODEL_APP_LIST; 708 709 if (mesh_model_is_bluetooth_sig(model_identifier)){ 710 transport_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_sig_model_app_get, dest, model_identifier); 711 } else { 712 transport_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_vendor_model_app_get, dest, model_identifier); 713 ack_opcode = MESH_FOUNDATION_OPERATION_VENDOR_MODEL_APP_LIST; 714 } 715 716 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu, ack_opcode); 717 return ERROR_CODE_SUCCESS; 718 } 719 720 721 // Model Operations 722 static void mesh_configuration_client_composition_data_status_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 723 // Composition Data has variable of element descriptions, with two lists of model lists 724 // Pass raw data to application but provide convenient setters instead of parsing pdu here 725 726 // reuse part of the mesh_network_t / mesh_transport_t struct to create event without memcpy or allocation 727 uint8_t * data = mesh_pdu_data(pdu); 728 uint8_t * event = &data[-6]; 729 730 int pos = 0; 731 event[pos++] = HCI_EVENT_MESH_META; 732 // Composite Data might be larger than 251 bytes - in this case only lower 8 bit are stored here. packet size is correct 733 event[pos++] = (uint8_t) (6 + mesh_pdu_len(pdu)); 734 event[pos++] = MESH_SUBEVENT_CONFIGURATION_COMPOSITION_DATA; 735 // dest 736 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 737 pos += 2; 738 event[pos++] = ERROR_CODE_SUCCESS; 739 740 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); 741 mesh_access_message_processed(pdu); 742 } 743 744 uint8_t mesh_subevent_configuration_composition_data_get_page(const uint8_t * event){ 745 return event[6]; 746 } 747 748 uint16_t mesh_subevent_configuration_composition_data_get_cid(const uint8_t * event){ 749 return little_endian_read_16(event, 7); 750 } 751 752 uint16_t mesh_subevent_configuration_composition_data_get_pid(const uint8_t * event){ 753 return little_endian_read_16(event, 9); 754 } 755 756 uint16_t mesh_subevent_configuration_composition_data_get_vid(const uint8_t * event){ 757 return little_endian_read_16(event, 11); 758 } 759 760 uint16_t mesh_subevent_configuration_composition_data_get_crpl(const uint8_t * event){ 761 return little_endian_read_16(event, 13); 762 } 763 764 uint16_t mesh_subevent_configuration_composition_data_get_features(const uint8_t * event){ 765 return little_endian_read_16(event, 15); 766 } 767 768 769 static inline void mesh_configuration_client_handle_uint8_value(mesh_model_t *mesh_model, mesh_pdu_t * pdu, uint8_t subevent_type){ 770 mesh_access_parser_state_t parser; 771 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 772 773 uint8_t value = mesh_access_parser_get_u8(&parser); 774 775 uint8_t event[7]; 776 int pos = 0; 777 778 event[pos++] = HCI_EVENT_MESH_META; 779 event[pos++] = sizeof(event) - 2; 780 event[pos++] = subevent_type; 781 // dest 782 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 783 pos += 2; 784 event[pos++] = ERROR_CODE_SUCCESS; 785 event[pos++] = value; 786 787 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); 788 mesh_access_message_processed(pdu); 789 } 790 791 static void mesh_configuration_client_beacon_status_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 792 mesh_configuration_client_handle_uint8_value(mesh_model, pdu, MESH_SUBEVENT_CONFIGURATION_BEACON); 793 } 794 795 static void mesh_configuration_client_default_ttl_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 796 mesh_configuration_client_handle_uint8_value(mesh_model, pdu, MESH_SUBEVENT_CONFIGURATION_DEFAULT_TTL); 797 } 798 799 static void mesh_configuration_client_gatt_proxy_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 800 mesh_configuration_client_handle_uint8_value(mesh_model, pdu, MESH_SUBEVENT_CONFIGURATION_GATT_PROXY); 801 } 802 803 static void mesh_configuration_client_relay_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 804 mesh_access_parser_state_t parser; 805 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 806 807 uint8_t relay = mesh_access_parser_get_u8(&parser); 808 uint8_t retransmition = mesh_access_parser_get_u8(&parser); 809 810 uint8_t event[9]; 811 812 int pos = 0; 813 event[pos++] = HCI_EVENT_MESH_META; 814 event[pos++] = sizeof(event) - 2; 815 event[pos++] = MESH_SUBEVENT_CONFIGURATION_RELAY; 816 // dest 817 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 818 pos += 2; 819 event[pos++] = ERROR_CODE_SUCCESS; 820 event[pos++] = relay; 821 event[pos++] = (retransmition >> 5) + 1; 822 event[pos++] = ((retransmition & 0x07) + 1) * 10; 823 824 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); 825 mesh_access_message_processed(pdu); 826 } 827 828 static void mesh_configuration_client_model_publication_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 829 mesh_access_parser_state_t parser; 830 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 831 uint8_t status = mesh_access_parser_get_u8(&parser); 832 uint16_t publish_addres = mesh_access_parser_get_u16(&parser); 833 834 uint16_t value = mesh_access_parser_get_u16(&parser); 835 uint16_t appkey_index = value & 0xFFF; 836 uint8_t credential_flag = (value & 0x1000) >> 12; 837 838 uint8_t publish_ttl = mesh_access_parser_get_u8(&parser); 839 uint8_t publish_period = mesh_access_parser_get_u8(&parser); 840 841 uint8_t retransmit = mesh_access_parser_get_u8(&parser); 842 uint8_t publish_retransmit_count = retransmit & 0x111; 843 uint8_t publish_retransmit_interval_steps = retransmit >> 5; 844 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 845 846 uint8_t event[19]; 847 int pos = 0; 848 event[pos++] = HCI_EVENT_MESH_META; 849 event[pos++] = sizeof(event) - 2; 850 event[pos++] = MESH_SUBEVENT_CONFIGURATION_MODEL_PUBLICATION; 851 // dest 852 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 853 pos += 2; 854 event[pos++] = status; 855 856 little_endian_store_16(event, pos, publish_addres); 857 pos += 2; 858 859 little_endian_store_16(event, pos, appkey_index); 860 pos += 2; 861 862 event[pos++] = credential_flag; 863 event[pos++] = publish_ttl; 864 event[pos++] = publish_period; 865 event[pos++] = publish_retransmit_count; 866 event[pos++] = publish_retransmit_interval_steps; 867 868 little_endian_store_32(event, pos, model_identifier); 869 pos += 4; 870 871 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); 872 mesh_access_message_processed(pdu); 873 } 874 875 static void mesh_configuration_client_model_subscription_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 876 mesh_access_parser_state_t parser; 877 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 878 uint8_t status = mesh_access_parser_get_u8(&parser); 879 uint16_t address = mesh_access_parser_get_u16(&parser); 880 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 881 882 uint8_t event[12]; 883 int pos = 0; 884 event[pos++] = HCI_EVENT_MESH_META; 885 event[pos++] = sizeof(event) - 2; 886 event[pos++] = MESH_SUBEVENT_CONFIGURATION_MODEL_SUBSCRIPTION; 887 // dest 888 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 889 pos += 2; 890 event[pos++] = status; 891 892 little_endian_store_16(event, pos, address); 893 pos += 2; 894 895 little_endian_store_32(event, pos, model_identifier); 896 pos += 4; 897 898 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); 899 mesh_access_message_processed(pdu); 900 } 901 902 static void mesh_configuration_client_model_subscription_event(mesh_model_t *mesh_model, mesh_pdu_t * pdu, bool is_sig_model){ 903 mesh_access_parser_state_t parser; 904 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 905 uint8_t status = mesh_access_parser_get_u8(&parser); 906 uint16_t element_address = mesh_access_parser_get_u16(&parser); 907 uint32_t model_identifier; 908 909 if (element_address != mesh_pdu_src(pdu)){ 910 log_info("MESH_SUBEVENT_CONFIGURATION_MODEL_SUBSCRIPTION_LIST_ITEM event, element_address differs from mesh_pdu_src"); 911 } 912 913 if (is_sig_model == true) { 914 model_identifier = mesh_access_parser_get_sig_model_identifier(&parser); 915 } else { 916 model_identifier = mesh_access_parser_get_vendor_model_identifier(&parser); 917 } 918 uint8_t list_size = mesh_access_parser_available(&parser)/2; 919 920 uint8_t event[14]; 921 int pos = 0; 922 event[pos++] = HCI_EVENT_MESH_META; 923 event[pos++] = sizeof(event) - 2; 924 event[pos++] = MESH_SUBEVENT_CONFIGURATION_MODEL_SUBSCRIPTION_LIST_ITEM; 925 // dest 926 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 927 pos += 2; 928 event[pos++] = status; 929 930 little_endian_store_32(event, pos, model_identifier); 931 pos += 4; 932 933 event[pos++] = list_size; 934 uint8_t i; 935 for (i = 0; i < list_size; i++){ 936 event[pos++] = i; 937 little_endian_store_16(event, pos, mesh_access_parser_get_u16(&parser)); 938 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos + 2); 939 } 940 mesh_access_message_processed(pdu); 941 } 942 943 static void mesh_configuration_client_sig_model_subscription_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 944 mesh_configuration_client_model_subscription_event(mesh_model, pdu, true); 945 } 946 947 static void mesh_configuration_client_vendor_model_subscription_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 948 mesh_configuration_client_model_subscription_event(mesh_model, pdu, false); 949 } 950 951 static void mesh_configuration_client_netkey_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 952 mesh_access_parser_state_t parser; 953 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 954 uint8_t status = mesh_access_parser_get_u8(&parser); 955 956 uint8_t event[6]; 957 int pos = 0; 958 event[pos++] = HCI_EVENT_MESH_META; 959 event[pos++] = sizeof(event) - 2; 960 event[pos++] = MESH_SUBEVENT_CONFIGURATION_NETKEY_INDEX; 961 // dest 962 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 963 pos += 2; 964 event[pos++] = status; 965 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); 966 mesh_access_message_processed(pdu); 967 } 968 969 static void mesh_configuration_client_netkey_list_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 970 mesh_access_parser_state_t parser; 971 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 972 uint8_t status = 0; 973 uint8_t list_size = mesh_access_parser_available(&parser)/2; 974 975 uint8_t event[10]; 976 int pos = 0; 977 event[pos++] = HCI_EVENT_MESH_META; 978 event[pos++] = sizeof(event) - 2; 979 event[pos++] = MESH_SUBEVENT_CONFIGURATION_NETKEY_INDEX_LIST_ITEM; 980 // dest 981 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 982 pos += 2; 983 event[pos++] = status; 984 985 event[pos++] = list_size; 986 uint8_t i; 987 for (i = 0; i < list_size; i++){ 988 event[pos++] = i; 989 little_endian_store_16(event, pos, mesh_access_parser_get_u16(&parser)); 990 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos + 2); 991 } 992 mesh_access_message_processed(pdu); 993 } 994 995 static void mesh_configuration_client_appkey_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 996 mesh_access_parser_state_t parser; 997 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 998 uint8_t status = mesh_access_parser_get_u8(&parser); 999 uint32_t netappkey_index = mesh_access_parser_get_u24(&parser); 1000 uint16_t netkey_index = netappkey_index >> 12; 1001 uint16_t appkey_index = netappkey_index & 0xFFF; 1002 1003 uint8_t event[10]; 1004 int pos = 0; 1005 event[pos++] = HCI_EVENT_MESH_META; 1006 event[pos++] = sizeof(event) - 2; 1007 event[pos++] = MESH_SUBEVENT_CONFIGURATION_APPKEY_INDEX; 1008 // dest 1009 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 1010 pos += 2; 1011 event[pos++] = status; 1012 little_endian_store_16(event, pos, netkey_index); 1013 pos += 2; 1014 little_endian_store_16(event, pos, appkey_index); 1015 pos += 2; 1016 1017 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); 1018 mesh_access_message_processed(pdu); 1019 } 1020 1021 static void mesh_configuration_client_appkey_list_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 1022 mesh_access_parser_state_t parser; 1023 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1024 uint8_t status = 0; 1025 uint8_t list_size = mesh_access_parser_available(&parser)/2; 1026 1027 uint8_t event[12]; 1028 int pos = 0; 1029 event[pos++] = HCI_EVENT_MESH_META; 1030 event[pos++] = sizeof(event) - 2; 1031 event[pos++] = MESH_SUBEVENT_CONFIGURATION_APPKEY_INDEX_LIST_ITEM; 1032 // dest 1033 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 1034 pos += 2; 1035 event[pos++] = status; 1036 1037 event[pos++] = list_size; 1038 uint8_t i; 1039 for (i = 0; i < list_size; i++){ 1040 event[pos++] = i; 1041 uint32_t netappkey_index = mesh_access_parser_get_u24(&parser); 1042 little_endian_store_16(event, pos, netappkey_index >> 12); 1043 little_endian_store_16(event, pos + 2, netappkey_index & 0xFFF); 1044 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos + 4); 1045 } 1046 mesh_access_message_processed(pdu); 1047 } 1048 1049 static void mesh_configuration_client_node_identity_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 1050 mesh_access_parser_state_t parser; 1051 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1052 uint8_t status = mesh_access_parser_get_u8(&parser); 1053 uint16_t netkey_index = mesh_access_parser_get_u16(&parser); 1054 uint8_t identity_status = mesh_access_parser_get_u8(&parser); 1055 1056 uint8_t event[9]; 1057 int pos = 0; 1058 event[pos++] = HCI_EVENT_MESH_META; 1059 event[pos++] = sizeof(event) - 2; 1060 event[pos++] = MESH_SUBEVENT_CONFIGURATION_NODE_IDENTITY; 1061 // dest 1062 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 1063 pos += 2; 1064 event[pos++] = status; 1065 little_endian_store_16(event, pos, netkey_index); 1066 pos += 2; 1067 event[pos++] = identity_status; 1068 1069 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); 1070 mesh_access_message_processed(pdu); 1071 } 1072 1073 static void mesh_configuration_client_model_app_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 1074 mesh_access_parser_state_t parser; 1075 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1076 uint8_t status = mesh_access_parser_get_u8(&parser); 1077 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1078 uint16_t appkey_index = mesh_access_parser_get_u16(&parser); 1079 uint32_t model_id = 0; 1080 1081 if (element_address != mesh_pdu_src(pdu)){ 1082 log_info("MESH_SUBEVENT_CONFIGURATION_MODEL_APP event, element_address differs from mesh_pdu_src"); 1083 } 1084 1085 if (mesh_access_parser_available(&parser) == 4){ 1086 model_id = mesh_access_parser_get_u32(&parser); 1087 } else { 1088 model_id = mesh_access_parser_get_u16(&parser); 1089 } 1090 1091 uint8_t event[12]; 1092 int pos = 0; 1093 event[pos++] = HCI_EVENT_MESH_META; 1094 event[pos++] = sizeof(event) - 2; 1095 event[pos++] = MESH_SUBEVENT_CONFIGURATION_MODEL_APP; 1096 // dest 1097 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 1098 pos += 2; 1099 event[pos++] = status; 1100 1101 little_endian_store_16(event, pos, appkey_index); 1102 pos += 2; 1103 little_endian_store_32(event, pos, model_id); 1104 pos += 4; 1105 1106 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); 1107 mesh_access_message_processed(pdu); 1108 } 1109 1110 1111 static void mesh_configuration_client_model_app_list_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu, bool is_sig_model){ 1112 mesh_access_parser_state_t parser; 1113 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1114 1115 uint8_t status = mesh_access_parser_get_u8(&parser); 1116 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1117 uint32_t model_identifier; 1118 1119 if (element_address != mesh_pdu_src(pdu)){ 1120 log_info("MESH_SUBEVENT_CONFIGURATION_MODEL_APP_LIST_ITEM event, element_address differs from mesh_pdu_src"); 1121 } 1122 1123 if (is_sig_model == true) { 1124 model_identifier = mesh_access_parser_get_sig_model_identifier(&parser); 1125 } else { 1126 model_identifier = mesh_access_parser_get_vendor_model_identifier(&parser); 1127 } 1128 1129 uint8_t list_size = mesh_access_parser_available(&parser)/2; 1130 1131 uint8_t event[14]; 1132 int pos = 0; 1133 event[pos++] = HCI_EVENT_MESH_META; 1134 event[pos++] = sizeof(event) - 2; 1135 event[pos++] = MESH_SUBEVENT_CONFIGURATION_MODEL_APP_LIST_ITEM; 1136 // dest 1137 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 1138 pos += 2; 1139 event[pos++] = status; 1140 1141 little_endian_store_32(event, pos, model_identifier); 1142 pos += 4; 1143 1144 event[pos++] = list_size; 1145 uint8_t i; 1146 for (i = 0; i < list_size; i++){ 1147 event[pos++] = i; 1148 uint16_t appkey_index = mesh_access_parser_get_u16(&parser); 1149 little_endian_store_16(event, pos, appkey_index); 1150 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos + 2); 1151 } 1152 mesh_access_message_processed(pdu); 1153 } 1154 1155 static void mesh_configuration_client_sig_model_app_list_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 1156 mesh_configuration_client_model_app_list_handler(mesh_model, pdu, true); 1157 } 1158 1159 static void mesh_configuration_client_vendor_model_app_list_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 1160 mesh_configuration_client_model_app_list_handler(mesh_model, pdu, false); 1161 } 1162 1163 const static mesh_operation_t mesh_configuration_client_model_operations[] = { 1164 { MESH_FOUNDATION_OPERATION_BEACON_STATUS, 1, mesh_configuration_client_beacon_status_handler }, 1165 { MESH_FOUNDATION_OPERATION_COMPOSITION_DATA_STATUS, 10, mesh_configuration_client_composition_data_status_handler }, 1166 { MESH_FOUNDATION_OPERATION_DEFAULT_TTL_STATUS, 1, mesh_configuration_client_default_ttl_handler }, 1167 { MESH_FOUNDATION_OPERATION_GATT_PROXY_STATUS, 1, mesh_configuration_client_gatt_proxy_handler }, 1168 { MESH_FOUNDATION_OPERATION_RELAY_STATUS, 2, mesh_configuration_client_relay_handler }, 1169 { MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_STATUS, 12, mesh_configuration_client_model_publication_handler }, 1170 { MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_STATUS, 7, mesh_configuration_client_model_subscription_handler }, 1171 { MESH_FOUNDATION_OPERATION_SIG_MODEL_SUBSCRIPTION_LIST, 5, mesh_configuration_client_sig_model_subscription_handler}, 1172 { MESH_FOUNDATION_OPERATION_VENDOR_MODEL_SUBSCRIPTION_LIST, 7, mesh_configuration_client_vendor_model_subscription_handler}, 1173 { MESH_FOUNDATION_OPERATION_NETKEY_STATUS, 3, mesh_configuration_client_netkey_handler }, 1174 { MESH_FOUNDATION_OPERATION_NETKEY_LIST, 0, mesh_configuration_client_netkey_list_handler }, 1175 { MESH_FOUNDATION_OPERATION_APPKEY_STATUS, 4, mesh_configuration_client_appkey_handler }, 1176 { MESH_FOUNDATION_OPERATION_APPKEY_LIST, 3, mesh_configuration_client_appkey_list_handler }, 1177 { MESH_FOUNDATION_OPERATION_NODE_IDENTITY_STATUS, 4, mesh_configuration_client_node_identity_handler }, 1178 { MESH_FOUNDATION_OPERATION_MODEL_APP_STATUS, 7, mesh_configuration_client_model_app_handler }, 1179 { MESH_FOUNDATION_OPERATION_SIG_MODEL_APP_LIST, 5, mesh_configuration_client_sig_model_app_list_handler }, 1180 { MESH_FOUNDATION_OPERATION_VENDOR_MODEL_APP_LIST, 7, mesh_configuration_client_vendor_model_app_list_handler }, 1181 { 0, 0, NULL } 1182 }; 1183 1184 const mesh_operation_t * mesh_configuration_client_get_operations(void){ 1185 return mesh_configuration_client_model_operations; 1186 } 1187 1188 void mesh_configuration_client_register_packet_handler(mesh_model_t *configuration_client_model, btstack_packet_handler_t events_packet_handler){ 1189 btstack_assert(events_packet_handler != NULL); 1190 btstack_assert(configuration_client_model != NULL); 1191 1192 configuration_client_model->model_packet_handler = events_packet_handler; 1193 } 1194 1195