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