Mesh: Add Local Network Configuration
authorAnupam Roy <anupam.r@samsung.com>
Fri, 17 Jul 2020 10:35:51 +0000 (16:05 +0530)
committerAnupam Roy <anupam.r@samsung.com>
Fri, 17 Jul 2020 10:35:51 +0000 (16:05 +0530)
This patch handles Network operations
& requests to Mesh OAL layer
- Network Create
- Scan for unprovisioned devices
- Provision devices to Mesh Network
- Set Provisioner capabilities
- Authentication Reply

TODO: Following will be added in subsequent patches
- Secuity Key management API's
- Node management API's

Change-Id: I2409e216abfcdadfb44d73a6c365941e22c699ca
Signed-off-by: Anupam Roy <anupam.r@samsung.com>
bt-service/CMakeLists.txt
bt-service/services/mesh/bt-service-mesh-network.c [new file with mode: 0644]
bt-service/services/mesh/bt-service-mesh-network.h [new file with mode: 0644]

index cdc7843..b969812 100644 (file)
@@ -35,6 +35,7 @@ SET(SRCS
 ./services/mesh/bt-service-mesh-keys.c
 ./services/mesh/bt-service-mesh-cdb.c
 ./services/mesh/bt-service-mesh-nodes.c
+./services/mesh/bt-service-mesh-network.c
 )
 
 IF("$ENV{CFLAGS}" MATCHES "-DTIZEN_FEATURE_BT_OBEX")
diff --git a/bt-service/services/mesh/bt-service-mesh-network.c b/bt-service/services/mesh/bt-service-mesh-network.c
new file mode 100644 (file)
index 0000000..ed89107
--- /dev/null
@@ -0,0 +1,470 @@
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * @author: Anupam Roy <anupam.r@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *              http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include <glib.h>
+#include <dlog.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <ell/ell.h>
+
+#include "bt-service-common.h"
+#include "bt-service-core-adapter.h"
+#include "bt-service-event-receiver.h"
+#include "bt-request-handler.h"
+#include "bluetooth-api.h"
+
+#include "bluetooth-api.h"
+#include "bluetooth-mesh-api.h"
+#include "bt-internal-types.h"
+#include "bt-service-util.h"
+#include "bt-service-common.h"
+#include "bt-service-event.h"
+
+#include "bt-service-mesh-network.h"
+#include "bt-service-mesh-cdb.h"
+#include "bt-service-mesh-nodes.h"
+#include "bt-service-mesh-keys.h"
+#include "bt-service-mesh-util.h"
+
+#include "bt-internal-types.h"
+
+#include <oal-hardware.h>
+#include <oal-manager.h>
+#include <oal-event.h>
+#include <oal-adapter-mgr.h>
+#include <oal-device-mgr.h>
+#include <oal-mesh.h>
+
+/* Temp local node structure.
+   Create & save node temporarily till network creation */
+typedef struct {
+       const char *app_cred;
+       const char *sender;
+       bluetooth_mesh_vendor_info_t vendor_info;
+       uint8_t node_uuid[16];
+       uint16_t num_elems;
+       uint16_t prim_unicast;
+       GSList *model_list;
+} mesh_local_node_t;
+
+/* List of CDB's for the created networks */
+static GSList *cdb_list = NULL;
+
+/* List of local ndoes to be created: Free memory once saved in DB */
+static GSList *temp_nodes = NULL;
+
+/* Scanning state: Unprovisioned device scan */
+static bool bt_mesh_is_scanning = false;
+
+/* Provisoning state */
+static bool bt_mesh_is_provisoning = false;
+
+static gint __mesh_compare_hex_uuid(gconstpointer data,
+               gconstpointer user_data)
+{
+       const mesh_local_node_t *u1 = data;
+       const uint8_t *u2 = user_data;
+
+       retv_if(NULL == u1, -1);
+       retv_if(NULL == u2, -1);
+
+       return memcmp(u1->node_uuid, u2, 16);
+}
+
+static gint __mesh_compare_app_cdb_token(gconstpointer data,
+               gconstpointer user_data)
+{
+       char *token_str = NULL;
+       const _bt_mesh_cdb_t *cdb = data;
+       const char *token = user_data;
+       int ret = 0;
+
+       retv_if(NULL == cdb, -1);
+       retv_if(NULL == token, -1);
+
+       token_str = _bt_service_convert_hex_to_string(
+               (unsigned char*)cdb->token, 8);
+
+       ret = g_strcmp0(token_str, token);
+       g_free(token_str);
+       return ret;
+}
+
+int _bt_mesh_load_app_networks(const char *app_cred)
+{
+       int ret = BLUETOOTH_ERROR_NONE;
+
+       /* Load Mesh Networks for the current app */
+       if (!_bt_mesh_util_is_directory_exists(MESH_CDB_DEFAULT_DIR_PATH))
+               return BLUETOOTH_ERROR_INTERNAL;
+
+       return ret;
+}
+
+static void __bt_mesh_free_temp_node(mesh_local_node_t *tmp)
+{
+       temp_nodes = g_slist_remove(temp_nodes, tmp);
+       g_free((gpointer)tmp->app_cred);
+       g_free((gpointer)tmp->sender);
+       g_slist_free_full(tmp->model_list, g_free);
+       g_free(tmp);
+}
+
+int _bt_mesh_network_request_provisioning_data_request(uint8_t net_uuid[],
+               uint8_t count)
+{
+       uint16_t unicast;
+       int ret = OAL_STATUS_SUCCESS;
+       oal_uuid_t uuid;
+       unicast = _bt_mesh_node_get_next_unicast(net_uuid,
+                       MESH_DEFAULT_START_ADDRESS,
+                       MESH_DEFAULT_START_ADDRESS, count);
+       BT_INFO("Mesh: Network: Got unicast [0x%2x]", unicast);
+
+       memcpy(uuid.uuid, net_uuid, 16);
+       /* Register Mesh Node */
+       ret = mesh_network_send_provisioning_data(&uuid,
+                       MESH_PRIMARY_NET_IDX, unicast);
+       if (ret != OAL_STATUS_SUCCESS) {
+               BT_ERR("ret: %d", ret);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+       return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_mesh_network_create_cdb(int result,
+               const char *sender, const char *app_creds,
+                       uint8_t uuid[16], uint8_t token[8],
+                                const char *network)
+{
+       char *dir_path = NULL;
+       char *file_path = NULL;
+       GSList *l;
+       mesh_local_node_t *tmp;
+       _bt_mesh_cdb_t *cdb_cfg = NULL;
+       char uuid_string[33];
+
+       _bt_mesh_util_convert_hex_to_string(uuid, 16,
+                       uuid_string, sizeof(uuid_string));
+       BT_INFO("Mesh: Create CDB request for network UUID [%s]",
+                       uuid_string);
+       BT_INFO("Mesh: Temporary node count [%d]",
+                       g_slist_length(temp_nodes));
+
+       /* Find Temp Node */
+       l = g_slist_find_custom(temp_nodes, uuid,
+                       __mesh_compare_hex_uuid);
+       if (!l) {
+               BT_ERR("Mesh: Temp  Node not found for the UUID [%s]",
+                               uuid_string);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       tmp = (mesh_local_node_t*)l->data;
+
+       if (result != BLUETOOTH_ERROR_NONE) {
+               /* Free the node structure */
+               __bt_mesh_free_temp_node(tmp);
+               return result;
+       }
+
+       BT_INFO("Mesh: Create CDB for the New Network [%s]",
+                       network);
+       /* Stat/Create directory for new CDB file */
+       dir_path = g_strdup_printf(MESH_CDB_DEFAULT_DIR_PATH"/%s/",
+               "default");
+       BT_INFO("Mesh: Directory path for new Network CDB [%s]",
+                       dir_path);
+       if (!_bt_mesh_util_create_directory(dir_path)) {
+               g_free(dir_path);
+               __bt_mesh_free_temp_node(tmp);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       BT_INFO("Mesh: Directory Created successfully");
+       /* Create the CDB for the network */
+       file_path = g_strdup_printf("%s%s_config.json",
+                       dir_path, uuid_string);
+       BT_INFO("Mesh: CDB File path[%s]", file_path);
+       cdb_cfg = _bt_mesh_conf_database_create(file_path, uuid,
+                       token, network, app_creds);
+
+       /* Cleanup */
+       g_free(dir_path);
+       g_free(file_path);
+
+       if (!cdb_cfg) {
+               /* Free the memory of temporary node
+                  which was created during Network creation */
+               __bt_mesh_free_temp_node(tmp);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+       BT_INFO("Mesh: CDB CFG file created successfully");
+
+       _bt_mesh_conf_set_unicast_address_range(cdb_cfg,
+                       MESH_DEFAULT_START_ADDRESS,
+                               MESH_DEFAULT_MAX_ADDRESS);
+       BT_INFO("Mesh: Address range Set for network");
+
+       /* Create new network for saving network specific Keys */
+       _bt_mesh_keys_load_net(cdb_cfg->uuid);
+       BT_INFO("Mesh: Address range Set for network");
+       _bt_mesh_keys_add_net_key(cdb_cfg->uuid,
+                       MESH_PRIMARY_NET_IDX);
+       BT_INFO("Mesh: Primary net key added to network memeory");
+       _bt_mesh_conf_insert_network_key(cdb_cfg,
+                       MESH_PRIMARY_NET_IDX,
+                               MESH_KEY_REFRESH_PHASE_NONE);
+       BT_INFO("Mesh: Primary net key added to CDB");
+
+       /* Create new network for saving network specific nodes */
+       _bt_mesh_node_load_net(cdb_cfg->uuid);
+       BT_INFO("Mesh: local Node loaded to memory");
+       _bt_mesh_node_add_node(cdb_cfg->uuid, tmp->node_uuid,
+                       tmp->prim_unicast, tmp->num_elems,
+                               MESH_PRIMARY_NET_IDX);
+       BT_INFO("Mesh: Added basic info (num elems, UUID, primary NetIDx)");
+
+       /* Add Primary Node as 1st entry in CDB */
+       _bt_mesh_conf_insert_node_object(cdb_cfg, /* Dev UUID */uuid,
+                       tmp->num_elems, tmp->prim_unicast,
+                               MESH_PRIMARY_NET_IDX);
+       BT_INFO("Mesh: Added Local node's basic info  in CDB");
+
+       cdb_list = g_slist_append(cdb_list, cdb_cfg);
+       BT_INFO("Mesh: CDB added to list");
+
+       __bt_mesh_free_temp_node(tmp);
+       BT_INFO("Mesh: temp node freed");
+       return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_mesh_network_scan(const char *app_cred,
+       const char *sender,
+               bluetooth_mesh_network_t *network,
+                       bluetooth_mesh_scan_param_t *param)
+{
+       int ret = OAL_STATUS_SUCCESS;
+       oal_uuid_t net_uuid;
+
+       /* If Scanning is going on */
+       if (_bt_mesh_is_provisioning() ||
+                       _bt_mesh_is_scanning()) {
+               BT_ERR("Device is already scanning..");
+               return BLUETOOTH_ERROR_DEVICE_BUSY;
+       }
+       _bt_mesh_util_convert_string_to_hex(network->uuid,
+               strlen(network->uuid), net_uuid.uuid, 16);
+       /* Register Mesh Node */
+       ret = mesh_network_start_scan(&net_uuid,
+               (oal_mesh_scan_params_t*) param);
+       if (ret != OAL_STATUS_SUCCESS) {
+               BT_ERR("ret: %d", ret);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       /* Set scanning state to true */
+       _bt_mesh_set_scanning_state(true);
+       return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_mesh_network_scan_cancel(const char *app_cred,
+       const char *sender, bluetooth_mesh_network_t *network)
+{
+       int ret = OAL_STATUS_SUCCESS;
+       oal_uuid_t net_uuid;
+
+       _bt_mesh_util_convert_string_to_hex(network->uuid,
+               strlen(network->uuid), net_uuid.uuid, 16);
+       /* Register Mesh Node */
+       ret = mesh_network_scan_cancel(&net_uuid);
+       if (ret != OAL_STATUS_SUCCESS) {
+               BT_ERR("ret: %d", ret);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_mesh_network_set_provisioner_caps(const char *app_cred,
+               const char *sender, bluetooth_mesh_network_t *network,
+                       bluetooth_mesh_provisioner_caps_t *caps)
+{
+       int ret = OAL_STATUS_SUCCESS;
+       oal_uuid_t net_uuid;
+
+       _bt_mesh_util_convert_string_to_hex(network->uuid,
+               strlen(network->uuid), net_uuid.uuid, 16);
+
+       /* Register Mesh Node */
+       ret = mesh_network_set_provisioning_capabilities(&net_uuid,
+               (oal_mesh_capabilities_t*) caps);
+       if (ret != OAL_STATUS_SUCCESS) {
+               BT_ERR("ret: %d", ret);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       return BLUETOOTH_ERROR_NONE;
+}
+
+bool _bt_mesh_is_scanning(void)
+{
+       return bt_mesh_is_scanning;
+}
+
+void _bt_mesh_set_scanning_state(bool state)
+{
+       bt_mesh_is_scanning = state;
+}
+
+bool _bt_mesh_is_provisioning(void)
+{
+       return bt_mesh_is_scanning;
+}
+
+void _bt_mesh_set_provisioning_state(bool state)
+{
+       bt_mesh_is_provisoning = state;
+}
+
+int _bt_mesh_network_provision_device(const char *app_cred,
+               const char *sender,
+                       bluetooth_mesh_provisioning_request_t *req)
+{
+       int ret = OAL_STATUS_SUCCESS;
+       oal_uuid_t net_uuid;
+       oal_uuid_t dev_uuid;
+
+       /* If Scanning is going on */
+       if (_bt_mesh_is_provisioning() ||
+                       _bt_mesh_is_scanning()) {
+               BT_ERR("Device is buzy..");
+               return BLUETOOTH_ERROR_DEVICE_BUSY;
+       }
+
+       _bt_mesh_util_convert_string_to_hex(req->net_uuid,
+               strlen(req->net_uuid), net_uuid.uuid, 16);
+       _bt_mesh_util_convert_string_to_hex(req->dev_uuid,
+               strlen(req->dev_uuid), dev_uuid.uuid, 16);
+
+       ret = mesh_network_provision_device(&net_uuid, &dev_uuid);
+
+       if (ret != OAL_STATUS_SUCCESS) {
+               BT_ERR("ret: %d", ret);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       /* Set Provisioning state */
+       _bt_mesh_set_provisioning_state(true);
+
+       return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_mesh_authentication_reply(int auth_type,
+               const char *auth_value, gboolean reply)
+{
+       int ret = OAL_STATUS_SUCCESS;
+
+       if (!_bt_mesh_is_provisioning())
+               return BLUETOOTH_ERROR_NOT_IN_OPERATION;
+
+       if (!auth_value)
+               return BLUETOOTH_ERROR_INVALID_PARAM;
+
+       ret = mesh_authentication_reply(
+                       (oal_mesh_variant_authentication_e)auth_type,
+                       auth_value);
+
+       if (ret != OAL_STATUS_SUCCESS) {
+               BT_ERR("ret: %d", ret);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_mesh_eleiment_get_models(const char *app_cred, const char *sender,
+               bluetooth_mesh_network_t *network,  uint16_t unicast,
+                       int elem_idx, GArray **out_param)
+{
+       GSList *l;
+       _bt_mesh_cdb_t *cdb_cfg = NULL;
+
+       /* Find CDB */
+       l = g_slist_find_custom(cdb_list, network->token.token,
+                       __mesh_compare_app_cdb_token);
+       if (!l)
+               return BLUETOOTH_ERROR_INVALID_PARAM;
+
+       cdb_cfg = (_bt_mesh_cdb_t*)l->data;
+
+       if (_bt_mesh_node_get_models(cdb_cfg->uuid, unicast,
+                               elem_idx, out_param))
+               return BLUETOOTH_ERROR_NONE;
+       else
+               return BLUETOOTH_ERROR_INTERNAL;
+}
+
+int _bt_mesh_network_create(const char *app_cred,
+               const char *sender, const char *network_name,
+                       bluetooth_mesh_node_t *node, GSList *model_list)
+{
+       int ret = OAL_STATUS_SUCCESS;
+
+       BT_INFO("Mesh: App Cred [%s] sender [%s] network [%s]",
+                       app_cred, sender, network_name);
+
+       /* Sanity Check: CDB directory creation */
+       if (!_bt_mesh_util_is_directory_exists(MESH_CDB_DEFAULT_DIR_PATH)) {
+               BT_INFO("MESH: CDB directory does not exist");
+               if (!_bt_mesh_util_create_directory(MESH_CDB_DEFAULT_DIR_PATH)) {
+                       BT_ERR("MESH: Fail to create Mesh CDB directory");
+                       return BLUETOOTH_ERROR_INTERNAL;
+               }
+       }
+
+       BT_INFO("Mesh: Send Local Network Creation Request to OAL");
+
+       /* Register Mesh Node */
+       ret = mesh_register_node((oal_mesh_node_t*)node, model_list, true);
+       if (ret != OAL_STATUS_SUCCESS) {
+               BT_ERR("ret: %d", ret);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       BT_INFO("Mesh: Request Sent to Stack successfully");
+       /* Create a temporary node & wait for Network Created event */
+       mesh_local_node_t *temp = g_malloc0(sizeof(mesh_local_node_t));
+       memcpy(temp->node_uuid, node->uuid, 16);
+       temp->num_elems = node->num_elements;
+       temp->prim_unicast = node->primary_unicast;
+       temp->sender = g_strdup(sender);
+       temp->app_cred = g_strdup(app_cred);
+       temp->vendor_info = node->vendor_info;
+       temp->model_list = model_list;
+       temp_nodes = g_slist_append(temp_nodes, temp);
+
+       return BLUETOOTH_ERROR_NONE;
+}
diff --git a/bt-service/services/mesh/bt-service-mesh-network.h b/bt-service/services/mesh/bt-service-mesh-network.h
new file mode 100644 (file)
index 0000000..322a7d7
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * @author: Anupam Roy <anupam.r@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *              http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef BT_SERVICE_MESH_NETWORK_H_
+#define BT_SERVICE_MESH_NETWORK_H_
+
+#include <glib.h>
+#include <sys/types.h>
+#include "bluetooth-api.h"
+#include "bluetooth-mesh-api.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int _bt_mesh_network_create(const char *app_key,
+               const char *sender, const char *network_name,
+                       bluetooth_mesh_node_t *node, GSList *model_list);
+
+int _bt_mesh_network_create_cdb(int result,
+               const char *sender, const char *app_creds,
+                       uint8_t uuid[16], uint8_t token[8],
+                               const char *network);
+
+int _bt_mesh_network_request_provisioning_data_request(
+               uint8_t net_uuid[], uint8_t count);
+
+int _bt_mesh_network_scan(const char *app_cred, const char *sender,
+               bluetooth_mesh_network_t *network,
+                       bluetooth_mesh_scan_param_t *param);
+
+int _bt_mesh_network_scan_cancel(const char *app_cred,
+               const char *sender, bluetooth_mesh_network_t *network);
+
+bool _bt_mesh_is_scanning(void);
+
+void _bt_mesh_set_scanning_state(bool state);
+
+bool _bt_mesh_is_provisioning(void);
+
+void _bt_mesh_set_provisioning_state(bool state);
+
+int _bt_mesh_network_set_provisioner_caps(const char *app_cred,
+               const char *sender, bluetooth_mesh_network_t *network,
+                       bluetooth_mesh_provisioner_caps_t *caps);
+
+int _bt_mesh_network_provision_device(const char *app_cred,
+               const char *sender,
+                       bluetooth_mesh_provisioning_request_t *req);
+
+int _bt_mesh_authentication_reply(int auth_type,
+               const char *auth_value, gboolean reply);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* BT_MESH_NETWORK_H_ */