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) {
921 for (int j =0 ; j < sz; j++)
927 /* TODO: Need to handle vendor models */
932 bool _bt_mesh_conf_get_element_count(_bt_mesh_cdb_t *cfg,
938 json_object *jarray = NULL;
947 jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
951 json_object_object_get_ex(jnode, "elements", &jarray);
953 if (!jarray || json_object_get_type(jarray) != json_type_array)
956 sz = json_object_array_length(jarray);
964 bool _bt_mesh_conf_fetch_vendor_specific_info(_bt_mesh_cdb_t *cfg,
965 uint16_t *cid, uint16_t *vid,
966 uint16_t *version, uint16_t *crpl,
967 int *relay, int *friend,
968 int *proxy, int *lpn)
972 json_object *jobj = NULL;
973 json_object *jobjfeature = NULL;
983 jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
988 if (!json_object_object_get_ex(jnode, "crpl", &jobj))
991 str = json_object_get_string(jobj);
994 if (sscanf(str, "%04hx", crpl) != 1)
998 if (!json_object_object_get_ex(jnode, "cid", &jobj))
1001 str = json_object_get_string(jobj);
1004 if (sscanf(str, "%04hx", cid) != 1)
1008 if (!json_object_object_get_ex(jnode, "pid", &jobj))
1011 str = json_object_get_string(jobj);
1015 if (sscanf(str, "%04hx", vid) != 1)
1018 /* Get Version ID */
1019 if (!json_object_object_get_ex(jnode, "vid", &jobj))
1022 str = json_object_get_string(jobj);
1025 if (sscanf(str, "%04hx", version) != 1)
1028 jobj = json_object_object_get(jnode, "features");
1031 if (json_object_object_get_ex(jobj, "relay", &jobjfeature)) {
1032 str = json_object_get_string(jobj);
1034 sscanf(str, "%d", relay);
1037 if (json_object_object_get_ex(jobj, "friend", &jobjfeature)) {
1038 str = json_object_get_string(jobj);
1040 sscanf(str, "%d", friend);
1043 if (json_object_object_get_ex(jobj, "proxy", &jobjfeature)) {
1044 str = json_object_get_string(jobj);
1046 sscanf(str, "%d", proxy);
1048 if (json_object_object_get_ex(jobj, "lowPower", &jobjfeature)) {
1049 str = json_object_get_string(jobj);
1051 sscanf(str, "%d", lpn);
1057 GSList *_bt_mesh_conf_load_group_info(_bt_mesh_cdb_t *cfg)
1059 json_object *jgroups;
1060 GSList *groups = NULL;
1063 if (!cfg || !cfg->jcfg)
1066 if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups)) {
1067 jgroups = json_object_new_array();
1071 json_object_object_add(cfg->jcfg, "groups", jgroups);
1074 sz = json_object_array_length(jgroups);
1076 for (i = 0; i < sz; ++i) {
1077 json_object *jgroup, *jval;
1078 _bt_mesh_group_t *grp;
1079 uint16_t addr, addr_len;
1082 jgroup = json_object_array_get_idx(jgroups, i);
1086 if (!json_object_object_get_ex(jgroup, "name", &jval))
1089 str = json_object_get_string(jval);
1090 if (strlen(str) != 10)
1093 if (sscanf(str + 6, "%04hx", &addr) != 1)
1095 if (!json_object_object_get_ex(jgroup, "address", &jval))
1098 str = json_object_get_string(jval);
1099 addr_len = strlen(str);
1100 if (addr_len != 4 && addr_len != 32)
1103 if (addr_len == 32 && !MESH_IS_VIRTUAL(addr))
1106 grp = g_malloc0(sizeof(_bt_mesh_group_t));
1109 sscanf(str, "%04hx", &grp->grp_addr);
1111 _bt_mesh_util_convert_string_to_hex(str,
1112 32, grp->label_uuid, 16);
1113 grp->grp_addr = addr;
1116 groups = g_slist_append(groups, grp);
1122 bool _bt_mesh_conf_insert_group_info(_bt_mesh_cdb_t *cfg,
1123 _bt_mesh_group_t *grp)
1125 json_object *jgroup, *jgroups, *jval;
1128 if (!cfg || !cfg->jcfg)
1131 if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups))
1134 jgroup = json_object_new_object();
1138 snprintf(buf, 11, "Group_%4.4x", grp->grp_addr);
1139 jval = json_object_new_string(buf);
1140 json_object_object_add(jgroup, "name", jval);
1142 if (MESH_IS_VIRTUAL(grp->grp_addr)) {
1143 if (!__mesh_add_u8_16(jgroup, "address", grp->label_uuid))
1146 if (!__mesh_write_uint16_hex(jgroup, "address", grp->grp_addr))
1150 json_object_array_add(jgroups, jgroup);
1152 return __bt_mesh_save_configruation_file(cfg);
1155 json_object_put(jgroup);
1159 bool _bt_mesh_conf_set_network_friendly_name(_bt_mesh_cdb_t *cfg,
1160 const char *network_name)
1171 json_object_object_del(jcfg, "Network_Name");
1172 __mesh_add_string(jcfg, "Network_Name", network_name);
1175 BT_INFO("Mesh: CDB: Network New Name [%s]", network_name);
1176 return __bt_mesh_save_configruation_file(cfg);
1179 const char * _bt_mesh_conf_get_network_friendly_name(_bt_mesh_cdb_t *cfg)
1182 json_object *jobj = NULL;
1192 /* Get Network Name */
1193 if (!json_object_object_get_ex(jcfg, "Network_Name", &jobj))
1196 str = json_object_get_string(jobj);
1200 BT_INFO("Mesh: CDB: Network Name [%s]", str);
1204 static bool __mesh_load_composition(_bt_mesh_cdb_t *cfg,
1205 json_object *jnode, uint16_t unicast)
1207 json_object *jarray;
1210 if (!json_object_object_get_ex(jnode, "elements", &jarray))
1213 if (json_object_get_type(jarray) != json_type_array)
1216 ele_cnt = json_object_array_length(jarray);
1218 for (i = 0; i < ele_cnt; ++i) {
1219 json_object *jentry, *jval, *jmods;
1223 jentry = json_object_array_get_idx(jarray, i);
1224 if (!json_object_object_get_ex(jentry, "index", &jval))
1227 index = json_object_get_int(jval);
1231 if (!json_object_object_get_ex(jentry, "models", &jmods))
1234 mod_cnt = json_object_array_length(jmods);
1236 for (k = 0; k < mod_cnt; ++k) {
1237 json_object *jmod, *jid;
1238 uint32_t mod_id, len;
1241 jmod = json_object_array_get_idx(jmods, k);
1242 if (!json_object_object_get_ex(jmod, "modelId", &jid))
1245 str = json_object_get_string(jid);
1248 if (len != 4 && len != 8)
1251 if ((len == 4) && (sscanf(str, "%04x", &mod_id) != 1))
1254 if ((len == 8) && (sscanf(str, "%08x", &mod_id) != 1))
1257 _bt_mesh_node_set_model(cfg->uuid,
1258 unicast, index, mod_id, len == 8);
1265 bool _bt_mesh_conf_set_node_comp_data(_bt_mesh_cdb_t *cfg,
1266 uint16_t unicast, uint8_t *data, uint16_t len)
1270 json_object *jnode, *jobj, *jelements;
1273 if (!cfg || !cfg->jcfg)
1276 jnode = __mesh_get_node_by_unicast(cfg, unicast);
1280 /* skip page -- We only support Page Zero */
1284 /* If "crpl" property is present, composition is already recorded */
1285 if (json_object_object_get_ex(jnode, "crpl", &jobj))
1288 if (!__mesh_write_uint16_hex(jnode, "cid", l_get_le16(&data[0])))
1291 if (!__mesh_write_uint16_hex(jnode, "pid", l_get_le16(&data[2])))
1294 if (!__mesh_write_uint16_hex(jnode, "vid", l_get_le16(&data[4])))
1297 crpl = l_get_le16(&data[6]);
1299 features = l_get_le16(&data[8]);
1303 jobj = json_object_object_get(jnode, "features");
1305 jobj = json_object_new_object();
1306 json_object_object_add(jnode, "features", jobj);
1309 if ((features & MESH_FEATURE_RELAY))
1310 __mesh_write_int(jobj, "relay", 1);
1312 __mesh_write_int(jobj, "relay", 0);
1314 if ((features & MESH_FEATURE_FRIEND))
1315 __mesh_write_int(jobj, "friend", 1);
1317 __mesh_write_int(jobj, "friend", 0);
1319 if ((features & MESH_FEATURE_PROXY))
1320 __mesh_write_int(jobj, "proxy", 1);
1322 __mesh_write_int(jobj, "proxy", 0);
1324 if ((features & MESH_FEATURE_LPN))
1325 __mesh_write_int(jobj, "lowPower", 1);
1327 __mesh_write_int(jobj, "lowPower", 0);
1329 jelements = json_object_object_get(jnode, "elements");
1333 sz = json_object_array_length(jelements);
1336 json_object *jentry, *jmods;
1340 /* Mismatch in the element count */
1344 jentry = json_object_array_get_idx(jelements, i);
1346 __mesh_write_int(jentry, "index", i);
1348 if (!__mesh_write_uint16_hex(jentry, "location", l_get_le16(data)))
1358 jmods = json_object_object_get(jentry, "models");
1360 /* For backwards compatibility */
1361 jmods = json_object_new_array();
1362 json_object_object_add(jentry, "models", jmods);
1365 while (len >= 2 && m--) {
1366 mod_id = l_get_le16(data);
1368 jobj = __mesh_init_model(mod_id);
1372 json_object_array_add(jmods, jobj);
1377 while (len >= 4 && v--) {
1378 jobj = json_object_new_object();
1379 mod_id = l_get_le16(data + 2);
1380 mod_id = l_get_le16(data) << 16 | mod_id;
1382 jobj = __mesh_init_vendor_model(mod_id);
1386 json_object_array_add(jmods, jobj);
1395 /* CRPL is written last. Will be used to check composition's presence */
1396 if (!__mesh_write_uint16_hex(jnode, "crpl", crpl))
1399 /* Initiate remote's composition from storage */
1400 if (!__mesh_load_composition(cfg, jnode, unicast))
1403 return __bt_mesh_save_configruation_file(cfg);
1406 /* Reset elements array */
1407 json_object_object_del(jnode, "elements");
1408 __mesh_init_elements(sz);
1413 _bt_mesh_cdb_t* _bt_mesh_conf_load(const char *file_name,
1416 char *token_str = NULL;
1422 _bt_mesh_cdb_t *cfg;
1424 fd = open(file_name, O_RDONLY);
1428 if (fstat(fd, &st) == -1) {
1433 str = (char *) g_malloc0(st.st_size + 1);
1439 sz = read(fd, str, st.st_size);
1440 if (sz != st.st_size) {
1441 BT_ERR("Mesh: Failed to read configuration file [%s]", file_name);
1446 jcfg = json_tokener_parse(str);
1453 cfg = g_malloc0(sizeof(_bt_mesh_cdb_t));
1456 cfg->cfg_fname = g_strdup(file_name);
1458 if (!__mesh_get_uuid(jcfg, cfg->uuid)) {
1459 BT_ERR("Mesh: Configuration file missing UUID");
1463 if (!__mesh_get_token(jcfg, cfg->token)) {
1464 BT_ERR("Mesh: Configuration file missing token");
1468 token_str = _bt_service_convert_hex_to_string((unsigned char*)cfg->token, 8);
1470 /* Match CDB file tken with user's token */
1471 if (g_strcmp0(token_str, token)) {
1472 BT_INFO("Mesh: Token did not match! File token [%s] requested token [%s]",
1476 /* TODO: Load keys and remotes */
1479 _bt_mesh_conf_free(cfg);
1483 bool _bt_mesh_conf_load_all_nodes(_bt_mesh_cdb_t *cfg)
1485 json_object *jnodes;
1486 int i, sz, node_count = 0;
1488 json_object_object_get_ex(cfg->jcfg, "nodes", &jnodes);
1489 if (!jnodes || json_object_get_type(jnodes) != json_type_array)
1492 sz = json_object_array_length(jnodes);
1494 for (i = 0; i < sz; ++i) {
1495 json_object *jnode, *jval, *jarray;
1497 uint16_t unicast, key_idx;
1499 int ele_cnt, key_cnt;
1502 jnode = json_object_array_get_idx(jnodes, i);
1506 if (!json_object_object_get_ex(jnode, "uuid", &jval))
1509 str = json_object_get_string(jval);
1510 if (strlen(str) != 32)
1513 _bt_mesh_util_convert_string_to_hex(str, 32, uuid, 16);
1515 if (!json_object_object_get_ex(jnode, "unicastAddress", &jval))
1518 str = json_object_get_string(jval);
1519 if (sscanf(str, "%04hx", &unicast) != 1)
1522 json_object_object_get_ex(jnode, "elements", &jarray);
1523 if (!jarray || json_object_get_type(jarray) != json_type_array)
1526 ele_cnt = json_object_array_length(jarray);
1528 if (ele_cnt > MESH_MAX_ELE_COUNT)
1531 json_object_object_get_ex(jnode, "netKeys", &jarray);
1532 if (!jarray || json_object_get_type(jarray) != json_type_array)
1535 key_cnt = json_object_array_length(jarray);
1539 key_idx = __mesh_node_parse_key(jarray, 0);
1540 if (key_idx == MESH_KEY_IDX_INVALID)
1543 _bt_mesh_node_add_node(cfg->uuid, (const uint8_t *)uuid, unicast, ele_cnt,
1545 for (j = 1; j < key_cnt; j++) {
1546 key_idx = __mesh_node_parse_key(jarray, j);
1548 if (key_idx != MESH_KEY_IDX_INVALID)
1549 _bt_mesh_node_add_net_key(cfg->uuid, unicast, key_idx);
1552 json_object_object_get_ex(jnode, "appKeys", &jarray);
1553 if (!jarray || json_object_get_type(jarray) != json_type_array)
1556 key_cnt = json_object_array_length(jarray);
1557 for (j = 0; j < key_cnt; j++) {
1558 key_idx = __mesh_node_parse_key(jarray, j);
1560 if (key_idx != MESH_KEY_IDX_INVALID)
1561 _bt_mesh_node_add_app_key(cfg->uuid, unicast, key_idx);
1564 __mesh_load_composition(cfg, jnode, unicast);
1568 /* TODO: Add the rest of the configuration */
1571 if (node_count != sz)
1572 BT_ERR("Mesh: CDB: The remote node configuration load is incomplete!");
1577 bool _bt_mesh_conf_load_all_keys(_bt_mesh_cdb_t* cfg)
1579 json_object *jarray, *jentry;
1580 int net_idx, app_idx;
1582 json_object *jobj = cfg->jcfg;
1584 json_object_object_get_ex(jobj, "netKeys", &jarray);
1585 if (!jarray || json_object_get_type(jarray) != json_type_array)
1588 key_cnt = json_object_array_length(jarray);
1592 for (i = 0; i < key_cnt; ++i) {
1595 jentry = json_object_array_get_idx(jarray, i);
1597 if (!__mesh_get_int(jentry, "index", &net_idx))
1600 _bt_mesh_keys_add_net_key(cfg->uuid, (uint16_t) net_idx);
1602 if (!__mesh_get_int(jentry, "phase", &phase))
1605 _bt_mesh_keys_set_net_key_phase(cfg, net_idx, (uint8_t) phase, false);
1608 json_object_object_get_ex(jobj, "appKeys", &jarray);
1609 if (!jarray || json_object_get_type(jarray) != json_type_array)
1612 key_cnt = json_object_array_length(jarray);
1616 for (i = 0; i < key_cnt; ++i) {
1618 jentry = json_object_array_get_idx(jarray, i);
1619 if (!__mesh_get_int(jentry, "boundNetKey", &net_idx))
1622 if (!__mesh_get_int(jentry, "index", &app_idx))
1625 _bt_mesh_keys_add_app_key(cfg->uuid, (uint16_t) net_idx, (uint16_t) app_idx);