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);
463 g_free(cfg->app_cred);
464 json_object_put(cfg->jcfg);
465 g_slist_free_full(cfg->groups, g_free);
469 bool _bt_mesh_conf_parse_data(void *cfg, int k)
471 _bt_mesh_cdb_t *conf = (_bt_mesh_cdb_t*) cfg;
477 static bool __mesh_jarray_group_delete(json_object *jarray, uint16_t group_addr)
479 int i, sz = json_object_array_length(jarray);
483 for (i = 0; i < sz; ++i) {
488 jentry = json_object_array_get_idx(jarray, i);
489 if (!json_object_object_get_ex(jentry, "name",
493 str = json_object_get_string(jval);
496 memcpy(buf, str + 6, 5);
497 BT_INFO("Mesh: JSON Group string:[%s]", buf);
498 if (sscanf(buf, "%04hx", &addr) != 1)
500 BT_INFO("Mesh: JSON Group in Hex [0x%2.2x]", addr);
502 if (group_addr == addr)
507 BT_INFO("Mesh: Failed to remove group");
511 json_object_array_del_idx(jarray, i, 1);
515 static void __mesh_jarray_key_del(json_object *jarray, int16_t idx)
517 int i, sz = json_object_array_length(jarray);
519 for (i = 0; i < sz; ++i) {
523 jentry = json_object_array_get_idx(jarray, i);
525 if (!__mesh_get_int(jentry, "index", &val))
529 json_object_array_del_idx(jarray, i, 1);
535 static bool __mesh_delete_group(_bt_mesh_cdb_t *cfg,
536 json_object *jobj, const char *desc, uint16_t addr)
540 if (!json_object_object_get_ex(jobj, desc, &jarray))
543 if (!__mesh_jarray_group_delete(jarray, addr))
546 return __bt_mesh_save_configruation_file(cfg);
549 static bool __mesh_delete_key(_bt_mesh_cdb_t *cfg,
550 json_object *jobj, const char *desc, uint16_t idx)
554 if (!json_object_object_get_ex(jobj, desc, &jarray))
557 __mesh_jarray_key_del(jarray, idx);
559 return __bt_mesh_save_configruation_file(cfg);
562 bool _bt_mesh_conf_set_phase_network_key(_bt_mesh_cdb_t *cfg,
563 uint16_t net_idx, uint8_t phase)
565 json_object *jval, *jarray, *jkey;
567 if (!cfg || !cfg->jcfg)
570 json_object_object_get_ex(cfg->jcfg, "netKeys", &jarray);
571 if (!jarray || json_object_get_type(jarray) != json_type_array)
574 jkey = __mesh_get_key_object(jarray, net_idx);
578 jval = json_object_new_int(phase);
582 json_object_object_add(jkey, "phase", jval);
584 return __bt_mesh_save_configruation_file(cfg);
587 bool _bt_mesh_conf_delete_application_key(_bt_mesh_cdb_t *cfg, uint16_t app_idx)
589 if (!cfg || !cfg->jcfg)
592 return __mesh_delete_key(cfg, cfg->jcfg, "appKeys", app_idx);
595 bool _bt_mesh_conf_set_unicast_address_range(_bt_mesh_cdb_t *cfg,
596 uint16_t low, uint16_t high)
598 if (!cfg || !cfg->jcfg)
601 if (!__mesh_write_uint16_hex(cfg->jcfg, "low", low))
604 if (!__mesh_write_uint16_hex(cfg->jcfg, "high", high))
607 return __bt_mesh_save_configruation_file(cfg);
610 bool _bt_mesh_conf_insert_node_object(_bt_mesh_cdb_t *cfg,
611 uint8_t uuid[16], uint8_t num_els,
612 uint16_t unicast, uint16_t net_idx)
615 json_object *jelements, *jnodes, *jnetkeys, *jappkeys;
618 if (!cfg || !cfg->jcfg)
621 jnode = __mesh_get_node_by_uuid(cfg->jcfg, uuid);
623 BT_ERR("MESH:Node already exists");
627 jnode = json_object_new_object();
631 if (!__mesh_add_u8_16(jnode, "uuid", uuid))
634 jelements = json_object_new_array();
638 for (i = 0; i < num_els; ++i) {
639 json_object *jelement = json_object_new_object();
642 json_object_put(jelements);
646 __mesh_write_int(jelement, "elementIndex", i);
647 json_object_array_add(jelements, jelement);
650 json_object_object_add(jnode, "elements", jelements);
652 jnetkeys = json_object_new_array();
656 json_object_object_add(jnode, "netKeys", jnetkeys);
658 if (!__mesh_add_node_key(cfg, jnode, "netKeys", net_idx))
661 jappkeys = json_object_new_array();
665 json_object_object_add(jnode, "appKeys", jappkeys);
667 if (!__mesh_write_uint16_hex(jnode, "unicastAddress", unicast))
670 if (!json_object_object_get_ex(cfg->jcfg, "nodes", &jnodes))
673 json_object_array_add(jnodes, jnode);
675 if (!__bt_mesh_save_configruation_file(cfg))
681 json_object_put(jnode);
685 bool _bt_mesh_conf_insert_application_key(_bt_mesh_cdb_t *cfg,
686 uint16_t net_idx, uint16_t app_idx)
688 if (!cfg || !cfg->jcfg)
691 if (!__mesh_add_app_key(cfg->jcfg, net_idx, app_idx))
694 return __bt_mesh_save_configruation_file(cfg);
697 bool _bt_mesh_conf_insert_network_key(_bt_mesh_cdb_t *cfg,
698 uint16_t net_idx, uint8_t key_refresh)
700 json_object *jkey, *jarray;
702 if (!cfg || !cfg->jcfg)
705 json_object_object_get_ex(cfg->jcfg, "netKeys", &jarray);
706 if (!jarray || json_object_get_type(jarray) != json_type_array)
709 if (__mesh_get_key_object(jarray, net_idx))
712 jkey = json_object_new_object();
714 if (!__mesh_write_int(jkey, "index", net_idx))
717 if (!__mesh_write_int(jkey, "phase", key_refresh))
720 json_object_array_add(jarray, jkey);
722 return __bt_mesh_save_configruation_file(cfg);
725 json_object_put(jkey);
729 bool _bt_mesh_conf_delete_network_key(_bt_mesh_cdb_t *cfg,
732 if (!cfg || !cfg->jcfg)
735 return __mesh_delete_key(cfg, cfg->jcfg, "netKeys", net_idx);
739 bool _bt_mesh_conf_node_set_timetolive_value(_bt_mesh_cdb_t *cfg,
740 uint16_t unicast, uint8_t ttl)
744 if (!cfg || !cfg->jcfg)
747 jnode = __mesh_get_node_by_unicast(cfg, unicast);
751 if (!__mesh_write_int(jnode, "defaultTTL", ttl))
754 return __bt_mesh_save_configruation_file(cfg);
757 bool _bt_mesh_conf_node_insert_network_key(_bt_mesh_cdb_t *cfg,
758 uint16_t unicast, uint16_t net_idx)
762 if (!cfg || !cfg->jcfg)
765 jnode = __mesh_get_node_by_unicast(cfg, unicast);
769 return __mesh_add_node_key(cfg, jnode, "netKeys", net_idx);
772 bool _bt_mesh_conf_node_delete_network_key(_bt_mesh_cdb_t *cfg,
773 uint16_t unicast, uint16_t net_idx)
777 if (!cfg || !cfg->jcfg)
780 jnode = __mesh_get_node_by_unicast(cfg, unicast);
784 return __mesh_delete_key(cfg, jnode, "netKeys", net_idx);
787 bool _bt_mesh_conf_node_insert_application_key(_bt_mesh_cdb_t *cfg,
788 uint16_t unicast, uint16_t idx)
792 if (!cfg || !cfg->jcfg)
795 jnode = __mesh_get_node_by_unicast(cfg, unicast);
799 return __mesh_add_node_key(cfg, jnode, "appKeys", idx);
802 bool _bt_mesh_conf_node_delete_application_key(_bt_mesh_cdb_t *cfg,
803 uint16_t unicast, uint16_t idx)
807 if (!cfg || !cfg->jcfg)
810 jnode = __mesh_get_node_by_unicast(cfg, unicast);
814 return __mesh_delete_key(cfg, jnode, "appKeys", idx);
817 _bt_mesh_cdb_t *_bt_mesh_conf_database_create(const char *file_name,
818 const uint8_t uuid[16],
819 const uint8_t token[8], const char *network_name,
820 const char *sender, const char *app_cred)
823 json_object *jcfg, *jarray;
834 jcfg = json_object_new_object();
838 cfg = g_malloc0(sizeof(_bt_mesh_cdb_t));
840 cfg->cfg_fname = g_strdup(file_name);
841 cfg->owner = g_strdup(sender);
842 cfg->app_cred = g_strdup(app_cred);
843 memcpy(&cfg->token, (void*)token, 8);
844 memcpy(&cfg->uuid, (void*)uuid, 16);
846 if (!__mesh_add_u8_8(jcfg, "Network_Token", token))
849 if (!__mesh_add_u8_16(jcfg, "Config_Node_UUID", uuid))
852 if (!__mesh_add_string(jcfg, "Network_Name", network_name))
855 if (!__mesh_add_string(jcfg, "Application_Credential", app_cred))
858 jarray = json_object_new_array();
862 json_object_object_add(jcfg, "nodes", jarray);
864 jarray = json_object_new_array();
868 json_object_object_add(jcfg, "netKeys", jarray);
870 jarray = json_object_new_array();
874 json_object_object_add(jcfg, "appKeys", jarray);
876 if (!__bt_mesh_save_configruation_file(cfg))
882 _bt_mesh_conf_free(cfg);
887 bool _bt_mesh_conf_delete_node(_bt_mesh_cdb_t *cfg, uint16_t unicast)
892 if (!json_object_object_get_ex(cfg->jcfg, "nodes", &jarray))
895 if (!jarray || json_object_get_type(jarray) != json_type_array)
898 sz = json_object_array_length(jarray);
900 for (i = 0; i < sz; ++i) {
901 json_object *jentry, *jval;
905 jentry = json_object_array_get_idx(jarray, i);
906 if (!json_object_object_get_ex(jentry, "unicastAddress",
910 str = json_object_get_string(jval);
911 if (sscanf(str, "%04hx", &addr) != 1)
921 json_object_array_del_idx(jarray, i, 1);
923 return __bt_mesh_save_configruation_file(cfg);
926 uint16_t** _bt_mesh_conf_get_all_model_info(_bt_mesh_cdb_t *cfg,
927 int element_index, int *num_models)
933 json_object *jarray = NULL;
934 json_object *jelement = NULL;
935 json_object *jmodelarray = NULL;
946 jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
950 /* Get element array object */
951 json_object_object_get_ex(jnode, "elements", &jarray);
953 if (!jarray || json_object_get_type(jarray) != json_type_array)
956 /* Get specific element by index */
957 jelement = __mesh_get_key_object(jarray, element_index);
962 /* Get Model array object inside the selected element */
963 json_object_object_get_ex(jelement, "models", &jmodelarray);
965 if (!jmodelarray || json_object_get_type(jmodelarray) != json_type_array)
968 sz = json_object_array_length(jmodelarray);
969 models = (uint16_t**) g_malloc0(sz * sizeof(uint16_t*));
971 for (i = 0; i < sz; ++i) {
974 jentry = json_object_array_get_idx(jmodelarray, i);
975 str = json_object_get_string(jentry);
976 /* Only standard models are handled now */
977 if (sscanf(str, "%04hx", models[i]) != 1) {
978 for (int j = 0 ; j < sz; j++)
984 /* TODO: Need to handle vendor models */
989 bool _bt_mesh_conf_get_element_count(_bt_mesh_cdb_t *cfg,
995 json_object *jarray = NULL;
1004 jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
1008 json_object_object_get_ex(jnode, "elements", &jarray);
1010 if (!jarray || json_object_get_type(jarray) != json_type_array)
1013 sz = json_object_array_length(jarray);
1021 bool _bt_mesh_conf_fetch_vendor_specific_info(
1022 _bt_mesh_cdb_t *cfg, uint16_t unicast,
1023 uint16_t *cid, uint16_t *vid,
1024 uint16_t *version, uint16_t *crpl,
1025 int *relay, int *friend,
1026 int *proxy, int *lpn)
1030 json_object *jobj = NULL;
1031 json_object *jobjfeature = NULL;
1040 jnode = __mesh_get_node_by_unicast(cfg, unicast);
1045 if (!json_object_object_get_ex(jnode, "crpl", &jobj))
1048 str = json_object_get_string(jobj);
1052 if (sscanf(str, "%04hx", crpl) != 1)
1055 BT_INFO("Mesh: Got CRPL[%s]", str);
1056 /* Get Company ID */
1057 if (!json_object_object_get_ex(jnode, "cid", &jobj))
1060 str = json_object_get_string(jobj);
1063 if (sscanf(str, "%04hx", cid) != 1)
1066 BT_INFO("Mesh: Got CID[%s]", str);
1068 if (!json_object_object_get_ex(jnode, "pid", &jobj))
1071 str = json_object_get_string(jobj);
1075 if (sscanf(str, "%04hx", vid) != 1)
1078 BT_INFO("Mesh: Got PID[%s]", str);
1079 /* Get Version ID */
1080 if (!json_object_object_get_ex(jnode, "vid", &jobj))
1083 str = json_object_get_string(jobj);
1086 if (sscanf(str, "%04hx", version) != 1)
1089 BT_INFO("Mesh: got version [%s]", str);
1090 jobj = json_object_object_get(jnode, "features");
1093 if (json_object_object_get_ex(jobj, "relay", &jobjfeature)) {
1094 str = json_object_get_string(jobjfeature);
1096 sscanf(str, "%d", relay);
1097 BT_INFO("Mesh: Got Relay [%s]", str);
1101 if (json_object_object_get_ex(jobj, "friend", &jobjfeature)) {
1102 str = json_object_get_string(jobjfeature);
1104 sscanf(str, "%d", friend);
1105 BT_INFO("Mesh: Got Friend [%s]", str);
1109 if (json_object_object_get_ex(jobj, "proxy", &jobjfeature)) {
1110 str = json_object_get_string(jobjfeature);
1112 sscanf(str, "%d", proxy);
1113 BT_INFO("Mesh: Got Proxy[%s]", str);
1116 if (json_object_object_get_ex(jobj, "lowPower", &jobjfeature)) {
1117 str = json_object_get_string(jobjfeature);
1119 sscanf(str, "%d", lpn);
1120 BT_INFO("Mesh: Got LPN[%s]", str);
1127 GSList *_bt_mesh_conf_load_group_info(_bt_mesh_cdb_t *cfg)
1129 json_object *jgroups;
1130 GSList *groups = NULL;
1133 if (!cfg || !cfg->jcfg)
1136 if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups)) {
1137 jgroups = json_object_new_array();
1141 json_object_object_add(cfg->jcfg, "groups", jgroups);
1144 sz = json_object_array_length(jgroups);
1146 for (i = 0; i < sz; ++i) {
1147 json_object *jgroup, *jval;
1148 _bt_mesh_group_t *grp;
1149 uint16_t addr, addr_len;
1152 jgroup = json_object_array_get_idx(jgroups, i);
1156 if (!json_object_object_get_ex(jgroup, "name", &jval))
1159 str = json_object_get_string(jval);
1160 if (strlen(str) != 10)
1163 if (sscanf(str + 6, "%04hx", &addr) != 1)
1165 if (!json_object_object_get_ex(jgroup, "address", &jval))
1168 str = json_object_get_string(jval);
1169 addr_len = strlen(str);
1170 if (addr_len != 4 && addr_len != 32)
1173 if (addr_len == 32 && !MESH_IS_VIRTUAL(addr))
1176 grp = g_malloc0(sizeof(_bt_mesh_group_t));
1179 sscanf(str, "%04hx", &grp->grp_addr);
1181 _bt_mesh_util_convert_string_to_hex(str,
1182 32, grp->label_uuid, 16);
1183 grp->grp_addr = addr;
1186 groups = g_slist_append(groups, grp);
1192 bool _bt_mesh_conf_insert_group_info(_bt_mesh_cdb_t *cfg,
1193 _bt_mesh_group_t *grp)
1195 json_object *jgroup, *jgroups, *jval;
1198 if (!cfg || !cfg->jcfg)
1201 if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups)) {
1202 BT_INFO("Mesh: Group JSON object is not present: Create");
1203 jgroups = json_object_new_array();
1207 json_object_object_add(cfg->jcfg, "groups", jgroups);
1210 jgroup = json_object_new_object();
1214 snprintf(buf, 11, "Group_%4.4x", grp->grp_addr);
1215 jval = json_object_new_string(buf);
1216 json_object_object_add(jgroup, "name", jval);
1218 if (MESH_IS_VIRTUAL(grp->grp_addr)) {
1219 if (!__mesh_add_u8_16(jgroup, "address", grp->label_uuid))
1222 if (!__mesh_write_uint16_hex(jgroup, "address", grp->grp_addr))
1226 json_object_array_add(jgroups, jgroup);
1228 return __bt_mesh_save_configruation_file(cfg);
1231 json_object_put(jgroup);
1235 bool _bt_mesh_conf_delete_group_entry(_bt_mesh_cdb_t *cfg, uint16_t addr)
1237 if (!cfg || !cfg->jcfg)
1240 return __mesh_delete_group(cfg, cfg->jcfg, "groups", addr);
1243 bool _bt_mesh_conf_set_network_friendly_name(_bt_mesh_cdb_t *cfg,
1244 const char *network_name)
1255 json_object_object_del(jcfg, "Network_Name");
1256 __mesh_add_string(jcfg, "Network_Name", network_name);
1259 BT_INFO("Mesh: CDB: Network New Name [%s]", network_name);
1260 return __bt_mesh_save_configruation_file(cfg);
1263 const char * _bt_mesh_conf_get_network_friendly_name(_bt_mesh_cdb_t *cfg)
1266 json_object *jobj = NULL;
1276 /* Get Network Name */
1277 if (!json_object_object_get_ex(jcfg, "Network_Name", &jobj))
1280 str = json_object_get_string(jobj);
1284 BT_INFO("Mesh: CDB: Network Name [%s]", str);
1288 static bool __mesh_load_composition(_bt_mesh_cdb_t *cfg,
1289 json_object *jnode, uint16_t unicast)
1291 json_object *jarray;
1294 if (!json_object_object_get_ex(jnode, "elements", &jarray))
1297 if (json_object_get_type(jarray) != json_type_array)
1300 ele_cnt = json_object_array_length(jarray);
1302 for (i = 0; i < ele_cnt; ++i) {
1303 json_object *jentry, *jval, *jmods;
1307 jentry = json_object_array_get_idx(jarray, i);
1308 if (!json_object_object_get_ex(jentry, "index", &jval))
1311 index = json_object_get_int(jval);
1315 if (!json_object_object_get_ex(jentry, "models", &jmods))
1318 mod_cnt = json_object_array_length(jmods);
1319 BT_INFO("Mesh: Total Model count in element Index [%d] is [%d]",
1322 for (k = 0; k < mod_cnt; ++k) {
1323 json_object *jmod, *jid;
1324 uint32_t mod_id, len;
1327 jmod = json_object_array_get_idx(jmods, k);
1328 if (!json_object_object_get_ex(jmod, "modelId", &jid))
1331 str = json_object_get_string(jid);
1334 if (len != 4 && len != 8)
1337 if ((len == 4) && (sscanf(str, "%04x", &mod_id) != 1))
1340 if ((len == 8) && (sscanf(str, "%08x", &mod_id) != 1))
1343 _bt_mesh_node_set_model(cfg->uuid,
1344 unicast, index, mod_id, len == 8);
1351 bool _bt_mesh_conf_set_node_comp_data(_bt_mesh_cdb_t *cfg,
1352 uint16_t unicast, uint8_t *data, uint16_t len)
1356 json_object *jnode, *jobj, *jelements;
1359 if (!cfg || !cfg->jcfg)
1362 jnode = __mesh_get_node_by_unicast(cfg, unicast);
1366 /* skip page -- We only support Page Zero */
1370 /* If "crpl" property is present, composition is already recorded */
1371 if (json_object_object_get_ex(jnode, "crpl", &jobj))
1374 if (!__mesh_write_uint16_hex(jnode, "cid", l_get_le16(&data[0])))
1377 if (!__mesh_write_uint16_hex(jnode, "pid", l_get_le16(&data[2])))
1380 if (!__mesh_write_uint16_hex(jnode, "vid", l_get_le16(&data[4])))
1383 crpl = l_get_le16(&data[6]);
1385 features = l_get_le16(&data[8]);
1389 jobj = json_object_object_get(jnode, "features");
1391 jobj = json_object_new_object();
1392 json_object_object_add(jnode, "features", jobj);
1395 if ((features & MESH_FEATURE_RELAY))
1396 __mesh_write_int(jobj, "relay", 1);
1398 __mesh_write_int(jobj, "relay", 0);
1400 if ((features & MESH_FEATURE_FRIEND))
1401 __mesh_write_int(jobj, "friend", 1);
1403 __mesh_write_int(jobj, "friend", 0);
1405 if ((features & MESH_FEATURE_PROXY))
1406 __mesh_write_int(jobj, "proxy", 1);
1408 __mesh_write_int(jobj, "proxy", 0);
1410 if ((features & MESH_FEATURE_LPN))
1411 __mesh_write_int(jobj, "lowPower", 1);
1413 __mesh_write_int(jobj, "lowPower", 0);
1415 jelements = json_object_object_get(jnode, "elements");
1419 sz = json_object_array_length(jelements);
1422 json_object *jentry, *jmods;
1426 /* Mismatch in the element count */
1430 jentry = json_object_array_get_idx(jelements, i);
1432 __mesh_write_int(jentry, "index", i);
1434 if (!__mesh_write_uint16_hex(jentry, "location", l_get_le16(data)))
1444 jmods = json_object_object_get(jentry, "models");
1446 /* For backwards compatibility */
1447 jmods = json_object_new_array();
1448 json_object_object_add(jentry, "models", jmods);
1451 while (len >= 2 && m--) {
1452 mod_id = l_get_le16(data);
1454 jobj = __mesh_init_model(mod_id);
1458 json_object_array_add(jmods, jobj);
1463 while (len >= 4 && v--) {
1464 jobj = json_object_new_object();
1465 mod_id = l_get_le16(data + 2);
1466 mod_id = l_get_le16(data) << 16 | mod_id;
1468 jobj = __mesh_init_vendor_model(mod_id);
1472 json_object_array_add(jmods, jobj);
1481 /* CRPL is written last. Will be used to check composition's presence */
1482 if (!__mesh_write_uint16_hex(jnode, "crpl", crpl))
1485 /* Initiate remote's composition from storage */
1486 if (!__mesh_load_composition(cfg, jnode, unicast))
1489 return __bt_mesh_save_configruation_file(cfg);
1492 /* Reset elements array */
1493 json_object_object_del(jnode, "elements");
1494 __mesh_init_elements(sz);
1499 _bt_mesh_cdb_t* _bt_mesh_conf_load(const char *file_name,
1502 char *token_str = NULL;
1508 _bt_mesh_cdb_t *cfg;
1510 fd = open(file_name, O_RDONLY);
1514 if (fstat(fd, &st) == -1) {
1519 str = (char *) g_malloc0(st.st_size + 1);
1525 sz = read(fd, str, st.st_size);
1526 if (sz != st.st_size) {
1527 BT_ERR("Mesh: Failed to read configuration file [%s]", file_name);
1532 jcfg = json_tokener_parse(str);
1539 cfg = g_malloc0(sizeof(_bt_mesh_cdb_t));
1542 cfg->cfg_fname = g_strdup(file_name);
1544 if (!__mesh_get_uuid(jcfg, cfg->uuid)) {
1545 BT_ERR("Mesh: Configuration file missing UUID");
1549 if (!__mesh_get_token(jcfg, cfg->token)) {
1550 BT_ERR("Mesh: Configuration file missing token");
1554 token_str = _bt_service_convert_hex_to_string((unsigned char*)cfg->token, 8);
1556 /* Match CDB file tken with user's token */
1557 if (g_strcmp0(token_str, token)) {
1558 BT_INFO("Mesh: Token did not match! File token [%s] requested token [%s]",
1562 /* TODO: Load keys and remotes */
1565 _bt_mesh_conf_free(cfg);
1569 bool _bt_mesh_conf_load_all_nodes(_bt_mesh_cdb_t *cfg)
1571 json_object *jnodes;
1572 int i, sz, node_count = 0;
1574 json_object_object_get_ex(cfg->jcfg, "nodes", &jnodes);
1575 if (!jnodes || json_object_get_type(jnodes) != json_type_array)
1578 sz = json_object_array_length(jnodes);
1580 for (i = 0; i < sz; ++i) {
1581 json_object *jnode, *jval, *jarray;
1583 uint16_t unicast, key_idx;
1585 int ele_cnt, key_cnt;
1588 jnode = json_object_array_get_idx(jnodes, i);
1592 if (!json_object_object_get_ex(jnode, "uuid", &jval))
1595 str = json_object_get_string(jval);
1596 if (strlen(str) != 32)
1599 _bt_mesh_util_convert_string_to_hex(str, 32, uuid, 16);
1601 if (!json_object_object_get_ex(jnode, "unicastAddress", &jval))
1604 str = json_object_get_string(jval);
1605 if (sscanf(str, "%04hx", &unicast) != 1)
1608 json_object_object_get_ex(jnode, "elements", &jarray);
1609 if (!jarray || json_object_get_type(jarray) != json_type_array)
1612 ele_cnt = json_object_array_length(jarray);
1614 if (ele_cnt > MESH_MAX_ELE_COUNT)
1617 json_object_object_get_ex(jnode, "netKeys", &jarray);
1618 if (!jarray || json_object_get_type(jarray) != json_type_array)
1621 key_cnt = json_object_array_length(jarray);
1625 key_idx = __mesh_node_parse_key(jarray, 0);
1626 if (key_idx == MESH_KEY_IDX_INVALID)
1629 _bt_mesh_node_add_node(cfg->uuid, (const uint8_t *)uuid, unicast, ele_cnt,
1631 for (j = 1; j < key_cnt; j++) {
1632 key_idx = __mesh_node_parse_key(jarray, j);
1634 if (key_idx != MESH_KEY_IDX_INVALID)
1635 _bt_mesh_node_add_net_key(cfg->uuid, unicast, key_idx);
1638 json_object_object_get_ex(jnode, "appKeys", &jarray);
1639 if (!jarray || json_object_get_type(jarray) != json_type_array)
1642 key_cnt = json_object_array_length(jarray);
1643 for (j = 0; j < key_cnt; j++) {
1644 key_idx = __mesh_node_parse_key(jarray, j);
1646 if (key_idx != MESH_KEY_IDX_INVALID)
1647 _bt_mesh_node_add_app_key(cfg->uuid, unicast, key_idx);
1650 __mesh_load_composition(cfg, jnode, unicast);
1654 /* TODO: Add the rest of the configuration */
1657 if (node_count != sz)
1658 BT_ERR("Mesh: CDB: The remote node configuration load is incomplete!");
1663 bool _bt_mesh_conf_load_all_keys(_bt_mesh_cdb_t* cfg)
1665 json_object *jarray, *jentry;
1666 int net_idx, app_idx;
1668 json_object *jobj = cfg->jcfg;
1670 json_object_object_get_ex(jobj, "netKeys", &jarray);
1671 if (!jarray || json_object_get_type(jarray) != json_type_array)
1674 key_cnt = json_object_array_length(jarray);
1678 for (i = 0; i < key_cnt; ++i) {
1681 jentry = json_object_array_get_idx(jarray, i);
1683 if (!__mesh_get_int(jentry, "index", &net_idx))
1686 _bt_mesh_keys_add_net_key(cfg->uuid, (uint16_t) net_idx);
1688 if (!__mesh_get_int(jentry, "phase", &phase))
1691 _bt_mesh_keys_set_net_key_phase(cfg, net_idx, (uint8_t) phase, false);
1694 json_object_object_get_ex(jobj, "appKeys", &jarray);
1695 if (!jarray || json_object_get_type(jarray) != json_type_array)
1698 key_cnt = json_object_array_length(jarray);
1702 for (i = 0; i < key_cnt; ++i) {
1704 jentry = json_object_array_get_idx(jarray, i);
1705 if (!__mesh_get_int(jentry, "boundNetKey", &net_idx))
1708 if (!__mesh_get_int(jentry, "index", &app_idx))
1711 _bt_mesh_keys_add_app_key(cfg->uuid, (uint16_t) net_idx, (uint16_t) app_idx);