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 bool __mesh_jarray_group_delete(json_object *jarray, uint16_t group_addr)
475 int i, sz = json_object_array_length(jarray);
479 for (i = 0; i < sz; ++i) {
484 jentry = json_object_array_get_idx(jarray, i);
485 if (!json_object_object_get_ex(jentry, "name",
489 str = json_object_get_string(jval);
490 memcpy(buf, str + 6, 5);
491 BT_INFO("Mesh: JSON Group string:[%s]", buf);
492 if (sscanf(buf, "%04hx", &addr) != 1)
494 BT_INFO("Mesh: JSON Group in Hex [0x%2.2x]", addr);
496 if (group_addr == addr)
501 BT_INFO("Mesh: Failed to remove group");
505 json_object_array_del_idx(jarray, i, 1);
509 static void __mesh_jarray_key_del(json_object *jarray, int16_t idx)
511 int i, sz = json_object_array_length(jarray);
513 for (i = 0; i < sz; ++i) {
517 jentry = json_object_array_get_idx(jarray, i);
519 if (!__mesh_get_int(jentry, "index", &val))
523 json_object_array_del_idx(jarray, i, 1);
529 static bool __mesh_delete_group(_bt_mesh_cdb_t *cfg,
530 json_object *jobj, const char *desc, uint16_t addr)
534 if (!json_object_object_get_ex(jobj, desc, &jarray))
537 if (!__mesh_jarray_group_delete(jarray, addr))
540 return __bt_mesh_save_configruation_file(cfg);
543 static bool __mesh_delete_key(_bt_mesh_cdb_t *cfg,
544 json_object *jobj, const char *desc, uint16_t idx)
548 if (!json_object_object_get_ex(jobj, desc, &jarray))
551 __mesh_jarray_key_del(jarray, idx);
553 return __bt_mesh_save_configruation_file(cfg);
556 bool _bt_mesh_conf_set_phase_network_key(_bt_mesh_cdb_t *cfg,
557 uint16_t net_idx, uint8_t phase)
559 json_object *jval, *jarray, *jkey;
561 if (!cfg || !cfg->jcfg)
564 json_object_object_get_ex(cfg->jcfg, "netKeys", &jarray);
565 if (!jarray || json_object_get_type(jarray) != json_type_array)
568 jkey = __mesh_get_key_object(jarray, net_idx);
572 jval = json_object_new_int(phase);
576 json_object_object_add(jkey, "phase", jval);
578 return __bt_mesh_save_configruation_file(cfg);
581 bool _bt_mesh_conf_delete_application_key(_bt_mesh_cdb_t *cfg, uint16_t app_idx)
583 if (!cfg || !cfg->jcfg)
586 return __mesh_delete_key(cfg, cfg->jcfg, "appKeys", app_idx);
589 bool _bt_mesh_conf_set_unicast_address_range(_bt_mesh_cdb_t *cfg,
590 uint16_t low, uint16_t high)
592 if (!cfg || !cfg->jcfg)
595 if (!__mesh_write_uint16_hex(cfg->jcfg, "low", low))
598 if (!__mesh_write_uint16_hex(cfg->jcfg, "high", high))
601 return __bt_mesh_save_configruation_file(cfg);
604 bool _bt_mesh_conf_insert_node_object(_bt_mesh_cdb_t *cfg,
605 uint8_t uuid[16], uint8_t num_els,
606 uint16_t unicast, uint16_t net_idx)
609 json_object *jelements, *jnodes, *jnetkeys, *jappkeys;
612 if (!cfg || !cfg->jcfg)
615 jnode = __mesh_get_node_by_uuid(cfg->jcfg, uuid);
617 BT_ERR("MESH:Node already exists");
621 jnode = json_object_new_object();
625 if (!__mesh_add_u8_16(jnode, "uuid", uuid))
628 jelements = json_object_new_array();
632 for (i = 0; i < num_els; ++i) {
633 json_object *jelement = json_object_new_object();
636 json_object_put(jelements);
640 __mesh_write_int(jelement, "elementIndex", i);
641 json_object_array_add(jelements, jelement);
644 json_object_object_add(jnode, "elements", jelements);
646 jnetkeys = json_object_new_array();
650 json_object_object_add(jnode, "netKeys", jnetkeys);
652 if (!__mesh_add_node_key(cfg, jnode, "netKeys", net_idx))
655 jappkeys = json_object_new_array();
659 json_object_object_add(jnode, "appKeys", jappkeys);
661 if (!__mesh_write_uint16_hex(jnode, "unicastAddress", unicast))
664 if (!json_object_object_get_ex(cfg->jcfg, "nodes", &jnodes))
667 json_object_array_add(jnodes, jnode);
669 if (!__bt_mesh_save_configruation_file(cfg))
675 json_object_put(jnode);
679 bool _bt_mesh_conf_insert_application_key(_bt_mesh_cdb_t *cfg,
680 uint16_t net_idx, uint16_t app_idx)
682 if (!cfg || !cfg->jcfg)
685 if (!__mesh_add_app_key(cfg->jcfg, net_idx, app_idx))
688 return __bt_mesh_save_configruation_file(cfg);
691 bool _bt_mesh_conf_insert_network_key(_bt_mesh_cdb_t *cfg,
692 uint16_t net_idx, uint8_t key_refresh)
694 json_object *jkey, *jarray;
696 if (!cfg || !cfg->jcfg)
699 json_object_object_get_ex(cfg->jcfg, "netKeys", &jarray);
700 if (!jarray || json_object_get_type(jarray) != json_type_array)
703 if (__mesh_get_key_object(jarray, net_idx))
706 jkey = json_object_new_object();
708 if (!__mesh_write_int(jkey, "index", net_idx))
711 if (!__mesh_write_int(jkey, "phase", key_refresh))
714 json_object_array_add(jarray, jkey);
716 return __bt_mesh_save_configruation_file(cfg);
719 json_object_put(jkey);
723 bool _bt_mesh_conf_delete_network_key(_bt_mesh_cdb_t *cfg,
726 if (!cfg || !cfg->jcfg)
729 return __mesh_delete_key(cfg, cfg->jcfg, "netKeys", net_idx);
733 bool _bt_mesh_conf_node_set_timetolive_value(_bt_mesh_cdb_t *cfg,
734 uint16_t unicast, uint8_t ttl)
738 if (!cfg || !cfg->jcfg)
741 jnode = __mesh_get_node_by_unicast(cfg, unicast);
745 if (!__mesh_write_int(jnode, "defaultTTL", ttl))
748 return __bt_mesh_save_configruation_file(cfg);
751 bool _bt_mesh_conf_node_insert_network_key(_bt_mesh_cdb_t *cfg,
752 uint16_t unicast, uint16_t net_idx)
756 if (!cfg || !cfg->jcfg)
759 jnode = __mesh_get_node_by_unicast(cfg, unicast);
763 return __mesh_add_node_key(cfg, jnode, "netKeys", net_idx);
766 bool _bt_mesh_conf_node_delete_network_key(_bt_mesh_cdb_t *cfg,
767 uint16_t unicast, uint16_t net_idx)
771 if (!cfg || !cfg->jcfg)
774 jnode = __mesh_get_node_by_unicast(cfg, unicast);
778 return __mesh_delete_key(cfg, jnode, "netKeys", net_idx);
781 bool _bt_mesh_conf_node_insert_application_key(_bt_mesh_cdb_t *cfg,
782 uint16_t unicast, uint16_t idx)
786 if (!cfg || !cfg->jcfg)
789 jnode = __mesh_get_node_by_unicast(cfg, unicast);
793 return __mesh_add_node_key(cfg, jnode, "appKeys", idx);
796 bool _bt_mesh_conf_node_delete_application_key(_bt_mesh_cdb_t *cfg,
797 uint16_t unicast, uint16_t idx)
801 if (!cfg || !cfg->jcfg)
804 jnode = __mesh_get_node_by_unicast(cfg, unicast);
808 return __mesh_delete_key(cfg, jnode, "appKeys", idx);
811 _bt_mesh_cdb_t *_bt_mesh_conf_database_create(const char *file_name,
812 const uint8_t uuid[16],
813 const uint8_t token[8], const char *network_name,
814 const char *app_cred)
817 json_object *jcfg, *jarray;
828 jcfg = json_object_new_object();
832 cfg = g_malloc0(sizeof(_bt_mesh_cdb_t));
834 cfg->cfg_fname = g_strdup(file_name);
835 cfg->app_cred = g_strdup(app_cred);
836 memcpy(&cfg->token, (void*)token, 8);
837 memcpy(&cfg->uuid, (void*)uuid, 16);
839 if (!__mesh_add_u8_8(jcfg, "Network_Token", token))
842 if (!__mesh_add_u8_16(jcfg, "Config_Node_UUID", uuid))
845 if (!__mesh_add_string(jcfg, "Network_Name", network_name))
848 if (!__mesh_add_string(jcfg, "Application_Credential", app_cred))
851 jarray = json_object_new_array();
855 json_object_object_add(jcfg, "nodes", jarray);
857 jarray = json_object_new_array();
861 json_object_object_add(jcfg, "netKeys", jarray);
863 jarray = json_object_new_array();
867 json_object_object_add(jcfg, "appKeys", jarray);
869 if (!__bt_mesh_save_configruation_file(cfg))
875 _bt_mesh_conf_free(cfg);
880 bool _bt_mesh_conf_delete_node(_bt_mesh_cdb_t *cfg, uint16_t unicast)
885 if (!json_object_object_get_ex(cfg->jcfg, "nodes", &jarray))
888 if (!jarray || json_object_get_type(jarray) != json_type_array)
891 sz = json_object_array_length(jarray);
893 for (i = 0; i < sz; ++i) {
894 json_object *jentry, *jval;
898 jentry = json_object_array_get_idx(jarray, i);
899 if (!json_object_object_get_ex(jentry, "unicastAddress",
903 str = json_object_get_string(jval);
904 if (sscanf(str, "%04hx", &addr) != 1)
914 json_object_array_del_idx(jarray, i, 1);
916 return __bt_mesh_save_configruation_file(cfg);
919 uint16_t** _bt_mesh_conf_get_all_model_info(_bt_mesh_cdb_t *cfg,
920 int element_index, int *num_models)
926 json_object *jarray = NULL;
927 json_object *jelement = NULL;
928 json_object *jmodelarray = NULL;
939 jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
943 /* Get element array object */
944 json_object_object_get_ex(jnode, "elements", &jarray);
946 if (!jarray || json_object_get_type(jarray) != json_type_array)
949 /* Get specific element by index */
950 jelement = __mesh_get_key_object(jarray, element_index);
955 /* Get Model array object inside the selected element */
956 json_object_object_get_ex(jelement, "models", &jmodelarray);
958 if (!jmodelarray || json_object_get_type(jmodelarray) != json_type_array)
961 sz = json_object_array_length(jmodelarray);
962 models = (uint16_t**) g_malloc0(sz * sizeof(uint16_t*));
964 for (i = 0; i < sz; ++i) {
967 jentry = json_object_array_get_idx(jmodelarray, i);
968 str = json_object_get_string(jentry);
969 /* Only standard models are handled now */
970 if (sscanf(str, "%04hx", models[i]) != 1) {
971 for (int j =0 ; j < sz; j++)
977 /* TODO: Need to handle vendor models */
982 bool _bt_mesh_conf_get_element_count(_bt_mesh_cdb_t *cfg,
988 json_object *jarray = NULL;
997 jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
1001 json_object_object_get_ex(jnode, "elements", &jarray);
1003 if (!jarray || json_object_get_type(jarray) != json_type_array)
1006 sz = json_object_array_length(jarray);
1014 bool _bt_mesh_conf_fetch_vendor_specific_info(_bt_mesh_cdb_t *cfg,
1015 uint16_t *cid, uint16_t *vid,
1016 uint16_t *version, uint16_t *crpl,
1017 int *relay, int *friend,
1018 int *proxy, int *lpn)
1022 json_object *jobj = NULL;
1023 json_object *jobjfeature = NULL;
1033 jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
1038 if (!json_object_object_get_ex(jnode, "crpl", &jobj))
1041 str = json_object_get_string(jobj);
1044 if (sscanf(str, "%04hx", crpl) != 1)
1047 /* Get Company ID */
1048 if (!json_object_object_get_ex(jnode, "cid", &jobj))
1051 str = json_object_get_string(jobj);
1054 if (sscanf(str, "%04hx", cid) != 1)
1058 if (!json_object_object_get_ex(jnode, "pid", &jobj))
1061 str = json_object_get_string(jobj);
1065 if (sscanf(str, "%04hx", vid) != 1)
1068 /* Get Version ID */
1069 if (!json_object_object_get_ex(jnode, "vid", &jobj))
1072 str = json_object_get_string(jobj);
1075 if (sscanf(str, "%04hx", version) != 1)
1078 jobj = json_object_object_get(jnode, "features");
1081 if (json_object_object_get_ex(jobj, "relay", &jobjfeature)) {
1082 str = json_object_get_string(jobj);
1084 sscanf(str, "%d", relay);
1087 if (json_object_object_get_ex(jobj, "friend", &jobjfeature)) {
1088 str = json_object_get_string(jobj);
1090 sscanf(str, "%d", friend);
1093 if (json_object_object_get_ex(jobj, "proxy", &jobjfeature)) {
1094 str = json_object_get_string(jobj);
1096 sscanf(str, "%d", proxy);
1098 if (json_object_object_get_ex(jobj, "lowPower", &jobjfeature)) {
1099 str = json_object_get_string(jobj);
1101 sscanf(str, "%d", lpn);
1107 GSList *_bt_mesh_conf_load_group_info(_bt_mesh_cdb_t *cfg)
1109 json_object *jgroups;
1110 GSList *groups = NULL;
1113 if (!cfg || !cfg->jcfg)
1116 if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups)) {
1117 jgroups = json_object_new_array();
1121 json_object_object_add(cfg->jcfg, "groups", jgroups);
1124 sz = json_object_array_length(jgroups);
1126 for (i = 0; i < sz; ++i) {
1127 json_object *jgroup, *jval;
1128 _bt_mesh_group_t *grp;
1129 uint16_t addr, addr_len;
1132 jgroup = json_object_array_get_idx(jgroups, i);
1136 if (!json_object_object_get_ex(jgroup, "name", &jval))
1139 str = json_object_get_string(jval);
1140 if (strlen(str) != 10)
1143 if (sscanf(str + 6, "%04hx", &addr) != 1)
1145 if (!json_object_object_get_ex(jgroup, "address", &jval))
1148 str = json_object_get_string(jval);
1149 addr_len = strlen(str);
1150 if (addr_len != 4 && addr_len != 32)
1153 if (addr_len == 32 && !MESH_IS_VIRTUAL(addr))
1156 grp = g_malloc0(sizeof(_bt_mesh_group_t));
1159 sscanf(str, "%04hx", &grp->grp_addr);
1161 _bt_mesh_util_convert_string_to_hex(str,
1162 32, grp->label_uuid, 16);
1163 grp->grp_addr = addr;
1166 groups = g_slist_append(groups, grp);
1172 bool _bt_mesh_conf_insert_group_info(_bt_mesh_cdb_t *cfg,
1173 _bt_mesh_group_t *grp)
1175 json_object *jgroup, *jgroups, *jval;
1178 if (!cfg || !cfg->jcfg)
1181 if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups)) {
1182 BT_INFO("Mesh: Group JSON object is not present: Create");
1183 jgroups = json_object_new_array();
1187 json_object_object_add(cfg->jcfg, "groups", jgroups);
1190 jgroup = json_object_new_object();
1194 snprintf(buf, 11, "Group_%4.4x", grp->grp_addr);
1195 jval = json_object_new_string(buf);
1196 json_object_object_add(jgroup, "name", jval);
1198 if (MESH_IS_VIRTUAL(grp->grp_addr)) {
1199 if (!__mesh_add_u8_16(jgroup, "address", grp->label_uuid))
1202 if (!__mesh_write_uint16_hex(jgroup, "address", grp->grp_addr))
1206 json_object_array_add(jgroups, jgroup);
1208 return __bt_mesh_save_configruation_file(cfg);
1211 json_object_put(jgroup);
1215 bool _bt_mesh_conf_delete_group_entry(_bt_mesh_cdb_t *cfg, uint16_t addr)
1217 if (!cfg || !cfg->jcfg)
1220 return __mesh_delete_group(cfg, cfg->jcfg, "groups", addr);
1223 bool _bt_mesh_conf_set_network_friendly_name(_bt_mesh_cdb_t *cfg,
1224 const char *network_name)
1235 json_object_object_del(jcfg, "Network_Name");
1236 __mesh_add_string(jcfg, "Network_Name", network_name);
1239 BT_INFO("Mesh: CDB: Network New Name [%s]", network_name);
1240 return __bt_mesh_save_configruation_file(cfg);
1243 const char * _bt_mesh_conf_get_network_friendly_name(_bt_mesh_cdb_t *cfg)
1246 json_object *jobj = NULL;
1256 /* Get Network Name */
1257 if (!json_object_object_get_ex(jcfg, "Network_Name", &jobj))
1260 str = json_object_get_string(jobj);
1264 BT_INFO("Mesh: CDB: Network Name [%s]", str);
1268 static bool __mesh_load_composition(_bt_mesh_cdb_t *cfg,
1269 json_object *jnode, uint16_t unicast)
1271 json_object *jarray;
1274 if (!json_object_object_get_ex(jnode, "elements", &jarray))
1277 if (json_object_get_type(jarray) != json_type_array)
1280 ele_cnt = json_object_array_length(jarray);
1282 for (i = 0; i < ele_cnt; ++i) {
1283 json_object *jentry, *jval, *jmods;
1287 jentry = json_object_array_get_idx(jarray, i);
1288 if (!json_object_object_get_ex(jentry, "index", &jval))
1291 index = json_object_get_int(jval);
1295 if (!json_object_object_get_ex(jentry, "models", &jmods))
1298 mod_cnt = json_object_array_length(jmods);
1299 BT_INFO("Mesh: Total Model count in element Index [%d] is [%d]",
1302 for (k = 0; k < mod_cnt; ++k) {
1303 json_object *jmod, *jid;
1304 uint32_t mod_id, len;
1307 jmod = json_object_array_get_idx(jmods, k);
1308 if (!json_object_object_get_ex(jmod, "modelId", &jid))
1311 str = json_object_get_string(jid);
1314 if (len != 4 && len != 8)
1317 if ((len == 4) && (sscanf(str, "%04x", &mod_id) != 1))
1320 if ((len == 8) && (sscanf(str, "%08x", &mod_id) != 1))
1323 _bt_mesh_node_set_model(cfg->uuid,
1324 unicast, index, mod_id, len == 8);
1331 bool _bt_mesh_conf_set_node_comp_data(_bt_mesh_cdb_t *cfg,
1332 uint16_t unicast, uint8_t *data, uint16_t len)
1336 json_object *jnode, *jobj, *jelements;
1339 if (!cfg || !cfg->jcfg)
1342 jnode = __mesh_get_node_by_unicast(cfg, unicast);
1346 /* skip page -- We only support Page Zero */
1350 /* If "crpl" property is present, composition is already recorded */
1351 if (json_object_object_get_ex(jnode, "crpl", &jobj))
1354 if (!__mesh_write_uint16_hex(jnode, "cid", l_get_le16(&data[0])))
1357 if (!__mesh_write_uint16_hex(jnode, "pid", l_get_le16(&data[2])))
1360 if (!__mesh_write_uint16_hex(jnode, "vid", l_get_le16(&data[4])))
1363 crpl = l_get_le16(&data[6]);
1365 features = l_get_le16(&data[8]);
1369 jobj = json_object_object_get(jnode, "features");
1371 jobj = json_object_new_object();
1372 json_object_object_add(jnode, "features", jobj);
1375 if ((features & MESH_FEATURE_RELAY))
1376 __mesh_write_int(jobj, "relay", 1);
1378 __mesh_write_int(jobj, "relay", 0);
1380 if ((features & MESH_FEATURE_FRIEND))
1381 __mesh_write_int(jobj, "friend", 1);
1383 __mesh_write_int(jobj, "friend", 0);
1385 if ((features & MESH_FEATURE_PROXY))
1386 __mesh_write_int(jobj, "proxy", 1);
1388 __mesh_write_int(jobj, "proxy", 0);
1390 if ((features & MESH_FEATURE_LPN))
1391 __mesh_write_int(jobj, "lowPower", 1);
1393 __mesh_write_int(jobj, "lowPower", 0);
1395 jelements = json_object_object_get(jnode, "elements");
1399 sz = json_object_array_length(jelements);
1402 json_object *jentry, *jmods;
1406 /* Mismatch in the element count */
1410 jentry = json_object_array_get_idx(jelements, i);
1412 __mesh_write_int(jentry, "index", i);
1414 if (!__mesh_write_uint16_hex(jentry, "location", l_get_le16(data)))
1424 jmods = json_object_object_get(jentry, "models");
1426 /* For backwards compatibility */
1427 jmods = json_object_new_array();
1428 json_object_object_add(jentry, "models", jmods);
1431 while (len >= 2 && m--) {
1432 mod_id = l_get_le16(data);
1434 jobj = __mesh_init_model(mod_id);
1438 json_object_array_add(jmods, jobj);
1443 while (len >= 4 && v--) {
1444 jobj = json_object_new_object();
1445 mod_id = l_get_le16(data + 2);
1446 mod_id = l_get_le16(data) << 16 | mod_id;
1448 jobj = __mesh_init_vendor_model(mod_id);
1452 json_object_array_add(jmods, jobj);
1461 /* CRPL is written last. Will be used to check composition's presence */
1462 if (!__mesh_write_uint16_hex(jnode, "crpl", crpl))
1465 /* Initiate remote's composition from storage */
1466 if (!__mesh_load_composition(cfg, jnode, unicast))
1469 return __bt_mesh_save_configruation_file(cfg);
1472 /* Reset elements array */
1473 json_object_object_del(jnode, "elements");
1474 __mesh_init_elements(sz);
1479 _bt_mesh_cdb_t* _bt_mesh_conf_load(const char *file_name,
1482 char *token_str = NULL;
1488 _bt_mesh_cdb_t *cfg;
1490 fd = open(file_name, O_RDONLY);
1494 if (fstat(fd, &st) == -1) {
1499 str = (char *) g_malloc0(st.st_size + 1);
1505 sz = read(fd, str, st.st_size);
1506 if (sz != st.st_size) {
1507 BT_ERR("Mesh: Failed to read configuration file [%s]", file_name);
1512 jcfg = json_tokener_parse(str);
1519 cfg = g_malloc0(sizeof(_bt_mesh_cdb_t));
1522 cfg->cfg_fname = g_strdup(file_name);
1524 if (!__mesh_get_uuid(jcfg, cfg->uuid)) {
1525 BT_ERR("Mesh: Configuration file missing UUID");
1529 if (!__mesh_get_token(jcfg, cfg->token)) {
1530 BT_ERR("Mesh: Configuration file missing token");
1534 token_str = _bt_service_convert_hex_to_string((unsigned char*)cfg->token, 8);
1536 /* Match CDB file tken with user's token */
1537 if (g_strcmp0(token_str, token)) {
1538 BT_INFO("Mesh: Token did not match! File token [%s] requested token [%s]",
1542 /* TODO: Load keys and remotes */
1545 _bt_mesh_conf_free(cfg);
1549 bool _bt_mesh_conf_load_all_nodes(_bt_mesh_cdb_t *cfg)
1551 json_object *jnodes;
1552 int i, sz, node_count = 0;
1554 json_object_object_get_ex(cfg->jcfg, "nodes", &jnodes);
1555 if (!jnodes || json_object_get_type(jnodes) != json_type_array)
1558 sz = json_object_array_length(jnodes);
1560 for (i = 0; i < sz; ++i) {
1561 json_object *jnode, *jval, *jarray;
1563 uint16_t unicast, key_idx;
1565 int ele_cnt, key_cnt;
1568 jnode = json_object_array_get_idx(jnodes, i);
1572 if (!json_object_object_get_ex(jnode, "uuid", &jval))
1575 str = json_object_get_string(jval);
1576 if (strlen(str) != 32)
1579 _bt_mesh_util_convert_string_to_hex(str, 32, uuid, 16);
1581 if (!json_object_object_get_ex(jnode, "unicastAddress", &jval))
1584 str = json_object_get_string(jval);
1585 if (sscanf(str, "%04hx", &unicast) != 1)
1588 json_object_object_get_ex(jnode, "elements", &jarray);
1589 if (!jarray || json_object_get_type(jarray) != json_type_array)
1592 ele_cnt = json_object_array_length(jarray);
1594 if (ele_cnt > MESH_MAX_ELE_COUNT)
1597 json_object_object_get_ex(jnode, "netKeys", &jarray);
1598 if (!jarray || json_object_get_type(jarray) != json_type_array)
1601 key_cnt = json_object_array_length(jarray);
1605 key_idx = __mesh_node_parse_key(jarray, 0);
1606 if (key_idx == MESH_KEY_IDX_INVALID)
1609 _bt_mesh_node_add_node(cfg->uuid, (const uint8_t *)uuid, unicast, ele_cnt,
1611 for (j = 1; j < key_cnt; j++) {
1612 key_idx = __mesh_node_parse_key(jarray, j);
1614 if (key_idx != MESH_KEY_IDX_INVALID)
1615 _bt_mesh_node_add_net_key(cfg->uuid, unicast, key_idx);
1618 json_object_object_get_ex(jnode, "appKeys", &jarray);
1619 if (!jarray || json_object_get_type(jarray) != json_type_array)
1622 key_cnt = json_object_array_length(jarray);
1623 for (j = 0; j < key_cnt; j++) {
1624 key_idx = __mesh_node_parse_key(jarray, j);
1626 if (key_idx != MESH_KEY_IDX_INVALID)
1627 _bt_mesh_node_add_app_key(cfg->uuid, unicast, key_idx);
1630 __mesh_load_composition(cfg, jnode, unicast);
1634 /* TODO: Add the rest of the configuration */
1637 if (node_count != sz)
1638 BT_ERR("Mesh: CDB: The remote node configuration load is incomplete!");
1643 bool _bt_mesh_conf_load_all_keys(_bt_mesh_cdb_t* cfg)
1645 json_object *jarray, *jentry;
1646 int net_idx, app_idx;
1648 json_object *jobj = cfg->jcfg;
1650 json_object_object_get_ex(jobj, "netKeys", &jarray);
1651 if (!jarray || json_object_get_type(jarray) != json_type_array)
1654 key_cnt = json_object_array_length(jarray);
1658 for (i = 0; i < key_cnt; ++i) {
1661 jentry = json_object_array_get_idx(jarray, i);
1663 if (!__mesh_get_int(jentry, "index", &net_idx))
1666 _bt_mesh_keys_add_net_key(cfg->uuid, (uint16_t) net_idx);
1668 if (!__mesh_get_int(jentry, "phase", &phase))
1671 _bt_mesh_keys_set_net_key_phase(cfg, net_idx, (uint8_t) phase, false);
1674 json_object_object_get_ex(jobj, "appKeys", &jarray);
1675 if (!jarray || json_object_get_type(jarray) != json_type_array)
1678 key_cnt = json_object_array_length(jarray);
1682 for (i = 0; i < key_cnt; ++i) {
1684 jentry = json_object_array_get_idx(jarray, i);
1685 if (!__mesh_get_int(jentry, "boundNetKey", &net_idx))
1688 if (!__mesh_get_int(jentry, "index", &app_idx))
1691 _bt_mesh_keys_add_app_key(cfg->uuid, (uint16_t) net_idx, (uint16_t) app_idx);