esp_ble_mesh_networking_api.c
1 // Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <stdint.h> 16 #include <string.h> 17 18 #include "esp_err.h" 19 20 #include "btc_ble_mesh_prov.h" 21 #include "esp_ble_mesh_networking_api.h" 22 23 #define ESP_BLE_MESH_TX_SDU_MAX ((CONFIG_BLE_MESH_ADV_BUF_COUNT - 3) * 12) 24 25 static esp_err_t ble_mesh_model_send_msg(esp_ble_mesh_model_t *model, 26 esp_ble_mesh_msg_ctx_t *ctx, 27 uint32_t opcode, 28 btc_ble_mesh_model_act_t act, 29 uint16_t length, uint8_t *data, 30 int32_t msg_timeout, bool need_rsp, 31 esp_ble_mesh_dev_role_t device_role) 32 { 33 btc_ble_mesh_model_args_t arg = {0}; 34 uint8_t op_len = 0, mic_len = 0; 35 uint8_t *msg_data = NULL; 36 btc_msg_t msg = {0}; 37 esp_err_t status = ESP_OK; 38 39 ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); 40 41 if (ctx && ctx->addr == ESP_BLE_MESH_ADDR_UNASSIGNED) { 42 BT_ERR("Invalid destination address 0x0000"); 43 return ESP_ERR_INVALID_ARG; 44 } 45 46 if (device_role > ROLE_FAST_PROV) { 47 BT_ERR("Invalid device role 0x%02x", device_role); 48 return ESP_ERR_INVALID_ARG; 49 } 50 51 /* When data is NULL, it is mandatory to set length to 0 to prevent users from misinterpreting parameters. */ 52 if (data == NULL) { 53 length = 0; 54 } 55 56 if (opcode < 0x100) { 57 op_len = 1; 58 } else if (opcode < 0x10000) { 59 op_len = 2; 60 } else { 61 op_len = 3; 62 } 63 64 if (act == BTC_BLE_MESH_ACT_MODEL_PUBLISH) { 65 if (op_len + length > model->pub->msg->size) { 66 BT_ERR("Too small publication msg size %d", model->pub->msg->size); 67 return ESP_ERR_INVALID_ARG; 68 } 69 } 70 71 if (act == BTC_BLE_MESH_ACT_MODEL_PUBLISH) { 72 mic_len = ESP_BLE_MESH_MIC_SHORT; 73 } else { 74 mic_len = ctx->send_rel ? ESP_BLE_MESH_MIC_LONG : ESP_BLE_MESH_MIC_SHORT; 75 } 76 77 if (op_len + length + mic_len > MIN(ESP_BLE_MESH_SDU_MAX_LEN, ESP_BLE_MESH_TX_SDU_MAX)) { 78 BT_ERR("Too large data length %d", length); 79 return ESP_ERR_INVALID_ARG; 80 } 81 82 if (act == BTC_BLE_MESH_ACT_MODEL_PUBLISH) { 83 bt_mesh_model_msg_init(model->pub->msg, opcode); 84 net_buf_simple_add_mem(model->pub->msg, data, length); 85 } else { 86 msg_data = (uint8_t *)bt_mesh_malloc(op_len + length); 87 if (msg_data == NULL) { 88 return ESP_ERR_NO_MEM; 89 } 90 esp_ble_mesh_model_msg_opcode_init(msg_data, opcode); 91 memcpy(msg_data + op_len, data, length); 92 } 93 94 msg.sig = BTC_SIG_API_CALL; 95 msg.pid = BTC_PID_MODEL; 96 msg.act = act; 97 98 if (act == BTC_BLE_MESH_ACT_MODEL_PUBLISH) { 99 arg.model_publish.model = model; 100 arg.model_publish.device_role = device_role; 101 } else { 102 arg.model_send.model = model; 103 arg.model_send.ctx = ctx; 104 arg.model_send.need_rsp = need_rsp; 105 arg.model_send.opcode = opcode; 106 arg.model_send.length = op_len + length; 107 arg.model_send.data = msg_data; 108 arg.model_send.device_role = device_role; 109 arg.model_send.msg_timeout = msg_timeout; 110 } 111 112 status = (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_model_args_t), btc_ble_mesh_model_arg_deep_copy) 113 == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); 114 115 bt_mesh_free(msg_data); 116 117 return status; 118 } 119 120 esp_err_t esp_ble_mesh_register_custom_model_callback(esp_ble_mesh_model_cb_t callback) 121 { 122 ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); 123 124 return (btc_profile_cb_set(BTC_PID_MODEL, callback) == 0 ? ESP_OK : ESP_FAIL); 125 } 126 127 esp_err_t esp_ble_mesh_model_msg_opcode_init(uint8_t *data, uint32_t opcode) 128 { 129 uint16_t val = 0; 130 131 if (data == NULL) { 132 return ESP_ERR_INVALID_ARG; 133 } 134 135 if (opcode < 0x100) { 136 /* 1-byte OpCode */ 137 data[0] = opcode & 0xff; 138 return ESP_OK; 139 } 140 141 if (opcode < 0x10000) { 142 /* 2-byte OpCode, big endian */ 143 val = sys_cpu_to_be16 (opcode); 144 memcpy(data, &val, 2); 145 return ESP_OK; 146 } 147 148 /* 3-byte OpCode, note that little endian for the least 2 bytes(Company ID) of opcode */ 149 data[0] = (opcode >> 16) & 0xff; 150 val = sys_cpu_to_le16(opcode & 0xffff); 151 memcpy(&data[1], &val, 2); 152 153 return ESP_OK; 154 } 155 156 esp_err_t esp_ble_mesh_client_model_init(esp_ble_mesh_model_t *model) 157 { 158 if (model == NULL) { 159 return ESP_ERR_INVALID_ARG; 160 } 161 162 ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); 163 164 return btc_ble_mesh_client_model_init(model); 165 } 166 167 #if CONFIG_BLE_MESH_DEINIT 168 esp_err_t esp_ble_mesh_client_model_deinit(esp_ble_mesh_model_t *model) 169 { 170 if (model == NULL) { 171 return ESP_ERR_INVALID_ARG; 172 } 173 174 ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); 175 176 return btc_ble_mesh_client_model_deinit(model); 177 } 178 #endif /* CONFIG_BLE_MESH_DEINIT */ 179 180 esp_err_t esp_ble_mesh_server_model_send_msg(esp_ble_mesh_model_t *model, 181 esp_ble_mesh_msg_ctx_t *ctx, 182 uint32_t opcode, 183 uint16_t length, uint8_t *data) 184 { 185 if (model == NULL || ctx == NULL || 186 ctx->net_idx == ESP_BLE_MESH_KEY_UNUSED || 187 ctx->app_idx == ESP_BLE_MESH_KEY_UNUSED) { 188 return ESP_ERR_INVALID_ARG; 189 } 190 191 return ble_mesh_model_send_msg(model, ctx, opcode, BTC_BLE_MESH_ACT_SERVER_MODEL_SEND, 192 length, data, 0, false, ROLE_NODE); 193 } 194 195 esp_err_t esp_ble_mesh_client_model_send_msg(esp_ble_mesh_model_t *model, 196 esp_ble_mesh_msg_ctx_t *ctx, 197 uint32_t opcode, 198 uint16_t length, uint8_t *data, 199 int32_t msg_timeout, bool need_rsp, 200 esp_ble_mesh_dev_role_t device_role) 201 { 202 if (model == NULL || ctx == NULL || 203 ctx->net_idx == ESP_BLE_MESH_KEY_UNUSED || 204 ctx->app_idx == ESP_BLE_MESH_KEY_UNUSED) { 205 return ESP_ERR_INVALID_ARG; 206 } 207 208 return ble_mesh_model_send_msg(model, ctx, opcode, BTC_BLE_MESH_ACT_CLIENT_MODEL_SEND, 209 length, data, msg_timeout, need_rsp, device_role); 210 } 211 212 esp_err_t esp_ble_mesh_model_publish(esp_ble_mesh_model_t *model, uint32_t opcode, 213 uint16_t length, uint8_t *data, 214 esp_ble_mesh_dev_role_t device_role) 215 { 216 if (model == NULL || model->pub == NULL || model->pub->msg == NULL || 217 model->pub->publish_addr == ESP_BLE_MESH_ADDR_UNASSIGNED) { 218 return ESP_ERR_INVALID_ARG; 219 } 220 221 return ble_mesh_model_send_msg(model, NULL, opcode, BTC_BLE_MESH_ACT_MODEL_PUBLISH, 222 length, data, 0, false, device_role); 223 } 224 225 #if CONFIG_BLE_MESH_SERVER_MODEL 226 esp_err_t esp_ble_mesh_server_model_update_state(esp_ble_mesh_model_t *model, 227 esp_ble_mesh_server_state_type_t type, 228 esp_ble_mesh_server_state_value_t *value) 229 { 230 btc_ble_mesh_model_args_t arg = {0}; 231 btc_msg_t msg = {0}; 232 233 if (!model || !value || type >= ESP_BLE_MESH_SERVER_MODEL_STATE_MAX) { 234 return ESP_ERR_INVALID_ARG; 235 } 236 237 ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); 238 239 arg.model_update_state.model = model; 240 arg.model_update_state.type = type; 241 arg.model_update_state.value = value; 242 243 msg.sig = BTC_SIG_API_CALL; 244 msg.pid = BTC_PID_MODEL; 245 msg.act = BTC_BLE_MESH_ACT_SERVER_MODEL_UPDATE_STATE; 246 247 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_model_args_t), btc_ble_mesh_model_arg_deep_copy) 248 == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); 249 } 250 #endif /* CONFIG_BLE_MESH_SERVER_MODEL */ 251 252 esp_err_t esp_ble_mesh_node_local_reset(void) 253 { 254 btc_msg_t msg = {0}; 255 256 ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); 257 258 msg.sig = BTC_SIG_API_CALL; 259 msg.pid = BTC_PID_PROV; 260 msg.act = BTC_BLE_MESH_ACT_NODE_RESET; 261 262 return (btc_transfer_context(&msg, NULL, 0, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); 263 } 264 265 #if (CONFIG_BLE_MESH_PROVISIONER) 266 267 esp_err_t esp_ble_mesh_provisioner_set_node_name(uint16_t index, const char *name) 268 { 269 btc_ble_mesh_prov_args_t arg = {0}; 270 btc_msg_t msg = {0}; 271 272 if (!name || (strlen(name) > ESP_BLE_MESH_NODE_NAME_MAX_LEN)) { 273 return ESP_ERR_INVALID_ARG; 274 } 275 276 ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); 277 278 msg.sig = BTC_SIG_API_CALL; 279 msg.pid = BTC_PID_PROV; 280 msg.act = BTC_BLE_MESH_ACT_PROVISIONER_SET_NODE_NAME; 281 282 arg.set_node_name.index = index; 283 memset(arg.set_node_name.name, 0, sizeof(arg.set_node_name.name)); 284 strncpy(arg.set_node_name.name, name, ESP_BLE_MESH_NODE_NAME_MAX_LEN); 285 286 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) 287 == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); 288 } 289 290 const char *esp_ble_mesh_provisioner_get_node_name(uint16_t index) 291 { 292 return bt_mesh_provisioner_get_node_name(index); 293 } 294 295 uint16_t esp_ble_mesh_provisioner_get_node_index(const char *name) 296 { 297 if (!name || (strlen(name) > ESP_BLE_MESH_NODE_NAME_MAX_LEN)) { 298 return ESP_BLE_MESH_INVALID_NODE_INDEX; 299 } 300 301 return bt_mesh_provisioner_get_node_index(name); 302 } 303 304 esp_err_t esp_ble_mesh_provisioner_store_node_comp_data(uint16_t unicast_addr, 305 uint8_t *data, uint16_t length) 306 { 307 btc_ble_mesh_prov_args_t arg = {0}; 308 btc_msg_t msg = {0}; 309 310 if (!ESP_BLE_MESH_ADDR_IS_UNICAST(unicast_addr) || !data || length <= 14) { 311 return ESP_ERR_INVALID_ARG; 312 } 313 314 ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); 315 316 msg.sig = BTC_SIG_API_CALL; 317 msg.pid = BTC_PID_PROV; 318 msg.act = BTC_BLE_MESH_ACT_PROVISIONER_STORE_NODE_COMP_DATA; 319 320 arg.store_node_comp_data.unicast_addr = unicast_addr; 321 arg.store_node_comp_data.length = length; 322 arg.store_node_comp_data.data = data; 323 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), btc_ble_mesh_prov_arg_deep_copy) 324 == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); 325 } 326 327 esp_ble_mesh_node_t *esp_ble_mesh_provisioner_get_node_with_uuid(const uint8_t uuid[16]) 328 { 329 if (!uuid) { 330 return NULL; 331 } 332 333 return btc_ble_mesh_provisioner_get_node_with_uuid(uuid); 334 } 335 336 esp_ble_mesh_node_t *esp_ble_mesh_provisioner_get_node_with_addr(uint16_t unicast_addr) 337 { 338 if (!ESP_BLE_MESH_ADDR_IS_UNICAST(unicast_addr)) { 339 return NULL; 340 } 341 342 return btc_ble_mesh_provisioner_get_node_with_addr(unicast_addr); 343 } 344 345 esp_ble_mesh_node_t *esp_ble_mesh_provisioner_get_node_with_name(const char *name) 346 { 347 if (!name || (strlen(name) > ESP_BLE_MESH_NODE_NAME_MAX_LEN)) { 348 return NULL; 349 } 350 351 return btc_ble_mesh_provisioner_get_node_with_name(name); 352 } 353 354 uint16_t esp_ble_mesh_provisioner_get_prov_node_count(void) 355 { 356 return btc_ble_mesh_provisioner_get_prov_node_count(); 357 } 358 359 const esp_ble_mesh_node_t **esp_ble_mesh_provisioner_get_node_table_entry(void) 360 { 361 return btc_ble_mesh_provisioner_get_node_table_entry(); 362 } 363 364 esp_err_t esp_ble_mesh_provisioner_delete_node_with_uuid(const uint8_t uuid[16]) 365 { 366 btc_ble_mesh_prov_args_t arg = {0}; 367 btc_msg_t msg = {0}; 368 369 if (!uuid) { 370 return ESP_ERR_INVALID_ARG; 371 } 372 373 ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); 374 375 msg.sig = BTC_SIG_API_CALL; 376 msg.pid = BTC_PID_PROV; 377 msg.act = BTC_BLE_MESH_ACT_PROVISIONER_DELETE_NODE_WITH_UUID; 378 379 memcpy(arg.delete_node_with_uuid.uuid, uuid, 16); 380 381 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) 382 == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); 383 } 384 385 esp_err_t esp_ble_mesh_provisioner_delete_node_with_addr(uint16_t unicast_addr) 386 { 387 btc_ble_mesh_prov_args_t arg = {0}; 388 btc_msg_t msg = {0}; 389 390 if (!ESP_BLE_MESH_ADDR_IS_UNICAST(unicast_addr)) { 391 return ESP_ERR_INVALID_ARG; 392 } 393 394 ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); 395 396 msg.sig = BTC_SIG_API_CALL; 397 msg.pid = BTC_PID_PROV; 398 msg.act = BTC_BLE_MESH_ACT_PROVISIONER_DELETE_NODE_WITH_ADDR; 399 400 arg.delete_node_with_addr.unicast_addr = unicast_addr; 401 402 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) 403 == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); 404 } 405 406 esp_err_t esp_ble_mesh_provisioner_add_local_app_key(const uint8_t app_key[16], 407 uint16_t net_idx, uint16_t app_idx) 408 { 409 btc_ble_mesh_prov_args_t arg = {0}; 410 btc_msg_t msg = {0}; 411 412 ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); 413 414 msg.sig = BTC_SIG_API_CALL; 415 msg.pid = BTC_PID_PROV; 416 msg.act = BTC_BLE_MESH_ACT_PROVISIONER_ADD_LOCAL_APP_KEY; 417 418 arg.add_local_app_key.net_idx = net_idx; 419 arg.add_local_app_key.app_idx = app_idx; 420 if (app_key) { 421 memcpy(arg.add_local_app_key.app_key, app_key, 16); 422 } else { 423 bzero(arg.add_local_app_key.app_key, 16); 424 } 425 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) 426 == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); 427 } 428 429 esp_err_t esp_ble_mesh_provisioner_update_local_app_key(const uint8_t app_key[16], 430 uint16_t net_idx, uint16_t app_idx) 431 { 432 btc_ble_mesh_prov_args_t arg = {0}; 433 btc_msg_t msg = {0}; 434 435 if (app_key == NULL) { 436 return ESP_ERR_INVALID_ARG; 437 } 438 439 ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); 440 441 msg.sig = BTC_SIG_API_CALL; 442 msg.pid = BTC_PID_PROV; 443 msg.act = BTC_BLE_MESH_ACT_PROVISIONER_UPDATE_LOCAL_APP_KEY; 444 445 memcpy(arg.update_local_app_key.app_key, app_key, 16); 446 arg.update_local_app_key.net_idx = net_idx; 447 arg.update_local_app_key.app_idx = app_idx; 448 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) 449 == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); 450 } 451 452 const uint8_t *esp_ble_mesh_provisioner_get_local_app_key(uint16_t net_idx, uint16_t app_idx) 453 { 454 return bt_mesh_provisioner_local_app_key_get(net_idx, app_idx); 455 } 456 457 esp_err_t esp_ble_mesh_provisioner_bind_app_key_to_local_model(uint16_t element_addr, uint16_t app_idx, 458 uint16_t model_id, uint16_t company_id) 459 { 460 btc_ble_mesh_prov_args_t arg = {0}; 461 btc_msg_t msg = {0}; 462 463 if (!ESP_BLE_MESH_ADDR_IS_UNICAST(element_addr)) { 464 return ESP_ERR_INVALID_ARG; 465 } 466 467 ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); 468 469 msg.sig = BTC_SIG_API_CALL; 470 msg.pid = BTC_PID_PROV; 471 msg.act = BTC_BLE_MESH_ACT_PROVISIONER_BIND_LOCAL_MOD_APP; 472 473 arg.local_mod_app_bind.elem_addr = element_addr; 474 arg.local_mod_app_bind.app_idx = app_idx; 475 arg.local_mod_app_bind.model_id = model_id; 476 arg.local_mod_app_bind.cid = company_id; 477 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) 478 == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); 479 } 480 481 esp_err_t esp_ble_mesh_provisioner_add_local_net_key(const uint8_t net_key[16], uint16_t net_idx) 482 { 483 btc_ble_mesh_prov_args_t arg = {0}; 484 btc_msg_t msg = {0}; 485 486 if (net_idx == ESP_BLE_MESH_KEY_PRIMARY) { 487 return ESP_ERR_INVALID_ARG; 488 } 489 490 ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); 491 492 msg.sig = BTC_SIG_API_CALL; 493 msg.pid = BTC_PID_PROV; 494 msg.act = BTC_BLE_MESH_ACT_PROVISIONER_ADD_LOCAL_NET_KEY; 495 496 arg.add_local_net_key.net_idx = net_idx; 497 if (net_key) { 498 memcpy(arg.add_local_net_key.net_key, net_key, 16); 499 } else { 500 bzero(arg.add_local_net_key.net_key, 16); 501 } 502 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) 503 == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); 504 } 505 506 esp_err_t esp_ble_mesh_provisioner_update_local_net_key(const uint8_t net_key[16], uint16_t net_idx) 507 { 508 btc_ble_mesh_prov_args_t arg = {0}; 509 btc_msg_t msg = {0}; 510 511 if (net_key == NULL) { 512 return ESP_ERR_INVALID_ARG; 513 } 514 515 ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); 516 517 msg.sig = BTC_SIG_API_CALL; 518 msg.pid = BTC_PID_PROV; 519 msg.act = BTC_BLE_MESH_ACT_PROVISIONER_UPDATE_LOCAL_NET_KEY; 520 521 memcpy(arg.update_local_net_key.net_key, net_key, 16); 522 arg.update_local_net_key.net_idx = net_idx; 523 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) 524 == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); 525 } 526 527 const uint8_t *esp_ble_mesh_provisioner_get_local_net_key(uint16_t net_idx) 528 { 529 return bt_mesh_provisioner_local_net_key_get(net_idx); 530 } 531 #endif /* CONFIG_BLE_MESH_PROVISIONER */ 532 533 #if (CONFIG_BLE_MESH_FAST_PROV) 534 const uint8_t *esp_ble_mesh_get_fast_prov_app_key(uint16_t net_idx, uint16_t app_idx) 535 { 536 return bt_mesh_get_fast_prov_app_key(net_idx, app_idx); 537 } 538 #endif /* CONFIG_BLE_MESH_FAST_PROV */ 539