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));
339 BT_INFO("Mesh: Find Node with UUID [%s]", buf);
341 json_object_object_get_ex(jcfg, "nodes", &jarray);
342 if (!jarray || json_object_get_type(jarray) != json_type_array)
345 sz = json_object_array_length(jarray);
346 BT_INFO("Mesh: Total nodes present in CDB [%d]", sz);
348 for (i = 0; i < sz; ++i) {
349 json_object *jentry, *jval;
352 jentry = json_object_array_get_idx(jarray, i);
353 if (!json_object_object_get_ex(jentry, "uuid", &jval))
356 str = json_object_get_string(jval);
357 if (strlen(str) != 32)
359 BT_INFO("Mesh: Got one node with UUID [%s]", str);
360 if (!g_strcmp0(buf, str))
367 static json_object *__mesh_get_key_object(json_object *jarray,
370 int i, sz = json_object_array_length(jarray);
372 for (i = 0; i < sz; ++i) {
376 jentry = json_object_array_get_idx(jarray, i);
377 if (!__mesh_get_int(jentry, "index", &jidx))
387 static bool __mesh_add_string(json_object *jobj,
388 const char *desc, const char *str)
390 json_object *jstring = json_object_new_string(str);
395 json_object_object_add(jobj, desc, jstring);
399 static bool __mesh_get_token(json_object *jobj, uint8_t token[8])
404 if (!json_object_object_get_ex(jobj, "token", &jval))
407 str = json_object_get_string(jval);
408 if (!_bt_mesh_util_convert_string_to_hex(str, strlen(str), token, 8))
414 static bool __mesh_get_uuid(json_object *jobj, uint8_t uuid[16])
419 if (!json_object_object_get_ex(jobj, "uuid", &jval))
422 str = json_object_get_string(jval);
423 if (!_bt_mesh_util_convert_string_to_hex(str, strlen(str), uuid, 16))
429 static bool __mesh_add_u8_8(json_object *jobj,
430 const char *desc, const uint8_t value[8])
432 json_object *jstring;
435 _bt_mesh_util_convert_hex_to_string((uint8_t *) value, 8, buf, 17);
436 jstring = json_object_new_string(buf);
440 json_object_object_add(jobj, desc, jstring);
444 static bool __mesh_add_u8_16(json_object *jobj,
445 const char *desc, const uint8_t value[16])
447 json_object *jstring;
450 _bt_mesh_util_convert_hex_to_string((uint8_t *) value, 16, buf, 33);
451 jstring = json_object_new_string(buf);
455 json_object_object_add(jobj, desc, jstring);
459 void _bt_mesh_conf_free(_bt_mesh_cdb_t *cfg)
461 g_free(cfg->cfg_fname);
462 g_free(cfg->app_cred);
463 json_object_put(cfg->jcfg);
464 g_slist_free_full(cfg->groups, g_free);
468 bool _bt_mesh_conf_parse_data(void *cfg, int k)
470 _bt_mesh_cdb_t *conf = (_bt_mesh_cdb_t*) cfg;
476 static bool __mesh_jarray_group_delete(json_object *jarray, uint16_t group_addr)
478 int i, sz = json_object_array_length(jarray);
482 for (i = 0; i < sz; ++i) {
487 jentry = json_object_array_get_idx(jarray, i);
488 if (!json_object_object_get_ex(jentry, "name",
492 str = json_object_get_string(jval);
495 memcpy(buf, str + 6, 5);
496 BT_INFO("Mesh: JSON Group string:[%s]", buf);
497 if (sscanf(buf, "%04hx", &addr) != 1)
499 BT_INFO("Mesh: JSON Group in Hex [0x%2.2x]", addr);
501 if (group_addr == addr)
506 BT_INFO("Mesh: Failed to remove group");
510 json_object_array_del_idx(jarray, i, 1);
514 static void __mesh_jarray_key_del(json_object *jarray, int16_t idx)
516 int i, sz = json_object_array_length(jarray);
518 for (i = 0; i < sz; ++i) {
522 jentry = json_object_array_get_idx(jarray, i);
524 if (!__mesh_get_int(jentry, "index", &val))
528 json_object_array_del_idx(jarray, i, 1);
534 static bool __mesh_delete_group(_bt_mesh_cdb_t *cfg,
535 json_object *jobj, const char *desc, uint16_t addr)
539 if (!json_object_object_get_ex(jobj, desc, &jarray))
542 if (!__mesh_jarray_group_delete(jarray, addr))
545 return __bt_mesh_save_configruation_file(cfg);
548 static bool __mesh_delete_key(_bt_mesh_cdb_t *cfg,
549 json_object *jobj, const char *desc, uint16_t idx)
553 if (!json_object_object_get_ex(jobj, desc, &jarray))
556 __mesh_jarray_key_del(jarray, idx);
558 return __bt_mesh_save_configruation_file(cfg);
561 bool _bt_mesh_conf_set_phase_network_key(_bt_mesh_cdb_t *cfg,
562 uint16_t net_idx, uint8_t phase)
564 json_object *jval, *jarray, *jkey;
566 if (!cfg || !cfg->jcfg)
569 json_object_object_get_ex(cfg->jcfg, "netKeys", &jarray);
570 if (!jarray || json_object_get_type(jarray) != json_type_array)
573 jkey = __mesh_get_key_object(jarray, net_idx);
577 jval = json_object_new_int(phase);
581 json_object_object_add(jkey, "phase", jval);
583 return __bt_mesh_save_configruation_file(cfg);
586 bool _bt_mesh_conf_delete_application_key(_bt_mesh_cdb_t *cfg, uint16_t app_idx)
588 if (!cfg || !cfg->jcfg)
591 return __mesh_delete_key(cfg, cfg->jcfg, "appKeys", app_idx);
594 bool _bt_mesh_conf_set_unicast_address_range(_bt_mesh_cdb_t *cfg,
595 uint16_t low, uint16_t high)
597 if (!cfg || !cfg->jcfg)
600 if (!__mesh_write_uint16_hex(cfg->jcfg, "low", low))
603 if (!__mesh_write_uint16_hex(cfg->jcfg, "high", high))
606 return __bt_mesh_save_configruation_file(cfg);
609 bool _bt_mesh_conf_insert_node_object(_bt_mesh_cdb_t *cfg,
610 uint8_t uuid[16], uint8_t num_els,
611 uint16_t unicast, uint16_t net_idx)
614 json_object *jelements, *jnodes, *jnetkeys, *jappkeys;
617 if (!cfg || !cfg->jcfg)
620 jnode = __mesh_get_node_by_uuid(cfg->jcfg, uuid);
622 BT_ERR("MESH:Node already exists");
626 jnode = json_object_new_object();
630 if (!__mesh_add_u8_16(jnode, "uuid", uuid))
633 jelements = json_object_new_array();
637 for (i = 0; i < num_els; ++i) {
638 json_object *jelement = json_object_new_object();
641 json_object_put(jelements);
645 __mesh_write_int(jelement, "elementIndex", i);
646 json_object_array_add(jelements, jelement);
649 json_object_object_add(jnode, "elements", jelements);
651 jnetkeys = json_object_new_array();
655 json_object_object_add(jnode, "netKeys", jnetkeys);
657 if (!__mesh_add_node_key(cfg, jnode, "netKeys", net_idx))
660 jappkeys = json_object_new_array();
664 json_object_object_add(jnode, "appKeys", jappkeys);
666 if (!__mesh_write_uint16_hex(jnode, "unicastAddress", unicast))
669 if (!json_object_object_get_ex(cfg->jcfg, "nodes", &jnodes))
672 json_object_array_add(jnodes, jnode);
674 if (!__bt_mesh_save_configruation_file(cfg))
680 json_object_put(jnode);
684 bool _bt_mesh_conf_insert_application_key(_bt_mesh_cdb_t *cfg,
685 uint16_t net_idx, uint16_t app_idx)
687 if (!cfg || !cfg->jcfg)
690 if (!__mesh_add_app_key(cfg->jcfg, net_idx, app_idx))
693 return __bt_mesh_save_configruation_file(cfg);
696 bool _bt_mesh_conf_insert_network_key(_bt_mesh_cdb_t *cfg,
697 uint16_t net_idx, uint8_t key_refresh)
699 json_object *jkey, *jarray;
701 if (!cfg || !cfg->jcfg)
704 json_object_object_get_ex(cfg->jcfg, "netKeys", &jarray);
705 if (!jarray || json_object_get_type(jarray) != json_type_array)
708 if (__mesh_get_key_object(jarray, net_idx))
711 jkey = json_object_new_object();
713 if (!__mesh_write_int(jkey, "index", net_idx))
716 if (!__mesh_write_int(jkey, "phase", key_refresh))
719 json_object_array_add(jarray, jkey);
721 return __bt_mesh_save_configruation_file(cfg);
724 json_object_put(jkey);
728 bool _bt_mesh_conf_delete_network_key(_bt_mesh_cdb_t *cfg,
731 if (!cfg || !cfg->jcfg)
734 return __mesh_delete_key(cfg, cfg->jcfg, "netKeys", net_idx);
738 bool _bt_mesh_conf_node_set_timetolive_value(_bt_mesh_cdb_t *cfg,
739 uint16_t unicast, uint8_t ttl)
743 if (!cfg || !cfg->jcfg)
746 jnode = __mesh_get_node_by_unicast(cfg, unicast);
750 if (!__mesh_write_int(jnode, "defaultTTL", ttl))
753 return __bt_mesh_save_configruation_file(cfg);
756 bool _bt_mesh_conf_node_insert_network_key(_bt_mesh_cdb_t *cfg,
757 uint16_t unicast, uint16_t net_idx)
761 if (!cfg || !cfg->jcfg)
764 jnode = __mesh_get_node_by_unicast(cfg, unicast);
768 return __mesh_add_node_key(cfg, jnode, "netKeys", net_idx);
771 bool _bt_mesh_conf_node_delete_network_key(_bt_mesh_cdb_t *cfg,
772 uint16_t unicast, uint16_t net_idx)
776 if (!cfg || !cfg->jcfg)
779 jnode = __mesh_get_node_by_unicast(cfg, unicast);
783 return __mesh_delete_key(cfg, jnode, "netKeys", net_idx);
786 bool _bt_mesh_conf_node_insert_application_key(_bt_mesh_cdb_t *cfg,
787 uint16_t unicast, uint16_t idx)
791 if (!cfg || !cfg->jcfg)
794 jnode = __mesh_get_node_by_unicast(cfg, unicast);
798 return __mesh_add_node_key(cfg, jnode, "appKeys", idx);
801 bool _bt_mesh_conf_node_delete_application_key(_bt_mesh_cdb_t *cfg,
802 uint16_t unicast, uint16_t idx)
806 if (!cfg || !cfg->jcfg)
809 jnode = __mesh_get_node_by_unicast(cfg, unicast);
813 return __mesh_delete_key(cfg, jnode, "appKeys", idx);
816 _bt_mesh_cdb_t *_bt_mesh_conf_database_create(const char *file_name,
817 const uint8_t uuid[16],
818 const uint8_t token[8], const char *network_name,
819 const char *app_cred)
822 json_object *jcfg, *jarray;
833 jcfg = json_object_new_object();
837 cfg = g_malloc0(sizeof(_bt_mesh_cdb_t));
839 cfg->cfg_fname = g_strdup(file_name);
840 cfg->app_cred = g_strdup(app_cred);
841 memcpy(&cfg->token, (void*)token, 8);
842 memcpy(&cfg->uuid, (void*)uuid, 16);
844 if (!__mesh_add_u8_8(jcfg, "Network_Token", token))
847 if (!__mesh_add_u8_16(jcfg, "Config_Node_UUID", uuid))
850 if (!__mesh_add_string(jcfg, "Network_Name", network_name))
853 if (!__mesh_add_string(jcfg, "Application_Credential", app_cred))
856 jarray = json_object_new_array();
860 json_object_object_add(jcfg, "nodes", jarray);
862 jarray = json_object_new_array();
866 json_object_object_add(jcfg, "netKeys", jarray);
868 jarray = json_object_new_array();
872 json_object_object_add(jcfg, "appKeys", jarray);
874 if (!__bt_mesh_save_configruation_file(cfg))
880 _bt_mesh_conf_free(cfg);
885 bool _bt_mesh_conf_delete_node(_bt_mesh_cdb_t *cfg, uint16_t unicast)
890 if (!json_object_object_get_ex(cfg->jcfg, "nodes", &jarray))
893 if (!jarray || json_object_get_type(jarray) != json_type_array)
896 sz = json_object_array_length(jarray);
898 for (i = 0; i < sz; ++i) {
899 json_object *jentry, *jval;
903 jentry = json_object_array_get_idx(jarray, i);
904 if (!json_object_object_get_ex(jentry, "unicastAddress",
908 str = json_object_get_string(jval);
909 if (sscanf(str, "%04hx", &addr) != 1)
919 json_object_array_del_idx(jarray, i, 1);
921 return __bt_mesh_save_configruation_file(cfg);
924 uint16_t** _bt_mesh_conf_get_all_model_info(_bt_mesh_cdb_t *cfg,
925 int element_index, int *num_models)
931 json_object *jarray = NULL;
932 json_object *jelement = NULL;
933 json_object *jmodelarray = NULL;
944 jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
948 /* Get element array object */
949 json_object_object_get_ex(jnode, "elements", &jarray);
951 if (!jarray || json_object_get_type(jarray) != json_type_array)
954 /* Get specific element by index */
955 jelement = __mesh_get_key_object(jarray, element_index);
960 /* Get Model array object inside the selected element */
961 json_object_object_get_ex(jelement, "models", &jmodelarray);
963 if (!jmodelarray || json_object_get_type(jmodelarray) != json_type_array)
966 sz = json_object_array_length(jmodelarray);
967 models = (uint16_t**) g_malloc0(sz * sizeof(uint16_t*));
969 for (i = 0; i < sz; ++i) {
972 jentry = json_object_array_get_idx(jmodelarray, i);
973 str = json_object_get_string(jentry);
974 /* Only standard models are handled now */
975 if (sscanf(str, "%04hx", models[i]) != 1) {
976 for (int j = 0 ; j < sz; j++)
982 /* TODO: Need to handle vendor models */
987 bool _bt_mesh_conf_get_element_count(_bt_mesh_cdb_t *cfg,
993 json_object *jarray = NULL;
1002 jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
1006 json_object_object_get_ex(jnode, "elements", &jarray);
1008 if (!jarray || json_object_get_type(jarray) != json_type_array)
1011 sz = json_object_array_length(jarray);
1019 bool _bt_mesh_conf_fetch_vendor_specific_info(
1020 _bt_mesh_cdb_t *cfg, uint16_t unicast,
1021 uint16_t *cid, uint16_t *vid,
1022 uint16_t *version, uint16_t *crpl,
1023 int *relay, int *friend,
1024 int *proxy, int *lpn)
1028 json_object *jobj = NULL;
1029 json_object *jobjfeature = NULL;
1038 jnode = __mesh_get_node_by_unicast(cfg, unicast);
1043 if (!json_object_object_get_ex(jnode, "crpl", &jobj))
1046 str = json_object_get_string(jobj);
1050 if (sscanf(str, "%04hx", crpl) != 1)
1053 BT_INFO("Mesh: Got CRPL[%s]", str);
1054 /* Get Company ID */
1055 if (!json_object_object_get_ex(jnode, "cid", &jobj))
1058 str = json_object_get_string(jobj);
1061 if (sscanf(str, "%04hx", cid) != 1)
1064 BT_INFO("Mesh: Got CID[%s]", str);
1066 if (!json_object_object_get_ex(jnode, "pid", &jobj))
1069 str = json_object_get_string(jobj);
1073 if (sscanf(str, "%04hx", vid) != 1)
1076 BT_INFO("Mesh: Got PID[%s]", str);
1077 /* Get Version ID */
1078 if (!json_object_object_get_ex(jnode, "vid", &jobj))
1081 str = json_object_get_string(jobj);
1084 if (sscanf(str, "%04hx", version) != 1)
1087 BT_INFO("Mesh: got version [%s]", str);
1088 jobj = json_object_object_get(jnode, "features");
1091 if (json_object_object_get_ex(jobj, "relay", &jobjfeature)) {
1092 str = json_object_get_string(jobjfeature);
1094 sscanf(str, "%d", relay);
1095 BT_INFO("Mesh: Got Relay [%s]", str);
1099 if (json_object_object_get_ex(jobj, "friend", &jobjfeature)) {
1100 str = json_object_get_string(jobjfeature);
1102 sscanf(str, "%d", friend);
1103 BT_INFO("Mesh: Got Friend [%s]", str);
1107 if (json_object_object_get_ex(jobj, "proxy", &jobjfeature)) {
1108 str = json_object_get_string(jobjfeature);
1110 sscanf(str, "%d", proxy);
1111 BT_INFO("Mesh: Got Proxy[%s]", str);
1114 if (json_object_object_get_ex(jobj, "lowPower", &jobjfeature)) {
1115 str = json_object_get_string(jobjfeature);
1117 sscanf(str, "%d", lpn);
1118 BT_INFO("Mesh: Got LPN[%s]", str);
1125 GSList *_bt_mesh_conf_load_group_info(_bt_mesh_cdb_t *cfg)
1127 json_object *jgroups;
1128 GSList *groups = NULL;
1131 if (!cfg || !cfg->jcfg)
1134 if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups)) {
1135 jgroups = json_object_new_array();
1139 json_object_object_add(cfg->jcfg, "groups", jgroups);
1142 sz = json_object_array_length(jgroups);
1144 for (i = 0; i < sz; ++i) {
1145 json_object *jgroup, *jval;
1146 _bt_mesh_group_t *grp;
1147 uint16_t addr, addr_len;
1150 jgroup = json_object_array_get_idx(jgroups, i);
1154 if (!json_object_object_get_ex(jgroup, "name", &jval))
1157 str = json_object_get_string(jval);
1158 if (strlen(str) != 10)
1161 if (sscanf(str + 6, "%04hx", &addr) != 1)
1163 if (!json_object_object_get_ex(jgroup, "address", &jval))
1166 str = json_object_get_string(jval);
1167 addr_len = strlen(str);
1168 if (addr_len != 4 && addr_len != 32)
1171 if (addr_len == 32 && !MESH_IS_VIRTUAL(addr))
1174 grp = g_malloc0(sizeof(_bt_mesh_group_t));
1177 sscanf(str, "%04hx", &grp->grp_addr);
1179 _bt_mesh_util_convert_string_to_hex(str,
1180 32, grp->label_uuid, 16);
1181 grp->grp_addr = addr;
1184 groups = g_slist_append(groups, grp);
1190 bool _bt_mesh_conf_insert_group_info(_bt_mesh_cdb_t *cfg,
1191 _bt_mesh_group_t *grp)
1193 json_object *jgroup, *jgroups, *jval;
1196 if (!cfg || !cfg->jcfg)
1199 if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups)) {
1200 BT_INFO("Mesh: Group JSON object is not present: Create");
1201 jgroups = json_object_new_array();
1205 json_object_object_add(cfg->jcfg, "groups", jgroups);
1208 jgroup = json_object_new_object();
1212 snprintf(buf, 11, "Group_%4.4x", grp->grp_addr);
1213 jval = json_object_new_string(buf);
1214 json_object_object_add(jgroup, "name", jval);
1216 if (MESH_IS_VIRTUAL(grp->grp_addr)) {
1217 if (!__mesh_add_u8_16(jgroup, "address", grp->label_uuid))
1220 if (!__mesh_write_uint16_hex(jgroup, "address", grp->grp_addr))
1224 json_object_array_add(jgroups, jgroup);
1226 return __bt_mesh_save_configruation_file(cfg);
1229 json_object_put(jgroup);
1233 bool _bt_mesh_conf_delete_group_entry(_bt_mesh_cdb_t *cfg, uint16_t addr)
1235 if (!cfg || !cfg->jcfg)
1238 return __mesh_delete_group(cfg, cfg->jcfg, "groups", addr);
1241 bool _bt_mesh_conf_set_network_friendly_name(_bt_mesh_cdb_t *cfg,
1242 const char *network_name)
1253 json_object_object_del(jcfg, "Network_Name");
1254 __mesh_add_string(jcfg, "Network_Name", network_name);
1257 BT_INFO("Mesh: CDB: Network New Name [%s]", network_name);
1258 return __bt_mesh_save_configruation_file(cfg);
1261 const char * _bt_mesh_conf_get_network_friendly_name(_bt_mesh_cdb_t *cfg)
1264 json_object *jobj = NULL;
1274 /* Get Network Name */
1275 if (!json_object_object_get_ex(jcfg, "Network_Name", &jobj))
1278 str = json_object_get_string(jobj);
1282 BT_INFO("Mesh: CDB: Network Name [%s]", str);
1286 static bool __mesh_load_composition(_bt_mesh_cdb_t *cfg,
1287 json_object *jnode, uint16_t unicast)
1289 json_object *jarray;
1292 if (!json_object_object_get_ex(jnode, "elements", &jarray))
1295 if (json_object_get_type(jarray) != json_type_array)
1298 ele_cnt = json_object_array_length(jarray);
1300 for (i = 0; i < ele_cnt; ++i) {
1301 json_object *jentry, *jval, *jmods;
1305 jentry = json_object_array_get_idx(jarray, i);
1306 if (!json_object_object_get_ex(jentry, "index", &jval))
1309 index = json_object_get_int(jval);
1313 if (!json_object_object_get_ex(jentry, "models", &jmods))
1316 mod_cnt = json_object_array_length(jmods);
1317 BT_INFO("Mesh: Total Model count in element Index [%d] is [%d]",
1320 for (k = 0; k < mod_cnt; ++k) {
1321 json_object *jmod, *jid;
1322 uint32_t mod_id, len;
1325 jmod = json_object_array_get_idx(jmods, k);
1326 if (!json_object_object_get_ex(jmod, "modelId", &jid))
1329 str = json_object_get_string(jid);
1332 if (len != 4 && len != 8)
1335 if ((len == 4) && (sscanf(str, "%04x", &mod_id) != 1))
1338 if ((len == 8) && (sscanf(str, "%08x", &mod_id) != 1))
1341 _bt_mesh_node_set_model(cfg->uuid,
1342 unicast, index, mod_id, len == 8);
1349 bool _bt_mesh_conf_set_node_comp_data(_bt_mesh_cdb_t *cfg,
1350 uint16_t unicast, uint8_t *data, uint16_t len)
1354 json_object *jnode, *jobj, *jelements;
1357 if (!cfg || !cfg->jcfg)
1360 jnode = __mesh_get_node_by_unicast(cfg, unicast);
1364 /* skip page -- We only support Page Zero */
1368 /* If "crpl" property is present, composition is already recorded */
1369 if (json_object_object_get_ex(jnode, "crpl", &jobj))
1372 if (!__mesh_write_uint16_hex(jnode, "cid", l_get_le16(&data[0])))
1375 if (!__mesh_write_uint16_hex(jnode, "pid", l_get_le16(&data[2])))
1378 if (!__mesh_write_uint16_hex(jnode, "vid", l_get_le16(&data[4])))
1381 crpl = l_get_le16(&data[6]);
1383 features = l_get_le16(&data[8]);
1387 jobj = json_object_object_get(jnode, "features");
1389 jobj = json_object_new_object();
1390 json_object_object_add(jnode, "features", jobj);
1393 if ((features & MESH_FEATURE_RELAY))
1394 __mesh_write_int(jobj, "relay", 1);
1396 __mesh_write_int(jobj, "relay", 0);
1398 if ((features & MESH_FEATURE_FRIEND))
1399 __mesh_write_int(jobj, "friend", 1);
1401 __mesh_write_int(jobj, "friend", 0);
1403 if ((features & MESH_FEATURE_PROXY))
1404 __mesh_write_int(jobj, "proxy", 1);
1406 __mesh_write_int(jobj, "proxy", 0);
1408 if ((features & MESH_FEATURE_LPN))
1409 __mesh_write_int(jobj, "lowPower", 1);
1411 __mesh_write_int(jobj, "lowPower", 0);
1413 jelements = json_object_object_get(jnode, "elements");
1417 sz = json_object_array_length(jelements);
1420 json_object *jentry, *jmods;
1424 /* Mismatch in the element count */
1428 jentry = json_object_array_get_idx(jelements, i);
1430 __mesh_write_int(jentry, "index", i);
1432 if (!__mesh_write_uint16_hex(jentry, "location", l_get_le16(data)))
1442 jmods = json_object_object_get(jentry, "models");
1444 /* For backwards compatibility */
1445 jmods = json_object_new_array();
1446 json_object_object_add(jentry, "models", jmods);
1449 while (len >= 2 && m--) {
1450 mod_id = l_get_le16(data);
1452 jobj = __mesh_init_model(mod_id);
1456 json_object_array_add(jmods, jobj);
1461 while (len >= 4 && v--) {
1462 jobj = json_object_new_object();
1463 mod_id = l_get_le16(data + 2);
1464 mod_id = l_get_le16(data) << 16 | mod_id;
1466 jobj = __mesh_init_vendor_model(mod_id);
1470 json_object_array_add(jmods, jobj);
1479 /* CRPL is written last. Will be used to check composition's presence */
1480 if (!__mesh_write_uint16_hex(jnode, "crpl", crpl))
1483 /* Initiate remote's composition from storage */
1484 if (!__mesh_load_composition(cfg, jnode, unicast))
1487 return __bt_mesh_save_configruation_file(cfg);
1490 /* Reset elements array */
1491 json_object_object_del(jnode, "elements");
1492 __mesh_init_elements(sz);
1497 _bt_mesh_cdb_t* _bt_mesh_conf_load(const char *file_name,
1500 char *token_str = NULL;
1506 _bt_mesh_cdb_t *cfg;
1508 fd = open(file_name, O_RDONLY);
1512 if (fstat(fd, &st) == -1) {
1517 str = (char *) g_malloc0(st.st_size + 1);
1523 sz = read(fd, str, st.st_size);
1524 if (sz != st.st_size) {
1525 BT_ERR("Mesh: Failed to read configuration file [%s]", file_name);
1530 jcfg = json_tokener_parse(str);
1537 cfg = g_malloc0(sizeof(_bt_mesh_cdb_t));
1540 cfg->cfg_fname = g_strdup(file_name);
1542 if (!__mesh_get_uuid(jcfg, cfg->uuid)) {
1543 BT_ERR("Mesh: Configuration file missing UUID");
1547 if (!__mesh_get_token(jcfg, cfg->token)) {
1548 BT_ERR("Mesh: Configuration file missing token");
1552 token_str = _bt_service_convert_hex_to_string((unsigned char*)cfg->token, 8);
1554 /* Match CDB file tken with user's token */
1555 if (g_strcmp0(token_str, token)) {
1556 BT_INFO("Mesh: Token did not match! File token [%s] requested token [%s]",
1560 /* TODO: Load keys and remotes */
1563 _bt_mesh_conf_free(cfg);
1567 bool _bt_mesh_conf_load_all_nodes(_bt_mesh_cdb_t *cfg)
1569 json_object *jnodes;
1570 int i, sz, node_count = 0;
1572 json_object_object_get_ex(cfg->jcfg, "nodes", &jnodes);
1573 if (!jnodes || json_object_get_type(jnodes) != json_type_array)
1576 sz = json_object_array_length(jnodes);
1578 for (i = 0; i < sz; ++i) {
1579 json_object *jnode, *jval, *jarray;
1581 uint16_t unicast, key_idx;
1583 int ele_cnt, key_cnt;
1586 jnode = json_object_array_get_idx(jnodes, i);
1590 if (!json_object_object_get_ex(jnode, "uuid", &jval))
1593 str = json_object_get_string(jval);
1594 if (strlen(str) != 32)
1597 _bt_mesh_util_convert_string_to_hex(str, 32, uuid, 16);
1599 if (!json_object_object_get_ex(jnode, "unicastAddress", &jval))
1602 str = json_object_get_string(jval);
1603 if (sscanf(str, "%04hx", &unicast) != 1)
1606 json_object_object_get_ex(jnode, "elements", &jarray);
1607 if (!jarray || json_object_get_type(jarray) != json_type_array)
1610 ele_cnt = json_object_array_length(jarray);
1612 if (ele_cnt > MESH_MAX_ELE_COUNT)
1615 json_object_object_get_ex(jnode, "netKeys", &jarray);
1616 if (!jarray || json_object_get_type(jarray) != json_type_array)
1619 key_cnt = json_object_array_length(jarray);
1623 key_idx = __mesh_node_parse_key(jarray, 0);
1624 if (key_idx == MESH_KEY_IDX_INVALID)
1627 _bt_mesh_node_add_node(cfg->uuid, (const uint8_t *)uuid, unicast, ele_cnt,
1629 for (j = 1; j < key_cnt; j++) {
1630 key_idx = __mesh_node_parse_key(jarray, j);
1632 if (key_idx != MESH_KEY_IDX_INVALID)
1633 _bt_mesh_node_add_net_key(cfg->uuid, unicast, key_idx);
1636 json_object_object_get_ex(jnode, "appKeys", &jarray);
1637 if (!jarray || json_object_get_type(jarray) != json_type_array)
1640 key_cnt = json_object_array_length(jarray);
1641 for (j = 0; j < key_cnt; j++) {
1642 key_idx = __mesh_node_parse_key(jarray, j);
1644 if (key_idx != MESH_KEY_IDX_INVALID)
1645 _bt_mesh_node_add_app_key(cfg->uuid, unicast, key_idx);
1648 __mesh_load_composition(cfg, jnode, unicast);
1652 /* TODO: Add the rest of the configuration */
1655 if (node_count != sz)
1656 BT_ERR("Mesh: CDB: The remote node configuration load is incomplete!");
1661 bool _bt_mesh_conf_load_all_keys(_bt_mesh_cdb_t* cfg)
1663 json_object *jarray, *jentry;
1664 int net_idx, app_idx;
1666 json_object *jobj = cfg->jcfg;
1668 json_object_object_get_ex(jobj, "netKeys", &jarray);
1669 if (!jarray || json_object_get_type(jarray) != json_type_array)
1672 key_cnt = json_object_array_length(jarray);
1676 for (i = 0; i < key_cnt; ++i) {
1679 jentry = json_object_array_get_idx(jarray, i);
1681 if (!__mesh_get_int(jentry, "index", &net_idx))
1684 _bt_mesh_keys_add_net_key(cfg->uuid, (uint16_t) net_idx);
1686 if (!__mesh_get_int(jentry, "phase", &phase))
1689 _bt_mesh_keys_set_net_key_phase(cfg, net_idx, (uint8_t) phase, false);
1692 json_object_object_get_ex(jobj, "appKeys", &jarray);
1693 if (!jarray || json_object_get_type(jarray) != json_type_array)
1696 key_cnt = json_object_array_length(jarray);
1700 for (i = 0; i < key_cnt; ++i) {
1702 jentry = json_object_array_get_idx(jarray, i);
1703 if (!__mesh_get_int(jentry, "boundNetKey", &net_idx))
1706 if (!__mesh_get_int(jentry, "index", &app_idx))
1709 _bt_mesh_keys_add_app_key(cfg->uuid, (uint16_t) net_idx, (uint16_t) app_idx);