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