./services/audio/hf/bt-service-hf-client.c
./services/mesh/bt-service-mesh-util.c
./services/mesh/bt-service-mesh-keys.c
+./services/mesh/bt-service-mesh-cdb.c
+./services/mesh/bt-service-mesh-nodes.c
)
IF("$ENV{CFLAGS}" MATCHES "-DTIZEN_FEATURE_BT_OBEX")
--- /dev/null
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * @author: Anupam Roy <anupam.r@samsung.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef BT_SERVICE_MESH_CDB_H_
+#define BT_SERVICE_MESH_CDB_H_
+
+#include <glib.h>
+#include <sys/types.h>
+#include "bluetooth-api.h"
+#include "bluetooth-mesh-api.h"
+#include <json-c/json.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ char *cfg_fname;
+ char *app_cred;
+ json_object *jcfg;
+ uint8_t token[8];
+ uint8_t uuid[16]; /* Network UUID */
+ struct timeval write_time;
+ GSList *groups;
+} _bt_mesh_cdb_t;
+
+/* Virtual Group */
+typedef struct {
+ uint8_t label_uuid[16];
+ uint16_t grp_addr;
+} _bt_mesh_group_t;
+
+
+void _bt_mesh_conf_free(_bt_mesh_cdb_t *cfg);
+
+bool _bt_mesh_conf_parse_data(void *cfg, int k);
+
+_bt_mesh_cdb_t * _bt_mesh_conf_database_create(const char *file_name,
+ const uint8_t uuid[16], const uint8_t token[8],
+ const char *network_name,
+ const char *app_cred);
+
+bool _bt_mesh_conf_set_phase_network_key(_bt_mesh_cdb_t *cfg,
+ uint16_t net_idx, uint8_t phase);
+
+bool _bt_mesh_conf_delete_application_key(_bt_mesh_cdb_t *cfg,
+ uint16_t app_idx);
+
+bool _bt_mesh_conf_insert_network_key(_bt_mesh_cdb_t *cfg,
+ uint16_t idx, uint8_t key_refresh);
+
+bool _bt_mesh_conf_delete_network_key(_bt_mesh_cdb_t *cfg,
+ uint16_t net_idx);
+
+bool _bt_mesh_conf_set_unicast_address_range(_bt_mesh_cdb_t *cfg,
+ uint16_t low, uint16_t high);
+
+bool _bt_mesh_conf_insert_node_object(_bt_mesh_cdb_t *cfg,
+ uint8_t uuid[16], uint8_t num_els,
+ uint16_t unicast, uint16_t net_idx);
+
+bool _bt_mesh_conf_get_element_count(_bt_mesh_cdb_t *cfg,
+ uint16_t *num_elems);
+
+uint16_t** _bt_mesh_conf_get_all_model_info(_bt_mesh_cdb_t *cfg,
+ int element_index, int *num_models);
+
+bool _bt_mesh_conf_get_token_info(uint8_t token[8]);
+
+bool _bt_mesh_conf_insert_application_key(_bt_mesh_cdb_t *cfg,
+ uint16_t net_idx, uint16_t app_idx);
+
+bool _bt_mesh_conf_get_unicast_address_range(uint16_t *low,
+ uint16_t *high);
+
+bool _bt_mesh_conf_node_set_network_transmission(uint16_t unicast,
+ uint8_t cnt, uint16_t interval);
+
+bool _bt_mesh_conf_node_insert_network_key(_bt_mesh_cdb_t *cfg,
+ uint16_t unicast, uint16_t idx);
+
+bool _bt_mesh_conf_node_delete_network_key(_bt_mesh_cdb_t *cfg,
+ uint16_t unicast, uint16_t idx);
+
+bool _bt_mesh_conf_node_insert_application_key(_bt_mesh_cdb_t *cfg,
+ uint16_t unicast, uint16_t idx);
+
+bool _bt_mesh_conf_node_delete_application_key(_bt_mesh_cdb_t *cfg,
+ uint16_t unicast, uint16_t idx);
+
+bool _bt_mesh_conf_node_set_timetolive_value(_bt_mesh_cdb_t *cfg,
+ uint16_t unicast, uint8_t ttl);
+
+bool _bt_mesh_conf_node_set_write_op_mode(uint16_t unicast,
+ const char *keyword, int value);
+
+bool _bt_mesh_conf_bind_model(uint16_t unicast,
+ uint8_t ele, bool vendor,
+ uint32_t mod_id, uint16_t app_idx);
+
+bool _bt_mesh_conf_unbind_model(uint16_t unicast,
+ uint8_t ele, bool vendor,
+ uint32_t mod_id, uint16_t app_idx);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* BT_SERVICE_MESH_CDB_H_ */
--- /dev/null
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * @author: Anupam Roy <anupam.r@samsung.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef BT_SERVICE_MESH_NODES_H_
+#define BT_SERVICE_MESH_NODES_H_
+
+#include <glib.h>
+#include <sys/types.h>
+#include "bluetooth-api.h"
+#include "bluetooth-mesh-api.h"
+#include "bt-service-mesh-cdb.h"
+#include <json-c/json.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void _bt_mesh_node_load_net(uint8_t net_uuid[]);
+
+void _bt_mesh_node_unload_net(_bt_mesh_cdb_t *cfg);
+
+bool _bt_mesh_node_add_node(uint8_t net_uuid[],
+ const uint8_t uuid[16], uint16_t unicast,
+ uint8_t ele_cnt, uint16_t net_idx);
+
+uint8_t _bt_mesh_node_del_node(_bt_mesh_cdb_t *cfg,
+ uint16_t unicast);
+
+bool _bt_mesh_node_set_model(uint8_t net_uuid[],
+ uint16_t unicast, uint8_t ele_idx,
+ uint32_t mod_id, bool vendor);
+
+uint16_t _bt_mesh_node_get_next_unicast(uint8_t net_uuid[],
+ uint16_t low, uint16_t high,
+ uint8_t ele_cnt);
+
+bool _bt_mesh_node_is_netkey_added(uint8_t net_uuid[],
+ uint16_t net_idx);
+
+bool _bt_mesh_node_is_appkey_added(uint8_t net_uuid[],
+ uint16_t app_idx);
+
+bool _bt_mesh_node_add_net_key(uint8_t net_uuid[],
+ uint16_t addr, uint16_t net_idx);
+
+bool _bt_mesh_node_del_net_key(_bt_mesh_cdb_t *cfg,
+ uint8_t net_uuid[], uint16_t addr,
+ uint16_t net_idx);
+
+bool _bt_mesh_node_add_app_key(uint8_t net_uuid[],
+ uint16_t addr, uint16_t app_idx);
+
+bool _bt_mesh_node_del_app_key(uint8_t net_uuid[],
+ uint16_t addr, uint16_t app_idx);
+
+uint16_t _bt_mesh_node_get_subnet_idx(uint8_t net_uuid[],
+ uint16_t addr);
+
+void _bt_mesh_node_print_node(uint8_t net_uuid[],
+ uint16_t addr);
+
+void _bt_mesh_node_print_all(uint8_t net_uuid[]);
+
+bool _bt_mesh_node_get_all(uint8_t net_uuid[], GArray **out);
+
+bool _bt_mesh_node_get_models(uint8_t net_uuid[],
+ uint16_t unicast, uint8_t ele_idx,
+ GArray **out);
+
+bool _bt_mesh_node_get_unicast_from_dev_uuid(uint8_t net_uuid[],
+ const uint8_t dev_uuid[16], uint16_t *unicast);
+
+bool _bt_mesh_node_get_element_count(uint8_t net_uuid[],
+ uint16_t unicast, uint8_t *count);
+
+bool _bt_mesh_node_get_all_netkeys(uint8_t net_uuid[],
+ uint16_t unicast, GArray **out);
+
+bool _bt_mesh_node_get_all_appkeys(uint8_t net_uuid[],
+ uint16_t unicast, GArray **out);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* BT_SERVICE_MESH_NODES_H_ */
--- /dev/null
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * @author: Anupam Roy <anupam.r@samsung.com>
+ *
+ * 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 <glib.h>
+#include <dlog.h>
+#include "bt-service-common.h"
+#include "bt-service-core-adapter.h"
+#include "bt-service-event-receiver.h"
+#include "bt-request-handler.h"
+#include "bluetooth-api.h"
+
+#include "bluetooth-api.h"
+#include "bluetooth-mesh-api.h"
+#include "bt-internal-types.h"
+#include "bt-service-util.h"
+#include "bt-service-common.h"
+#include "bt-service-event.h"
+#include "bt-service-mesh-cdb.h"
+#include "bt-service-mesh-nodes.h"
+#include "bt-service-mesh-keys.h"
+#include "bt-service-mesh-util.h"
+
+#include "bt-internal-types.h"
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <ftw.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <ell/ell.h>
+
+#include <oal-hardware.h>
+#include <oal-manager.h>
+#include <oal-event.h>
+#include <oal-adapter-mgr.h>
+#include <oal-device-mgr.h>
+#include <oal-gatt.h>
+
+static const char *bak_ext = ".bak";
+static const char *tmp_ext = ".tmp";
+
+static bool __bt_mesh_save_cdb(
+ _bt_mesh_cdb_t *cfg, const char *fname)
+{
+ FILE *outfile;
+ const char *str;
+ bool result = false;
+
+ outfile = fopen(fname, "w");
+ if (!outfile) {
+ BT_ERR("Failed to save configuration to %s",
+ cfg->cfg_fname);
+ return false;
+ }
+
+ str = json_object_to_json_string_ext(cfg->jcfg,
+ JSON_C_TO_STRING_PRETTY);
+
+ if (fwrite(str, sizeof(char), strlen(str), outfile) < strlen(str))
+ BT_ERR("Incomplete write of mesh configuration");
+ else
+ result = true;
+
+ fclose(outfile);
+
+ return result;
+}
+
+static bool __bt_mesh_save_configruation_file(_bt_mesh_cdb_t *cfg)
+{
+ char *fname_tmp, *fname_bak, *fname_cfg;
+ bool result = false;
+
+ fname_cfg = cfg->cfg_fname;
+ fname_tmp = g_strdup_printf("%s%s", fname_cfg, tmp_ext);
+ fname_bak = g_strdup_printf("%s%s", fname_cfg, bak_ext);
+ remove(fname_tmp);
+
+ result = __bt_mesh_save_cdb(cfg, fname_tmp);
+
+ if (result) {
+ remove(fname_bak);
+ rename(fname_cfg, fname_bak);
+ rename(fname_tmp, fname_cfg);
+ }
+
+ remove(fname_tmp);
+
+ g_free(fname_tmp);
+ g_free(fname_bak);
+
+ gettimeofday(&cfg->write_time, NULL);
+
+ return result;
+}
+
+static bool __mesh_get_int(json_object *jobj,
+ const char *keyword, int *value)
+{
+ json_object *jvalue;
+
+ if (!json_object_object_get_ex(jobj, keyword, &jvalue))
+ return false;
+
+ *value = json_object_get_int(jvalue);
+ if (errno == EINVAL) {
+ BT_ERR("MESH:Error: %s should contain an integer value\n",
+ keyword);
+ return false;
+ }
+
+ return true;
+}
+
+static bool __mesh_write_int(json_object *jobj,
+ const char *keyword, int val)
+{
+ json_object *jval;
+
+ json_object_object_del(jobj, keyword);
+
+ jval = json_object_new_int(val);
+ if (!jval)
+ return false;
+
+ json_object_object_add(jobj, keyword, jval);
+ return true;
+}
+
+static bool __mesh_write_uint16_hex(json_object *jobj,
+ const char *desc, uint16_t value)
+{
+ json_object *jstring;
+ char buf[5];
+
+ snprintf(buf, 5, "%4.4x", value);
+ jstring = json_object_new_string(buf);
+ if (!jstring)
+ return false;
+
+ json_object_object_add(jobj, desc, jstring);
+ return true;
+}
+
+static bool __mesh_add_app_key(json_object *jobj,
+ uint16_t net_idx, uint16_t app_idx)
+{
+ json_object *jkey, *jarray;
+
+ json_object_object_get_ex(jobj, "appKeys", &jarray);
+ if (!jarray || json_object_get_type(jarray) != json_type_array)
+ return false;
+
+ jkey = json_object_new_object();
+
+ if (!__mesh_write_int(jkey, "boundNetKey", (int)net_idx))
+ goto fail;
+
+ if (!__mesh_write_int(jkey, "index", (int)app_idx))
+ goto fail;
+
+ json_object_array_add(jarray, jkey);
+
+ return true;
+fail:
+ json_object_put(jkey);
+ return false;
+}
+
+static bool __mesh_add_node_key(_bt_mesh_cdb_t *cfg,
+ json_object *jobj, const char *desc, uint16_t idx)
+{
+ json_object *jkey, *jarray;
+
+ json_object_object_get_ex(jobj, desc, &jarray);
+ if (!jarray || json_object_get_type(jarray) != json_type_array)
+ return false;
+
+ jkey = json_object_new_object();
+
+ if (!__mesh_write_int(jkey, "index", (int)idx)) {
+ json_object_put(jkey);
+ return false;
+ }
+
+ json_object_array_add(jarray, jkey);
+
+ return __bt_mesh_save_configruation_file(cfg);
+}
+
+static json_object *__mesh_get_node_by_unicast(_bt_mesh_cdb_t *cfg,
+ uint16_t unicast)
+{
+ json_object *jarray;
+ int i, sz;
+
+ if (!json_object_object_get_ex(cfg->jcfg, "nodes", &jarray))
+ return NULL;
+
+ if (!jarray || json_object_get_type(jarray) != json_type_array)
+ return NULL;
+
+ sz = json_object_array_length(jarray);
+
+ for (i = 0; i < sz; ++i) {
+ json_object *jentry, *jval;
+ uint16_t addr;
+ const char *str;
+
+ jentry = json_object_array_get_idx(jarray, i);
+ if (!json_object_object_get_ex(jentry, "unicastAddress",
+ &jval))
+ return NULL;
+
+ str = json_object_get_string(jval);
+ if (sscanf(str, "%04hx", &addr) != 1)
+ continue;
+
+ if (addr == unicast)
+ return jentry;
+ }
+
+ return NULL;
+}
+
+static json_object *__mesh_get_node_by_uuid(json_object *jcfg,
+ uint8_t uuid[16])
+{
+ json_object *jarray = NULL;
+ char buf[33];
+ int i, sz;
+
+ _bt_mesh_util_convert_hex_to_string(uuid, 16, buf, sizeof(buf));
+
+ json_object_object_get_ex(jcfg, "nodes", &jarray);
+ if (!jarray || json_object_get_type(jarray) != json_type_array)
+ return NULL;
+
+ sz = json_object_array_length(jarray);
+
+ for (i = 0; i < sz; ++i) {
+ json_object *jentry, *jval;
+ const char *str;
+
+ jentry = json_object_array_get_idx(jarray, i);
+ if (!json_object_object_get_ex(jentry, "uuid", &jval))
+ return NULL;
+
+ str = json_object_get_string(jval);
+ if (strlen(str) != 32)
+ continue;
+
+ if (!g_strcmp0(buf, str))
+ return jentry;
+ }
+
+ return NULL;
+}
+
+static json_object *__mesh_get_key_object(json_object *jarray,
+ uint16_t idx)
+{
+ int i, sz = json_object_array_length(jarray);
+
+ for (i = 0; i < sz; ++i) {
+ json_object *jentry;
+ int jidx;
+
+ jentry = json_object_array_get_idx(jarray, i);
+ if (!__mesh_get_int(jentry, "index", &jidx))
+ return NULL;
+
+ if (jidx == idx)
+ return jentry;
+ }
+
+ return NULL;
+}
+
+static bool __mesh_add_string(json_object *jobj,
+ const char *desc, const char *str)
+{
+ json_object *jstring = json_object_new_string(str);
+
+ if (!jstring)
+ return false;
+
+ json_object_object_add(jobj, desc, jstring);
+ return true;
+}
+
+static bool __mesh_add_u8_8(json_object *jobj,
+ const char *desc, const uint8_t value[8])
+{
+ json_object *jstring;
+ char buf[17];
+
+ _bt_mesh_util_convert_hex_to_string((uint8_t *) value, 8, buf, 17);
+ jstring = json_object_new_string(buf);
+ if (!jstring)
+ return false;
+
+ json_object_object_add(jobj, desc, jstring);
+ return true;
+}
+
+static bool __mesh_add_u8_16(json_object *jobj,
+ const char *desc, const uint8_t value[16])
+{
+ json_object *jstring;
+ char buf[33];
+
+ _bt_mesh_util_convert_hex_to_string((uint8_t *) value, 16, buf, 33);
+ jstring = json_object_new_string(buf);
+ if (!jstring)
+ return false;
+
+ json_object_object_add(jobj, desc, jstring);
+ return true;
+}
+
+void _bt_mesh_conf_free(_bt_mesh_cdb_t *cfg)
+{
+ g_free(cfg->cfg_fname);
+ g_free(cfg->app_cred);
+ json_object_put(cfg->jcfg);
+ g_free(cfg);
+}
+
+bool _bt_mesh_conf_parse_data(void *cfg, int k)
+{
+ _bt_mesh_cdb_t *conf = (_bt_mesh_cdb_t*) cfg;
+ if (!conf)
+ return false;
+ return true;
+}
+
+static void __mesh_jarray_key_del(json_object *jarray, int16_t idx)
+{
+ int i, sz = json_object_array_length(jarray);
+
+ for (i = 0; i < sz; ++i) {
+ json_object *jentry;
+ int val;
+
+ jentry = json_object_array_get_idx(jarray, i);
+
+ if (!__mesh_get_int(jentry, "index", &val))
+ continue;
+
+ if (val == idx) {
+ json_object_array_del_idx(jarray, i, 1);
+ return;
+ }
+ }
+}
+
+static bool __mesh_delete_key(_bt_mesh_cdb_t *cfg,
+ json_object *jobj, const char *desc, uint16_t idx)
+{
+ json_object *jarray;
+
+ if (!json_object_object_get_ex(jobj, desc, &jarray))
+ return true;
+
+ __mesh_jarray_key_del(jarray, idx);
+
+ return __bt_mesh_save_configruation_file(cfg);
+}
+
+bool _bt_mesh_conf_set_phase_network_key(_bt_mesh_cdb_t *cfg,
+ uint16_t net_idx, uint8_t phase)
+{
+ json_object *jval, *jarray, *jkey;
+
+ if (!cfg || !cfg->jcfg)
+ return false;
+
+ json_object_object_get_ex(cfg->jcfg, "netKeys", &jarray);
+ if (!jarray || json_object_get_type(jarray) != json_type_array)
+ return false;
+
+ jkey = __mesh_get_key_object(jarray, net_idx);
+ if (!jkey)
+ return false;
+
+ jval = json_object_new_int(phase);
+ if (!jval)
+ return false;
+
+ json_object_object_add(jkey, "phase", jval);
+
+ return __bt_mesh_save_configruation_file(cfg);
+}
+
+bool _bt_mesh_conf_delete_application_key(_bt_mesh_cdb_t *cfg, uint16_t app_idx)
+{
+ if (!cfg || !cfg->jcfg)
+ return false;
+
+ return __mesh_delete_key(cfg, cfg->jcfg, "appKeys", app_idx);
+}
+
+bool _bt_mesh_conf_set_unicast_address_range(_bt_mesh_cdb_t *cfg,
+ uint16_t low, uint16_t high)
+{
+ if (!cfg || !cfg->jcfg)
+ return false;
+
+ if (!__mesh_write_uint16_hex(cfg->jcfg, "low", low))
+ return false;
+
+ if (!__mesh_write_uint16_hex(cfg->jcfg, "high", high))
+ return false;
+
+ return __bt_mesh_save_configruation_file(cfg);
+}
+
+bool _bt_mesh_conf_insert_node_object(_bt_mesh_cdb_t *cfg,
+ uint8_t uuid[16], uint8_t num_els,
+ uint16_t unicast, uint16_t net_idx)
+{
+ json_object *jnode;
+ json_object *jelements, *jnodes, *jnetkeys, *jappkeys;
+ int i;
+
+ if (!cfg || !cfg->jcfg)
+ return false;
+
+ jnode = __mesh_get_node_by_uuid(cfg->jcfg, uuid);
+ if (jnode) {
+ BT_ERR("MESH:Node already exists");
+ return false;
+ }
+
+ jnode = json_object_new_object();
+ if (!jnode)
+ return false;
+
+ if (!__mesh_add_u8_16(jnode, "uuid", uuid))
+ goto fail;
+
+ jelements = json_object_new_array();
+ if (!jelements)
+ goto fail;
+
+ for (i = 0; i < num_els; ++i) {
+ json_object *jelement = json_object_new_object();
+
+ if (!jelement) {
+ json_object_put(jelements);
+ goto fail;
+ }
+
+ __mesh_write_int(jelement, "elementIndex", i);
+ json_object_array_add(jelements, jelement);
+ }
+
+ json_object_object_add(jnode, "elements", jelements);
+
+ jnetkeys = json_object_new_array();
+ if (!jnetkeys)
+ goto fail;
+
+ json_object_object_add(jnode, "netKeys", jnetkeys);
+
+ if (!__mesh_add_node_key(cfg, jnode, "netKeys", net_idx))
+ goto fail;
+
+ jappkeys = json_object_new_array();
+ if (!jappkeys)
+ goto fail;
+
+ json_object_object_add(jnode, "appKeys", jappkeys);
+
+ if (!__mesh_write_uint16_hex(jnode, "unicastAddress", unicast))
+ goto fail;
+
+ if (!json_object_object_get_ex(cfg->jcfg, "nodes", &jnodes))
+ goto fail;
+
+ json_object_array_add(jnodes, jnode);
+
+ if (!__bt_mesh_save_configruation_file(cfg))
+ goto fail;
+
+ return true;
+
+fail:
+ json_object_put(jnode);
+ return false;
+}
+
+bool _bt_mesh_conf_insert_application_key(_bt_mesh_cdb_t *cfg,
+ uint16_t net_idx, uint16_t app_idx)
+{
+ if (!cfg || !cfg->jcfg)
+ return false;
+
+ if (!__mesh_add_app_key(cfg->jcfg, net_idx, app_idx))
+ return false;
+
+ return __bt_mesh_save_configruation_file(cfg);
+}
+
+bool _bt_mesh_conf_insert_network_key(_bt_mesh_cdb_t *cfg,
+ uint16_t net_idx, uint8_t key_refresh)
+{
+ json_object *jkey, *jarray;
+
+ if (!cfg || !cfg->jcfg)
+ return false;
+
+ json_object_object_get_ex(cfg->jcfg, "netKeys", &jarray);
+ if (!jarray || json_object_get_type(jarray) != json_type_array)
+ return false;
+
+ if (__mesh_get_key_object(jarray, net_idx))
+ return true;
+
+ jkey = json_object_new_object();
+
+ if (!__mesh_write_int(jkey, "index", net_idx))
+ goto fail;
+
+ if (!__mesh_write_int(jkey, "phase", key_refresh))
+ goto fail;
+
+ json_object_array_add(jarray, jkey);
+
+ return __bt_mesh_save_configruation_file(cfg);
+
+fail:
+ json_object_put(jkey);
+ return false;
+}
+
+bool _bt_mesh_conf_delete_network_key(_bt_mesh_cdb_t *cfg,
+ uint16_t net_idx)
+{
+ if (!cfg || !cfg->jcfg)
+ return false;
+
+ return __mesh_delete_key(cfg, cfg->jcfg, "netKeys", net_idx);
+}
+
+
+bool _bt_mesh_conf_node_set_timetolive_value(_bt_mesh_cdb_t *cfg,
+ uint16_t unicast, uint8_t ttl)
+{
+ json_object *jnode;
+
+ if (!cfg || !cfg->jcfg)
+ return false;
+
+ jnode = __mesh_get_node_by_unicast(cfg, unicast);
+ if (!jnode)
+ return false;
+
+ if (!__mesh_write_int(jnode, "defaultTTL", ttl))
+ return false;
+
+ return __bt_mesh_save_configruation_file(cfg);
+}
+
+bool _bt_mesh_conf_node_insert_network_key(_bt_mesh_cdb_t *cfg,
+ uint16_t unicast, uint16_t net_idx)
+{
+ json_object *jnode;
+
+ if (!cfg || !cfg->jcfg)
+ return false;
+
+ jnode = __mesh_get_node_by_unicast(cfg, unicast);
+ if (!jnode)
+ return false;
+
+ return __mesh_add_node_key(cfg, jnode, "netKeys", net_idx);
+}
+
+bool _bt_mesh_conf_node_delete_network_key(_bt_mesh_cdb_t *cfg,
+ uint16_t unicast, uint16_t net_idx)
+{
+ json_object *jnode;
+
+ if (!cfg || !cfg->jcfg)
+ return false;
+
+ jnode = __mesh_get_node_by_unicast(cfg, unicast);
+ if (!jnode)
+ return false;
+
+ return __mesh_delete_key(cfg, jnode, "netKeys", net_idx);
+}
+
+bool _bt_mesh_conf_node_insert_application_key(_bt_mesh_cdb_t *cfg,
+ uint16_t unicast, uint16_t idx)
+{
+ json_object *jnode;
+
+ if (!cfg || !cfg->jcfg)
+ return false;
+
+ jnode = __mesh_get_node_by_unicast(cfg, unicast);
+ if (!jnode)
+ return false;
+
+ return __mesh_add_node_key(cfg, jnode, "appKeys", idx);
+}
+
+bool _bt_mesh_conf_node_delete_application_key(_bt_mesh_cdb_t *cfg,
+ uint16_t unicast, uint16_t idx)
+{
+ json_object *jnode;
+
+ if (!cfg || !cfg->jcfg)
+ return false;
+
+ jnode = __mesh_get_node_by_unicast(cfg, unicast);
+ if (!jnode)
+ return false;
+
+ return __mesh_delete_key(cfg, jnode, "appKeys", idx);
+}
+
+_bt_mesh_cdb_t *_bt_mesh_conf_database_create(const char *file_name,
+ const uint8_t uuid[16],
+ const uint8_t token[8], const char *network_name,
+ const char *app_cred)
+{
+ _bt_mesh_cdb_t *cfg;
+ json_object *jcfg, *jarray;
+
+ if (!file_name)
+ return NULL;
+
+ if (!network_name)
+ return NULL;
+
+ if (!app_cred)
+ return NULL;
+
+ jcfg = json_object_new_object();
+ if (!jcfg)
+ return NULL;
+
+ cfg = g_malloc0(sizeof(_bt_mesh_cdb_t));
+ cfg->jcfg = jcfg;
+ cfg->cfg_fname = g_strdup(file_name);
+ cfg->app_cred = g_strdup(app_cred);
+ memcpy(&cfg->token, (void*)token, 8);
+ memcpy(&cfg->uuid, (void*)uuid, 16);
+
+ if (!__mesh_add_u8_8(jcfg, "Network_Token", token))
+ goto fail;
+
+ if (!__mesh_add_u8_16(jcfg, "Config_Node_UUID", uuid))
+ goto fail;
+
+ if (!__mesh_add_string(jcfg, "Network_Name", network_name))
+ goto fail;
+
+ if (!__mesh_add_string(jcfg, "Application_Credential", app_cred))
+ goto fail;
+
+ jarray = json_object_new_array();
+ if (!jarray)
+ goto fail;
+
+ json_object_object_add(jcfg, "nodes", jarray);
+
+ jarray = json_object_new_array();
+ if (!jarray)
+ goto fail;
+
+ json_object_object_add(jcfg, "netKeys", jarray);
+
+ jarray = json_object_new_array();
+ if (!jarray)
+ goto fail;
+
+ json_object_object_add(jcfg, "appKeys", jarray);
+
+ if (!__bt_mesh_save_configruation_file(cfg))
+ goto fail;
+
+ return cfg;
+
+fail:
+ _bt_mesh_conf_free(cfg);
+
+ return NULL;
+}
+
+bool _bt_mesh_conf_delete_node(_bt_mesh_cdb_t *cfg, uint16_t unicast)
+{
+ json_object *jarray;
+ int i, sz;
+
+ if (!json_object_object_get_ex(cfg->jcfg, "nodes", &jarray))
+ return false;
+
+ if (!jarray || json_object_get_type(jarray) != json_type_array)
+ return false;
+
+ sz = json_object_array_length(jarray);
+
+ for (i = 0; i < sz; ++i) {
+ json_object *jentry, *jval;
+ uint16_t addr;
+ const char *str;
+
+ jentry = json_object_array_get_idx(jarray, i);
+ if (!json_object_object_get_ex(jentry, "unicastAddress",
+ &jval))
+ continue;
+
+ str = json_object_get_string(jval);
+ if (sscanf(str, "%04hx", &addr) != 1)
+ continue;
+
+ if (addr == unicast)
+ break;
+ }
+
+ if (i == sz)
+ return true;
+
+ json_object_array_del_idx(jarray, i, 1);
+
+ return __bt_mesh_save_configruation_file(cfg);
+}
+
+uint16_t** _bt_mesh_conf_get_all_model_info(_bt_mesh_cdb_t *cfg,
+ int element_index, int *num_models)
+{
+ int sz;
+ int i;
+ json_object *jcfg;
+ json_object *jnode;
+ json_object *jarray = NULL;
+ json_object *jelement = NULL;
+ json_object *jmodelarray = NULL;
+ const char *str;
+ uint16_t **models;
+
+ if (!cfg)
+ return NULL;
+
+ jcfg = cfg->jcfg;
+ if (!jcfg)
+ return NULL;
+
+ jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
+ if (jnode)
+ return NULL;
+
+ /* Get element array object */
+ json_object_object_get_ex(jnode, "elements", &jarray);
+
+ if (!jarray || json_object_get_type(jarray) != json_type_array)
+ return NULL;
+
+ /* Get specific element by index */
+ jelement = __mesh_get_key_object(jarray, element_index);
+ if (!jelement)
+ return NULL;
+
+
+ /* Get Model array object inside the selected element */
+ json_object_object_get_ex(jelement, "models", &jmodelarray);
+
+ if (!jmodelarray || json_object_get_type(jmodelarray) != json_type_array)
+ return NULL;
+
+ sz = json_object_array_length(jmodelarray);
+ models = (uint16_t**) g_malloc0(sz * sizeof(uint16_t*));
+
+ for (i = 0; i < sz; ++i) {
+ json_object *jentry;
+
+ jentry = json_object_array_get_idx(jmodelarray, i);
+ str = json_object_get_string(jentry);
+ /* Only standard models are handled now */
+ if (sscanf(str, "%04hx", models[i]) != 1)
+ return NULL;
+ }
+ /* TODO: Need to handle vendor models */
+ *num_models = sz;
+ return models;
+}
+
+bool _bt_mesh_conf_get_element_count(_bt_mesh_cdb_t *cfg,
+ uint16_t *num_elems)
+{
+ int sz;
+ json_object *jcfg;
+ json_object *jnode;
+ json_object *jarray = NULL;
+
+ if (!cfg)
+ return false;
+
+ jcfg = cfg->jcfg;
+ if (!jcfg)
+ return false;
+
+ jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
+ if (jnode)
+ return false;
+
+ json_object_object_get_ex(jnode, "elements", &jarray);
+
+ if (!jarray || json_object_get_type(jarray) != json_type_array)
+ return false;
+
+ sz = json_object_array_length(jarray);
+ if (sz == 0)
+ return false;
+ *num_elems = sz;
+
+ return true;
+}
--- /dev/null
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * @author: Anupam Roy <anupam.r@samsung.com>
+ *
+ * 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 <glib.h>
+#include <dlog.h>
+#include "bt-service-common.h"
+#include "bt-service-core-adapter.h"
+#include "bt-service-event-receiver.h"
+#include "bt-request-handler.h"
+#include "bluetooth-api.h"
+
+#include "bluetooth-api.h"
+#include "bluetooth-mesh-api.h"
+#include "bt-internal-types.h"
+#include "bt-service-util.h"
+#include "bt-service-common.h"
+#include "bt-service-event.h"
+
+#include "bt-service-mesh-cdb.h"
+#include "bt-service-mesh-keys.h"
+#include "bt-service-mesh-util.h"
+
+#include <ell/ell.h>
+
+#include "bt-internal-types.h"
+
+struct _bt_mesh_node_t {
+ uint16_t unicast;
+ struct l_queue *net_keys;
+ struct l_queue *app_keys;
+ struct l_queue **els;
+ uint8_t uuid[16];
+ uint8_t num_ele;
+};
+
+struct mesh_network_t {
+ uint8_t net_uuid[16];
+ struct l_queue *nodes;
+};
+
+static struct l_queue *networks;
+
+struct mesh_key_index {
+ uint8_t uuid[16];
+ uint16_t idx;
+};
+
+static bool __mesh_match_node_dev_uuid(const void *a, const void *b)
+{
+ const struct _bt_mesh_node_t *node = a;
+ uint8_t* dev_uuid = (uint8_t*)b;
+
+ if (memcmp(node->uuid, dev_uuid, 16) == 0) {
+ BT_INFO("Mesh: Found Node with given Dev UUID");
+ return true;
+ }
+
+ return false;
+}
+
+static bool __mesh_net_uuid_match(const void *a, const void *b)
+{
+ const struct mesh_network_t *net = a;
+ uint8_t* uuid = (uint8_t*)b;
+
+ if (memcmp(net->net_uuid, uuid, 16) == 0) {
+ BT_INFO("Mesh: Found network with given Net UUID");
+ return true;
+ }
+
+ return false;
+}
+
+static bool __mesh_key_present(struct l_queue *keys, uint16_t app_idx)
+{
+ const struct l_queue_entry *l;
+
+ for (l = l_queue_get_entries(keys); l; l = l->next) {
+ uint16_t idx = L_PTR_TO_UINT(l->data);
+
+ if (idx == app_idx)
+ return true;
+ }
+
+ return false;
+}
+
+static int __mesh_compare_mod_id(const void *a, const void *b,
+ void *user_data)
+{
+ uint32_t id1 = L_PTR_TO_UINT(a);
+ uint32_t id2 = L_PTR_TO_UINT(b);
+
+ if (id1 >= MESH_VENDOR_ID_MASK)
+ id1 &= ~MESH_VENDOR_ID_MASK;
+
+ if (id2 >= MESH_VENDOR_ID_MASK)
+ id2 &= ~MESH_VENDOR_ID_MASK;
+
+ if (id1 < id2)
+ return -1;
+
+ if (id1 > id2)
+ return 1;
+
+ return 0;
+}
+
+static int __mesh_compare_unicast(const void *a, const void *b,
+ void *user_data)
+{
+ const struct _bt_mesh_node_t *a_rmt = a;
+ const struct _bt_mesh_node_t *b_rmt = b;
+
+ if (a_rmt->unicast < b_rmt->unicast)
+ return -1;
+
+ if (a_rmt->unicast > b_rmt->unicast)
+ return 1;
+
+ return 0;
+}
+
+static bool __mesh_match_node_addr(const void *a, const void *b)
+{
+ const struct _bt_mesh_node_t *rmt = a;
+ uint16_t addr = L_PTR_TO_UINT(b);
+
+ if (addr >= rmt->unicast &&
+ addr <= (rmt->unicast + rmt->num_ele - 1))
+ return true;
+
+ return false;
+}
+
+void _bt_mesh_node_load_net(uint8_t net_uuid[])
+{
+ struct mesh_network_t *network;
+ BT_INFO("Mesh:Nodes: Create new network");
+
+ if (l_queue_find(networks, __mesh_net_uuid_match, net_uuid))
+ return;
+
+ if (!networks)
+ networks = l_queue_new();
+
+ network = l_new(struct mesh_network_t, 1);
+ memcpy(network->net_uuid, net_uuid, 16);
+ network->nodes = l_queue_new();
+ l_queue_push_tail(networks, network);
+}
+
+bool _bt_mesh_node_get_unicast_from_dev_uuid(uint8_t net_uuid[],
+ const uint8_t dev_uuid[], uint16_t *unicast)
+{
+ struct _bt_mesh_node_t *rmt;
+ struct mesh_network_t *network;
+
+ network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return false;
+
+ rmt = l_queue_find(network->nodes,
+ __mesh_match_node_dev_uuid, dev_uuid);
+ if (rmt)
+ return false;
+
+ *unicast = rmt->unicast;
+ return true;
+}
+
+bool _bt_mesh_node_get_element_count(uint8_t net_uuid[],
+ uint16_t unicast, uint8_t *count)
+{
+ struct _bt_mesh_node_t *rmt;
+ struct mesh_network_t *network;
+
+ network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return false;
+
+ rmt = l_queue_find(network->nodes, __mesh_match_node_addr,
+ L_UINT_TO_PTR(unicast));
+ if (rmt)
+ return false;
+
+ *count = rmt->num_ele;
+
+ return true;
+}
+
+bool _bt_mesh_node_add_node(uint8_t net_uuid[],
+ const uint8_t node_uuid[16], uint16_t unicast,
+ uint8_t ele_cnt, uint16_t net_idx)
+{
+ struct _bt_mesh_node_t *rmt;
+ struct mesh_network_t *network;
+
+ network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return false;
+
+ rmt = l_queue_find(network->nodes,
+ __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
+ if (rmt)
+ return false;
+
+ rmt = l_new(struct _bt_mesh_node_t, 1);
+ memcpy(rmt->uuid, node_uuid, 16);
+ rmt->unicast = unicast;
+ rmt->num_ele = ele_cnt;
+ rmt->net_keys = l_queue_new();
+
+ l_queue_push_tail(rmt->net_keys, L_UINT_TO_PTR(net_idx));
+
+ rmt->els = l_new(struct l_queue *, ele_cnt);
+
+ if (!network->nodes)
+ network->nodes = l_queue_new();
+
+ l_queue_insert(network->nodes, rmt, __mesh_compare_unicast, NULL);
+ return true;
+}
+
+bool _bt_mesh_node_get_models(uint8_t net_uuid[],
+ uint16_t unicast, uint8_t ele_idx,
+ GArray **out)
+{
+ struct _bt_mesh_node_t *rmt;
+ struct mesh_network_t *network;
+ const struct l_queue_entry *entry;
+
+ network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return false;
+
+ rmt = l_queue_find(network->nodes,
+ __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
+ if (!rmt)
+ return false;
+
+ if (!rmt->els[ele_idx])
+ return false;
+
+ entry = l_queue_get_entries(rmt->els[ele_idx]);
+
+ for (; entry; entry = entry->next) {
+ uint32_t model = L_PTR_TO_UINT(entry->data);
+ g_array_append_vals(*out, &model, sizeof(uint32_t));
+ }
+ return true;
+}
+
+bool _bt_mesh_node_set_model(uint8_t net_uuid[],
+ uint16_t unicast, uint8_t ele_idx,
+ uint32_t mod_id, bool vendor)
+{
+ struct _bt_mesh_node_t *rmt;
+ struct mesh_network_t *network;
+
+ network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return false;
+
+ rmt = l_queue_find(network->nodes,
+ __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
+ if (!rmt)
+ return false;
+
+ if (ele_idx >= rmt->num_ele)
+ return false;
+
+ if (!rmt->els[ele_idx])
+ rmt->els[ele_idx] = l_queue_new();
+
+ if (!vendor)
+ mod_id = MESH_VENDOR_ID_MASK | mod_id;
+
+ l_queue_insert(rmt->els[ele_idx], L_UINT_TO_PTR(mod_id),
+ __mesh_compare_mod_id, NULL);
+
+ return true;
+}
+
+bool _bt_mesh_node_get_all_appkeys(uint8_t net_uuid[],
+ uint16_t unicast, GArray **out)
+{
+ struct mesh_network_t *network;
+ const struct l_queue_entry *entry;
+ struct _bt_mesh_node_t *rmt;
+
+ network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return false;
+
+ rmt = l_queue_find(network->nodes,
+ __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
+ if (!rmt)
+ return false;
+
+ entry = l_queue_get_entries(rmt->app_keys);
+
+ for (; entry; entry = entry->next) {
+
+ uint16_t app_idx = L_PTR_TO_UINT(entry->data);
+
+ g_array_append_vals(*out, &app_idx, sizeof(uint16_t));
+ }
+ return true;
+}
+
+bool _bt_mesh_node_get_all_netkeys(uint8_t net_uuid[],
+ uint16_t unicast, GArray **out)
+{
+ struct mesh_network_t *network;
+ const struct l_queue_entry *entry;
+ struct _bt_mesh_node_t *rmt;
+
+ network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return false;
+
+ rmt = l_queue_find(network->nodes,
+ __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
+ if (!rmt)
+ return false;
+
+ entry = l_queue_get_entries(rmt->net_keys);
+
+ for (; entry; entry = entry->next) {
+
+ uint16_t net_idx = L_PTR_TO_UINT(entry->data);
+
+ g_array_append_vals(*out, &net_idx, sizeof(uint16_t));
+ }
+ return true;
+}
+
+bool _bt_mesh_node_get_all(uint8_t net_uuid[], GArray **out)
+{
+ struct mesh_network_t *network;
+ const struct l_queue_entry *entry;
+ bluetooth_mesh_node_info_t n;
+
+ network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return false;
+
+ entry = l_queue_get_entries(network->nodes);
+
+ for (; entry; entry = entry->next) {
+
+ memset(&n, 0x00, sizeof(bluetooth_mesh_node_info_t));
+ struct _bt_mesh_node_t *node = entry->data;
+
+ n.primary_unicast = node->unicast;
+ n.num_elements = node->num_ele;
+
+ g_array_append_vals(*out, &n,
+ sizeof(bluetooth_mesh_node_info_t));
+ }
+ return true;
+}
+
+bool _bt_mesh_node_is_netkey_added(uint8_t net_uuid[],
+ uint16_t net_idx)
+{
+ struct mesh_network_t *network;
+ const struct l_queue_entry *entry;
+
+ network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return false;
+
+ entry = l_queue_get_entries(network->nodes);
+
+ for (; entry; entry = entry->next) {
+ struct _bt_mesh_node_t *node = entry->data;
+
+ if (__mesh_key_present(node->net_keys, net_idx))
+ return true;
+ }
+ return false;
+}
+
+bool _bt_mesh_node_is_appkey_added(uint8_t net_uuid[],
+ uint16_t app_idx)
+{
+ struct mesh_network_t *network;
+ const struct l_queue_entry *entry;
+
+ network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return false;
+
+ entry = l_queue_get_entries(network->nodes);
+
+ for (; entry; entry = entry->next) {
+ struct _bt_mesh_node_t *node = entry->data;
+
+ if (__mesh_key_present(node->app_keys, app_idx))
+ return true;
+ }
+ return false;
+}
+
+bool _bt_mesh_node_add_net_key(uint8_t net_uuid[],
+ uint16_t addr, uint16_t net_idx)
+{
+ struct _bt_mesh_node_t *rmt;
+ struct mesh_network_t *network;
+
+ network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return false;
+
+ rmt = l_queue_find(network->nodes,
+ __mesh_match_node_addr, L_UINT_TO_PTR(addr));
+ if (!rmt)
+ return false;
+
+ if (__mesh_key_present(rmt->net_keys, net_idx))
+ return false;
+
+ l_queue_push_tail(rmt->net_keys, L_UINT_TO_PTR(net_idx));
+ return true;
+}
+
+bool _bt_mesh_node_add_app_key(uint8_t net_uuid[],
+ uint16_t addr, uint16_t app_idx)
+{
+ struct _bt_mesh_node_t *rmt;
+ struct mesh_network_t *network;
+
+ network = l_queue_find(networks,
+ __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return false;
+
+ rmt = l_queue_find(network->nodes,
+ __mesh_match_node_addr, L_UINT_TO_PTR(addr));
+ if (!rmt)
+ return false;
+
+ if (!rmt->app_keys)
+ rmt->app_keys = l_queue_new();
+
+ if (__mesh_key_present(rmt->app_keys, app_idx))
+ return false;
+
+ l_queue_push_tail(rmt->app_keys, L_UINT_TO_PTR(app_idx));
+ return true;
+}
+
+bool _bt_mesh_node_del_app_key(uint8_t net_uuid[],
+ uint16_t addr, uint16_t app_idx)
+{
+ struct _bt_mesh_node_t *rmt;
+ struct mesh_network_t *network;
+
+ network = l_queue_find(networks,
+ __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return false;
+
+ rmt = l_queue_find(network->nodes,
+ __mesh_match_node_addr, L_UINT_TO_PTR(addr));
+ if (!rmt)
+ return false;
+
+ return l_queue_remove(rmt->app_keys, L_UINT_TO_PTR(app_idx));
+}
+
+uint16_t _bt_mesh_node_get_subnet_idx(uint8_t net_uuid[],
+ uint16_t addr)
+{
+ struct _bt_mesh_node_t *rmt;
+ uint32_t net_idx;
+ struct mesh_network_t *network;
+
+ network = l_queue_find(networks,
+ __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return MESH_NET_IDX_INVALID;
+
+ rmt = l_queue_find(network->nodes,
+ __mesh_match_node_addr, L_UINT_TO_PTR(addr));
+
+ if (!rmt || l_queue_isempty(rmt->net_keys))
+ return MESH_NET_IDX_INVALID;
+
+ net_idx = L_PTR_TO_UINT(l_queue_peek_head(rmt->net_keys));
+
+ return (uint16_t) net_idx;
+}
+
+uint16_t _bt_mesh_node_get_next_unicast(uint8_t net_uuid[],
+ uint16_t low, uint16_t high, uint8_t ele_cnt)
+{
+ struct _bt_mesh_node_t *rmt;
+ const struct l_queue_entry *l;
+ uint16_t addr;
+ struct mesh_network_t *network;
+
+ network = l_queue_find(networks,
+ __mesh_net_uuid_match, net_uuid);
+ if (!network)
+ return 0;
+
+ /* Note: the address space includes both
+ low and high terminal values */
+ if (ele_cnt > (high - low + 1))
+ return 0;
+
+ if (!network->nodes || l_queue_isempty(network->nodes))
+ return low;
+
+ addr = low;
+ l = l_queue_get_entries(network->nodes);
+
+ /* Cycle through the sorted (by unicast) node list */
+ for (; l; l = l->next) {
+ rmt = l->data;
+
+ if (rmt->unicast >= (addr + ele_cnt))
+ return addr;
+
+ if ((rmt->unicast + rmt->num_ele) > addr)
+ addr = rmt->unicast + rmt->num_ele;
+ }
+
+ if ((addr + ele_cnt - 1) <= high)
+ return addr;
+
+ return 0;
+}