/* * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved * * @author: Anupam Roy * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include "bluetooth.h" #include "bluetooth_internal.h" #include "bluetooth_private.h" #include "bluetooth-mesh-api.h" #define BT_MESH_MAX_NETWORKS 5 #define BT_MESH_MAX_ELEMENTS 32767 #define BT_MESH_MAX_MODELS 32767 #define BT_MESH_MAX_NODES 32767 #define BT_MESH_MAX_SUBNETS 4096 #define BT_MESH_FIXED_GROUP_LOW 0xff00 #define BT_MESH_FIXED_GROUP_HIGH 0xffff #define BT_MESH_ALL_NODES_ADDRESS 0xffff #define BT_MESH_VIRTUAL_ADDRESS_LOW 0x8000 #define BT_MESH_VIRTUAL_ADDRESS_HIGH 0xbfff #define BT_MESH_GROUP_ADDRESS_LOW 0xc000 #define BT_MESH_GROUP_ADDRESS_HIGH 0xfeff #define BT_MESH_IS_GROUP(x) ((((x) >= BT_MESH_GROUP_ADDRESS_LOW) && \ ((x) < BT_MESH_FIXED_GROUP_HIGH)) || \ ((x) == BT_MESH_ALL_NODES_ADDRESS)) static bool is_mesh_initialized = false; /**< List of Local handles >*/ GSList *networks; GSList *node_list; GSList *element_list; GSList *model_list; GSList *appkey_list; GSList *netkey_list; GSList *group_list; #define BT_CHECK_MESH_SUPPORT() \ { \ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); \ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_LE); \ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_MESH); \ } #define BT_CHECK_MESH_INIT_STATUS() \ if (__bt_check_mesh_init_status() == BT_ERROR_NOT_INITIALIZED) { \ LOGE("[%s] NOT_INITIALIZED(0x%08x)", __FUNCTION__, BT_ERROR_NOT_INITIALIZED); \ return BT_ERROR_NOT_INITIALIZED; \ } #define BT_CHECK_MESH_REMOTE(handle) \ { if (handle->is_local) return BT_ERROR_OPERATION_FAILED; } #define BT_CHECK_MESH_LOCAL(handle) \ { if (!handle->is_local) return BT_ERROR_OPERATION_FAILED; } #define BT_CHECK_MESH_IS_ATTACHED(handle) \ { if (handle->is_attached) return BT_ERROR_OPERATION_FAILED; } #define BT_MESH_VALIDATE_HANDLE(h1, list) \ { \ GSList *l; \ bool valid = FALSE; \ for (l = list; l; l = g_slist_next(l)) { \ void *h2 = (void *)l->data; \ if (h1 == h2) { \ BT_INFO("Handle matched [%p]", h2); \ valid = TRUE; break; \ } \ } \ if (valid == FALSE) { \ BT_ERR("Handle [%p] did not match with any stored handles!!", h1); \ return BT_ERROR_INVALID_PARAMETER; \ } \ } \ size_t __bt_mesh_util_convert_hex_to_string(uint8_t *in, size_t in_len, char *out, size_t out_len) { static const char hexdigits[] = "0123456789abcdef"; size_t i; if (in_len * 2 > (out_len - 1)) return 0; for (i = 0; i < in_len; i++) { out[i * 2] = hexdigits[in[i] >> 4]; out[i * 2 + 1] = hexdigits[in[i] & 0xf]; } out[in_len * 2] = '\0'; return i; } static int __compare_group_address(gconstpointer a, gconstpointer b) { const bt_mesh_group_s *group = a; uint16_t addr = GPOINTER_TO_UINT(b); return (group->addr - addr); } static int __compare_node_primary_unicast(gconstpointer a, gconstpointer b) { const bt_mesh_node_s *node = a; uint16_t index = GPOINTER_TO_UINT(b); return (node->unicast - index); } static int __compare_node_element_index(gconstpointer a, gconstpointer b) { const bt_mesh_element_s *element = a; int index = GPOINTER_TO_UINT(b); return (element->index - index); } static int __compare_network_group_address(gconstpointer a, gconstpointer b) { const bt_mesh_group_s *group = a; uint16_t group_addr = GPOINTER_TO_UINT(b); return (group->addr - group_addr); } static int __compare_model_id(gconstpointer a, gconstpointer b) { const bt_mesh_model_s *model_s = a; uint32_t model = GPOINTER_TO_UINT(b); return (model_s->id - model); } static int __compare_netkey_index(gconstpointer a, gconstpointer b) { const bt_mesh_netkey_s *nk = a; uint16_t netkey_index = GPOINTER_TO_UINT(b); return (nk->netkey_index - netkey_index); } static int __simple_compare(gconstpointer a, gconstpointer b) { if (a == b) return 0; else return 1; } static int __compare_appkey_index(gconstpointer a, gconstpointer b) { const bt_mesh_appkey_s *ak = a; uint16_t appkey_index = GPOINTER_TO_UINT(b); return (ak->appkey_index - appkey_index); } static int __compare_element_index(gconstpointer a, gconstpointer b) { const bt_mesh_element_s *elem = a; uint16_t element_index = GPOINTER_TO_UINT(b); return (elem->index - element_index); } static bt_mesh_netkey_s * __bt_mesh_network_is_netkey_added( bt_mesh_network_s *network_s, uint16_t netkey_idx) { GSList *l; l = g_slist_find_custom(network_s->netkeys, GUINT_TO_POINTER(netkey_idx), (GCompareFunc)__compare_netkey_index); if (!l) return NULL; return (bt_mesh_netkey_s*) l->data; } bt_mesh_element_s *_bt_mesh_get_element_from_index( bt_mesh_node_s *node_s, int element_index) { GSList *l; l = g_slist_find_custom(node_s->elements, GUINT_TO_POINTER(element_index), (GCompareFunc)__compare_element_index); if (!l) return NULL; return (bt_mesh_element_s*) l->data; } bt_mesh_appkey_s *_bt_mesh_network_get_appkey_from_index( bt_mesh_network_s *network_s, uint16_t appkey_idx) { GSList *l, *l1; for (l = network_s->netkeys; l; l = l->next) { bt_mesh_netkey_s *netkey_s = l->data; l1 = g_slist_find_custom(netkey_s->appkeys, GUINT_TO_POINTER(appkey_idx), (GCompareFunc)__compare_appkey_index); if (l1) return l1->data; } return NULL; } bt_mesh_model_s *_bt_mesh_get_model_from_modelid( bt_mesh_element_s *element_s, uint32_t modelid) { GSList *l; l = g_slist_find_custom(element_s->models, GUINT_TO_POINTER(modelid), (GCompareFunc)__compare_model_id); if (!l) return NULL; return (bt_mesh_model_s*) l->data; } bt_mesh_group_s* _bt_mesh_network_get_group( bt_mesh_network_s *network_s, uint16_t group_addr) { GSList *l; bt_mesh_group_s *group_s = NULL; /* Unassigned address */ if (group_addr == 0x0000) return NULL; l = g_slist_find_custom(network_s->groups, GUINT_TO_POINTER(group_addr), (GCompareFunc) __compare_network_group_address); if (!l) { group_s = g_malloc0(sizeof(bt_mesh_group_s)); group_s->addr = group_addr; if (!BT_MESH_IS_GROUP(group_addr)) group_s->is_virtual = true; else group_s->is_virtual = false; group_s->parent = network_s; if (g_slist_append(network_s->groups, group_s)) BT_INFO("Mesh: Group created"); group_list = g_slist_append(group_list, group_s); } else group_s = l->data; return group_s; } bt_mesh_appkey_s* _bt_mesh_node_get_appkey( bt_mesh_node_s *node_s, uint16_t appkey_idx) { GSList *l; l = g_slist_find_custom(node_s->appkeys, GUINT_TO_POINTER(appkey_idx), (GCompareFunc)__compare_appkey_index); if (!l) return NULL; return (bt_mesh_appkey_s*) l->data; } static bt_mesh_appkey_s *__bt_mesh_network_is_appkey_added( bt_mesh_network_s *network_s, uint16_t netkey_idx, uint16_t appkey_idx) { GSList *l, *l1; const bt_mesh_netkey_s *netkey; l = g_slist_find_custom(network_s->netkeys, GUINT_TO_POINTER(netkey_idx), (GCompareFunc)__compare_netkey_index); if (!l) return NULL; netkey = l->data; l1 = g_slist_find_custom(netkey->appkeys, GUINT_TO_POINTER(appkey_idx), (GCompareFunc)__compare_appkey_index); if (!l1) return NULL; return (bt_mesh_appkey_s*) l1->data; } int __bt_check_mesh_init_status(void) { if (is_mesh_initialized != true) { BT_ERR("NOT_INITIALIZED(0x%08x)", BT_ERROR_NOT_INITIALIZED); return BT_ERROR_NOT_INITIALIZED; } return BT_ERROR_NONE; } /* Local static */ static void __bt_mesh_free_models(void *data) { bt_mesh_model_s *model = (bt_mesh_model_s*)data; model_list = g_slist_remove(model_list, model); g_free(model); } static void __bt_mesh_free_elements(void *data) { bt_mesh_element_s *elem = (bt_mesh_element_s*)data; element_list = g_slist_remove(element_list, elem); g_slist_free_full(elem->models, __bt_mesh_free_models); g_free(elem); } static gint __bt_mesh_compare_net_uuid(gpointer *a, gpointer *b) { bt_mesh_network_s *net = (bt_mesh_network_s *)a; char *net_uuid = (char *)b; return g_strcmp0(net->uuid, net_uuid); } static void __bt_mesh_insert_elements_in_node( bt_mesh_node_s *node, uint16_t unicast, int num_elements, bool is_local) { bt_mesh_element_s *element_s; for (int i = 0; i < num_elements; i++) { element_s = g_malloc0(sizeof(bt_mesh_element_s)); element_s->is_local = is_local; element_s->parent = node; element_s->index = i; node->elements = g_slist_append(node->elements, element_s); element_list = g_slist_append(element_list, element_s); } } bt_mesh_appkey_s *_bt_mesh_handle_node_appkey_configure( bt_mesh_network_s *network_s, bt_mesh_node_s *node_s, uint16_t netkey_idx, uint16_t appkey_idx, bt_mesh_node_key_configuration_e op) { bt_mesh_appkey_s *appkey_s; appkey_s = __bt_mesh_network_is_appkey_added( network_s, netkey_idx, appkey_idx); /* AppKey with index not found in network */ if (!appkey_s) { BT_ERR("Mesh: Exceptional case: AppKey not found in Network"); return NULL; } if (op == BT_MESH_NODE_KEY_ADD) { if (!g_slist_find_custom(node_s->appkeys,(gconstpointer) appkey_s, (GCompareFunc)__simple_compare)) { node_s->appkeys = g_slist_append(node_s->appkeys, appkey_s); } else BT_INFO("Mesh: AppKey Already added"); return appkey_s; } else if (op == BT_MESH_NODE_KEY_DELETE) { node_s->appkeys = g_slist_remove(node_s->appkeys, appkey_s); return NULL; } else /* Node NetKey update */ return appkey_s; } bt_mesh_netkey_s *_bt_mesh_handle_node_netkey_configure( bt_mesh_network_s *network_s, bt_mesh_node_s *node_s, uint16_t netkey_idx, bt_mesh_node_key_configuration_e op) { bt_mesh_netkey_s *netkey_s; netkey_s = __bt_mesh_network_is_netkey_added(network_s, netkey_idx); /* Netkey with index not found in network */ if (!netkey_s) { BT_ERR("Mesh: Exceptional case: Netkey not found in Network"); return NULL; } if (op == BT_MESH_NODE_KEY_ADD) { if (!g_slist_find_custom(node_s->netkeys,(gconstpointer) netkey_s, (GCompareFunc)__simple_compare)) { node_s->netkeys = g_slist_append(node_s->netkeys, netkey_s); } else BT_INFO("Mesh: NetKey Already added"); return netkey_s; } else if (op == BT_MESH_NODE_KEY_DELETE) { node_s->netkeys = g_slist_remove(node_s->netkeys, netkey_s); return NULL; } else /* Node NetKey update */ return netkey_s; } bt_mesh_group_s * _bt_mesh_get_group_from_sub( bt_mesh_network_s *network_s, bt_mesh_model_s *model_s, bt_mesh_model_subscription_op_e op, uint16_t sub_addr) { GSList *l; bt_mesh_group_s *group_s = NULL; l = g_slist_find_custom(network_s->groups, GUINT_TO_POINTER(sub_addr), (GCompareFunc) __compare_network_group_address); if (l) group_s = l->data; if (op == BT_MESH_MODEL_SUBSCRIPTION_DELETE_ALL) BT_INFO("Mesh: Event for BT_MESH_MODEL_SUBSCRIPTION_DELETE_ALL"); if (op == BT_MESH_MODEL_SUBSCRIPTION_ADD) BT_INFO("Mesh: Event for BT_MESH_MODEL_SUBSCRIPTION_ADD"); if (op == BT_MESH_MODEL_SUBSCRIPTION_DELETE) BT_INFO("Mesh: Event for BT_MESH_MODEL_SUBSCRIPTION_DELETE"); if (op == BT_MESH_MODEL_SUBSCRIPTION_OVERWRITE) BT_INFO("Mesh: Event for BT_MESH_MODEL_SUBSCRIPTION_OVERWRITE"); return group_s; } bt_mesh_model_s *_bt_mesh_get_node_get_model_from_element( char *net_uuid, uint16_t unicast, int elem_idx, uint32_t model) { GSList *l, *l1, *l2, *l3; bt_mesh_network_s *network_s; bt_mesh_node_s *node_s; bt_mesh_element_s *element_s; l = g_slist_find_custom(networks, net_uuid, (GCompareFunc)__bt_mesh_compare_net_uuid); if (!l) return NULL; network_s = (bt_mesh_network_s*) l->data; l1 = g_slist_find_custom(network_s->nodes, GUINT_TO_POINTER(unicast), (GCompareFunc)__compare_node_primary_unicast); if (!l1) return NULL; node_s = (bt_mesh_node_s*) l1->data; l2 = g_slist_find_custom(node_s->elements, GUINT_TO_POINTER(elem_idx), (GCompareFunc)__compare_node_element_index); if (!l2) return NULL; element_s = (bt_mesh_element_s*) l2->data; l3 = g_slist_find_custom(element_s->models, GUINT_TO_POINTER(model), (GCompareFunc) __compare_model_id); if (!l3) return NULL; return (bt_mesh_model_s*) l3->data; } bt_mesh_element_s * _bt_mesh_get_node_get_element_from_index(char *net_uuid, uint16_t unicast, int elem_idx) { GSList *l, *l1, *l2; bt_mesh_network_s *network_s; bt_mesh_node_s *node_s; l = g_slist_find_custom(networks, net_uuid, (GCompareFunc)__bt_mesh_compare_net_uuid); if (!l) return NULL; network_s = l->data; l1 = g_slist_find_custom(network_s->nodes, GUINT_TO_POINTER(unicast), (GCompareFunc)__compare_node_primary_unicast); if (!l1) return NULL; node_s = l1->data; l2 = g_slist_find_custom(node_s->elements, GUINT_TO_POINTER(elem_idx), (GCompareFunc)__compare_node_element_index); if (!l2) return NULL; return (bt_mesh_element_s*) l->data; } bt_mesh_node_s *_bt_mesh_get_node_from_unicast(char *net_uuid, uint16_t unicast) { GSList *l, *l1; bt_mesh_network_s *network_s; bt_mesh_node_s *node_s; l = g_slist_find_custom(networks, net_uuid, (GCompareFunc)__bt_mesh_compare_net_uuid); if (!l) return NULL; network_s = l->data; l1 = g_slist_find_custom(network_s->nodes, GUINT_TO_POINTER(unicast), (GCompareFunc)__compare_node_primary_unicast); if (!l1) return NULL; node_s = l1->data; return node_s; } bt_mesh_node_s *_bt_mesh_remote_node_browsed(char *net_uuid, char *dev_uuid, uint16_t unicast, int count) { GSList *l, *l1; bt_mesh_network_s *network_s; bt_mesh_node_s *node_s; l = g_slist_find_custom(networks, net_uuid, (GCompareFunc)__bt_mesh_compare_net_uuid); if (!l) return NULL; network_s = l->data; l1 = g_slist_find_custom(network_s->nodes, GUINT_TO_POINTER(unicast), (GCompareFunc)__compare_node_primary_unicast); if (l1) { node_s = l1->data; g_strlcpy(node_s->uuid, dev_uuid, sizeof(node_s->uuid)); } else { node_s = g_malloc0(sizeof(bt_mesh_node_s)); node_s->parent = network_s; node_s->unicast = unicast; node_s->is_attached = true; if (node_s->unicast == 0x0001) { node_s->is_local = true; node_s->is_provisioner = true; } g_strlcpy(node_s->uuid, dev_uuid, sizeof(node_s->uuid)); __bt_mesh_insert_elements_in_node(node_s, unicast, count, node_s->is_local? true : false); network_s->nodes = g_slist_append(network_s->nodes, node_s); node_list = g_slist_append(node_list, node_s); } return node_s; } bt_mesh_network_s * _bt_mesh_get_network_handle_info(char *net_uuid) { GSList *l; l = g_slist_find_custom(networks, net_uuid, (GCompareFunc)__bt_mesh_compare_net_uuid); if (!l) return NULL; return (bt_mesh_network_s*)l->data; } char * _bt_mesh_get_auth_string_from_value(int auth) { switch(auth) { case BT_MESH_AUTH_ALPHANUMERIC_DISPLAY: BT_INFO("Mesh: ALPHANUMERIC_DISPLAY"); return "ALPHANUMERIC_DISPLAY"; case BT_MESH_AUTH_NUMERIC_DISPLAY: BT_INFO("Mesh: NUMERIC_DISPLAY"); return "NUMERIC_DISPLAY"; case BT_MESH_AUTH_PUSH_COUNT_DISPLAY: BT_INFO("Mesh: PUSH_COUNT_DISPLAY"); return "PUSH_COUNT_DISPLAY"; case BT_MESH_AUTH_TWIST_COUNT_DISPLAY: BT_INFO("Mesh: TWIST_COUNT_DISPLAY"); return "TWIST_COUNT_DISPLAY"; /*< Input authentication request types */ case BT_MESH_AUTH_REQ_ALPHANUMERIC_INPUT: BT_INFO("Mesh: REQ_ALPHANUMERIC_INPUT"); return "REQ_ALPHANUMERIC_INPUT"; case BT_MESH_AUTH_REQ_NUMERIC_INPUT: BT_INFO("Mesh: REQ_NUMERIC_INPUT"); return "REQ_NUMERIC_INPUT"; case BT_MESH_AUTH_REQ_BLINK_COUNT_INPUT: BT_INFO("Mesh: REQ_BLINK_COUNT_INPUT"); return "REQ_BLINK_COUNT_INPUT"; case BT_MESH_AUTH_REQ_BEEP_COUNT_INPUT: BT_INFO("Mesh: REQ_BEEP_COUNT_INPUT"); return "REQ_BEEP_COUNT_INPUT"; case BT_MESH_AUTH_REQ_VIBRATE_COUNT_INPUT: BT_INFO("Mesh: REQ_VIBRATE_COUNT_INPUT"); return "REQ_VIBRATE_COUNT_INPUT"; /**< OOB Key Inputs */ case BT_MESH_AUTH_REQ_OOB_PUBLIC_KEY_INPUT: BT_INFO("Mesh: OOB_PUBLIC_KEY_INPUT"); return "OOB_PUBLIC_KEY_INPUT"; case BT_MESH_AUTH_REQ_OOB_STATIC_KEY_INPUT: BT_INFO("Mesh: OOB_STATIC_KEY_INPUT"); return "OOB_STATIC_KEY_INPUT"; default: return ""; } } /* Mesh API */ int bt_mesh_initialize(void) { FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); int ret = BT_ERROR_NONE; BT_INFO("Is Mesh initialized:[%s]", is_mesh_initialized ? "TRUE": "FALSE"); if (is_mesh_initialized) { BT_ERR("Mesh is initialized"); return BT_ERROR_NONE; } if (!is_mesh_initialized) { ret = _bt_get_error_code(bluetooth_mesh_init( _bt_mesh_event_proxy, NULL)); if (ret != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); return BT_ERROR_OPERATION_FAILED; } is_mesh_initialized = true; return BT_ERROR_NONE; } BT_INFO("Mesh is already initialized"); FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_deinitialize(void) { FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); int error; error = bluetooth_mesh_deinit(); error = _bt_get_error_code(error); if (BT_ERROR_NONE != error) BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error), error); is_mesh_initialized = false; FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_node_create(bt_mesh_node_features_s *features, bt_mesh_node_h *node_handle) { FUNC_ENTRY; bt_mesh_node_s *node = NULL; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(node_handle); BT_CHECK_INPUT_PARAMETER(features); node = g_malloc0(sizeof(bt_mesh_node_s)); if (!node) { BT_ERR("g_malloc0 failed"); return BT_ERROR_OUT_OF_MEMORY; } node->is_local = true; node->features = *features; node->unicast = 0x0001; node_list = g_slist_append(node_list, node); *node_handle = (bt_mesh_node_h)node; FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_node_destroy(bt_mesh_node_h node_handle) { FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(node_handle); bt_mesh_node_s *node = (bt_mesh_node_s*)node_handle; BT_MESH_VALIDATE_HANDLE(node, node_list); /* It is NOT allowed to destroy attached node: Do Reset */ BT_CHECK_MESH_IS_ATTACHED(node); node_list = g_slist_remove(node_list, node); g_slist_free_full(node->elements, __bt_mesh_free_elements); g_free(node); FUNC_EXIT; return BT_ERROR_NONE; } static void __bt_mesh_generate_element(bt_mesh_node_s *node_s, bt_mesh_element_s *elem_s) { GSList *l; uint16_t index = 0; for (l = node_s->elements; l; l = l->next) { bt_mesh_element_s *el = (bt_mesh_element_s*)l->data; if (el->index != index) break; index++; } elem_s->index = index; node_s->elements = g_slist_insert(node_s->elements, elem_s, index); } int bt_mesh_node_create_element(bt_mesh_node_h node_handle, bt_mesh_element_h *element_handle) { FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(node_handle); BT_CHECK_INPUT_PARAMETER(element_handle); bt_mesh_node_s *node = (bt_mesh_node_s*)node_handle; bt_mesh_element_s *element = NULL; BT_INFO("Mesh: Element creation request"); BT_MESH_VALIDATE_HANDLE(node, node_list); /* It is NOT allowed to add an element to a already attached node */ BT_CHECK_MESH_IS_ATTACHED(node); /* Check num elements already present in the node */ if (g_slist_length(node->elements) >= BT_MESH_MAX_ELEMENTS) return BT_ERROR_QUOTA_EXCEEDED; element = g_malloc0(sizeof(bt_mesh_element_s)); if (!element) { BT_ERR("g_malloc0 failed"); return BT_ERROR_OUT_OF_MEMORY; } element->is_local = true; element->parent = node; __bt_mesh_generate_element(node, element); element_list = g_slist_append(element_list, element); *element_handle = (bt_mesh_element_h)element; BT_INFO("Mesh: Element created successfully: element index [%d]", element->index); FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_element_destroy(bt_mesh_element_h element_handle) { FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(element_handle); BT_MESH_VALIDATE_HANDLE(element_handle, element_list); bt_mesh_node_s *node = (bt_mesh_node_s*)((bt_mesh_element_s*)element_handle)->parent; bt_mesh_element_s *element = (bt_mesh_element_s*)element_handle; /* It is NOT allowed to destroy remote element */ BT_CHECK_MESH_LOCAL(node); /* It is NOT allowed to destroy an attahced element */ BT_CHECK_MESH_IS_ATTACHED(node); element_list = g_slist_remove(element_list, element); node->elements = g_slist_remove(node->elements, element); g_slist_free_full(element->models, __bt_mesh_free_models); g_free(element); FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_element_create_model( bt_mesh_element_h element_handle, bt_mesh_model_id_s *model_id, bt_mesh_model_h *model_handle) { FUNC_ENTRY; uint32_t mod_id; bt_mesh_element_s *element = (bt_mesh_element_s*)element_handle; bt_mesh_model_s *model = NULL; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(element_handle); BT_CHECK_INPUT_PARAMETER(model_id); BT_CHECK_INPUT_PARAMETER(model_handle); BT_MESH_VALIDATE_HANDLE(element_handle, element_list); bt_mesh_node_s *node = (bt_mesh_node_s*)((bt_mesh_element_s*)element_handle)->parent; /* It is NOT allowed to add model to a remote element */ BT_CHECK_MESH_LOCAL(node); /* It is NOT allowed to add a Model to a already attached node */ BT_CHECK_MESH_IS_ATTACHED(node); BT_INFO("Mesh: Model creation request: Company ID [0x%2.2x] Model ID [0x%2.2x]", model_id->company_id, model_id->model_id); mod_id = model_id->company_id; mod_id <<= 16; mod_id |= model_id->model_id; /* Allow configuration server model only in primary element */ if ((model_id->model_id == BT_MESH_MODEL_ID_CFG_SRV) && element->index != 0) return BT_ERROR_OPERATION_FAILED; /* Check num models already present in the element */ if (g_slist_length(element->models) >= BT_MESH_MAX_MODELS) return BT_ERROR_QUOTA_EXCEEDED; /* Don't allow multiple instance of same model in an element */ if (g_slist_find_custom(element->models, GUINT_TO_POINTER(mod_id), (GCompareFunc)__compare_model_id)) return BT_ERROR_ALREADY_DONE; model = g_malloc0(sizeof(bt_mesh_model_s)); if (!model) { BT_ERR("g_malloc0 failed"); return BT_ERROR_OUT_OF_MEMORY; } model->is_local = true; model->parent = element; model->id = mod_id; BT_INFO("Mesh: Model ID [0x%2.2x]", model_id->model_id); BT_INFO("Mesh: Company ID [0x%2.2x]", model_id->company_id); BT_INFO("Mesh: MOD [0x%4.4x]", model->id); model_list = g_slist_append(model_list, model); element->models = g_slist_append(element->models, model); *model_handle = (bt_mesh_model_h)model; BT_INFO("Mesh: Model created successfully"); FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_model_destroy(bt_mesh_model_h model_handle) { FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(model_handle); bt_mesh_node_s *node = (bt_mesh_node_s*)((bt_mesh_element_s*)((bt_mesh_model_s*)model_handle)->parent)->parent; bt_mesh_model_s *model = (bt_mesh_model_s*)model_handle; bt_mesh_element_s *element = model->parent; BT_MESH_VALIDATE_HANDLE(model, model_list); BT_MESH_VALIDATE_HANDLE(element, element_list); /* It is NOT allowed to destroy remote model */ BT_CHECK_MESH_LOCAL(node); /* It is NOT allowed to destroy an attahced model */ BT_CHECK_MESH_IS_ATTACHED(node); model_list = g_slist_remove(model_list, model); element->models = g_slist_remove(element->models, model); g_free(model); FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_model_get_id(bt_mesh_model_h model_handle, bt_mesh_model_id_s *model_id) { FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(model_handle); BT_CHECK_INPUT_PARAMETER(model_id); bt_mesh_model_s *model = (bt_mesh_model_s*)model_handle; BT_MESH_VALIDATE_HANDLE(model, model_list); BT_INFO("Mesh: Model ID [0x%4.4x]", model->id); model_id->company_id = model->id >> 16; model_id->model_id = model->id; BT_INFO("Mesh: CID [0x%2.2x]", model_id->company_id); BT_INFO("Mesh: MID [0x%2.2x]", model_id->model_id); FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_node_get_network(bt_mesh_node_h node_handle, bt_mesh_network_h *network) { FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(node_handle); BT_CHECK_INPUT_PARAMETER(network); bt_mesh_node_s *node = (bt_mesh_node_s*)node_handle; BT_MESH_VALIDATE_HANDLE(node_handle, node_list); *network = node->parent; FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_element_get_node(bt_mesh_element_h element_handle, bt_mesh_node_h *node) { FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(element_handle); BT_CHECK_INPUT_PARAMETER(node); bt_mesh_element_s *element = (bt_mesh_element_s*)element_handle; BT_MESH_VALIDATE_HANDLE(element, element_list); *node = element->parent; FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_model_get_element(bt_mesh_model_h model_handle, bt_mesh_element_h *element) { FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(model_handle); BT_CHECK_INPUT_PARAMETER(element); bt_mesh_model_s *model = (bt_mesh_model_s*)model_handle; BT_MESH_VALIDATE_HANDLE(model, model_list); *element = model->parent; FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_appkey_get_netkey(bt_mesh_appkey_h appkey_handle, bt_mesh_netkey_h *netkey) { FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(appkey_handle); BT_CHECK_INPUT_PARAMETER(netkey); bt_mesh_appkey_s *appkey = (bt_mesh_appkey_s*)appkey_handle; BT_MESH_VALIDATE_HANDLE(appkey, appkey_list); *netkey = appkey->parent; FUNC_EXIT; return BT_ERROR_NONE; } /* Async API's to bt-service & stack */ int bt_mesh_network_create(bt_mesh_node_h config_client, const char *network_name, bt_mesh_network_h *network, char **token) { FUNC_ENTRY; int error_code = BT_ERROR_NONE; GSList *l1, *l2; int i, j; int offset = 0; int num_models = 0; bluetooth_mesh_network_t net; bluetooth_mesh_node_t param_node; bluetooth_mesh_model_t **param_model; bt_mesh_network_s *network_s; bt_mesh_netkey_s *netkey_s; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(config_client); BT_CHECK_INPUT_PARAMETER(network_name); BT_CHECK_INPUT_PARAMETER(network); BT_CHECK_INPUT_PARAMETER(token); BT_INFO("Mesh: Create Network: Name [%s]", network_name); bt_mesh_node_s *node = (bt_mesh_node_s*)config_client; BT_MESH_VALIDATE_HANDLE(node, node_list); /* Error if remote node*/ BT_CHECK_MESH_LOCAL(node); /* It is NOT allowed to create network out of a already attahced node */ BT_CHECK_MESH_IS_ATTACHED(node); memset(&net, 0x00, sizeof(bluetooth_mesh_network_t)); if (strlen(network_name) >= BT_MESH_NETWORK_NAME_STRING_MAX_LEN) return BT_ERROR_INVALID_PARAMETER; /* Node in network should contain at-least one element */ if (!g_slist_length(node->elements)) { BT_INFO("Mesh: No element present in Node: NOT ALLOWED!!"); return BT_ERROR_INVALID_PARAMETER; } /* Element in Node should contain at-least one Model */ for (l1 = node->elements; l1 != NULL; l1 = l1->next) { bt_mesh_element_s *el = l1->data; int models = 0; models = g_slist_length(el->models); BT_INFO("Mesh: Num models element [%u] has is [%d]", el->index, models); if (!models) { BT_INFO("Mesh: No Model present in element: NOT ALLOWED!!"); return BT_ERROR_INVALID_PARAMETER; } /* If Primary element does not contain CFG SRV model, create and append */ if (el->index == 0x0000) { uint32_t mod_id = 0xFFFF0000; /* CFG SRV */ if (!g_slist_find_custom(el->models, GUINT_TO_POINTER(mod_id), (GCompareFunc)__compare_model_id)) { bt_mesh_model_s *model_s; BT_ERR("Mesh: Primary element does not contain CFG SRV Model:Add it!"); model_s = g_malloc0(sizeof(bt_mesh_model_s)); model_s->is_local = true; model_s->parent = el; model_s->id = mod_id; model_list = g_slist_append(model_list, model_s); el->models = g_slist_append(el->models, model_s); num_models++; } else BT_INFO("Mesh: CFG SRV model is already added in primary element"); } num_models += models; } /* Check currently created network */ if (g_slist_length(networks) >= BT_MESH_MAX_NETWORKS) return BT_ERROR_QUOTA_EXCEEDED; memset(¶m_node, 0x00, sizeof(bluetooth_mesh_node_t)); memcpy(¶m_node.vendor_info, &(node->features), sizeof(node->features)); param_node.num_elements = g_slist_length(node->elements); param_node.primary_unicast = 0x0001; _bt_get_random_bytes(param_node.uuid, 16); BT_INFO("Mesh: Total Models [%d]", num_models); param_model = (bluetooth_mesh_model_t**)g_malloc0(num_models * sizeof(bluetooth_mesh_model_t*)); for (l1 = node->elements, i = 0; l1 != NULL; l1 = l1->next, i++) { bt_mesh_element_s *e = l1->data; for (l2 = e->models, j = 0; l2 != NULL; l2 = l2->next, j++) { bt_mesh_model_s *m = l2->data; param_model[j+offset] = g_malloc0(sizeof(bluetooth_mesh_model_t)); param_model[j+offset]->elem_index = i; param_model[j+offset]->model_id = m->id; } offset += g_slist_length(e->models); } BT_INFO("Mesh: Send Network create Request to FRWK"); error_code = _bt_get_error_code(bluetooth_mesh_network_create(network_name, ¶m_node, num_models, param_model, &net)); if (error_code != BT_ERROR_NONE) { BT_INFO("Mesh: Network could not be created!!"); BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); /* Cleanup */ for (int i = 0; i < num_models; i++) g_free(param_model[i]); return error_code; } BT_INFO("Mesh: Network created successfully"); /* Create Network object & fill data in network */ network_s = g_malloc0(sizeof(bt_mesh_network_s)); network_s->num_nodes = 1; network_s->is_local = true; network_s->is_discovered = true; /* Fill network name, token & UUID */ __bt_mesh_util_convert_hex_to_string((uint8_t *)param_node.uuid, 16, network_s->uuid, sizeof(network_s->uuid)); g_strlcpy(network_s->token, net.token.token, 17); g_strlcpy(network_s->name, network_name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1); network_s->nodes = g_slist_append(network_s->nodes, node); BT_INFO("Mesh: Network Name [%s]", network_s->name); BT_INFO("Mesh: Network Token[%s]", network_s->token); BT_INFO("Mesh: Network UUID [%s]", network_s->uuid); /* Create primary Netkey object */ netkey_s = g_malloc0(sizeof(bt_mesh_netkey_s)); netkey_s->parent = network_s; netkey_s->netkey_index = 0x0000; /* Primary index */ network_s->netkeys = g_slist_append(network_s->netkeys, netkey_s); netkey_list = g_slist_append(netkey_list, netkey_s); /* Fill Config Client Node Data */ node->is_attached = true; node->is_provisioner = true; __bt_mesh_util_convert_hex_to_string((uint8_t *)param_node.uuid, 16, node->uuid, sizeof(node->uuid)); node->unicast = 0x0001; node->parent = network_s; /* Prepare Out parameters */ *token = network_s->token; *network = (bt_mesh_network_h)network_s; /* Save network in list */ networks = g_slist_append(networks, network_s); /* Clean up memory */ for (int i = 0; i < num_models; i++) g_free(param_model[i]); FUNC_EXIT; return error_code; } int bt_mesh_network_load(const char *token, bt_mesh_network_h *network) { int error_code = BT_ERROR_NONE; bluetooth_mesh_network_t net; bt_mesh_network_s *network_s; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(token); BT_CHECK_INPUT_PARAMETER(network); memset(&net, 0x00, sizeof(bluetooth_mesh_network_t)); error_code = _bt_get_error_code(bluetooth_mesh_network_load(token, &net)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } /* Create Network object */ network_s = g_malloc0(sizeof(bt_mesh_network_s)); network_s->is_local = true; g_strlcpy(network_s->uuid, net.uuid, 33); g_strlcpy(network_s->token, token, 17); g_strlcpy(network_s->name, net.name.name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1); networks = g_slist_append(networks, network_s); FUNC_EXIT; return error_code; } int bt_mesh_network_get_name(bt_mesh_network_h network, char **network_name) { bt_mesh_network_s *network_s; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(network); BT_CHECK_INPUT_PARAMETER(network_name); BT_MESH_VALIDATE_HANDLE(network, networks); network_s = (bt_mesh_network_s*)network; *network_name = strdup(network_s->name); if (*network_name == NULL) { BT_ERR("OUT_OF_MEMORY(0x%08x)", BT_ERROR_OUT_OF_MEMORY); return BT_ERROR_OUT_OF_MEMORY; } FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_network_set_name(bt_mesh_network_h network, const char *network_name) { int error_code = BT_ERROR_NONE; bluetooth_mesh_network_t net; bt_mesh_network_s* network_s; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(network); BT_CHECK_INPUT_PARAMETER(network_name); network_s = (bt_mesh_network_s*)network; BT_MESH_VALIDATE_HANDLE(network_s, networks); memset(&net, 0x00, sizeof(bluetooth_mesh_network_t)); g_strlcpy(net.uuid, network_s->uuid, 33); g_strlcpy(net.token.token, network_s->token, 17); g_strlcpy(net.name.name, network_name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1); BT_INFO("Mesh: Set Network Name [%s]", network_name); error_code = _bt_get_error_code(bluetooth_mesh_network_set_name(&net)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } BT_INFO("Mesh: Network Name set successfully [%s]", network_name); g_strlcpy(network_s->name, network_name, sizeof(network_s->name)); FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_network_add_netkey(bt_mesh_network_h network, bt_mesh_netkey_h *netkey) { int error_code = BT_ERROR_NONE; bt_mesh_network_s *network_s; bt_mesh_netkey_s *netkey_s; bluetooth_mesh_network_t net; uint16_t netkey_idx; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(network); BT_CHECK_INPUT_PARAMETER(netkey); BT_MESH_VALIDATE_HANDLE(network, networks); network_s = (bt_mesh_network_s*)network; memset(&net, 0x00, sizeof(bluetooth_mesh_network_t)); g_strlcpy(net.uuid, network_s->uuid, 33); g_strlcpy(net.token.token, network_s->token, 17); g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1); error_code = _bt_get_error_code(bluetooth_mesh_network_add_netkey(&net, &netkey_idx)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } BT_INFO("Mesh: Subnet Key created: Index [%d]", netkey_idx); /* Create Netkey object */ netkey_s = g_malloc0(sizeof(bt_mesh_netkey_s)); netkey_s->parent = network_s; netkey_s->netkey_index = netkey_idx; network_s->netkeys = g_slist_append(network_s->netkeys, netkey_s); netkey_list = g_slist_append(netkey_list, netkey_s); *netkey = (bt_mesh_netkey_h)netkey_s; FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_network_foreach_netkeys(bt_mesh_network_h network, bt_mesh_network_netkey_info_cb callback, void *user_data) { bluetooth_mesh_network_t net; GPtrArray *netkeys = NULL; GSList *l; int error_code = BT_ERROR_NONE; uint16_t *netkey_idx = NULL; int i; int total; bt_mesh_network_s *network_s; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(network); BT_CHECK_INPUT_PARAMETER(callback); BT_MESH_VALIDATE_HANDLE(network, networks); netkeys = g_ptr_array_new(); if (netkeys == NULL) { BT_ERR("Mesh: OUT_OF_MEMORY(0x%08x)", BT_ERROR_OUT_OF_MEMORY); return BT_ERROR_OUT_OF_MEMORY; } network_s = (bt_mesh_network_s*)network; memset(&net, 0x00, sizeof(bluetooth_mesh_network_t)); g_strlcpy(net.uuid, network_s->uuid, 33); g_strlcpy(net.token.token, network_s->token, 17); g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1); error_code = _bt_get_error_code(bluetooth_mesh_network_get_all_netkey(&net, &netkeys)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); g_ptr_array_free(netkeys, TRUE); return error_code; } for (i = 0; i < netkeys->len; i++) { netkey_idx = g_ptr_array_index(netkeys, i); if (netkey_idx) { /* Create and insert netkey object in list */ if (!__bt_mesh_network_is_netkey_added(network_s, *netkey_idx)) { bt_mesh_netkey_s *nk; nk = g_malloc0(sizeof(bt_mesh_netkey_s)); nk->parent = network_s; nk->netkey_index = *netkey_idx; network_s->netkeys = g_slist_append(network_s->netkeys, nk); netkey_list = g_slist_append(netkey_list, nk); } } else { BT_ERR("Mesh: OPERATION_FAILED(0x%08x)", BT_ERROR_OPERATION_FAILED); error_code = BT_ERROR_OPERATION_FAILED; break; } } total = g_slist_length(network_s->netkeys); if (total == 0) { BT_INFO("Mesh: No netkey added in network"); callback(BT_ERROR_NONE, (bt_mesh_network_h)network_s, total, NULL, 0xFFFF, user_data); } for (l = network_s->netkeys; l != NULL; l = g_slist_next(l)) { bt_mesh_netkey_s *netkey; netkey = l->data; if (!callback(BT_ERROR_NONE, (bt_mesh_network_h)network_s, total, (bt_mesh_netkey_h) netkey, netkey->netkey_index, user_data)) { break; } } g_ptr_array_foreach(netkeys, (GFunc)g_free, NULL); g_ptr_array_free(netkeys, TRUE); FUNC_EXIT; return error_code; } int bt_mesh_netkey_get_index(bt_mesh_netkey_h netkey, uint16_t *index) { bt_mesh_netkey_s *netkey_s; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(netkey); BT_CHECK_INPUT_PARAMETER(index); BT_MESH_VALIDATE_HANDLE(netkey, netkey_list); netkey_s = (bt_mesh_netkey_s*)netkey; *index = netkey_s->netkey_index; FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_netkey_update(bt_mesh_netkey_h netkey) { int error_code = BT_ERROR_NONE; bt_mesh_network_s *network_s; bt_mesh_netkey_s *netkey_s; bluetooth_mesh_network_t net; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(netkey); netkey_s = (bt_mesh_netkey_s*)netkey; BT_MESH_VALIDATE_HANDLE(netkey_s, netkey_list); network_s = netkey_s->parent; BT_MESH_VALIDATE_HANDLE(network_s, networks); memset(&net, 0x00, sizeof(bluetooth_mesh_network_t)); g_strlcpy(net.uuid, network_s->uuid, 33); g_strlcpy(net.token.token, network_s->token, 17); g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1); error_code = _bt_get_error_code(bluetooth_mesh_network_update_netkey( &net, netkey_s->netkey_index)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_netkey_delete(bt_mesh_netkey_h netkey) { int error_code = BT_ERROR_NONE; bt_mesh_network_s *network_s; bt_mesh_netkey_s *netkey_s; bluetooth_mesh_network_t net; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(netkey); netkey_s = (bt_mesh_netkey_s*)netkey; BT_MESH_VALIDATE_HANDLE(netkey_s, netkey_list); network_s = netkey_s->parent; BT_MESH_VALIDATE_HANDLE(network_s, networks); memset(&net, 0x00, sizeof(bluetooth_mesh_network_t)); g_strlcpy(net.uuid, network_s->uuid, 33); g_strlcpy(net.token.token, network_s->token, 17); g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1); error_code = _bt_get_error_code(bluetooth_mesh_network_delete_netkey(&net, netkey_s->netkey_index)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } network_s->netkeys = g_slist_remove(network_s->netkeys, netkey_s); netkey_list = g_slist_remove(netkey_list, netkey_s); g_slist_free_full(netkey_s->appkeys, g_free); FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_netkey_add_appkey(bt_mesh_netkey_h netkey, bt_mesh_appkey_h *appkey) { int error_code = BT_ERROR_NONE; uint16_t appkey_idx; bt_mesh_network_s *network_s; bt_mesh_netkey_s *netkey_s; bt_mesh_appkey_s *appkey_s; bluetooth_mesh_network_t net; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(netkey); BT_CHECK_INPUT_PARAMETER(appkey); netkey_s = (bt_mesh_netkey_s*)netkey; BT_MESH_VALIDATE_HANDLE(netkey_s, netkey_list); network_s = netkey_s->parent; BT_MESH_VALIDATE_HANDLE(network_s, networks); memset(&net, 0x00, sizeof(bluetooth_mesh_network_t)); g_strlcpy(net.uuid, network_s->uuid, 33); g_strlcpy(net.token.token, network_s->token, 17); g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1); error_code = _bt_get_error_code(bluetooth_mesh_network_add_appkey( &net, netkey_s->netkey_index, &appkey_idx)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } /* Create Appkey object */ appkey_s = g_malloc0(sizeof(bt_mesh_appkey_s)); appkey_s->parent = netkey_s; appkey_s->appkey_index = appkey_idx; netkey_s->appkeys = g_slist_append(netkey_s->appkeys, appkey_s); appkey_list = g_slist_append(appkey_list, appkey_s); *appkey = (bt_mesh_appkey_h)appkey_s; FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_appkey_update(bt_mesh_appkey_h appkey) { int error_code = BT_ERROR_NONE; bt_mesh_network_s *network_s; bt_mesh_netkey_s *netkey_s; bt_mesh_appkey_s *appkey_s; bluetooth_mesh_network_t net; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(appkey); appkey_s = (bt_mesh_appkey_s*)appkey; BT_MESH_VALIDATE_HANDLE(appkey_s, appkey_list); netkey_s = appkey_s->parent; BT_MESH_VALIDATE_HANDLE(netkey_s, netkey_list); network_s = netkey_s->parent; BT_MESH_VALIDATE_HANDLE(network_s, networks); memset(&net, 0x00, sizeof(bluetooth_mesh_network_t)); g_strlcpy(net.uuid, network_s->uuid, 33); g_strlcpy(net.token.token, network_s->token, 17); g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1); error_code = _bt_get_error_code(bluetooth_mesh_network_update_appkey( &net, netkey_s->netkey_index, appkey_s->appkey_index)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_appkey_delete(bt_mesh_appkey_h appkey) { int error_code = BT_ERROR_NONE; bt_mesh_network_s *network_s; bt_mesh_netkey_s *netkey_s; bt_mesh_appkey_s *appkey_s; bluetooth_mesh_network_t net; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(appkey); appkey_s = (bt_mesh_appkey_s*)appkey; BT_MESH_VALIDATE_HANDLE(appkey_s, appkey_list); netkey_s = appkey_s->parent; BT_MESH_VALIDATE_HANDLE(netkey_s, netkey_list); network_s = netkey_s->parent; BT_MESH_VALIDATE_HANDLE(network_s, networks); memset(&net, 0x00, sizeof(bluetooth_mesh_network_t)); g_strlcpy(net.uuid, network_s->uuid, 33); g_strlcpy(net.token.token, network_s->token, 17); g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1); error_code = _bt_get_error_code(bluetooth_mesh_network_delete_appkey( &net, netkey_s->netkey_index, appkey_s->appkey_index)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } /* Delete Appkey Object */ netkey_s->appkeys = g_slist_remove(netkey_s->appkeys, appkey_s); appkey_list = g_slist_remove(appkey_list, appkey_s); g_free(appkey_s); FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_netkey_foreach_appkeys(bt_mesh_netkey_h netkey, bt_mesh_appkey_info_cb callback, void *user_data) { int error_code = BT_ERROR_NONE; bt_mesh_netkey_s *netkey_s; bt_mesh_network_s *network_s; bluetooth_mesh_network_t net; int total; int i; GSList *l; GPtrArray *appkeys = NULL; uint16_t *appkey_idx = NULL; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(netkey); BT_CHECK_INPUT_PARAMETER(callback); BT_MESH_VALIDATE_HANDLE(netkey, netkey_list); netkey_s = (bt_mesh_netkey_s*)netkey; network_s = netkey_s->parent; appkeys = g_ptr_array_new(); if (appkeys == NULL) { BT_ERR("Mesh: OUT_OF_MEMORY(0x%08x)", BT_ERROR_OUT_OF_MEMORY); return BT_ERROR_OUT_OF_MEMORY; } memset(&net, 0x00, sizeof(bluetooth_mesh_network_t)); g_strlcpy(net.uuid, network_s->uuid, 33); g_strlcpy(net.token.token, network_s->token, 17); g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1); BT_INFO("Mesh: Find all Appkeys for Netkey : index [%d]", netkey_s->netkey_index); error_code = _bt_get_error_code(bluetooth_mesh_netkey_get_all_appkey( &net, netkey_s->netkey_index, &appkeys)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); g_ptr_array_free(appkeys, TRUE); return error_code; } for (i = 0; i < appkeys->len; i++) { appkey_idx = g_ptr_array_index(appkeys, i); if (appkey_idx) { /* Create and insert netkey object in list */ if (!__bt_mesh_network_is_appkey_added(network_s, netkey_s->netkey_index, *appkey_idx)) { bt_mesh_appkey_s *key; key = g_malloc0(sizeof(bt_mesh_appkey_s)); key->parent = netkey_s; key->appkey_index = *appkey_idx; netkey_s->appkeys = g_slist_append(netkey_s->appkeys, key); appkey_list = g_slist_append(appkey_list, key); } } else { BT_ERR("Mesh: OPERATION_FAILED(0x%08x)", BT_ERROR_OPERATION_FAILED); error_code = BT_ERROR_OPERATION_FAILED; break; } } total = g_slist_length(netkey_s->appkeys); BT_INFO("Mesh: Total appkeys [%d]", total); if (!total) { BT_INFO("Mesh: No AppKey added in NetKey yet!"); callback(BT_ERROR_NONE, (bt_mesh_network_h) network_s, total, (bt_mesh_netkey_h) netkey_s, NULL, 0xFFFF, user_data); return BT_ERROR_NONE; } for (l = netkey_s->appkeys; l; l = g_slist_next(l)) { bt_mesh_appkey_s *appkey_s; appkey_s = l->data; if (!callback(BT_ERROR_NONE, (bt_mesh_network_h) network_s, total, (bt_mesh_netkey_h) netkey_s, (bt_mesh_appkey_h) appkey_s, appkey_s->appkey_index, user_data)) break; } g_ptr_array_foreach(appkeys, (GFunc)g_free, NULL); g_ptr_array_free(appkeys, TRUE); FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_appkey_get_index(bt_mesh_appkey_h appkey, uint16_t *index) { bt_mesh_appkey_s *appkey_s; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(appkey); BT_CHECK_INPUT_PARAMETER(index); BT_MESH_VALIDATE_HANDLE(appkey, appkey_list); appkey_s = (bt_mesh_appkey_s*)appkey; *index = appkey_s->appkey_index; FUNC_EXIT; return BT_ERROR_NONE; } /* Sync API's to bt-service: Discovery API's */ int bt_mesh_network_foreach_devices(bt_mesh_network_h network, bt_mesh_network_device_info_cb callback, void *user_data) { bluetooth_mesh_network_t net; bluetooth_mesh_node_info_t *node_info; GPtrArray *nodes = NULL; int error_code = BT_ERROR_NONE; int i; bt_mesh_network_s *network_s; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(network); BT_CHECK_INPUT_PARAMETER(callback); BT_MESH_VALIDATE_HANDLE(network, networks); nodes = g_ptr_array_new(); if (nodes == NULL) { BT_ERR("Mesh: OUT_OF_MEMORY(0x%08x)", BT_ERROR_OUT_OF_MEMORY); return BT_ERROR_OUT_OF_MEMORY; } network_s = (bt_mesh_network_s*)network; memset(&net, 0x00, sizeof(bluetooth_mesh_network_t)); g_strlcpy(net.uuid, network_s->uuid, 33); g_strlcpy(net.token.token, network_s->token, 17); g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1); error_code = _bt_get_error_code(bluetooth_mesh_network_get_all_nodes(&net, &nodes)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); g_ptr_array_free(nodes, TRUE); return error_code; } BT_INFO("Mesh: Total number of Devices found [%d]", nodes->len); for (i = 0; i < nodes->len; i++) { node_info = g_ptr_array_index(nodes, i); if (node_info) { if (!callback(BT_ERROR_NONE, (bt_mesh_network_h)network_s, nodes->len, node_info->dev_uuid, node_info->primary_unicast, user_data)) { break; } } else { BT_ERR("Mesh: OPERATION_FAILED(0x%08x)", BT_ERROR_OPERATION_FAILED); error_code = BT_ERROR_OPERATION_FAILED; break; } } g_ptr_array_foreach(nodes, (GFunc)g_free, NULL); g_ptr_array_free(nodes, TRUE); FUNC_EXIT; return error_code; } int bt_mesh_node_get_primary_address(bt_mesh_node_h node, uint16_t *primary_address) { bt_mesh_node_s *node_s; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(node); BT_CHECK_INPUT_PARAMETER(primary_address); BT_MESH_VALIDATE_HANDLE(node, node_list); node_s = (bt_mesh_node_s*) node; *primary_address = node_s->unicast; FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_node_foreach_element(bt_mesh_node_h node, bt_mesh_node_element_info_cb callback, void *user_data) { bt_mesh_node_s *node_s; int total = 0; GSList *l; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(node); BT_CHECK_INPUT_PARAMETER(callback); BT_MESH_VALIDATE_HANDLE(node, node_list); node_s = (bt_mesh_node_s*) node; /* Only for Node which is attached to the Network */ #if 0 if (!node_s->is_attached) return BT_ERROR_INVALID_PARAMETER; #endif total = g_slist_length(node_s->elements); if (!total) { callback(BT_ERROR_NONE, (bt_mesh_node_h) node, total, (bt_mesh_element_h) NULL, -1, 0xFFFF, user_data); } for (l = node_s->elements; l; l = g_slist_next(l)) { bt_mesh_element_s *element_s; element_s = l->data; if (!callback(BT_ERROR_NONE, (bt_mesh_node_h) node, total, (bt_mesh_element_h)element_s, element_s->index, (node_s->unicast + element_s->index), user_data)) break; } FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_element_foreach_models(bt_mesh_element_h element, bt_mesh_element_model_info_cb callback, void *user_data) { bluetooth_mesh_network_t net; bt_mesh_network_s *network_s; bt_mesh_node_s *node_s; bt_mesh_element_s *element_s; GPtrArray *models = NULL; GSList *l = NULL; uint32_t *model_info; int error_code = BT_ERROR_NONE; int i; int total; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(element); BT_CHECK_INPUT_PARAMETER(callback); BT_MESH_VALIDATE_HANDLE(element, element_list); element_s = (bt_mesh_element_s*) element; node_s = (bt_mesh_node_s*) element_s->parent; network_s = (bt_mesh_network_s*) node_s->parent; /* Only for local Node */ if (node_s->is_local) { GSList *l; BT_INFO("Mesh: Local element"); total = g_slist_length(element_s->models); if (!total) callback(BT_ERROR_NONE, (bt_mesh_element_h)element_s, 0, (bt_mesh_model_h) NULL, NULL, user_data); for (l = element_s->models; l; l = l->next) { bt_mesh_model_s *model_s = l->data; bt_mesh_model_id_s modid; modid.company_id = model_s->id >> 16; modid.model_id = model_s->id; if (!callback(BT_ERROR_NONE, (bt_mesh_element_h)element_s, total, (bt_mesh_model_h) model_s, &modid, user_data)) { break; } } FUNC_EXIT; return BT_ERROR_NONE; } models = g_ptr_array_new(); if (models == NULL) { BT_ERR("Mesh: OUT_OF_MEMORY(0x%08x)", BT_ERROR_OUT_OF_MEMORY); return BT_ERROR_OUT_OF_MEMORY; } memset(&net, 0x00, sizeof(bluetooth_mesh_network_t)); g_strlcpy(net.uuid, network_s->uuid, 33); g_strlcpy(net.token.token, network_s->token, 17); g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1); BT_INFO("Mesh: Get Models for element of Remote Node"); error_code = _bt_get_error_code(bluetooth_mesh_element_get_all_models(&net, /* Node identity */node_s->unicast, /* eleement identity */element_s->index, /*Output*/ &models)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); g_ptr_array_free(models, TRUE); return error_code; } total = models->len; BT_INFO("Mesh: Total models in element [%d]", total); for (i = 0; i < models->len; i++) { model_info = g_ptr_array_index(models, i); if (model_info) { BT_INFO("Mesh: Model ID [0x%4.4x]", *model_info); /* Skip if Model is already added in the element */ l = g_slist_find_custom(element_s->models, GUINT_TO_POINTER(*model_info), (GCompareFunc)__compare_model_id); if (l) { bt_mesh_model_id_s modid; bt_mesh_model_s *mod = (bt_mesh_model_s*)l->data; modid.company_id = mod->id >> 16; modid.model_id = mod->id; BT_INFO("Mesh: Model ID [0x%4.4x] is already present in element", *model_info); if (!callback(BT_ERROR_NONE, (bt_mesh_element_h)element_s, total, (bt_mesh_model_h) mod, &modid, user_data)) { break; } continue; } /* Create and insert model object in list */ bt_mesh_model_s *mod; bt_mesh_model_id_s modid; mod = g_malloc0(sizeof(bt_mesh_model_s)); mod->parent = element_s; if (node_s->unicast == 0x0001) { mod->is_local = true; } mod->id = *model_info; element_s->models = g_slist_append(element_s->models, mod); model_list = g_slist_append(model_list, mod); modid.company_id = *model_info >> 16; modid.model_id = *model_info; BT_INFO("Mesh: Model was not present in Element, created & inserted"); BT_INFO("Mesh: Total Models present in Element [%d]", g_slist_length(element_s->models)); /* Send Callback */ if (!callback(BT_ERROR_NONE, (bt_mesh_element_h)element_s, total, (bt_mesh_model_h) mod, &modid, user_data)) { break; } } else { BT_ERR("Mesh: OPERATION_FAILED(0x%08x)", BT_ERROR_OPERATION_FAILED); error_code = BT_ERROR_OPERATION_FAILED; break; } } g_ptr_array_foreach(models, (GFunc)g_free, NULL); g_ptr_array_free(models, TRUE); FUNC_EXIT; return error_code; } /* Provisioning & capabilities related*/ int bt_mesh_network_unprovisioned_device_scan(bt_mesh_network_h network, bt_mesh_scan_params_s *scan_params, bt_mesh_network_scan_unprovisioned_device_result_cb callback, void *user_data) { bt_mesh_network_s *network_s; bluetooth_mesh_network_t net; int error_code = BT_ERROR_NONE; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(network); BT_CHECK_INPUT_PARAMETER(scan_params); BT_CHECK_INPUT_PARAMETER(callback); BT_MESH_VALIDATE_HANDLE(network, networks); network_s = (bt_mesh_network_s*)network; memset(&net, 0x00, sizeof(bluetooth_mesh_network_t)); g_strlcpy(net.uuid, network_s->uuid, 33); g_strlcpy(net.token.token, network_s->token, 17); g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1); error_code = _bt_get_error_code(bluetooth_mesh_network_scan( &net, (bluetooth_mesh_scan_param_t*) scan_params)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } _bt_set_cb(BT_EVENT_MESH_NETWORK_SCAN_STATE_CHANGED, callback, user_data); FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_stop_unprovisioned_device_scan(bt_mesh_network_h network) { bt_mesh_network_s *network_s; bluetooth_mesh_network_t net; int error_code = BT_ERROR_NONE; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(network); BT_MESH_VALIDATE_HANDLE(network, networks); network_s = (bt_mesh_network_s*)network; memset(&net, 0x00, sizeof(bluetooth_mesh_network_t)); g_strlcpy(net.uuid, network_s->uuid, 33); g_strlcpy(net.token.token, network_s->token, 17); g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1); error_code = _bt_get_error_code(bluetooth_mesh_network_cancel_scan(&net)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_network_set_provisioning_capabilities(bt_mesh_network_h network, bt_mesh_provisioner_capabilities_s *capabilities) { bt_mesh_network_s *network_s; bluetooth_mesh_network_t net; bluetooth_mesh_provisioner_caps_t caps; int error_code = BT_ERROR_NONE; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(network); BT_CHECK_INPUT_PARAMETER(capabilities); BT_MESH_VALIDATE_HANDLE(network, networks); network_s = (bt_mesh_network_s*)network; memset(&net, 0x00, sizeof(bluetooth_mesh_network_t)); memset(&caps, 0x00, sizeof(bluetooth_mesh_provisioner_caps_t)); g_strlcpy(net.uuid, network_s->uuid, 33); g_strlcpy(net.token.token, network_s->token, 17); g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1); caps.public_oob = capabilities->public_oob; caps.static_oob = capabilities->static_oob; caps.out_oob = capabilities->out_oob; caps.in_oob = capabilities->in_oob; error_code = _bt_get_error_code(bluetooth_mesh_network_set_capabilities( &net,(bluetooth_mesh_provisioner_caps_t*) &caps)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_network_provision_device(bt_mesh_network_h network, const char *dev_uuid, bt_mesh_network_device_provision_cb callback, void *user_data) { bt_mesh_network_s *network_s; bluetooth_mesh_provisioning_request_t req; int error_code = BT_ERROR_NONE; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(network); BT_CHECK_INPUT_PARAMETER(dev_uuid); BT_CHECK_INPUT_PARAMETER(callback); BT_MESH_VALIDATE_HANDLE(network, networks); network_s = (bt_mesh_network_s*)network; memset(&req, 0x00, sizeof(bluetooth_mesh_provisioning_request_t)); g_strlcpy(req.net_uuid, network_s->uuid, 33); g_strlcpy(req.dev_uuid, dev_uuid, 33); BT_INFO("Mesh: Provision Device [%s]", dev_uuid); error_code = _bt_get_error_code(bluetooth_mesh_network_provision_device(&req)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } _bt_set_cb(BT_EVENT_MESH_NETWORK_PROVISIONING_RESULT, callback, user_data); FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_authentication_set_request_cb(bt_mesh_authentication_request_cb callback, void *user_data) { FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(callback); _bt_set_cb(BT_EVENT_MESH_AUTHENTICATION_REQUEST, callback, user_data); FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_authentication_unset_request_cb(bt_mesh_authentication_request_cb callback) { FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(callback); _bt_unset_cb(BT_EVENT_MESH_AUTHENTICATION_REQUEST); FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_authentication_reply(bt_mesh_authentication_type_e auth_type, const char *value, bool auth_reply) { int error_code = BT_ERROR_NONE; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(value); error_code = _bt_get_error_code(bluetooth_mesh_authentication_reply(auth_type, value, auth_reply)); if (error_code != BT_ERROR_NONE) BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); FUNC_EXIT; return error_code; } int bt_mesh_network_discover_node(bt_mesh_network_h network, const char *dev_uuid, bt_mesh_node_discover_status_cb callback, void *user_data) { int error_code = BT_ERROR_NONE; bt_mesh_network_s *network_s; bluetooth_mesh_node_discover_t req; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(network); BT_CHECK_INPUT_PARAMETER(dev_uuid); BT_CHECK_INPUT_PARAMETER(callback); BT_MESH_VALIDATE_HANDLE(network, networks); /* Check if node with dev_uuid is already created */ network_s = (bt_mesh_network_s*)network; memset(&req, 0x00, sizeof(bluetooth_mesh_node_discover_t)); g_strlcpy(req.net_uuid, network_s->uuid, 33); g_strlcpy(req.dev_uuid, dev_uuid, 33); error_code = _bt_get_error_code(bluetooth_mesh_browse_remote_node(&req)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } FUNC_EXIT; _bt_set_cb(BT_EVENT_MESH_NODE_BROWSING_COMPLETED, callback, user_data); return BT_ERROR_NONE; } int bt_mesh_node_configure_netkey(bt_mesh_node_h node, bt_mesh_node_key_configuration_e netkey_op, bt_mesh_netkey_h netkey, bt_mesh_netkey_status_cb callback, void *user_data) { int error_code = BT_ERROR_NONE; bt_mesh_network_s *network_s; bt_mesh_node_s *node_s; bt_mesh_netkey_s *netkey_s; bluetooth_mesh_key_configure_t req; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(node); BT_CHECK_INPUT_PARAMETER(netkey); BT_CHECK_INPUT_PARAMETER(callback); node_s = (bt_mesh_node_s*) node; network_s = node_s->parent; netkey_s = (bt_mesh_netkey_s*) netkey; BT_MESH_VALIDATE_HANDLE(network_s, networks); BT_MESH_VALIDATE_HANDLE(node_s, node_list); BT_MESH_VALIDATE_HANDLE(netkey_s, netkey_list); /* Return error, if node is not attached */ if (!node_s->is_attached) return BT_ERROR_INVALID_PARAMETER; /* Return error, if netkey is not present in the specific network */ if (netkey_s->parent != network_s) return BT_ERROR_INVALID_PARAMETER; #if 0 /* Return Already done, if netkey is present in the node */ if (g_slist_find_custom(node_s->netkeys,(gconstpointer) netkey_s, (GCompareFunc)__simple_compare)) return BT_ERROR_ALREADY_DONE; #endif memset(&req, 0x00, sizeof(bluetooth_mesh_key_configure_t)); g_strlcpy(req.net_uuid, network_s->uuid, 33); req.primary_unicast = node_s->unicast; req.netkey_idx = netkey_s->netkey_index; req.is_netkey = true; req.op = (bluetooth_mesh_node_key_conf_e) netkey_op; BT_INFO("Mesh: Add NetKey Idx [%d] to node", req.netkey_idx); error_code = _bt_get_error_code(bluetooth_mesh_node_configure_key(&req)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } FUNC_EXIT; _bt_set_cb(BT_EVENT_MESH_NODE_KEY_CONFIGURATION_COMPLETED, callback, user_data); return BT_ERROR_NONE; } int bt_mesh_node_configure_appkey(bt_mesh_node_h node, bt_mesh_node_key_configuration_e appkey_op, bt_mesh_appkey_h appkey, bt_mesh_appkey_status_cb callback, void *user_data) { int error_code = BT_ERROR_NONE; bt_mesh_network_s *network_s; bt_mesh_node_s *node_s; bt_mesh_netkey_s *netkey_s; bt_mesh_appkey_s *appkey_s; bluetooth_mesh_key_configure_t req; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(node); BT_CHECK_INPUT_PARAMETER(appkey); BT_CHECK_INPUT_PARAMETER(callback); node_s = (bt_mesh_node_s*) node; network_s = node_s->parent; appkey_s = (bt_mesh_appkey_s*) appkey; netkey_s = (bt_mesh_netkey_s*) appkey_s->parent; BT_MESH_VALIDATE_HANDLE(network_s, networks); BT_MESH_VALIDATE_HANDLE(node_s, node_list); BT_MESH_VALIDATE_HANDLE(appkey_s, appkey_list); BT_MESH_VALIDATE_HANDLE(netkey_s, netkey_list); /* Return error, if node is not attached */ if (!node_s->is_attached) return BT_ERROR_INVALID_PARAMETER; /* Return error, if netkey is not present in the specific network */ if (netkey_s->parent != network_s) return BT_ERROR_INVALID_PARAMETER; memset(&req, 0x00, sizeof(bluetooth_mesh_key_configure_t)); g_strlcpy(req.net_uuid, network_s->uuid, 33); req.primary_unicast = node_s->unicast; req.netkey_idx = netkey_s->netkey_index; req.appkey_idx = appkey_s->appkey_index; req.is_netkey = false; req.op = (bluetooth_mesh_node_key_conf_e) appkey_op; error_code = _bt_get_error_code(bluetooth_mesh_node_configure_key(&req)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } FUNC_EXIT; _bt_set_cb(BT_EVENT_MESH_NODE_KEY_CONFIGURATION_COMPLETED, callback, user_data); return BT_ERROR_NONE; } /* Remote Node Operations: CONFIG: Non Key */ int bt_mesh_node_get_features(bt_mesh_node_h node, bt_mesh_node_features_cb callback, void *user_data) { int error_code = BT_ERROR_NONE; bt_mesh_network_s *network_s; bt_mesh_node_s *node_s; bluetooth_mesh_node_features_t req; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(node); BT_CHECK_INPUT_PARAMETER(callback); node_s = (bt_mesh_node_s*) node; /* Return error, if node is not attached */ if (!node_s->is_attached) return BT_ERROR_INVALID_PARAMETER; network_s = (bt_mesh_network_s*) node_s->parent; BT_MESH_VALIDATE_HANDLE(network_s, networks); BT_MESH_VALIDATE_HANDLE(node_s, node_list); memset(&req, 0x00, sizeof(bluetooth_mesh_node_features_t)); g_strlcpy(req.net_uuid, network_s->uuid, 33); req.unicast = node_s->unicast; req.elem_count = node_s->unicast; error_code = _bt_get_error_code(bluetooth_mesh_node_browse_vendor_features(&req)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } FUNC_EXIT; _bt_set_cb(BT_EVENT_MESH_NODE_VENDOR_FEATURES, callback, user_data); return BT_ERROR_NONE; } int bt_mesh_node_get_ttl(bt_mesh_node_h node, bt_mesh_node_ttl_cb callback, void *user_data) { int error_code = BT_ERROR_NONE; bt_mesh_network_s *network_s; bt_mesh_node_s *node_s; bluetooth_mesh_node_ttl_info_t req; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(node); BT_CHECK_INPUT_PARAMETER(callback); node_s = (bt_mesh_node_s*) node; network_s = node_s->parent; BT_MESH_VALIDATE_HANDLE(network_s, networks); BT_MESH_VALIDATE_HANDLE(node_s, node_list); /* Return error, if node is not attached */ if (!node_s->is_attached) return BT_ERROR_INVALID_PARAMETER; memset(&req, 0x00, sizeof(bluetooth_mesh_node_ttl_info_t)); g_strlcpy(req.net_uuid, network_s->uuid, 33); req.unicast = node_s->unicast; req.is_set = false; error_code = _bt_get_error_code(bluetooth_mesh_node_ttl_execute(&req)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } FUNC_EXIT; _bt_set_cb(BT_EVENT_MESH_NODE_TTL_EXECUTE_COMPLETED, callback, user_data); return BT_ERROR_NONE; } int bt_mesh_node_set_ttl(bt_mesh_node_h node, uint8_t ttl, bt_mesh_node_ttl_cb callback, void *user_data) { int error_code = BT_ERROR_NONE; bt_mesh_network_s *network_s; bt_mesh_node_s *node_s; bluetooth_mesh_node_ttl_info_t req; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(node); BT_CHECK_INPUT_PARAMETER(callback); node_s = (bt_mesh_node_s*) node; network_s = node_s->parent; BT_CHECK_INPUT_PARAMETER(network_s); BT_MESH_VALIDATE_HANDLE(network_s, networks); BT_MESH_VALIDATE_HANDLE(node_s, node_list); /* Return error, if node is not attached */ if (!node_s->is_attached) return BT_ERROR_INVALID_PARAMETER; memset(&req, 0x00, sizeof(bluetooth_mesh_node_ttl_info_t)); g_strlcpy(req.net_uuid, network_s->uuid, 33); req.unicast = node_s->unicast; req.is_set = true; req.ttl = ttl; error_code = _bt_get_error_code(bluetooth_mesh_node_ttl_execute(&req)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } FUNC_EXIT; _bt_set_cb(BT_EVENT_MESH_NODE_TTL_EXECUTE_COMPLETED, callback, user_data); return BT_ERROR_NONE; } int bt_mesh_node_foreach_netkeys(bt_mesh_node_h node, bt_mesh_node_netkey_info_cb callback, void *user_data) { GPtrArray *netkeys = NULL; GSList *l; int error_code = BT_ERROR_NONE; uint16_t *netkey_idx = NULL; int i; int total; bluetooth_mesh_node_discover_t req; bt_mesh_network_s *network_s; bt_mesh_node_s *node_s; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(node); BT_CHECK_INPUT_PARAMETER(callback); node_s = (bt_mesh_node_s*) node; network_s = node_s->parent; BT_CHECK_INPUT_PARAMETER(network_s); BT_MESH_VALIDATE_HANDLE(network_s, networks); BT_MESH_VALIDATE_HANDLE(node_s, node_list); /* Return error, if node is not attached */ if (!node_s->is_attached) return BT_ERROR_INVALID_PARAMETER; netkeys = g_ptr_array_new(); if (netkeys == NULL) { BT_ERR("Mesh: OUT_OF_MEMORY(0x%08x)", BT_ERROR_OUT_OF_MEMORY); return BT_ERROR_OUT_OF_MEMORY; } memset(&req, 0x00, sizeof(bluetooth_mesh_node_discover_t)); g_strlcpy(req.net_uuid, network_s->uuid, 33); req.unicast = node_s->unicast; error_code = _bt_get_error_code(bluetooth_mesh_node_get_all_netkeys(&req, &netkeys)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); g_ptr_array_free(netkeys, TRUE); return error_code; } BT_INFO("Mesh: Total netkeys added in node is [%d]", netkeys->len); for (i = 0; i < netkeys->len; i++) { bt_mesh_netkey_s *netkey_local; netkey_idx = g_ptr_array_index(netkeys, i); if (netkey_idx) { /* Check if netkey index is present in network or not */ BT_INFO("Mesh: NetKey IDX [%d]", *netkey_idx); netkey_local = __bt_mesh_network_is_netkey_added(network_s, *netkey_idx); if (!netkey_local) { BT_ERR("Mesh: Network does not contain the netKey index, possibly reloaded"); /* Create Netkey object */ netkey_local = g_malloc0(sizeof(bt_mesh_netkey_s)); netkey_local->parent = network_s; netkey_local->netkey_index = *netkey_idx; network_s->netkeys = g_slist_append(network_s->netkeys, netkey_local); netkey_list = g_slist_append(netkey_list, netkey_local); if (!g_slist_find_custom(node_s->netkeys, GUINT_TO_POINTER(*netkey_idx), (GCompareFunc)__compare_netkey_index)) node_s->netkeys = g_slist_append(node_s->netkeys, netkey_local); } else { /* Check if netkey index is present in target node or not */ if (!g_slist_find_custom(node_s->netkeys,(gconstpointer) netkey_local, (GCompareFunc)__simple_compare)) { node_s->netkeys = g_slist_append(node_s->netkeys, netkey_local); } else { /* DO NOTHING*/ BT_INFO("Mesh: Netkey is already added in node"); } } } else { BT_ERR("Mesh: OPERATION_FAILED(0x%08x)", BT_ERROR_OPERATION_FAILED); error_code = BT_ERROR_OPERATION_FAILED; break; } } total = g_slist_length(node_s->netkeys); if (total == 0) { BT_ERR("Mesh: Unexpcted: No netkey added in node!!"); callback(BT_ERROR_NONE, (bt_mesh_node_h)node_s, total, NULL, 0xFFFF, user_data); } for (l = node_s->netkeys; l != NULL; l = g_slist_next(l)) { bt_mesh_netkey_s *netkey; netkey = l->data; if (!callback(BT_ERROR_NONE, (bt_mesh_node_h)node_s, total, (bt_mesh_netkey_h) netkey, netkey->netkey_index, user_data)) { break; } } if (netkeys) { g_ptr_array_foreach(netkeys, (GFunc)g_free, NULL); g_ptr_array_free(netkeys, TRUE); } FUNC_EXIT; return error_code; } int bt_mesh_node_foreach_appkeys(bt_mesh_node_h node, bt_mesh_netkey_h netkey, bt_mesh_node_appkey_info_cb callback, void *user_data) { GPtrArray *appkeys = NULL; int error_code = BT_ERROR_NONE; int i; bluetooth_mesh_node_discover_t req; uint16_t *appkey_idx = NULL; bt_mesh_network_s *network_s; bt_mesh_node_s *node_s; bt_mesh_netkey_s *netkey_s; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(node); BT_CHECK_INPUT_PARAMETER(netkey); BT_CHECK_INPUT_PARAMETER(callback); node_s = (bt_mesh_node_s*) node; network_s = node_s->parent; netkey_s = (bt_mesh_netkey_s*) netkey; BT_CHECK_INPUT_PARAMETER(network_s); BT_MESH_VALIDATE_HANDLE(network_s, networks); BT_MESH_VALIDATE_HANDLE(node_s, node_list); BT_MESH_VALIDATE_HANDLE(netkey_s, netkey_list); /* Return error, if node is not attached */ if (!node_s->is_attached) return BT_ERROR_INVALID_PARAMETER; appkeys = g_ptr_array_new(); if (appkeys == NULL) { BT_ERR("Mesh: OUT_OF_MEMORY(0x%08x)", BT_ERROR_OUT_OF_MEMORY); return BT_ERROR_OUT_OF_MEMORY; } memset(&req, 0x00, sizeof(bluetooth_mesh_node_discover_t)); g_strlcpy(req.net_uuid, network_s->uuid, 33); req.unicast = node_s->unicast; req.netkey_idx = netkey_s->netkey_index; error_code = _bt_get_error_code(bluetooth_mesh_node_get_all_appkeys(&req, &appkeys)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); g_ptr_array_free(appkeys, TRUE); return error_code; } BT_INFO("Mesh: Total appkeys found in Node [%d]", appkeys->len); for (i = 0; i < appkeys->len; i++) { bt_mesh_appkey_s *appkey_local; appkey_idx = g_ptr_array_index(appkeys, i); if (appkey_idx) { /* Check if appkey index is present in network or not */ BT_INFO("Mesh: AppKey index [%d]", *appkey_idx); appkey_local = __bt_mesh_network_is_appkey_added(network_s, netkey_s->netkey_index, *appkey_idx); if (!appkey_local) { BT_ERR("Mesh: Network does not AppKey index, possibly Network reloaded!!"); /* Create Appkey object */ appkey_local = g_malloc0(sizeof(bt_mesh_appkey_s)); appkey_local->parent = netkey_s; appkey_local->appkey_index = *appkey_idx; netkey_s->appkeys = g_slist_append(netkey_s->appkeys, appkey_local); appkey_list = g_slist_append(appkey_list, appkey_local); if (!g_slist_find_custom(node_s->appkeys, GUINT_TO_POINTER(*appkey_idx), (GCompareFunc)__compare_appkey_index)) node_s->appkeys = g_slist_append(node_s->appkeys, appkey_local); } else { /* Check if netkey index is present in target node or not */ if (!g_slist_find_custom(node_s->appkeys, GUINT_TO_POINTER(*appkey_idx), (GCompareFunc)__compare_appkey_index)) { node_s->appkeys = g_slist_append(node_s->appkeys, appkey_local); } else { /* DO NOTHING*/ BT_INFO("Mesh: AppKey is already added in node"); } } /* Send CallBack */ if (!callback(BT_ERROR_NONE, (bt_mesh_node_h)node_s, appkeys->len, (bt_mesh_netkey_h) netkey, (bt_mesh_appkey_h) appkey_local, appkey_local->appkey_index, user_data)) { break; } } else { BT_ERR("Mesh: OPERATION_FAILED(0x%08x)", BT_ERROR_OPERATION_FAILED); error_code = BT_ERROR_OPERATION_FAILED; break; } } if (appkeys->len == 0) { BT_ERR("Mesh: No appkey configured for the bound netkey Idx [%d]", req.netkey_idx); callback(BT_ERROR_NONE, (bt_mesh_node_h)node_s, 0, (bt_mesh_netkey_h) netkey_s, NULL, 0xFFFF, user_data); } if (appkeys) { g_ptr_array_foreach(appkeys, (GFunc)g_free, NULL); g_ptr_array_free(appkeys, TRUE); } FUNC_EXIT; return error_code; } int bt_mesh_model_bind_appkey(bt_mesh_model_h model, bt_mesh_appkey_h appkey, bt_mesh_model_bind_cb callback, void *user_data) { int error_code = BT_ERROR_NONE; bt_mesh_model_s *model_s; bt_mesh_element_s *element_s; bt_mesh_node_s *node_s; bt_mesh_network_s *network_s; bt_mesh_appkey_s *appkey_s; bluetooth_mesh_model_configure_t req; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(model); BT_CHECK_INPUT_PARAMETER(appkey); BT_CHECK_INPUT_PARAMETER(callback); model_s = (bt_mesh_model_s*) model; element_s = (bt_mesh_element_s*) model_s->parent; node_s = (bt_mesh_node_s*) element_s->parent; appkey_s = (bt_mesh_appkey_s*) appkey; network_s = (bt_mesh_network_s*) node_s->parent; BT_MESH_VALIDATE_HANDLE(model_s, model_list); BT_MESH_VALIDATE_HANDLE(element_s, element_list); BT_MESH_VALIDATE_HANDLE(appkey_s, appkey_list); BT_MESH_VALIDATE_HANDLE(node_s, node_list); BT_MESH_VALIDATE_HANDLE(network_s, networks); /* Return error, if node is not attached */ if (!node_s->is_attached) return BT_ERROR_INVALID_PARAMETER; memset(&req, 0x00, sizeof(bluetooth_mesh_model_configure_t)); g_strlcpy(req.net_uuid, network_s->uuid, 33); req.primary_unicast = node_s->unicast; req.elem_index = element_s->index; req.model = model_s->id; req.appkey_idx = appkey_s->appkey_index; req.is_bind = true; error_code = _bt_get_error_code(bluetooth_mesh_model_configure_appkey(&req)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } FUNC_EXIT; _bt_set_cb(BT_EVENT_MESH_NODE_MODEL_BIND_APPKEY_COMPLETED, callback, user_data); return BT_ERROR_NONE; } int bt_mesh_model_unbind_appkey(bt_mesh_model_h model, bt_mesh_appkey_h appkey, bt_mesh_model_unbind_cb callback, void *user_data) { int error_code = BT_ERROR_NONE; bt_mesh_model_s *model_s; bt_mesh_element_s *element_s; bt_mesh_node_s *node_s; bt_mesh_appkey_s *appkey_s; bt_mesh_network_s *network_s; bluetooth_mesh_model_configure_t req; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(model); BT_CHECK_INPUT_PARAMETER(appkey); BT_CHECK_INPUT_PARAMETER(callback); model_s = (bt_mesh_model_s*) model; element_s = (bt_mesh_element_s*) model_s->parent; node_s = (bt_mesh_node_s*) element_s->parent; appkey_s = (bt_mesh_appkey_s*) appkey; network_s = (bt_mesh_network_s*) node_s->parent; BT_MESH_VALIDATE_HANDLE(model_s, model_list); BT_MESH_VALIDATE_HANDLE(appkey_s, appkey_list); BT_MESH_VALIDATE_HANDLE(element_s, element_list); BT_MESH_VALIDATE_HANDLE(node_s, node_list); BT_MESH_VALIDATE_HANDLE(network_s, networks); /* Return error, if node is not attached */ if (!node_s->is_attached) return BT_ERROR_INVALID_PARAMETER; memset(&req, 0x00, sizeof(bluetooth_mesh_model_configure_t)); g_strlcpy(req.net_uuid, network_s->uuid, 33); req.primary_unicast = node_s->unicast; req.elem_index = element_s->index; req.model = model_s->id; req.appkey_idx = appkey_s->appkey_index; req.is_bind = false; error_code = _bt_get_error_code(bluetooth_mesh_model_configure_appkey(&req)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } FUNC_EXIT; _bt_set_cb(BT_EVENT_MESH_NODE_MODEL_BIND_APPKEY_COMPLETED, callback, user_data); return BT_ERROR_NONE; } int bt_mesh_model_get_appkey_list(bt_mesh_model_h model, bt_mesh_model_appkey_list_cb callback, void *user_data) { int error_code = BT_ERROR_NONE; bt_mesh_model_s *model_s; bt_mesh_element_s *element_s; bt_mesh_node_s *node_s; bt_mesh_network_s *network_s; bluetooth_mesh_model_configure_t req; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(model); BT_CHECK_INPUT_PARAMETER(callback); model_s = (bt_mesh_model_s*) model; BT_MESH_VALIDATE_HANDLE(model_s, model_list); element_s = (bt_mesh_element_s*) model_s->parent; BT_CHECK_INPUT_PARAMETER(element_s); BT_MESH_VALIDATE_HANDLE(element_s, element_list); node_s = (bt_mesh_node_s*) element_s->parent; BT_CHECK_INPUT_PARAMETER(node_s); BT_MESH_VALIDATE_HANDLE(node_s, node_list); network_s = (bt_mesh_network_s*) node_s->parent; BT_CHECK_INPUT_PARAMETER(network_s); BT_MESH_VALIDATE_HANDLE(network_s, networks); /* Return error, if node is not attached */ if (!node_s->is_attached) return BT_ERROR_INVALID_PARAMETER; memset(&req, 0x00, sizeof(bluetooth_mesh_model_configure_t)); g_strlcpy(req.net_uuid, network_s->uuid, 33); req.primary_unicast = node_s->unicast; req.elem_index = element_s->index; req.model = model_s->id; error_code = _bt_get_error_code(bluetooth_mesh_model_get_all_appkeys(&req)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } FUNC_EXIT; _bt_set_cb(BT_EVENT_MESH_NODE_MODEL_APPKEY_LIST, callback, user_data); return error_code; } int bt_mesh_network_foreach_groups(bt_mesh_network_h network, bt_mesh_network_group_info_cb callback, void *user_data) { int error_code = BT_ERROR_NONE; bluetooth_mesh_network_t net; bt_mesh_network_s *network_s; GPtrArray *groups = NULL; GSList *l = NULL; bluetooth_mesh_network_group_info_t *group_info = NULL; int i; int total; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(network); BT_CHECK_INPUT_PARAMETER(callback); BT_MESH_VALIDATE_HANDLE(network, networks); groups = g_ptr_array_new(); if (groups == NULL) { BT_ERR("Mesh: OUT_OF_MEMORY(0x%08x)", BT_ERROR_OUT_OF_MEMORY); return BT_ERROR_OUT_OF_MEMORY; } network_s = (bt_mesh_network_s*)network; memset(&net, 0x00, sizeof(bluetooth_mesh_network_t)); g_strlcpy(net.uuid, network_s->uuid, 33); g_strlcpy(net.token.token, network_s->token, 17); g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1); error_code = _bt_get_error_code(bluetooth_mesh_network_get_all_groups(&net, &groups)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); g_ptr_array_free(groups, TRUE); return error_code; } BT_INFO("Mesh: Total number of Groups in network [%d]", groups->len); for (i = 0; i < groups->len; i++) { group_info = g_ptr_array_index(groups, i); if (group_info) { BT_INFO("Mesh: Group Is Virtual [%s] Group Addr [0x%2.2x]", group_info->is_virtual ? "YES" : "NO", group_info->group_addr); if (group_info->is_virtual) BT_INFO("Mesh: Virtual label UUID [%s]", group_info->label_uuid); BT_INFO("Mesh: Total groups already present in Network [%d]", g_slist_length(network_s->groups)); /* Find or create group in network list */ if (!g_slist_find_custom(network_s->groups, GUINT_TO_POINTER(group_info->group_addr), (GCompareFunc)__compare_network_group_address)) { BT_INFO("Mesh: Its a new Group, add in network"); bt_mesh_group_s *group_s; group_s = g_malloc0(sizeof(bt_mesh_group_s)); group_s->addr = group_info->group_addr; group_s->parent = network_s; group_s->is_virtual = group_info->is_virtual; if (group_s->is_virtual) g_strlcpy(group_s->label_uuid, group_info->label_uuid, sizeof(group_s->label_uuid)); BT_INFO("Mesh: Group [0x%2.2x] added in network", group_s->addr); network_s->groups = g_slist_append(network_s->groups, group_s); group_list = g_slist_append(group_list, group_s); } else BT_INFO("Mesh: Group [0x%2.2x] Already Added in network", group_info->group_addr); } else { BT_ERR("Mesh: OPERATION_FAILED(0x%08x)", BT_ERROR_OPERATION_FAILED); error_code = BT_ERROR_OPERATION_FAILED; break; } } total = g_slist_length(network_s->groups); BT_INFO("Mesh: Total number of groups [%d]", total); if (total == 0) { BT_INFO("Mesh: No Groups added in network"); callback(BT_ERROR_NONE, (bt_mesh_network_h)network_s, total, NULL, user_data); } for (l = network_s->groups; l != NULL; l = g_slist_next(l)) { bt_mesh_group_s *group_s; group_s = l->data; if (!callback(BT_ERROR_NONE, (bt_mesh_network_h)network_s, total, (bt_mesh_group_h) group_s, user_data)) break; } g_ptr_array_foreach(groups, (GFunc)g_free, NULL); g_ptr_array_free(groups, TRUE); FUNC_EXIT; return error_code; } int bt_mesh_network_create_virtual_group(bt_mesh_network_h network, bt_mesh_group_h *group) { int error_code = BT_ERROR_NONE; bt_mesh_network_s *network_s; bt_mesh_group_s *group_s; bluetooth_mesh_network_group_info_t req; bluetooth_mesh_network_t net; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(network); network_s = (bt_mesh_network_s*) network; BT_MESH_VALIDATE_HANDLE(network_s, networks); memset(&net, 0x00, sizeof(bluetooth_mesh_network_t)); memset(&req, 0x00, sizeof(bluetooth_mesh_network_group_info_t)); g_strlcpy(net.uuid, network_s->uuid, 33); g_strlcpy(net.token.token, network_s->token, 17); g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1); error_code = _bt_get_error_code(bluetooth_mesh_network_create_group(&net, true, 0x0000, &req)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } group_s = g_malloc0(sizeof(bt_mesh_group_s)); group_s->addr = req.group_addr; group_s->is_virtual = true; group_s->parent = network_s; g_strlcpy(group_s->label_uuid, req.label_uuid, BT_MESH_UUID_STRING_LEN + 1); BT_INFO("Mesh: Virtual Group created : Addr [0x%2.2x]", req.group_addr); BT_INFO("Mesh: Virtual Group label UUID [%s]", group_s->label_uuid); network_s->groups = g_slist_append(network_s->groups, group_s); group_list = g_slist_append(group_list, group_s); *group = (bt_mesh_group_h) group_s; FUNC_EXIT; return error_code; } int bt_mesh_network_remove_group(bt_mesh_group_h group) { int error_code = BT_ERROR_NONE; bt_mesh_network_s *network_s; bt_mesh_group_s *group_s; bluetooth_mesh_network_group_info_t req; bluetooth_mesh_network_t net; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_INPUT_PARAMETER(group); group_s = (bt_mesh_group_s*) group; BT_MESH_VALIDATE_HANDLE(group_s, group_list); network_s = group_s->parent; memset(&net, 0x00, sizeof(bluetooth_mesh_network_t)); memset(&req, 0x00, sizeof(bluetooth_mesh_network_group_info_t)); BT_INFO("Mesh: Remove Group [0x%2.2x] from network", group_s->addr); BT_INFO("Mesh: Is Group Virtual [%s]", group_s->is_virtual? "YES": "NO"); if (group_s->is_virtual) BT_INFO("Mesh: Group Label UUID [%s]", group_s->label_uuid); /* Fill Network Info */ g_strlcpy(net.uuid, network_s->uuid, 33); g_strlcpy(net.token.token, network_s->token, 17); g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1); /* Fill Group Info */ g_strlcpy(req.net_uuid, network_s->uuid, 33); req.is_virtual = group_s->is_virtual; req.group_addr = group_s->addr; if (req.is_virtual) g_strlcpy(req.label_uuid, group_s->label_uuid, sizeof(req.label_uuid)); error_code = _bt_get_error_code(bluetooth_mesh_network_remove_group(&net, &req)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); FUNC_EXIT; return error_code; } network_s->groups = g_slist_remove(network_s->groups, group_s); group_list = g_slist_remove(group_list, group_s); g_free(group_s); FUNC_EXIT; return BT_ERROR_NONE; } int bt_mesh_network_create_group(bt_mesh_network_h network, uint16_t grp_addr, bt_mesh_group_h *group) { int error_code = BT_ERROR_NONE; bt_mesh_network_s *network_s; bt_mesh_group_s *group_s; bluetooth_mesh_network_t net; bluetooth_mesh_network_group_info_t req; GSList *l; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(network); BT_CHECK_INPUT_PARAMETER(group); network_s = (bt_mesh_network_s*) network; BT_MESH_VALIDATE_HANDLE(network_s, networks); /* Check for valid Group Address */ if (!BT_MESH_IS_GROUP(grp_addr)) { BT_INFO("Mesh: group Address [0x%2.2x] is not valid Group Address", grp_addr); return BT_ERROR_INVALID_PARAMETER; } l = g_slist_find_custom(network_s->groups, GUINT_TO_POINTER(grp_addr), (GCompareFunc)__compare_group_address); if (l) { BT_INFO("Mesh: Group [0x%2.2x]Already exist", grp_addr); group_s = l->data; *group = (bt_mesh_group_h) group_s; FUNC_EXIT; return error_code; } memset(&net, 0x00, sizeof(bluetooth_mesh_network_t)); memset(&req, 0x00, sizeof(bluetooth_mesh_network_group_info_t)); /* Fill Network Info */ g_strlcpy(net.uuid, network_s->uuid, 33); g_strlcpy(net.token.token, network_s->token, 17); g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1); error_code = _bt_get_error_code(bluetooth_mesh_network_create_group(&net, false, grp_addr, &req)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } BT_INFO("Mesh: Group created [0x%2.2x]", grp_addr); group_s = g_malloc0(sizeof(bt_mesh_group_s)); group_s->addr = grp_addr; group_s->is_virtual = false; group_s->parent = network_s; network_s->groups = g_slist_append(network_s->groups, group_s); group_list = g_slist_append(group_list, group_s); *group = (bt_mesh_group_h) group_s; FUNC_EXIT; return error_code; } int bt_mesh_model_configure_group_subscription(bt_mesh_model_subscription_op_e model_op, bt_mesh_model_h model, bt_mesh_group_h group, bt_mesh_model_subscription_op_cb callback, void *user_data) { int error_code = BT_ERROR_NONE; bt_mesh_model_s *model_s; bt_mesh_element_s *element_s; bt_mesh_node_s *node_s; bt_mesh_network_s *network_s; bt_mesh_group_s *group_s; bluetooth_mesh_model_configure_t req; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(model); BT_CHECK_INPUT_PARAMETER(group); BT_CHECK_INPUT_PARAMETER(callback); model_s = (bt_mesh_model_s*) model; BT_MESH_VALIDATE_HANDLE(model_s, model_list); group_s = (bt_mesh_group_s*) group; BT_MESH_VALIDATE_HANDLE(group_s, group_list); element_s = (bt_mesh_element_s*) model_s->parent; BT_MESH_VALIDATE_HANDLE(element_s, element_list); node_s = (bt_mesh_node_s*) element_s->parent; BT_MESH_VALIDATE_HANDLE(node_s, node_list); network_s = (bt_mesh_network_s*) node_s->parent; BT_MESH_VALIDATE_HANDLE(network_s, networks); BT_INFO("Mesh: Configure Group Request [%d]", model_op); BT_INFO("Mesh: Group Addr [0x%2.2x] Is Virtual [%s]", group_s->addr, group_s->is_virtual? "YES" : "NO"); /* Check group belongs to the same network */ if (network_s != group_s->parent) return BT_ERROR_INVALID_PARAMETER; /* Check group is non virtual */ if (group_s->is_virtual) return BT_ERROR_INVALID_PARAMETER; /* Return error, if node is not attached */ if (!node_s->is_attached) return BT_ERROR_INVALID_PARAMETER; if (model_op != BT_MESH_MODEL_SUBSCRIPTION_DELETE_ALL) req.sub_addr = group_s->addr; req.is_virtual_sub = false; req.op = model_op; g_strlcpy(req.net_uuid, network_s->uuid, 33); req.primary_unicast = node_s->unicast; req.elem_index = element_s->index; req.model = model_s->id; error_code = _bt_get_error_code(bluetooth_mesh_model_configure_group_sub(&req)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } FUNC_EXIT; _bt_set_cb(BT_EVENT_MESH_NODE_MODEL_GROUP_SUB, callback, user_data); return error_code; } int bt_mesh_model_configure_virtual_group_subscription(bt_mesh_model_subscription_op_e model_op, bt_mesh_model_h model, bt_mesh_group_h group, bt_mesh_model_subscription_op_cb callback, void *user_data) { int error_code = BT_ERROR_NONE; bt_mesh_model_s *model_s; bt_mesh_element_s *element_s; bt_mesh_node_s *node_s; bt_mesh_network_s *network_s; bt_mesh_group_s *group_s; bluetooth_mesh_model_configure_t req; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(model); BT_CHECK_INPUT_PARAMETER(group); BT_CHECK_INPUT_PARAMETER(callback); model_s = (bt_mesh_model_s*) model; BT_MESH_VALIDATE_HANDLE(model_s, model_list); group_s = (bt_mesh_group_s*) group; BT_MESH_VALIDATE_HANDLE(group_s, group_list); element_s = (bt_mesh_element_s*) model_s->parent; BT_MESH_VALIDATE_HANDLE(element_s, element_list); node_s = (bt_mesh_node_s*) element_s->parent; BT_MESH_VALIDATE_HANDLE(node_s, node_list); network_s = (bt_mesh_network_s*) node_s->parent; BT_MESH_VALIDATE_HANDLE(network_s, networks); BT_INFO("Mesh: Configure Virtual Group Request [%d]", model_op); BT_INFO("Mesh: Group Addr [0x%2.2x] Is Virtual [%s]", group_s->addr, group_s->is_virtual? "YES" : "NO"); /* Check group belongs to the same network */ if (network_s != group_s->parent) return BT_ERROR_INVALID_PARAMETER; /* Check group is non virtual */ if (!group_s->is_virtual) return BT_ERROR_INVALID_PARAMETER; /* Return error, if node is not attached */ if (!node_s->is_attached) return BT_ERROR_INVALID_PARAMETER; if (model_op != BT_MESH_MODEL_SUBSCRIPTION_DELETE_ALL) req.sub_addr = group_s->addr; req.is_virtual_sub = true; req.op = model_op; g_strlcpy(req.net_uuid, network_s->uuid, 33); req.primary_unicast = node_s->unicast; req.elem_index = element_s->index; req.model = model_s->id; error_code = _bt_get_error_code(bluetooth_mesh_model_configure_virtual_group_sub(&req)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } FUNC_EXIT; _bt_set_cb(BT_EVENT_MESH_NODE_MODEL_GROUP_VIR_SUB, callback, user_data); return error_code; } int bt_mesh_model_get_subscription_list(bt_mesh_model_h model, bt_mesh_model_subscription_list_cb callback, void *user_data) { int error_code = BT_ERROR_NONE; bt_mesh_model_s *model_s; bt_mesh_element_s *element_s; bt_mesh_node_s *node_s; bt_mesh_network_s *network_s; bluetooth_mesh_model_configure_t req; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(model); BT_CHECK_INPUT_PARAMETER(callback); model_s = (bt_mesh_model_s*) model; element_s = (bt_mesh_element_s*) model_s->parent; node_s = (bt_mesh_node_s*) element_s->parent; network_s = (bt_mesh_network_s*) node_s->parent; BT_CHECK_INPUT_PARAMETER(model_s); BT_CHECK_INPUT_PARAMETER(element_s); BT_CHECK_INPUT_PARAMETER(node_s); BT_CHECK_INPUT_PARAMETER(network_s); BT_MESH_VALIDATE_HANDLE(model_s, model_list); BT_MESH_VALIDATE_HANDLE(element_s, element_list); BT_MESH_VALIDATE_HANDLE(node_s, node_list); BT_MESH_VALIDATE_HANDLE(network_s, networks); /* Return error, if node is not attached */ if (!node_s->is_attached) return BT_ERROR_INVALID_PARAMETER; memset(&req, 0x00, sizeof(bluetooth_mesh_model_configure_t)); g_strlcpy(req.net_uuid, network_s->uuid, 33); req.primary_unicast = node_s->unicast; req.elem_index = element_s->index; req.model = model_s->id; error_code = _bt_get_error_code(bluetooth_mesh_model_get_subscriptopn_list(&req)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } FUNC_EXIT; _bt_set_cb(BT_EVENT_MESH_NODE_MODEL_APPKEY_LIST, callback, user_data); return error_code; } int bt_mesh_model_set_publication(bt_mesh_model_h model, bt_mesh_appkey_h appkey, bt_mesh_group_h group, bt_mesh_model_pub_params_s *params, bt_mesh_model_publication_status_cb callback, void *user_data) { int error_code = BT_ERROR_NONE; bt_mesh_model_s *model_s; bt_mesh_element_s *element_s; bt_mesh_node_s *node_s; bt_mesh_appkey_s *appkey_s; bt_mesh_network_s *network_s; bt_mesh_group_s *group_s; bluetooth_mesh_model_configure_t req; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(model); BT_CHECK_INPUT_PARAMETER(appkey); BT_CHECK_INPUT_PARAMETER(group); BT_CHECK_INPUT_PARAMETER(params); BT_CHECK_INPUT_PARAMETER(callback); model_s = (bt_mesh_model_s*) model; appkey_s = (bt_mesh_appkey_s*) appkey; group_s = (bt_mesh_group_s*) group; element_s = (bt_mesh_element_s*) model_s->parent; node_s = (bt_mesh_node_s*) element_s->parent; network_s = (bt_mesh_network_s*) node_s->parent; if (group_s->parent != network_s) return BT_ERROR_INVALID_PARAMETER; if (params->num_steps > BT_MESH_MAX_PUBISH_PERIOD_STEPS) return BT_ERROR_INVALID_PARAMETER; if (params->retrans_cnt > BT_MESH_MAX_PUBISH_RETRANSMIT_COUNT) return BT_ERROR_INVALID_PARAMETER; if (params->retrans_step > BT_MESH_MAX_PUBISH_RETRANSMIT_INTERVAL_STEPS) return BT_ERROR_INVALID_PARAMETER; BT_CHECK_INPUT_PARAMETER(element_s); BT_CHECK_INPUT_PARAMETER(node_s); BT_CHECK_INPUT_PARAMETER(network_s); BT_MESH_VALIDATE_HANDLE(model_s, model_list); BT_MESH_VALIDATE_HANDLE(element_s, element_list); BT_MESH_VALIDATE_HANDLE(node_s, node_list); BT_MESH_VALIDATE_HANDLE(network_s, networks); BT_MESH_VALIDATE_HANDLE(appkey_s, appkey_list); BT_MESH_VALIDATE_HANDLE(group_s, group_list); /* Return error, if node is not attached */ if (!node_s->is_attached) return BT_ERROR_INVALID_PARAMETER; memset(&req, 0x00, sizeof(bluetooth_mesh_model_configure_t)); g_strlcpy(req.net_uuid, network_s->uuid, 33); req.primary_unicast = node_s->unicast; req.elem_index = element_s->index; req.model = model_s->id; req.appkey_idx = appkey_s->appkey_index; req.pub_addr = group_s->addr; req.ttl = params->ttl; req.period = params->num_steps; req.period = req.period << 2; req.period |= params->per_res; req.retransmit = params->retrans_cnt; req.retransmit = req.retransmit << 5; req.retransmit |= params->retrans_step; error_code = _bt_get_error_code(bluetooth_mesh_model_set_publication(&req)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } FUNC_EXIT; _bt_set_cb(BT_EVENT_MESH_NODE_MODEL_PUBLICATION, callback, user_data); return error_code; } int bt_mesh_model_get_publication(bt_mesh_model_h model, bt_mesh_model_publication_status_cb callback, void *user_data) { int error_code = BT_ERROR_NONE; bt_mesh_model_s *model_s; bt_mesh_element_s *element_s; bt_mesh_node_s *node_s; bt_mesh_network_s *network_s; bluetooth_mesh_model_configure_t req; FUNC_ENTRY; BT_CHECK_MESH_SUPPORT(); BT_CHECK_MESH_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(model); BT_CHECK_INPUT_PARAMETER(callback); model_s = (bt_mesh_model_s*) model; element_s = (bt_mesh_element_s*) model_s->parent; node_s = (bt_mesh_node_s*) element_s->parent; network_s = (bt_mesh_network_s*) node_s->parent; BT_CHECK_INPUT_PARAMETER(model_s); BT_CHECK_INPUT_PARAMETER(element_s); BT_CHECK_INPUT_PARAMETER(node_s); BT_CHECK_INPUT_PARAMETER(network_s); BT_MESH_VALIDATE_HANDLE(model_s, model_list); BT_MESH_VALIDATE_HANDLE(element_s, element_list); BT_MESH_VALIDATE_HANDLE(node_s, node_list); BT_MESH_VALIDATE_HANDLE(network_s, networks); /* Return error, if node is not attached */ if (!node_s->is_attached) return BT_ERROR_INVALID_PARAMETER; memset(&req, 0x00, sizeof(bluetooth_mesh_model_configure_t)); g_strlcpy(req.net_uuid, network_s->uuid, 33); req.primary_unicast = node_s->unicast; req.elem_index = element_s->index; req.model = model_s->id; error_code = _bt_get_error_code(bluetooth_mesh_model_get_publication(&req)); if (error_code != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); return error_code; } FUNC_EXIT; _bt_set_cb(BT_EVENT_MESH_NODE_MODEL_PUBLICATION, callback, user_data); return error_code; }