4 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
6 * @author: Anupam Roy <anupam.r@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
24 #include "bt-service-common.h"
25 #include "bt-service-core-adapter.h"
26 #include "bt-service-event-receiver.h"
27 #include "bt-request-handler.h"
28 #include "bluetooth-api.h"
30 #include "bluetooth-api.h"
31 #include "bluetooth-mesh-api.h"
32 #include "bt-internal-types.h"
33 #include "bt-service-util.h"
34 #include "bt-service-common.h"
35 #include "bt-service-event.h"
36 #include "bt-service-mesh-cdb.h"
37 #include "bt-service-mesh-nodes.h"
38 #include "bt-service-mesh-keys.h"
39 #include "bt-service-mesh-util.h"
41 #include "bt-internal-types.h"
54 #include <oal-hardware.h>
55 #include <oal-manager.h>
56 #include <oal-event.h>
57 #include <oal-adapter-mgr.h>
58 #include <oal-device-mgr.h>
61 static const char *bak_ext = ".bak";
62 static const char *tmp_ext = ".tmp";
64 static bool __bt_mesh_save_cdb(
65 _bt_mesh_cdb_t *cfg, const char *fname)
71 outfile = fopen(fname, "w");
73 BT_ERR("Failed to save configuration to %s",
78 str = json_object_to_json_string_ext(cfg->jcfg,
79 JSON_C_TO_STRING_PRETTY);
81 if (fwrite(str, sizeof(char), strlen(str), outfile) < strlen(str))
82 BT_ERR("Incomplete write of mesh configuration");
91 static bool __bt_mesh_save_configruation_file(_bt_mesh_cdb_t *cfg)
93 char *fname_tmp, *fname_bak, *fname_cfg;
96 fname_cfg = cfg->cfg_fname;
97 fname_tmp = g_strdup_printf("%s%s", fname_cfg, tmp_ext);
98 fname_bak = g_strdup_printf("%s%s", fname_cfg, bak_ext);
101 result = __bt_mesh_save_cdb(cfg, fname_tmp);
105 rename(fname_cfg, fname_bak);
106 rename(fname_tmp, fname_cfg);
114 gettimeofday(&cfg->write_time, NULL);
119 static bool __mesh_get_int(json_object *jobj,
120 const char *keyword, int *value)
124 if (!json_object_object_get_ex(jobj, keyword, &jvalue))
127 *value = json_object_get_int(jvalue);
128 if (errno == EINVAL) {
129 BT_ERR("MESH:Error: %s should contain an integer value\n",
137 static uint16_t __mesh_node_parse_key(json_object *jarray, int i)
142 jkey = json_object_array_get_idx(jarray, i);
144 return MESH_KEY_IDX_INVALID;
146 if (!__mesh_get_int(jkey, "index", &idx))
147 return MESH_KEY_IDX_INVALID;
149 return (uint16_t)idx;
152 static bool __mesh_write_int(json_object *jobj,
153 const char *keyword, int val)
157 json_object_object_del(jobj, keyword);
159 jval = json_object_new_int(val);
163 json_object_object_add(jobj, keyword, jval);
167 static bool __mesh_write_uint32_hex(json_object *jobj,
168 const char *desc, uint32_t val)
170 json_object *jstring;
173 snprintf(buf, 9, "%8.8x", val);
174 jstring = json_object_new_string(buf);
178 /* Overwrite old value if present */
179 json_object_object_del(jobj, desc);
181 json_object_object_add(jobj, desc, jstring);
185 static bool __mesh_write_uint16_hex(json_object *jobj,
186 const char *desc, uint16_t value)
188 json_object *jstring;
191 snprintf(buf, 5, "%4.4x", value);
192 jstring = json_object_new_string(buf);
196 json_object_object_add(jobj, desc, jstring);
200 static json_object *__mesh_init_model(uint16_t mod_id)
204 jmod = json_object_new_object();
206 if (!__mesh_write_uint16_hex(jmod, "modelId", mod_id)) {
207 json_object_put(jmod);
214 static json_object *__mesh_init_vendor_model(uint32_t mod_id)
218 jmod = json_object_new_object();
220 if (!__mesh_write_uint32_hex(jmod, "modelId", mod_id)) {
221 json_object_put(jmod);
228 static json_object *__mesh_init_elements(uint8_t num_els)
230 json_object *jelements;
233 jelements = json_object_new_array();
235 for (i = 0; i < num_els; ++i) {
236 json_object *jelement, *jmods;
238 jelement = json_object_new_object();
240 __mesh_write_int(jelement, "index", i);
241 __mesh_write_uint16_hex(jelement, "location", MESH_DEFAULT_LOCATION);
242 jmods = json_object_new_array();
243 json_object_object_add(jelement, "models", jmods);
245 json_object_array_add(jelements, jelement);
250 static bool __mesh_add_app_key(json_object *jobj,
251 uint16_t net_idx, uint16_t app_idx)
253 json_object *jkey, *jarray;
255 json_object_object_get_ex(jobj, "appKeys", &jarray);
256 if (!jarray || json_object_get_type(jarray) != json_type_array)
259 jkey = json_object_new_object();
261 if (!__mesh_write_int(jkey, "boundNetKey", (int)net_idx))
264 if (!__mesh_write_int(jkey, "index", (int)app_idx))
267 json_object_array_add(jarray, jkey);
271 json_object_put(jkey);
275 static bool __mesh_add_node_key(_bt_mesh_cdb_t *cfg,
276 json_object *jobj, const char *desc, uint16_t idx)
278 json_object *jkey, *jarray;
280 json_object_object_get_ex(jobj, desc, &jarray);
281 if (!jarray || json_object_get_type(jarray) != json_type_array)
284 jkey = json_object_new_object();
286 if (!__mesh_write_int(jkey, "index", (int)idx)) {
287 json_object_put(jkey);
291 json_object_array_add(jarray, jkey);
293 return __bt_mesh_save_configruation_file(cfg);
296 static json_object *__mesh_get_node_by_unicast(_bt_mesh_cdb_t *cfg,
302 if (!json_object_object_get_ex(cfg->jcfg, "nodes", &jarray))
305 if (!jarray || json_object_get_type(jarray) != json_type_array)
308 sz = json_object_array_length(jarray);
310 for (i = 0; i < sz; ++i) {
311 json_object *jentry, *jval;
315 jentry = json_object_array_get_idx(jarray, i);
316 if (!json_object_object_get_ex(jentry, "unicastAddress",
320 str = json_object_get_string(jval);
321 if (sscanf(str, "%04hx", &addr) != 1)
331 static json_object *__mesh_get_node_by_uuid(json_object *jcfg,
334 json_object *jarray = NULL;
338 _bt_mesh_util_convert_hex_to_string(uuid, 16, buf, sizeof(buf));
340 json_object_object_get_ex(jcfg, "nodes", &jarray);
341 if (!jarray || json_object_get_type(jarray) != json_type_array)
344 sz = json_object_array_length(jarray);
346 for (i = 0; i < sz; ++i) {
347 json_object *jentry, *jval;
350 jentry = json_object_array_get_idx(jarray, i);
351 if (!json_object_object_get_ex(jentry, "uuid", &jval))
354 str = json_object_get_string(jval);
355 if (strlen(str) != 32)
358 if (!g_strcmp0(buf, str))
365 static json_object *__mesh_get_key_object(json_object *jarray,
368 int i, sz = json_object_array_length(jarray);
370 for (i = 0; i < sz; ++i) {
374 jentry = json_object_array_get_idx(jarray, i);
375 if (!__mesh_get_int(jentry, "index", &jidx))
385 static bool __mesh_add_string(json_object *jobj,
386 const char *desc, const char *str)
388 json_object *jstring = json_object_new_string(str);
393 json_object_object_add(jobj, desc, jstring);
397 static bool __mesh_get_token(json_object *jobj, uint8_t token[8])
402 if (!json_object_object_get_ex(jobj, "token", &jval))
405 str = json_object_get_string(jval);
406 if (!_bt_mesh_util_convert_string_to_hex(str, strlen(str), token, 8))
412 static bool __mesh_get_uuid(json_object *jobj, uint8_t uuid[16])
417 if (!json_object_object_get_ex(jobj, "uuid", &jval))
420 str = json_object_get_string(jval);
421 if (!_bt_mesh_util_convert_string_to_hex(str, strlen(str), uuid, 16))
427 static bool __mesh_add_u8_8(json_object *jobj,
428 const char *desc, const uint8_t value[8])
430 json_object *jstring;
433 _bt_mesh_util_convert_hex_to_string((uint8_t *) value, 8, buf, 17);
434 jstring = json_object_new_string(buf);
438 json_object_object_add(jobj, desc, jstring);
442 static bool __mesh_add_u8_16(json_object *jobj,
443 const char *desc, const uint8_t value[16])
445 json_object *jstring;
448 _bt_mesh_util_convert_hex_to_string((uint8_t *) value, 16, buf, 33);
449 jstring = json_object_new_string(buf);
453 json_object_object_add(jobj, desc, jstring);
457 void _bt_mesh_conf_free(_bt_mesh_cdb_t *cfg)
459 g_free(cfg->cfg_fname);
460 g_free(cfg->app_cred);
461 json_object_put(cfg->jcfg);
465 bool _bt_mesh_conf_parse_data(void *cfg, int k)
467 _bt_mesh_cdb_t *conf = (_bt_mesh_cdb_t*) cfg;
473 static void __mesh_jarray_key_del(json_object *jarray, int16_t idx)
475 int i, sz = json_object_array_length(jarray);
477 for (i = 0; i < sz; ++i) {
481 jentry = json_object_array_get_idx(jarray, i);
483 if (!__mesh_get_int(jentry, "index", &val))
487 json_object_array_del_idx(jarray, i, 1);
493 static bool __mesh_delete_key(_bt_mesh_cdb_t *cfg,
494 json_object *jobj, const char *desc, uint16_t idx)
498 if (!json_object_object_get_ex(jobj, desc, &jarray))
501 __mesh_jarray_key_del(jarray, idx);
503 return __bt_mesh_save_configruation_file(cfg);
506 bool _bt_mesh_conf_set_phase_network_key(_bt_mesh_cdb_t *cfg,
507 uint16_t net_idx, uint8_t phase)
509 json_object *jval, *jarray, *jkey;
511 if (!cfg || !cfg->jcfg)
514 json_object_object_get_ex(cfg->jcfg, "netKeys", &jarray);
515 if (!jarray || json_object_get_type(jarray) != json_type_array)
518 jkey = __mesh_get_key_object(jarray, net_idx);
522 jval = json_object_new_int(phase);
526 json_object_object_add(jkey, "phase", jval);
528 return __bt_mesh_save_configruation_file(cfg);
531 bool _bt_mesh_conf_delete_application_key(_bt_mesh_cdb_t *cfg, uint16_t app_idx)
533 if (!cfg || !cfg->jcfg)
536 return __mesh_delete_key(cfg, cfg->jcfg, "appKeys", app_idx);
539 bool _bt_mesh_conf_set_unicast_address_range(_bt_mesh_cdb_t *cfg,
540 uint16_t low, uint16_t high)
542 if (!cfg || !cfg->jcfg)
545 if (!__mesh_write_uint16_hex(cfg->jcfg, "low", low))
548 if (!__mesh_write_uint16_hex(cfg->jcfg, "high", high))
551 return __bt_mesh_save_configruation_file(cfg);
554 bool _bt_mesh_conf_insert_node_object(_bt_mesh_cdb_t *cfg,
555 uint8_t uuid[16], uint8_t num_els,
556 uint16_t unicast, uint16_t net_idx)
559 json_object *jelements, *jnodes, *jnetkeys, *jappkeys;
562 if (!cfg || !cfg->jcfg)
565 jnode = __mesh_get_node_by_uuid(cfg->jcfg, uuid);
567 BT_ERR("MESH:Node already exists");
571 jnode = json_object_new_object();
575 if (!__mesh_add_u8_16(jnode, "uuid", uuid))
578 jelements = json_object_new_array();
582 for (i = 0; i < num_els; ++i) {
583 json_object *jelement = json_object_new_object();
586 json_object_put(jelements);
590 __mesh_write_int(jelement, "elementIndex", i);
591 json_object_array_add(jelements, jelement);
594 json_object_object_add(jnode, "elements", jelements);
596 jnetkeys = json_object_new_array();
600 json_object_object_add(jnode, "netKeys", jnetkeys);
602 if (!__mesh_add_node_key(cfg, jnode, "netKeys", net_idx))
605 jappkeys = json_object_new_array();
609 json_object_object_add(jnode, "appKeys", jappkeys);
611 if (!__mesh_write_uint16_hex(jnode, "unicastAddress", unicast))
614 if (!json_object_object_get_ex(cfg->jcfg, "nodes", &jnodes))
617 json_object_array_add(jnodes, jnode);
619 if (!__bt_mesh_save_configruation_file(cfg))
625 json_object_put(jnode);
629 bool _bt_mesh_conf_insert_application_key(_bt_mesh_cdb_t *cfg,
630 uint16_t net_idx, uint16_t app_idx)
632 if (!cfg || !cfg->jcfg)
635 if (!__mesh_add_app_key(cfg->jcfg, net_idx, app_idx))
638 return __bt_mesh_save_configruation_file(cfg);
641 bool _bt_mesh_conf_insert_network_key(_bt_mesh_cdb_t *cfg,
642 uint16_t net_idx, uint8_t key_refresh)
644 json_object *jkey, *jarray;
646 if (!cfg || !cfg->jcfg)
649 json_object_object_get_ex(cfg->jcfg, "netKeys", &jarray);
650 if (!jarray || json_object_get_type(jarray) != json_type_array)
653 if (__mesh_get_key_object(jarray, net_idx))
656 jkey = json_object_new_object();
658 if (!__mesh_write_int(jkey, "index", net_idx))
661 if (!__mesh_write_int(jkey, "phase", key_refresh))
664 json_object_array_add(jarray, jkey);
666 return __bt_mesh_save_configruation_file(cfg);
669 json_object_put(jkey);
673 bool _bt_mesh_conf_delete_network_key(_bt_mesh_cdb_t *cfg,
676 if (!cfg || !cfg->jcfg)
679 return __mesh_delete_key(cfg, cfg->jcfg, "netKeys", net_idx);
683 bool _bt_mesh_conf_node_set_timetolive_value(_bt_mesh_cdb_t *cfg,
684 uint16_t unicast, uint8_t ttl)
688 if (!cfg || !cfg->jcfg)
691 jnode = __mesh_get_node_by_unicast(cfg, unicast);
695 if (!__mesh_write_int(jnode, "defaultTTL", ttl))
698 return __bt_mesh_save_configruation_file(cfg);
701 bool _bt_mesh_conf_node_insert_network_key(_bt_mesh_cdb_t *cfg,
702 uint16_t unicast, uint16_t net_idx)
706 if (!cfg || !cfg->jcfg)
709 jnode = __mesh_get_node_by_unicast(cfg, unicast);
713 return __mesh_add_node_key(cfg, jnode, "netKeys", net_idx);
716 bool _bt_mesh_conf_node_delete_network_key(_bt_mesh_cdb_t *cfg,
717 uint16_t unicast, uint16_t net_idx)
721 if (!cfg || !cfg->jcfg)
724 jnode = __mesh_get_node_by_unicast(cfg, unicast);
728 return __mesh_delete_key(cfg, jnode, "netKeys", net_idx);
731 bool _bt_mesh_conf_node_insert_application_key(_bt_mesh_cdb_t *cfg,
732 uint16_t unicast, uint16_t idx)
736 if (!cfg || !cfg->jcfg)
739 jnode = __mesh_get_node_by_unicast(cfg, unicast);
743 return __mesh_add_node_key(cfg, jnode, "appKeys", idx);
746 bool _bt_mesh_conf_node_delete_application_key(_bt_mesh_cdb_t *cfg,
747 uint16_t unicast, uint16_t idx)
751 if (!cfg || !cfg->jcfg)
754 jnode = __mesh_get_node_by_unicast(cfg, unicast);
758 return __mesh_delete_key(cfg, jnode, "appKeys", idx);
761 _bt_mesh_cdb_t *_bt_mesh_conf_database_create(const char *file_name,
762 const uint8_t uuid[16],
763 const uint8_t token[8], const char *network_name,
764 const char *app_cred)
767 json_object *jcfg, *jarray;
778 jcfg = json_object_new_object();
782 cfg = g_malloc0(sizeof(_bt_mesh_cdb_t));
784 cfg->cfg_fname = g_strdup(file_name);
785 cfg->app_cred = g_strdup(app_cred);
786 memcpy(&cfg->token, (void*)token, 8);
787 memcpy(&cfg->uuid, (void*)uuid, 16);
789 if (!__mesh_add_u8_8(jcfg, "Network_Token", token))
792 if (!__mesh_add_u8_16(jcfg, "Config_Node_UUID", uuid))
795 if (!__mesh_add_string(jcfg, "Network_Name", network_name))
798 if (!__mesh_add_string(jcfg, "Application_Credential", app_cred))
801 jarray = json_object_new_array();
805 json_object_object_add(jcfg, "nodes", jarray);
807 jarray = json_object_new_array();
811 json_object_object_add(jcfg, "netKeys", jarray);
813 jarray = json_object_new_array();
817 json_object_object_add(jcfg, "appKeys", jarray);
819 if (!__bt_mesh_save_configruation_file(cfg))
825 _bt_mesh_conf_free(cfg);
830 bool _bt_mesh_conf_delete_node(_bt_mesh_cdb_t *cfg, uint16_t unicast)
835 if (!json_object_object_get_ex(cfg->jcfg, "nodes", &jarray))
838 if (!jarray || json_object_get_type(jarray) != json_type_array)
841 sz = json_object_array_length(jarray);
843 for (i = 0; i < sz; ++i) {
844 json_object *jentry, *jval;
848 jentry = json_object_array_get_idx(jarray, i);
849 if (!json_object_object_get_ex(jentry, "unicastAddress",
853 str = json_object_get_string(jval);
854 if (sscanf(str, "%04hx", &addr) != 1)
864 json_object_array_del_idx(jarray, i, 1);
866 return __bt_mesh_save_configruation_file(cfg);
869 uint16_t** _bt_mesh_conf_get_all_model_info(_bt_mesh_cdb_t *cfg,
870 int element_index, int *num_models)
876 json_object *jarray = NULL;
877 json_object *jelement = NULL;
878 json_object *jmodelarray = NULL;
889 jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
893 /* Get element array object */
894 json_object_object_get_ex(jnode, "elements", &jarray);
896 if (!jarray || json_object_get_type(jarray) != json_type_array)
899 /* Get specific element by index */
900 jelement = __mesh_get_key_object(jarray, element_index);
905 /* Get Model array object inside the selected element */
906 json_object_object_get_ex(jelement, "models", &jmodelarray);
908 if (!jmodelarray || json_object_get_type(jmodelarray) != json_type_array)
911 sz = json_object_array_length(jmodelarray);
912 models = (uint16_t**) g_malloc0(sz * sizeof(uint16_t*));
914 for (i = 0; i < sz; ++i) {
917 jentry = json_object_array_get_idx(jmodelarray, i);
918 str = json_object_get_string(jentry);
919 /* Only standard models are handled now */
920 if (sscanf(str, "%04hx", models[i]) != 1)
923 /* TODO: Need to handle vendor models */
928 bool _bt_mesh_conf_get_element_count(_bt_mesh_cdb_t *cfg,
934 json_object *jarray = NULL;
943 jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
947 json_object_object_get_ex(jnode, "elements", &jarray);
949 if (!jarray || json_object_get_type(jarray) != json_type_array)
952 sz = json_object_array_length(jarray);
960 bool _bt_mesh_conf_fetch_vendor_specific_info(_bt_mesh_cdb_t *cfg,
961 uint16_t *cid, uint16_t *vid,
962 uint16_t *version, uint16_t *crpl,
963 int *relay, int *friend,
964 int *proxy, int *lpn)
968 json_object *jobj = NULL;
969 json_object *jobjfeature = NULL;
979 jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
984 if (!json_object_object_get_ex(jnode, "crpl", &jobj))
987 str = json_object_get_string(jobj);
990 if (sscanf(str, "%04hx", crpl) != 1)
994 if (!json_object_object_get_ex(jnode, "cid", &jobj))
997 str = json_object_get_string(jobj);
1000 if (sscanf(str, "%04hx", cid) != 1)
1004 if (!json_object_object_get_ex(jnode, "pid", &jobj))
1007 str = json_object_get_string(jobj);
1011 if (sscanf(str, "%04hx", vid) != 1)
1014 /* Get Version ID */
1015 if (!json_object_object_get_ex(jnode, "vid", &jobj))
1018 str = json_object_get_string(jobj);
1021 if (sscanf(str, "%04hx", version) != 1)
1024 jobj = json_object_object_get(jnode, "features");
1027 if (json_object_object_get_ex(jobj, "relay", &jobjfeature)) {
1028 str = json_object_get_string(jobj);
1030 sscanf(str, "%d", relay);
1033 if (json_object_object_get_ex(jobj, "friend", &jobjfeature)) {
1034 str = json_object_get_string(jobj);
1036 sscanf(str, "%d", friend);
1039 if (json_object_object_get_ex(jobj, "proxy", &jobjfeature)) {
1040 str = json_object_get_string(jobj);
1042 sscanf(str, "%d", proxy);
1044 if (json_object_object_get_ex(jobj, "lowPower", &jobjfeature)) {
1045 str = json_object_get_string(jobj);
1047 sscanf(str, "%d", lpn);
1053 GSList *_bt_mesh_conf_load_group_info(_bt_mesh_cdb_t *cfg)
1055 json_object *jgroups;
1056 GSList *groups = NULL;
1059 if (!cfg || !cfg->jcfg)
1062 if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups)) {
1063 jgroups = json_object_new_array();
1067 json_object_object_add(cfg->jcfg, "groups", jgroups);
1070 sz = json_object_array_length(jgroups);
1072 for (i = 0; i < sz; ++i) {
1073 json_object *jgroup, *jval;
1074 _bt_mesh_group_t *grp;
1075 uint16_t addr, addr_len;
1078 jgroup = json_object_array_get_idx(jgroups, i);
1082 if (!json_object_object_get_ex(jgroup, "name", &jval))
1085 str = json_object_get_string(jval);
1086 if (strlen(str) != 10)
1089 if (sscanf(str + 6, "%04hx", &addr) != 1)
1091 if (!json_object_object_get_ex(jgroup, "address", &jval))
1094 str = json_object_get_string(jval);
1095 addr_len = strlen(str);
1096 if (addr_len != 4 && addr_len != 32)
1099 if (addr_len == 32 && !MESH_IS_VIRTUAL(addr))
1102 grp = g_malloc0(sizeof(_bt_mesh_group_t));
1105 sscanf(str, "%04hx", &grp->grp_addr);
1107 _bt_mesh_util_convert_string_to_hex(str,
1108 32, grp->label_uuid, 16);
1109 grp->grp_addr = addr;
1112 groups = g_slist_append(groups, grp);
1118 bool _bt_mesh_conf_insert_group_info(_bt_mesh_cdb_t *cfg,
1119 _bt_mesh_group_t *grp)
1121 json_object *jgroup, *jgroups, *jval;
1124 if (!cfg || !cfg->jcfg)
1127 if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups))
1130 jgroup = json_object_new_object();
1134 snprintf(buf, 11, "Group_%4.4x", grp->grp_addr);
1135 jval = json_object_new_string(buf);
1136 json_object_object_add(jgroup, "name", jval);
1138 if (MESH_IS_VIRTUAL(grp->grp_addr)) {
1139 if (!__mesh_add_u8_16(jgroup, "address", grp->label_uuid))
1142 if (!__mesh_write_uint16_hex(jgroup, "address", grp->grp_addr))
1146 json_object_array_add(jgroups, jgroup);
1148 return __bt_mesh_save_configruation_file(cfg);
1151 json_object_put(jgroup);
1155 bool _bt_mesh_conf_set_network_friendly_name(_bt_mesh_cdb_t *cfg,
1156 const char *network_name)
1167 json_object_object_del(jcfg, "Network_Name");
1168 __mesh_add_string(jcfg, "Network_Name", network_name);
1171 BT_INFO("Mesh: CDB: Network New Name [%s]", network_name);
1172 return __bt_mesh_save_configruation_file(cfg);
1175 const char * _bt_mesh_conf_get_network_friendly_name(_bt_mesh_cdb_t *cfg)
1178 json_object *jobj = NULL;
1188 /* Get Network Name */
1189 if (!json_object_object_get_ex(jcfg, "Network_Name", &jobj))
1192 str = json_object_get_string(jobj);
1196 BT_INFO("Mesh: CDB: Network Name [%s]", str);
1200 static bool __mesh_load_composition(_bt_mesh_cdb_t *cfg,
1201 json_object *jnode, uint16_t unicast)
1203 json_object *jarray;
1206 if (!json_object_object_get_ex(jnode, "elements", &jarray))
1209 if (json_object_get_type(jarray) != json_type_array)
1212 ele_cnt = json_object_array_length(jarray);
1214 for (i = 0; i < ele_cnt; ++i) {
1215 json_object *jentry, *jval, *jmods;
1219 jentry = json_object_array_get_idx(jarray, i);
1220 if (!json_object_object_get_ex(jentry, "index", &jval))
1223 index = json_object_get_int(jval);
1227 if (!json_object_object_get_ex(jentry, "models", &jmods))
1230 mod_cnt = json_object_array_length(jmods);
1232 for (k = 0; k < mod_cnt; ++k) {
1233 json_object *jmod, *jid;
1234 uint32_t mod_id, len;
1237 jmod = json_object_array_get_idx(jmods, k);
1238 if (!json_object_object_get_ex(jmod, "modelId", &jid))
1241 str = json_object_get_string(jid);
1244 if (len != 4 && len != 8)
1247 if ((len == 4) && (sscanf(str, "%04x", &mod_id) != 1))
1250 if ((len == 8) && (sscanf(str, "%08x", &mod_id) != 1))
1253 _bt_mesh_node_set_model(cfg->uuid,
1254 unicast, index, mod_id, len == 8);
1261 bool _bt_mesh_conf_set_node_comp_data(_bt_mesh_cdb_t *cfg,
1262 uint16_t unicast, uint8_t *data, uint16_t len)
1266 json_object *jnode, *jobj, *jelements;
1269 if (!cfg || !cfg->jcfg)
1272 jnode = __mesh_get_node_by_unicast(cfg, unicast);
1276 /* skip page -- We only support Page Zero */
1280 /* If "crpl" property is present, composition is already recorded */
1281 if (json_object_object_get_ex(jnode, "crpl", &jobj))
1284 if (!__mesh_write_uint16_hex(jnode, "cid", l_get_le16(&data[0])))
1287 if (!__mesh_write_uint16_hex(jnode, "pid", l_get_le16(&data[2])))
1290 if (!__mesh_write_uint16_hex(jnode, "vid", l_get_le16(&data[4])))
1293 crpl = l_get_le16(&data[6]);
1295 features = l_get_le16(&data[8]);
1299 jobj = json_object_object_get(jnode, "features");
1301 jobj = json_object_new_object();
1302 json_object_object_add(jnode, "features", jobj);
1305 if ((features & MESH_FEATURE_RELAY))
1306 __mesh_write_int(jobj, "relay", 1);
1308 __mesh_write_int(jobj, "relay", 0);
1310 if ((features & MESH_FEATURE_FRIEND))
1311 __mesh_write_int(jobj, "friend", 1);
1313 __mesh_write_int(jobj, "friend", 0);
1315 if ((features & MESH_FEATURE_PROXY))
1316 __mesh_write_int(jobj, "proxy", 1);
1318 __mesh_write_int(jobj, "proxy", 0);
1320 if ((features & MESH_FEATURE_LPN))
1321 __mesh_write_int(jobj, "lowPower", 1);
1323 __mesh_write_int(jobj, "lowPower", 0);
1325 jelements = json_object_object_get(jnode, "elements");
1329 sz = json_object_array_length(jelements);
1332 json_object *jentry, *jmods;
1336 /* Mismatch in the element count */
1340 jentry = json_object_array_get_idx(jelements, i);
1342 __mesh_write_int(jentry, "index", i);
1344 if (!__mesh_write_uint16_hex(jentry, "location", l_get_le16(data)))
1354 jmods = json_object_object_get(jentry, "models");
1356 /* For backwards compatibility */
1357 jmods = json_object_new_array();
1358 json_object_object_add(jentry, "models", jmods);
1361 while (len >= 2 && m--) {
1362 mod_id = l_get_le16(data);
1364 jobj = __mesh_init_model(mod_id);
1368 json_object_array_add(jmods, jobj);
1373 while (len >= 4 && v--) {
1374 jobj = json_object_new_object();
1375 mod_id = l_get_le16(data + 2);
1376 mod_id = l_get_le16(data) << 16 | mod_id;
1378 jobj = __mesh_init_vendor_model(mod_id);
1382 json_object_array_add(jmods, jobj);
1391 /* CRPL is written last. Will be used to check composition's presence */
1392 if (!__mesh_write_uint16_hex(jnode, "crpl", crpl))
1395 /* Initiate remote's composition from storage */
1396 if (!__mesh_load_composition(cfg, jnode, unicast))
1399 return __bt_mesh_save_configruation_file(cfg);
1402 /* Reset elements array */
1403 json_object_object_del(jnode, "elements");
1404 __mesh_init_elements(sz);
1409 _bt_mesh_cdb_t* _bt_mesh_cdb_load(const char *file_name,
1412 char *token_str = NULL;
1418 _bt_mesh_cdb_t *cfg;
1420 fd = open(file_name, O_RDONLY);
1424 if (fstat(fd, &st) == -1) {
1429 str = (char *) g_malloc0(st.st_size + 1);
1435 sz = read(fd, str, st.st_size);
1436 if (sz != st.st_size) {
1437 BT_ERR("Mesh: Failed to read configuration file [%s]", file_name);
1441 jcfg = json_tokener_parse(str);
1448 cfg = g_malloc0(sizeof(_bt_mesh_cdb_t));
1451 cfg->cfg_fname = g_strdup(file_name);
1453 if (!__mesh_get_uuid(jcfg, cfg->uuid)) {
1454 BT_ERR("Mesh: Configuration file missing UUID");
1458 if (!__mesh_get_token(jcfg, cfg->token)) {
1459 BT_ERR("Mesh: Configuration file missing token");
1463 token_str = _bt_service_convert_hex_to_string((unsigned char*)cfg->token, 8);
1465 /* Match CDB file tken with user's token */
1466 if (g_strcmp0(token_str, token)) {
1467 BT_INFO("Mesh: Token did not match! File token [%s] requested token [%s]",
1471 /* TODO: Load keys and remotes */
1474 _bt_mesh_conf_free(cfg);
1478 bool _bt_mesh_cdb_load_nodes(_bt_mesh_cdb_t *cfg)
1480 json_object *jnodes;
1481 int i, sz, node_count = 0;
1483 json_object_object_get_ex(cfg->jcfg, "nodes", &jnodes);
1484 if (!jnodes || json_object_get_type(jnodes) != json_type_array)
1487 sz = json_object_array_length(jnodes);
1489 for (i = 0; i < sz; ++i) {
1490 json_object *jnode, *jval, *jarray;
1492 uint16_t unicast, key_idx;
1494 int ele_cnt, key_cnt;
1497 jnode = json_object_array_get_idx(jnodes, i);
1501 if (!json_object_object_get_ex(jnode, "uuid", &jval))
1504 str = json_object_get_string(jval);
1505 if (strlen(str) != 32)
1508 _bt_mesh_util_convert_string_to_hex(str, 32, uuid, 16);
1510 if (!json_object_object_get_ex(jnode, "unicastAddress", &jval))
1513 str = json_object_get_string(jval);
1514 if (sscanf(str, "%04hx", &unicast) != 1)
1517 json_object_object_get_ex(jnode, "elements", &jarray);
1518 if (!jarray || json_object_get_type(jarray) != json_type_array)
1521 ele_cnt = json_object_array_length(jarray);
1523 if (ele_cnt > MESH_MAX_ELE_COUNT)
1526 json_object_object_get_ex(jnode, "netKeys", &jarray);
1527 if (!jarray || json_object_get_type(jarray) != json_type_array)
1530 key_cnt = json_object_array_length(jarray);
1534 key_idx = __mesh_node_parse_key(jarray, 0);
1535 if (key_idx == MESH_KEY_IDX_INVALID)
1538 _bt_mesh_node_add_node(cfg->uuid, (const uint8_t *)uuid, unicast, ele_cnt,
1540 for (j = 1; j < key_cnt; j++) {
1541 key_idx = __mesh_node_parse_key(jarray, j);
1543 if (key_idx != MESH_KEY_IDX_INVALID)
1544 _bt_mesh_node_add_net_key(cfg->uuid, unicast, key_idx);
1547 json_object_object_get_ex(jnode, "appKeys", &jarray);
1548 if (!jarray || json_object_get_type(jarray) != json_type_array)
1551 key_cnt = json_object_array_length(jarray);
1552 for (j = 0; j < key_cnt; j++) {
1553 key_idx = __mesh_node_parse_key(jarray, j);
1555 if (key_idx != MESH_KEY_IDX_INVALID)
1556 _bt_mesh_node_add_app_key(cfg->uuid, unicast, key_idx);
1559 __mesh_load_composition(cfg, jnode, unicast);
1563 /* TODO: Add the rest of the configuration */
1566 if (node_count != sz)
1567 BT_ERR("Mesh: CDB: The remote node configuration load is incomplete!");
1572 bool _bt_mesh_conf_load_all_keys(_bt_mesh_cdb_t* cfg)
1574 json_object *jarray, *jentry;
1575 int net_idx, app_idx;
1577 json_object *jobj = cfg->jcfg;
1579 json_object_object_get_ex(jobj, "netKeys", &jarray);
1580 if (!jarray || json_object_get_type(jarray) != json_type_array)
1583 key_cnt = json_object_array_length(jarray);
1587 for (i = 0; i < key_cnt; ++i) {
1590 jentry = json_object_array_get_idx(jarray, i);
1592 if (!__mesh_get_int(jentry, "index", &net_idx))
1595 _bt_mesh_keys_add_net_key(cfg->uuid, (uint16_t) net_idx);
1597 if (!__mesh_get_int(jentry, "phase", &phase))
1600 _bt_mesh_keys_set_net_key_phase(cfg, net_idx, (uint8_t) phase, false);
1603 json_object_object_get_ex(jobj, "appKeys", &jarray);
1604 if (!jarray || json_object_get_type(jarray) != json_type_array)
1607 key_cnt = json_object_array_length(jarray);
1611 for (i = 0; i < key_cnt; ++i) {
1613 jentry = json_object_array_get_idx(jarray, i);
1614 if (!__mesh_get_int(jentry, "boundNetKey", &net_idx))
1617 if (!__mesh_get_int(jentry, "index", &app_idx))
1620 _bt_mesh_keys_add_app_key(cfg->uuid, (uint16_t) net_idx, (uint16_t) app_idx);