Mesh: Maintain group subscription list in cdb 43/243843/1
authorAbhay Agarwal <ay.agarwal@samsung.com>
Wed, 2 Sep 2020 04:40:37 +0000 (10:10 +0530)
committerAbhay Agarwal <ay.agarwal@samsung.com>
Mon, 7 Sep 2020 17:16:54 +0000 (22:46 +0530)
This patch updates the cdb when subscription status is received
on request of sub add, delete, delete all and sub overwrite.

Change-Id: I5b1d9b2748173ec70c971c0a64f63b073d602390
Signed-off-by: Abhay Agarwal <ay.agarwal@samsung.com>
bt-service/services/include/bt-service-mesh-cdb.h
bt-service/services/include/bt-service-mesh-network.h
bt-service/services/mesh/bt-service-mesh-cdb.c
bt-service/services/mesh/bt-service-mesh-config-client.c
bt-service/services/mesh/bt-service-mesh-network.c

index 1e988da..8868a0c 100644 (file)
@@ -155,6 +155,18 @@ bool _bt_mesh_conf_insert_group_info(_bt_mesh_cdb_t *cfg,
 bool _bt_mesh_conf_delete_group_entry(_bt_mesh_cdb_t *cfg,
                uint16_t addr);
 
+bool _bt_mesh_conf_add_model_config_data(_bt_mesh_cdb_t *cfg, uint16_t unicast,
+                       int element_index, uint32_t model_id, uint16_t group_addr);
+
+bool _bt_mesh_conf_delete_model_config_data(_bt_mesh_cdb_t *cfg, uint16_t unicast,
+                       int element_index, uint32_t model_id, uint16_t group_addr);
+
+bool _bt_mesh_conf_delete_all_model_config_data(_bt_mesh_cdb_t *cfg, uint16_t unicast,
+                       int element_index, uint32_t model_id);
+
+bool _bt_mesh_conf_overwrite_model_config_data(_bt_mesh_cdb_t *cfg, uint16_t unicast,
+                       int element_index, uint32_t model_id, uint16_t group_addr);
+
 bool _bt_mesh_conf_set_network_friendly_name(_bt_mesh_cdb_t *cfg,
                const char *network_name);
 
index 148f648..9344f71 100644 (file)
@@ -153,6 +153,22 @@ bool _bt_mesh_network_save_remote_node_composition(uint8_t net_uuid[],
                uint16_t remote_unicast,
                        uint8_t *data, uint16_t data_len);
 
+bool _bt_mesh_network_add_model_subscription(uint8_t net_uuid[],
+               uint16_t remote_unicast, int ele_idx,
+                       uint32_t mod_id, uint16_t group_addr);
+
+bool _bt_mesh_network_delete_model_subscription(uint8_t net_uuid[],
+               uint16_t remote_unicast, int ele_idx,
+                       uint32_t mod_id, uint16_t group_addr);
+
+bool _bt_mesh_network_delete_all_model_subscription(uint8_t net_uuid[],
+               uint16_t remote_unicast, int ele_idx,
+                       uint32_t mod_id);
+
+bool _bt_mesh_network_overwrite_model_subscription(uint8_t net_uuid[],
+               uint16_t remote_unicast, int ele_idx,
+                       uint32_t mod_id, uint16_t group_addr);
+
 bool _bt_mesh_network_save_remote_node_netkey(uint8_t net_uuid[],
                uint16_t remote_unicast, uint16_t netkey_idx);
 
index a897564..43c9a1b 100644 (file)
@@ -1406,6 +1406,339 @@ bool _bt_mesh_conf_delete_group_entry(_bt_mesh_cdb_t *cfg, uint16_t addr)
        return __mesh_delete_group(cfg, cfg->jcfg, "groups", addr);
 }
 
+static json_object *__mesh_get_model_by_modelid(json_object *jelement,
+               uint32_t model_id)
+{
+       int sz;
+       json_object *jval = NULL;
+       json_object *jmodelarray = NULL;
+
+       /* Get Model array object inside the selected element */
+       json_object_object_get_ex(jelement, "models", &jmodelarray);
+
+       if (!jmodelarray || json_object_get_type(jmodelarray) != json_type_array) {
+               BT_ERR("Mesh: Could not get Model Array");
+               return NULL;
+       }
+
+       /* Get specific model object inside model array */
+       sz = json_object_array_length(jmodelarray);
+       BT_INFO("Mesh: Total number of Models in Element is [%d]", sz);
+
+       for (int i = 0; i < sz; ++i) {
+               uint16_t mod_id;
+               const char *str;
+               json_object *jentry = NULL;
+
+               BT_INFO("Mesh: Model [%d]", i);
+               jentry = json_object_array_get_idx(jmodelarray, i);
+
+               if (!json_object_object_get_ex(jentry, "modelId", &jval)) {
+                       BT_ERR("Mesh: Failed to read Model in index [%d]", i);
+                       return NULL;
+               }
+
+               str = json_object_get_string(jval);
+               if (sscanf(str, "%04hx", &mod_id) != 1) {
+                       BT_INFO("Mesh: Failed to read Model ID from Model entry [%s]", str);
+                       return NULL;
+               }
+
+               BT_INFO("Mesh: Model string [%s] Model ID [0x%4.4x]", str, mod_id);
+               if ((uint16_t)model_id == mod_id) {
+                       BT_INFO("Mesh: Found required model");
+                       return jentry;
+               }
+       }
+       /* TODO: Need to handle vendor models */
+
+       return NULL;
+}
+
+static json_object *__mesh_get_model_by_unicast_modelid(_bt_mesh_cdb_t *cfg,
+               uint16_t unicast, int element_index, uint32_t model_id)
+{
+       json_object *jnode = NULL;
+       json_object *jarray = NULL;
+       json_object *jelement = NULL;
+       json_object *jmodel = NULL;
+
+       if (!cfg || !cfg->jcfg)
+               return NULL;
+
+       /* Get specific node by unicast */
+       jnode = __mesh_get_node_by_unicast(cfg, unicast);
+       if (!jnode)
+               return NULL;
+
+       /* Get element array object inside node */
+       json_object_object_get_ex(jnode, "elements", &jarray);
+       if (!jarray || json_object_get_type(jarray) != json_type_array) {
+               BT_ERR("Mesh:could not get element array");
+               return NULL;
+       }
+
+       /* Get specific element by index */
+       jelement = __mesh_get_key_object(jarray, element_index);
+       if (!jelement) {
+               BT_ERR("Mesh: Could not find element");
+               return NULL;
+       }
+
+       /* Get specific model by model-id */
+       jmodel = __mesh_get_model_by_modelid(jelement, model_id);
+       if (!jmodel)
+               return NULL;
+
+       return jmodel;
+}
+
+static json_object *__mesh_get_sub_group(json_object *jgroups, uint16_t group_addr)
+{
+       json_object *jval = NULL;
+       int sz = json_object_array_length(jgroups);
+       BT_INFO("Mesh: Total sub-addr entry present is [%d]", sz);
+
+       for (int i = 0; i < sz; ++i) {
+               uint16_t group_address;
+               const char *str;
+               json_object *jentry = NULL;
+
+               BT_INFO("Mesh: sub-addr [%d]", i);
+               jentry = json_object_array_get_idx(jgroups, i);
+
+               if (!json_object_object_get_ex(jentry, "sub-addr", &jval)) {
+                       BT_ERR("Mesh: Failed to read sub-addr in index [%d]", i);
+                       return NULL;
+               }
+
+               str = json_object_get_string(jval);
+               if (sscanf(str, "%04hx", &group_address) != 1) {
+                       BT_INFO("Mesh: Failed to read group address from sub-addr entry [%s]", str);
+                       return NULL;
+               }
+
+               BT_INFO("Mesh: group addr string [%s] sub-addr [0x%4.4x]", str, group_address);
+               if (group_addr == group_address) {
+                       BT_INFO("Mesh: Found required sub-addr");
+                       return jentry;
+               }
+       }
+       return NULL;
+}
+
+static bool __mesh_del_sub_group(json_object *jgroups, uint16_t group_addr)
+{
+       json_object *jval = NULL;
+       int i = 0;
+       int sz = json_object_array_length(jgroups);
+       BT_INFO("Mesh: Total sub-addr entry present is [%d]", sz);
+
+       for (i = 0; i < sz; ++i) {
+               uint16_t group_address;
+               const char *str;
+               json_object *jentry = NULL;
+
+               BT_INFO("Mesh: sub-addr [%d]", i);
+               jentry = json_object_array_get_idx(jgroups, i);
+
+               if (!json_object_object_get_ex(jentry, "sub-addr", &jval)) {
+                       BT_ERR("Mesh: Failed to read sub-addr in index [%d]", i);
+                       return false;
+               }
+
+               str = json_object_get_string(jval);
+               if (sscanf(str, "%04hx", &group_address) != 1) {
+                       BT_INFO("Mesh: Failed to read group address from sub-addr entry [%s]", str);
+                       return NULL;
+               }
+
+               BT_INFO("Mesh: group addr string [%s] sub-addr [0x%4.4x]", str, group_address);
+               if (group_addr == group_address) {
+                       BT_INFO("Mesh: Found required sub-addr");
+                       break;
+               }
+       }
+
+       if (i == sz)
+               return true;
+
+       json_object_array_del_idx(jgroups, i, 1);
+
+       return true;
+}
+
+bool _bt_mesh_conf_add_model_config_data(_bt_mesh_cdb_t *cfg, uint16_t unicast,
+                       int element_index, uint32_t model_id, uint16_t group_addr)
+{
+       json_object *jmodel = NULL;
+       json_object *jgroups = NULL;
+       json_object *jgroup = NULL;
+
+       BT_INFO("Mesh: Set model config informations in the node [0x%2.2x] \
+                       element index [%d] model [0x%4.4x] group addr [0x%2.2x]",
+                       unicast, element_index, model_id, group_addr);
+
+       if (!cfg || !cfg->jcfg)
+               return false;
+
+       /* Get model to be updated */
+       jmodel = __mesh_get_model_by_unicast_modelid(cfg, unicast,
+                                               element_index, model_id);
+       if (!jmodel)
+               return false;
+
+       /* Find existing sub-addr group */
+       if (!json_object_object_get_ex(jmodel, "sub-addr", &jgroups)) {
+               BT_INFO("Mesh: Sub-addr group JSON object is not present: Create");
+               jgroups = json_object_new_array();
+               if (!jgroups)
+                       return false;
+
+               json_object_object_add(jmodel, "sub-addr", jgroups);
+       }
+
+       jgroup = __mesh_get_sub_group(jgroups, group_addr);
+       if (jgroup) {
+               BT_DBG("sub-addr already present in list");
+               return true;
+       }
+
+       /* Write group address */
+       jgroup = json_object_new_object();
+       if (!jgroup)
+               return false;
+
+       if (!__mesh_write_uint16_hex(jgroup, "sub-addr", group_addr))
+               return false;
+
+       json_object_array_add(jgroups, jgroup);
+
+       /* Save */
+       return  __bt_mesh_save_configruation_file(cfg);
+}
+
+bool _bt_mesh_conf_delete_model_config_data(_bt_mesh_cdb_t *cfg, uint16_t unicast,
+                       int element_index, uint32_t model_id, uint16_t group_addr)
+{
+       json_object *jmodel = NULL;
+       json_object *jgroups = NULL;
+
+       BT_INFO("Mesh: Set model config informations in the node [0x%2.2x] \
+                       element index [%d] model [0x%4.4x] group addr [0x%2.2x]",
+                       unicast, element_index, model_id, group_addr);
+
+       if (!cfg || !cfg->jcfg)
+               return false;
+
+       /* Get model to be updated */
+       jmodel = __mesh_get_model_by_unicast_modelid(cfg, unicast,
+                                               element_index, model_id);
+       if (!jmodel)
+               return false;
+
+       /* Delete group address */
+       if (!json_object_object_get_ex(jmodel, "sub-addr", &jgroups)) {
+               return false;
+       }
+
+       if(!__mesh_del_sub_group(jgroups, group_addr))
+               return false;
+
+       /* Save */
+       return  __bt_mesh_save_configruation_file(cfg);
+}
+
+bool _bt_mesh_conf_delete_all_model_config_data(_bt_mesh_cdb_t *cfg, uint16_t unicast,
+                                               int element_index, uint32_t model_id)
+{
+       json_object *jmodel = NULL;
+       json_object *jgroups = NULL;
+       int sz;
+
+       BT_INFO("Mesh: Delete all model sub informations in the node [0x%2.2x] \
+                                       element index [%d] model [0x%4.4x]",
+                                       unicast, element_index, model_id);
+
+       if (!cfg || !cfg->jcfg)
+               return false;
+
+       /* Get model to be updated */
+       jmodel = __mesh_get_model_by_unicast_modelid(cfg, unicast,
+                                               element_index, model_id);
+       if (!jmodel)
+               return false;
+
+       /* Delete all roup address */
+       if (!json_object_object_get_ex(jmodel, "sub-addr", &jgroups)) {
+               return false;
+       }
+
+       sz = json_object_array_length(jgroups);
+       BT_INFO("Mesh: Total sub-addr entry present is [%d]", sz);
+
+       for (int i = sz - 1; i >= 0 ; --i) {
+               json_object_array_del_idx(jgroups, i, 1);
+       }
+
+       /* Save */
+       return  __bt_mesh_save_configruation_file(cfg);
+}
+
+bool _bt_mesh_conf_overwrite_model_config_data(_bt_mesh_cdb_t *cfg, uint16_t unicast,
+                       int element_index, uint32_t model_id, uint16_t group_addr)
+{
+       json_object *jmodel = NULL;
+       json_object *jgroups = NULL;
+       json_object *jgroup = NULL;
+       int sz;
+
+       BT_INFO("Mesh: Set model config informations in the node [0x%2.2x] \
+                       element index [%d] model [0x%4.4x] group addr [0x%2.2x]",
+                       unicast, element_index, model_id, group_addr);
+
+       if (!cfg || !cfg->jcfg)
+               return false;
+
+       /* Get model to be updated */
+       jmodel = __mesh_get_model_by_unicast_modelid(cfg, unicast,
+                                               element_index, model_id);
+       if (!jmodel)
+               return false;
+
+       /* Find group array */
+       if (!json_object_object_get_ex(jmodel, "sub-addr", &jgroups)) {
+               BT_INFO("Mesh: Sub-addr group JSON object is not present: Create");
+               jgroups = json_object_new_array();
+               if (!jgroups)
+                       return false;
+
+               json_object_object_add(jmodel, "sub-addr", jgroups);
+       } else {
+               /* Found group array: Delete all group address */
+               sz = json_object_array_length(jgroups);
+               BT_INFO("Mesh: Total sub-addr entry present is [%d]", sz);
+
+               for (int i = sz - 1; i >= 0 ; --i) {
+                       BT_INFO("Mesh: Delete sub-addr entry [%d]", i);
+                       json_object_array_del_idx(jgroups, i, 1);
+               }
+       }
+
+       /* Over-write new group address */
+       jgroup = json_object_new_object();
+       if (!jgroup)
+               return false;
+
+       if (!__mesh_write_uint16_hex(jgroup, "sub-addr", group_addr))
+               return false;
+
+       json_object_array_add(jgroups, jgroup);
+
+       /* Save */
+       return  __bt_mesh_save_configruation_file(cfg);
+}
+
 bool _bt_mesh_conf_set_network_friendly_name(_bt_mesh_cdb_t *cfg,
                const char *network_name)
 {
index d005d1f..5a7810b 100644 (file)
@@ -1285,6 +1285,43 @@ void _bt_mesh_config_client_devkey_msg_handler(
                BT_INFO("Subscr Addr\t%4.4x\n", addr);
                BT_INFO("Model ID\t%4.4x\n", mod_id);
 
+               if (data[0] == MESH_STATUS_SUCCESS) {
+                       /* Update cdb */
+                       switch (cmd->opcode) {
+                       case MESH_OPCODE_CONFIG_MODEL_SUB_ADD:
+                       case MESH_OPCODE_CONFIG_MODEL_SUB_VIRT_ADD:
+                               if (!_bt_mesh_network_add_model_subscription(
+                                       event->net_uuid.uuid, event->source,
+                                       ele_addr - event->source, mod_id, addr)) {
+                                       BT_INFO("Failed to add model subscription!");
+                               }
+                       break;
+                       case MESH_OPCODE_CONFIG_MODEL_SUB_DELETE:
+                       case MESH_OPCODE_CONFIG_MODEL_SUB_VIRT_DELETE:
+                               if (!_bt_mesh_network_delete_model_subscription(
+                                       event->net_uuid.uuid, event->source,
+                                       ele_addr - event->source, mod_id, addr)) {
+                                       BT_INFO("Failed to delete model subscription!");
+                               }
+                       break;
+                       case MESH_OPCODE_CONFIG_MODEL_SUB_DELETE_ALL:
+                               if (!_bt_mesh_network_delete_all_model_subscription(
+                                       event->net_uuid.uuid, event->source,
+                                       ele_addr - event->source, mod_id)) {
+                                       BT_INFO("Failed to delete all model subscription!");
+                               }
+                       break;
+                       case MESH_OPCODE_CONFIG_MODEL_SUB_OVERWRITE:
+                       case MESH_OPCODE_CONFIG_MODEL_SUB_VIRT_OVERWRITE:
+                               if (!_bt_mesh_network_overwrite_model_subscription(
+                                       event->net_uuid.uuid, event->source,
+                                       ele_addr - event->source, mod_id, addr)) {
+                                       BT_INFO("Failed to overwrite model subscription!");
+                               }
+                       break;
+                       }
+               }
+
                if (cmd)
                        __mesh_handle_model_subscription_event(result, &param, cmd);
 
@@ -1458,6 +1495,9 @@ void _bt_mesh_config_client_devkey_msg_handler(
                                *param.sub_list[k] = l_get_le16(data + i);
                        }
                }
+
+               /* <TO-DO> Update model sub in cdb */
+
                __bt_mesh_handle_pending_dev_config_request_info(result,
                        BT_MESH_MODEL_GET_SUBSCRIPTION_LIST, &param,
                                sizeof(bluetooth_mesh_model_configure_t));
index a742b10..e68ccce 100644 (file)
@@ -1323,6 +1323,82 @@ bool _bt_mesh_network_delete_remote_node_netkey(
        return false;
 }
 
+bool _bt_mesh_network_add_model_subscription(
+               uint8_t net_uuid[], uint16_t remote_unicast,
+               int ele_idx, uint32_t mod_id, uint16_t group_addr)
+{
+       GSList *l;
+       _bt_mesh_cdb_t *cdb_cfg = NULL;
+
+       /* Find CDB */
+       l = g_slist_find_custom(cdb_list, net_uuid,
+               __mesh_compare_app_network_uuid);
+       if (!l)
+               return false;
+
+       cdb_cfg = (_bt_mesh_cdb_t*)l->data;
+
+       return _bt_mesh_conf_add_model_config_data(cdb_cfg,
+                       remote_unicast, ele_idx, mod_id, group_addr);
+}
+
+bool _bt_mesh_network_delete_model_subscription(
+               uint8_t net_uuid[], uint16_t remote_unicast,
+               int ele_idx, uint32_t mod_id, uint16_t group_addr)
+{
+       GSList *l;
+       _bt_mesh_cdb_t *cdb_cfg = NULL;
+
+       /* Find CDB */
+       l = g_slist_find_custom(cdb_list, net_uuid,
+               __mesh_compare_app_network_uuid);
+       if (!l)
+               return false;
+
+       cdb_cfg = (_bt_mesh_cdb_t*)l->data;
+
+       return _bt_mesh_conf_delete_model_config_data(cdb_cfg,
+                       remote_unicast, ele_idx, mod_id, group_addr);
+}
+
+bool _bt_mesh_network_delete_all_model_subscription(
+               uint8_t net_uuid[], uint16_t remote_unicast,
+               int ele_idx, uint32_t mod_id)
+{
+       GSList *l;
+       _bt_mesh_cdb_t *cdb_cfg = NULL;
+
+       /* Find CDB */
+       l = g_slist_find_custom(cdb_list, net_uuid,
+               __mesh_compare_app_network_uuid);
+       if (!l)
+               return false;
+
+       cdb_cfg = (_bt_mesh_cdb_t*)l->data;
+
+       return _bt_mesh_conf_delete_all_model_config_data(cdb_cfg,
+                       remote_unicast, ele_idx, mod_id);
+}
+
+bool _bt_mesh_network_overwrite_model_subscription(
+               uint8_t net_uuid[], uint16_t remote_unicast,
+               int ele_idx, uint32_t mod_id, uint16_t group_addr)
+{
+       GSList *l;
+       _bt_mesh_cdb_t *cdb_cfg = NULL;
+
+       /* Find CDB */
+       l = g_slist_find_custom(cdb_list, net_uuid,
+               __mesh_compare_app_network_uuid);
+       if (!l)
+               return false;
+
+       cdb_cfg = (_bt_mesh_cdb_t*)l->data;
+
+       return _bt_mesh_conf_overwrite_model_config_data(cdb_cfg,
+                       remote_unicast, ele_idx, mod_id, group_addr);
+}
+
 bool _bt_mesh_network_save_remote_node_composition(
                uint8_t net_uuid[], uint16_t remote_unicast,
                                uint8_t *data, uint16_t data_len)