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 274 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){ 275 uint8_t ttl = mesh_foundation_default_ttl_get(); 276 mesh_upper_transport_setup_access_pdu_header(pdu, netkey_index, appkey_index, ttl, src, dest, 0); 277 mesh_access_send_acknowledged_pdu(pdu, mesh_access_acknowledged_message_retransmissions(), ack_opcode); 278 } 279 280 static uint8_t mesh_access_validate_envelop_params(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index){ 281 btstack_assert(mesh_model != NULL); 282 // TODO: validate other params 283 UNUSED(mesh_model); 284 UNUSED(dest); 285 UNUSED(netkey_index); 286 UNUSED(appkey_index); 287 288 return ERROR_CODE_SUCCESS; 289 } 290 291 uint8_t mesh_configuration_client_send_beacon_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index){ 292 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 293 if (status != ERROR_CODE_SUCCESS) return status; 294 295 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_beacon_get); 296 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 297 298 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); 299 return ERROR_CODE_SUCCESS; 300 } 301 302 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){ 303 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 304 if (status != ERROR_CODE_SUCCESS) return status; 305 306 if (beacon > 1) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 307 308 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_beacon_set, beacon); 309 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 310 311 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); 312 return ERROR_CODE_SUCCESS; 313 } 314 315 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){ 316 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 317 if (status != ERROR_CODE_SUCCESS) return status; 318 319 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_composition_data_get, page); 320 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 321 322 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); 323 return ERROR_CODE_SUCCESS; 324 } 325 326 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){ 327 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 328 if (status != ERROR_CODE_SUCCESS) return status; 329 330 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_default_ttl_get); 331 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 332 333 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); 334 return ERROR_CODE_SUCCESS; 335 } 336 337 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){ 338 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 339 if (status != ERROR_CODE_SUCCESS) return status; 340 341 if (ttl == 0x01 || ttl >= 0x80) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 342 343 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_default_ttl_set, ttl); 344 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 345 346 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); 347 return ERROR_CODE_SUCCESS; 348 } 349 350 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){ 351 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 352 if (status != ERROR_CODE_SUCCESS) return status; 353 354 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_gatt_proxy_get); 355 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 356 357 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); 358 return ERROR_CODE_SUCCESS; 359 } 360 361 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){ 362 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 363 if (status != ERROR_CODE_SUCCESS) return status; 364 365 if (gatt_proxy_state > 2) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 366 367 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_gatt_proxy_set, gatt_proxy_state); 368 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 369 370 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); 371 return ERROR_CODE_SUCCESS; 372 } 373 374 uint8_t mesh_configuration_client_send_relay_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index){ 375 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 376 if (status != ERROR_CODE_SUCCESS) return status; 377 378 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_relay_get); 379 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 380 381 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); 382 return ERROR_CODE_SUCCESS; 383 } 384 385 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){ 386 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 387 if (status != ERROR_CODE_SUCCESS) return status; 388 389 if (relay_retransmit_count > 0x07) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 390 if (relay_retransmit_interval_steps > 0x1F) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 391 392 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); 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_RELAY_SET); 396 return ERROR_CODE_SUCCESS; 397 } 398 399 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){ 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 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_model_publication_get, dest, model_id); 404 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 405 406 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); 407 return ERROR_CODE_SUCCESS; 408 } 409 410 static uint8_t mesh_validate_publication_model_config_parameters(mesh_publication_model_config_t * publication_config, bool use_unicast_address){ 411 if (publication_config->appkey_index > 0xFFF) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 412 if (publication_config->credential_flag > 1) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 413 if (publication_config->publish_retransmit_count > 0x07) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 414 if (publication_config->publish_retransmit_interval_steps > 0x1F) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 415 if (use_unicast_address && mesh_network_address_virtual(publication_config->publish_address_unicast)) return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 416 return ERROR_CODE_SUCCESS; 417 } 418 419 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){ 420 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 421 if (status != ERROR_CODE_SUCCESS) return status; 422 423 if (!mesh_network_address_unicast(dest) || 424 mesh_validate_publication_model_config_parameters(publication_config, true) != ERROR_CODE_SUCCESS){ 425 return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 426 } 427 428 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_model_publication_set, 429 dest, 430 publication_config->publish_address_unicast, 431 (publication_config->credential_flag << 12) | publication_config->appkey_index, 432 publication_config->publish_ttl, 433 publication_config->publish_period, 434 (publication_config->publish_retransmit_interval_steps << 3) | publication_config->publish_retransmit_count, 435 model_id); 436 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 437 438 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); 439 return ERROR_CODE_SUCCESS; 440 441 } 442 443 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){ 444 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 445 if (status != ERROR_CODE_SUCCESS) return status; 446 447 if (!mesh_network_address_unicast(dest) || 448 mesh_validate_publication_model_config_parameters(publication_config, false) != ERROR_CODE_SUCCESS){ 449 return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE; 450 } 451 452 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_model_publication_virtual_address_set, 453 dest, 454 publication_config->publish_address_virtual, 455 (publication_config->credential_flag << 12) | publication_config->appkey_index, 456 publication_config->publish_ttl, 457 publication_config->publish_period, 458 (publication_config->publish_retransmit_interval_steps << 3) | publication_config->publish_retransmit_count, 459 model_id); 460 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 461 462 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); 463 return ERROR_CODE_SUCCESS; 464 } 465 466 467 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){ 468 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 469 if (status != ERROR_CODE_SUCCESS) return status; 470 471 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_model_subscription_add, dest, address, model_id); 472 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 473 474 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); 475 return ERROR_CODE_SUCCESS; 476 } 477 478 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){ 479 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 480 if (status != ERROR_CODE_SUCCESS) return status; 481 482 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_model_subscription_virtual_address_add, dest, address, model_id); 483 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 484 485 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); 486 return ERROR_CODE_SUCCESS; 487 } 488 489 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){ 490 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 491 if (status != ERROR_CODE_SUCCESS) return status; 492 493 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_model_subscription_delete, dest, address, model_id); 494 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 495 496 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); 497 return ERROR_CODE_SUCCESS; 498 } 499 500 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){ 501 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 502 if (status != ERROR_CODE_SUCCESS) return status; 503 504 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_model_subscription_virtual_address_delete, dest, address, model_id); 505 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 506 507 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); 508 return ERROR_CODE_SUCCESS; 509 } 510 511 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){ 512 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 513 if (status != ERROR_CODE_SUCCESS) return status; 514 515 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_model_subscription_overwrite, dest, address, model_id); 516 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 517 518 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); 519 return ERROR_CODE_SUCCESS; 520 } 521 522 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){ 523 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 524 if (status != ERROR_CODE_SUCCESS) return status; 525 526 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_model_subscription_virtual_address_overwrite, dest, address, model_id); 527 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 528 529 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); 530 return ERROR_CODE_SUCCESS; 531 } 532 533 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){ 534 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 535 if (status != ERROR_CODE_SUCCESS) return status; 536 537 mesh_network_pdu_t * network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_model_subscription_delete_all, dest, address, model_id); 538 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 539 540 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); 541 return ERROR_CODE_SUCCESS; 542 } 543 544 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){ 545 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 546 if (status != ERROR_CODE_SUCCESS) return status; 547 548 mesh_network_pdu_t * network_pdu = NULL; 549 uint32_t ack_opcode = MESH_FOUNDATION_OPERATION_SIG_MODEL_SUBSCRIPTION_LIST; 550 551 if (mesh_model_is_bluetooth_sig(model_id)){ 552 network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_sig_model_subscription_get, dest, model_id); 553 } else { 554 network_pdu = mesh_access_setup_unsegmented_message(&mesh_configuration_client_vendor_model_subscription_get, dest, model_id); 555 ack_opcode = MESH_FOUNDATION_OPERATION_VENDOR_MODEL_SUBSCRIPTION_LIST; 556 } 557 558 if (!network_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 559 560 mesh_configuration_client_send_acknowledged(mesh_access_get_element_address(mesh_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) network_pdu, ack_opcode); 561 return ERROR_CODE_SUCCESS; 562 } 563 564 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){ 565 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 566 if (status != ERROR_CODE_SUCCESS) return status; 567 568 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_netkey_add, index, netkey); 569 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 570 571 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); 572 return ERROR_CODE_SUCCESS; 573 } 574 575 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){ 576 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 577 if (status != ERROR_CODE_SUCCESS) return status; 578 579 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_netkey_update, index, netkey); 580 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 581 582 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); 583 return ERROR_CODE_SUCCESS; 584 } 585 586 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){ 587 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 588 if (status != ERROR_CODE_SUCCESS) return status; 589 590 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_netkey_delete, index); 591 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 592 593 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); 594 return ERROR_CODE_SUCCESS; 595 } 596 597 uint8_t mesh_configuration_client_send_netkey_get(mesh_model_t * mesh_model, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index){ 598 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 599 if (status != ERROR_CODE_SUCCESS) return status; 600 601 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_netkey_get); 602 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 603 604 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); 605 return ERROR_CODE_SUCCESS; 606 } 607 608 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){ 609 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 610 if (status != ERROR_CODE_SUCCESS) return status; 611 612 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_appkey_add, netk_index << 12 | appk_index, appkey); 613 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 614 615 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); 616 return ERROR_CODE_SUCCESS; 617 } 618 619 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){ 620 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 621 if (status != ERROR_CODE_SUCCESS) return status; 622 623 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_appkey_update, netk_index << 12 | appk_index, appkey); 624 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 625 626 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); 627 return ERROR_CODE_SUCCESS; 628 } 629 630 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){ 631 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 632 if (status != ERROR_CODE_SUCCESS) return status; 633 634 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_appkey_delete, netk_index << 12 | appk_index); 635 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 636 637 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); 638 return ERROR_CODE_SUCCESS; 639 } 640 641 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){ 642 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 643 if (status != ERROR_CODE_SUCCESS) return status; 644 645 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_appkey_get, netk_index); 646 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 647 648 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); 649 return ERROR_CODE_SUCCESS; 650 } 651 652 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){ 653 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 654 if (status != ERROR_CODE_SUCCESS) return status; 655 656 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_node_identity_get, netk_index); 657 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 658 659 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); 660 return ERROR_CODE_SUCCESS; 661 } 662 663 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){ 664 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 665 if (status != ERROR_CODE_SUCCESS) return status; 666 667 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_node_identity_set, netk_index, node_identity_state); 668 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 669 670 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); 671 return ERROR_CODE_SUCCESS; 672 } 673 674 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){ 675 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 676 if (status != ERROR_CODE_SUCCESS) return status; 677 678 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_model_app_bind, dest, appk_index, model_identifier); 679 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 680 681 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); 682 return ERROR_CODE_SUCCESS; 683 } 684 685 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){ 686 uint8_t status = mesh_access_validate_envelop_params(mesh_model, dest, netkey_index, appkey_index); 687 if (status != ERROR_CODE_SUCCESS) return status; 688 689 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_configuration_client_model_app_unbind, dest, appk_index, model_identifier); 690 if (!transport_pdu) return BTSTACK_MEMORY_ALLOC_FAILED; 691 692 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); 693 return ERROR_CODE_SUCCESS; 694 } 695 696 697 // Model Operations 698 static void mesh_configuration_client_composition_data_status_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 699 // Composition Data has variable of element descriptions, with two lists of model lists 700 // Pass raw data to application but provide convenient setters instead of parsing pdu here 701 702 // reuse part of the mesh_network_t / mesh_transport_t struct to create event without memcpy or allocation 703 uint8_t * data = mesh_pdu_data(pdu); 704 uint8_t * event = &data[-6]; 705 706 int pos = 0; 707 event[pos++] = HCI_EVENT_MESH_META; 708 // Composite Data might be larger than 251 bytes - in this case only lower 8 bit are stored here. packet size is correct 709 event[pos++] = (uint8_t) (6 + mesh_pdu_len(pdu)); 710 event[pos++] = MESH_SUBEVENT_CONFIGURATION_COMPOSITION_DATA; 711 // dest 712 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 713 pos += 2; 714 event[pos++] = ERROR_CODE_SUCCESS; 715 716 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); 717 mesh_access_message_processed(pdu); 718 } 719 720 uint8_t mesh_subevent_configuration_composition_data_get_page(const uint8_t * event){ 721 return event[6]; 722 } 723 724 uint16_t mesh_subevent_configuration_composition_data_get_cid(const uint8_t * event){ 725 return little_endian_read_16(event, 7); 726 } 727 728 uint16_t mesh_subevent_configuration_composition_data_get_pid(const uint8_t * event){ 729 return little_endian_read_16(event, 9); 730 } 731 732 uint16_t mesh_subevent_configuration_composition_data_get_vid(const uint8_t * event){ 733 return little_endian_read_16(event, 11); 734 } 735 736 uint16_t mesh_subevent_configuration_composition_data_get_crpl(const uint8_t * event){ 737 return little_endian_read_16(event, 13); 738 } 739 740 uint16_t mesh_subevent_configuration_composition_data_get_features(const uint8_t * event){ 741 return little_endian_read_16(event, 15); 742 } 743 744 745 static inline void mesh_configuration_client_handle_uint8_value(mesh_model_t *mesh_model, mesh_pdu_t * pdu, uint8_t subevent_type){ 746 mesh_access_parser_state_t parser; 747 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 748 749 uint8_t value = mesh_access_parser_get_u8(&parser); 750 751 uint8_t event[7]; 752 int pos = 0; 753 754 event[pos++] = HCI_EVENT_MESH_META; 755 event[pos++] = sizeof(event) - 2; 756 event[pos++] = subevent_type; 757 // dest 758 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 759 pos += 2; 760 event[pos++] = ERROR_CODE_SUCCESS; 761 event[pos++] = value; 762 763 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); 764 mesh_access_message_processed(pdu); 765 } 766 767 static void mesh_configuration_client_beacon_status_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 768 mesh_configuration_client_handle_uint8_value(mesh_model, pdu, MESH_SUBEVENT_CONFIGURATION_BEACON); 769 } 770 771 static void mesh_configuration_client_default_ttl_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 772 mesh_configuration_client_handle_uint8_value(mesh_model, pdu, MESH_SUBEVENT_CONFIGURATION_DEFAULT_TTL); 773 } 774 775 static void mesh_configuration_client_gatt_proxy_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 776 mesh_configuration_client_handle_uint8_value(mesh_model, pdu, MESH_SUBEVENT_CONFIGURATION_GATT_PROXY); 777 } 778 779 static void mesh_configuration_client_relay_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 780 mesh_access_parser_state_t parser; 781 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 782 783 uint8_t relay = mesh_access_parser_get_u8(&parser); 784 uint8_t retransmition = mesh_access_parser_get_u8(&parser); 785 786 uint8_t event[9]; 787 788 int pos = 0; 789 event[pos++] = HCI_EVENT_MESH_META; 790 event[pos++] = sizeof(event) - 2; 791 event[pos++] = MESH_SUBEVENT_CONFIGURATION_RELAY; 792 // dest 793 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 794 pos += 2; 795 event[pos++] = ERROR_CODE_SUCCESS; 796 event[pos++] = relay; 797 event[pos++] = (retransmition >> 5) + 1; 798 event[pos++] = ((retransmition & 0x07) + 1) * 10; 799 800 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); 801 mesh_access_message_processed(pdu); 802 } 803 804 static void mesh_configuration_client_model_publication_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 805 mesh_access_parser_state_t parser; 806 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 807 uint8_t status = mesh_access_parser_get_u8(&parser); 808 uint16_t publish_addres = mesh_access_parser_get_u16(&parser); 809 810 uint16_t value = mesh_access_parser_get_u16(&parser); 811 uint16_t appkey_index = value & 0xFFF; 812 uint8_t credential_flag = (value & 0x1000) >> 12; 813 814 uint8_t publish_ttl = mesh_access_parser_get_u8(&parser); 815 uint8_t publish_period = mesh_access_parser_get_u8(&parser); 816 817 uint8_t retransmit = mesh_access_parser_get_u8(&parser); 818 uint8_t publish_retransmit_count = retransmit & 0x111; 819 uint8_t publish_retransmit_interval_steps = retransmit >> 5; 820 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 821 822 uint8_t event[19]; 823 int pos = 0; 824 event[pos++] = HCI_EVENT_MESH_META; 825 event[pos++] = sizeof(event) - 2; 826 event[pos++] = MESH_SUBEVENT_CONFIGURATION_MODEL_PUBLICATION; 827 // dest 828 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 829 pos += 2; 830 event[pos++] = status; 831 832 little_endian_store_16(event, pos, publish_addres); 833 pos += 2; 834 835 little_endian_store_16(event, pos, appkey_index); 836 pos += 2; 837 838 event[pos++] = credential_flag; 839 event[pos++] = publish_ttl; 840 event[pos++] = publish_period; 841 event[pos++] = publish_retransmit_count; 842 event[pos++] = publish_retransmit_interval_steps; 843 844 little_endian_store_32(event, pos, model_identifier); 845 pos += 4; 846 847 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); 848 mesh_access_message_processed(pdu); 849 } 850 851 static void mesh_configuration_client_model_subscription_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 852 mesh_access_parser_state_t parser; 853 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 854 uint8_t status = mesh_access_parser_get_u8(&parser); 855 uint16_t address = mesh_access_parser_get_u16(&parser); 856 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 857 858 uint8_t event[12]; 859 int pos = 0; 860 event[pos++] = HCI_EVENT_MESH_META; 861 event[pos++] = sizeof(event) - 2; 862 event[pos++] = MESH_SUBEVENT_CONFIGURATION_MODEL_SUBSCRIPTION; 863 // dest 864 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 865 pos += 2; 866 event[pos++] = status; 867 868 little_endian_store_16(event, pos, address); 869 pos += 2; 870 871 little_endian_store_32(event, pos, model_identifier); 872 pos += 4; 873 874 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); 875 mesh_access_message_processed(pdu); 876 } 877 878 static void mesh_configuration_client_model_subscription_event(mesh_model_t *mesh_model, mesh_pdu_t * pdu, uint8_t subevent_type){ 879 mesh_access_parser_state_t parser; 880 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 881 uint8_t status = mesh_access_parser_get_u8(&parser); 882 uint16_t address = mesh_access_parser_get_u16(&parser); 883 uint32_t model_identifier; 884 885 if (subevent_type == MESH_SUBEVENT_CONFIGURATION_SIG_MODEL_SUBSCRIPTION_LIST_ITEM) { 886 model_identifier = mesh_access_parser_get_sig_model_identifier(&parser); 887 } else { 888 model_identifier = mesh_access_parser_get_vendor_model_identifier(&parser); 889 } 890 uint8_t list_size = mesh_access_parser_available(&parser)/2; 891 892 uint8_t event[12]; 893 int pos = 0; 894 event[pos++] = HCI_EVENT_MESH_META; 895 event[pos++] = sizeof(event) - 2; 896 event[pos++] = subevent_type; 897 // dest 898 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 899 pos += 2; 900 event[pos++] = status; 901 902 little_endian_store_16(event, pos, address); 903 pos += 2; 904 905 event[pos++] = list_size; 906 uint8_t i; 907 for (i = 0; i < list_size; i++){ 908 event[pos++] = i; 909 little_endian_store_16(event, pos, mesh_access_parser_get_u16(&parser)); 910 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos + 2); 911 } 912 mesh_access_message_processed(pdu); 913 } 914 915 static void mesh_configuration_client_sig_model_subscription_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 916 mesh_configuration_client_model_subscription_event(mesh_model, pdu, MESH_SUBEVENT_CONFIGURATION_SIG_MODEL_SUBSCRIPTION_LIST_ITEM); 917 } 918 919 static void mesh_configuration_client_vendor_model_subscription_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 920 mesh_configuration_client_model_subscription_event(mesh_model, pdu, MESH_SUBEVENT_CONFIGURATION_VENDOR_MODEL_SUBSCRIPTION_LIST_ITEM); 921 } 922 923 static void mesh_configuration_client_netkey_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 924 mesh_access_parser_state_t parser; 925 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 926 uint8_t status = mesh_access_parser_get_u8(&parser); 927 928 uint8_t event[6]; 929 int pos = 0; 930 event[pos++] = HCI_EVENT_MESH_META; 931 event[pos++] = sizeof(event) - 2; 932 event[pos++] = MESH_SUBEVENT_CONFIGURATION_NETKEY_INDEX; 933 // dest 934 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 935 pos += 2; 936 event[pos++] = status; 937 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); 938 mesh_access_message_processed(pdu); 939 } 940 941 static void mesh_configuration_client_netkey_list_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 942 mesh_access_parser_state_t parser; 943 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 944 uint8_t status = 0; 945 uint8_t list_size = mesh_access_parser_available(&parser)/2; 946 947 uint8_t event[10]; 948 int pos = 0; 949 event[pos++] = HCI_EVENT_MESH_META; 950 event[pos++] = sizeof(event) - 2; 951 event[pos++] = MESH_SUBEVENT_CONFIGURATION_NETKEY_INDEX_LIST_ITEM; 952 // dest 953 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 954 pos += 2; 955 event[pos++] = status; 956 957 event[pos++] = list_size; 958 uint8_t i; 959 for (i = 0; i < list_size; i++){ 960 event[pos++] = i; 961 little_endian_store_16(event, pos, mesh_access_parser_get_u16(&parser)); 962 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos + 2); 963 } 964 mesh_access_message_processed(pdu); 965 } 966 967 static void mesh_configuration_client_appkey_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 968 mesh_access_parser_state_t parser; 969 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 970 uint8_t status = mesh_access_parser_get_u8(&parser); 971 uint32_t netappkey_index = mesh_access_parser_get_u24(&parser); 972 uint16_t netkey_index = netappkey_index >> 12; 973 uint16_t appkey_index = netappkey_index & 0xFFF; 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_APPKEY_INDEX; 980 // dest 981 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 982 pos += 2; 983 event[pos++] = status; 984 little_endian_store_16(event, pos, netkey_index); 985 pos += 2; 986 little_endian_store_16(event, pos, appkey_index); 987 pos += 2; 988 989 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); 990 mesh_access_message_processed(pdu); 991 } 992 993 static void mesh_configuration_client_appkey_list_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 994 mesh_access_parser_state_t parser; 995 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 996 uint8_t status = 0; 997 uint8_t list_size = mesh_access_parser_available(&parser)/2; 998 999 uint8_t event[12]; 1000 int pos = 0; 1001 event[pos++] = HCI_EVENT_MESH_META; 1002 event[pos++] = sizeof(event) - 2; 1003 event[pos++] = MESH_SUBEVENT_CONFIGURATION_APPKEY_INDEX_LIST_ITEM; 1004 // dest 1005 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 1006 pos += 2; 1007 event[pos++] = status; 1008 1009 event[pos++] = list_size; 1010 uint8_t i; 1011 for (i = 0; i < list_size; i++){ 1012 event[pos++] = i; 1013 uint32_t netappkey_index = mesh_access_parser_get_u24(&parser); 1014 little_endian_store_16(event, pos, netappkey_index >> 12); 1015 little_endian_store_16(event, pos + 2, netappkey_index & 0xFFF); 1016 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos + 4); 1017 } 1018 mesh_access_message_processed(pdu); 1019 } 1020 1021 static void mesh_configuration_client_node_identity_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 = mesh_access_parser_get_u8(&parser); 1025 uint16_t netkey_index = mesh_access_parser_get_u16(&parser); 1026 uint8_t identity_status = mesh_access_parser_get_u8(&parser); 1027 1028 uint8_t event[9]; 1029 int pos = 0; 1030 event[pos++] = HCI_EVENT_MESH_META; 1031 event[pos++] = sizeof(event) - 2; 1032 event[pos++] = MESH_SUBEVENT_CONFIGURATION_NODE_IDENTITY; 1033 // dest 1034 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 1035 pos += 2; 1036 event[pos++] = status; 1037 little_endian_store_16(event, pos, netkey_index); 1038 pos += 2; 1039 event[pos++] = identity_status; 1040 1041 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); 1042 mesh_access_message_processed(pdu); 1043 } 1044 1045 static void mesh_configuration_client_model_app_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 1046 mesh_access_parser_state_t parser; 1047 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1048 uint8_t status = mesh_access_parser_get_u8(&parser); 1049 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1050 uint16_t appkey_index = mesh_access_parser_get_u16(&parser); 1051 uint32_t model_id = 0; 1052 1053 if (mesh_access_parser_available(&parser) == 4){ 1054 model_id = mesh_access_parser_get_u32(&parser); 1055 } else { 1056 model_id = mesh_access_parser_get_u16(&parser); 1057 } 1058 1059 uint8_t event[9]; 1060 int pos = 0; 1061 event[pos++] = HCI_EVENT_MESH_META; 1062 event[pos++] = sizeof(event) - 2; 1063 event[pos++] = MESH_SUBEVENT_CONFIGURATION_MODEL_APP; 1064 // dest 1065 little_endian_store_16(event, pos, mesh_pdu_src(pdu)); 1066 pos += 2; 1067 event[pos++] = status; 1068 1069 little_endian_store_16(event, pos, element_address); 1070 pos += 2; 1071 little_endian_store_16(event, pos, appkey_index); 1072 pos += 2; 1073 little_endian_store_32(event, pos, model_id); 1074 pos += 4; 1075 1076 (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); 1077 mesh_access_message_processed(pdu); 1078 } 1079 1080 1081 const static mesh_operation_t mesh_configuration_client_model_operations[] = { 1082 { MESH_FOUNDATION_OPERATION_BEACON_STATUS, 1, mesh_configuration_client_beacon_status_handler }, 1083 { MESH_FOUNDATION_OPERATION_COMPOSITION_DATA_STATUS, 10, mesh_configuration_client_composition_data_status_handler }, 1084 { MESH_FOUNDATION_OPERATION_DEFAULT_TTL_STATUS, 1, mesh_configuration_client_default_ttl_handler }, 1085 { MESH_FOUNDATION_OPERATION_GATT_PROXY_STATUS, 1, mesh_configuration_client_gatt_proxy_handler }, 1086 { MESH_FOUNDATION_OPERATION_RELAY_STATUS, 2, mesh_configuration_client_relay_handler }, 1087 { MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_STATUS, 12, mesh_configuration_client_model_publication_handler }, 1088 { MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_STATUS, 7, mesh_configuration_client_model_subscription_handler }, 1089 { MESH_FOUNDATION_OPERATION_SIG_MODEL_SUBSCRIPTION_LIST, 5, mesh_configuration_client_sig_model_subscription_handler}, 1090 { MESH_FOUNDATION_OPERATION_VENDOR_MODEL_SUBSCRIPTION_LIST, 7, mesh_configuration_client_vendor_model_subscription_handler}, 1091 { MESH_FOUNDATION_OPERATION_NETKEY_STATUS, 3, mesh_configuration_client_netkey_handler }, 1092 { MESH_FOUNDATION_OPERATION_NETKEY_LIST, 0, mesh_configuration_client_netkey_list_handler }, 1093 { MESH_FOUNDATION_OPERATION_APPKEY_STATUS, 4, mesh_configuration_client_appkey_handler }, 1094 { MESH_FOUNDATION_OPERATION_APPKEY_LIST, 3, mesh_configuration_client_appkey_list_handler }, 1095 { MESH_FOUNDATION_OPERATION_NODE_IDENTITY_STATUS, 4, mesh_configuration_client_node_identity_handler }, 1096 { MESH_FOUNDATION_OPERATION_MODEL_APP_STATUS, 7, mesh_configuration_client_model_app_handler }, 1097 { 0, 0, NULL } 1098 }; 1099 1100 const mesh_operation_t * mesh_configuration_client_get_operations(void){ 1101 return mesh_configuration_client_model_operations; 1102 } 1103 1104 void mesh_configuration_client_register_packet_handler(mesh_model_t *configuration_client_model, btstack_packet_handler_t events_packet_handler){ 1105 btstack_assert(events_packet_handler != NULL); 1106 btstack_assert(configuration_client_model != NULL); 1107 1108 configuration_client_model->model_packet_handler = events_packet_handler; 1109 } 1110 1111