Mesh: Implement Mesh Framework API's
authorAnupam Roy <anupam.r@samsung.com>
Fri, 17 Jul 2020 11:08:01 +0000 (16:38 +0530)
committerAnupam Roy <anupam.r@samsung.com>
Fri, 17 Jul 2020 11:08:01 +0000 (16:38 +0530)
This patch-set is the initial implementation
of basic Mesh network operations
- Create Network
- Scan for Unprovisioned devices
- Scan Cancel
- Set Network Provisioning capabilities
- Provision a device into the network

Change-Id: Ie23af0276055e666a06b9fcbf9dbd7e74c147e8b
Signed-off-by: Anupam Roy <anupam.r@samsung.com>
bt-api/bt-mesh.c [new file with mode: 0644]
bt-service/services/bt-request-handler.c
bt-service/services/include/bt-service-mesh-network.h [moved from bt-service/services/mesh/bt-service-mesh-network.h with 100% similarity]

diff --git a/bt-api/bt-mesh.c b/bt-api/bt-mesh.c
new file mode 100644 (file)
index 0000000..b04fb25
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * @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 "bluetooth-api.h"
+#include "bt-internal-types.h"
+
+#include "bt-common.h"
+#include "bt-request-sender.h"
+#include "bt-event-handler.h"
+
+#include "bluetooth-mesh-api.h"
+
+#define BLUETOOTH_MESH_NETWORK_NAME_STRING_MAX 100
+#define BLUETOOTH_MESH_TOKEN_STRING_MAX 100
+
+BT_EXPORT_API int bluetooth_mesh_init(mesh_cb_func_ptr cb,
+                       void *user_data)
+{
+       int ret;
+
+       if (cb == NULL) {
+               BT_ERR("callback is NULL");
+               return BLUETOOTH_ERROR_INVALID_PARAM;
+       }
+       ret = _bt_init_event_handler();
+
+       if (ret != BLUETOOTH_ERROR_NONE &&
+                       ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
+               BT_ERR("Fail to init the event handler");
+               return ret;
+       }
+
+       _bt_set_user_data(BT_MESH, (void *)cb, user_data);
+
+       /* Register All events */
+       ret = _bt_register_event(BT_MESH_EVENT, (void *)cb, user_data);
+       if (ret != BLUETOOTH_ERROR_NONE &&
+                       ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
+               _bt_deinit_event_handler();
+               return ret;
+       }
+
+       BT_INFO("Mesh: Event registsred");
+       return BLUETOOTH_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_mesh_deinit(void)
+{
+       _bt_unregister_event(BT_MESH_EVENT);
+       _bt_set_user_data(BT_MESH, NULL, NULL);
+
+       return BLUETOOTH_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_mesh_network_create(
+       const char *net_name, bluetooth_mesh_node_t *node,
+               uint16_t total_models, bluetooth_mesh_model_t **models,
+                       bluetooth_mesh_network_t *network)
+{
+       int result;
+       char network_name[BLUETOOTH_MESH_NETWORK_NAME_STRING_MAX+1];
+
+       BT_CHECK_PARAMETER(net_name, return);
+       BT_CHECK_PARAMETER(node, return);
+       BT_CHECK_PARAMETER(models, return);
+
+       BT_INIT_PARAMS();
+       BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       g_array_append_vals(in_param1, node,  sizeof(bluetooth_mesh_node_t));
+
+       g_strlcpy(network_name, net_name, sizeof(network_name));
+       g_array_append_vals(in_param2, network_name,
+                       BLUETOOTH_MESH_NETWORK_NAME_STRING_MAX);
+
+       for(int i = 0; i < total_models; i++)
+               g_array_append_vals(in_param3, models[i],
+                               sizeof(bluetooth_mesh_model_t));
+
+       result = _bt_send_request(BT_BLUEZ_SERVICE,
+                       BT_MESH_NETWORK_CREATE,
+                               in_param1, in_param2, in_param3,
+                                       in_param4, &out_param);
+
+       if (result == BLUETOOTH_ERROR_NONE) {
+               *network = g_array_index(out_param,
+                               bluetooth_mesh_network_t, 0);
+       }
+
+       BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       return result;
+}
+
+BT_EXPORT_API int bluetooth_mesh_network_scan(
+                       bluetooth_mesh_network_t *network,
+                               bluetooth_mesh_scan_param_t *scan_param)
+{
+       int result;
+
+       BT_CHECK_PARAMETER(network, return);
+       BT_CHECK_PARAMETER(scan_param, return);
+
+       BT_INIT_PARAMS();
+       BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       g_array_append_vals(in_param1, network,  sizeof(bluetooth_mesh_network_t));
+
+       g_array_append_vals(in_param2, scan_param, sizeof(bluetooth_mesh_scan_param_t));
+
+       BT_INFO("Mesh:Start Scan, time [%u]", scan_param->scan_time);
+       result = _bt_send_request(BT_BLUEZ_SERVICE, BT_MESH_NETWORK_SCAN,
+                       in_param1, in_param2, in_param3, in_param4, &out_param);
+       BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       return result;
+}
+
+BT_EXPORT_API int bluetooth_mesh_network_cancel_scan(
+               bluetooth_mesh_network_t *network)
+{
+       int result;
+
+       BT_CHECK_PARAMETER(network, return);
+
+       BT_INIT_PARAMS();
+       BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       g_array_append_vals(in_param1, network,  sizeof(bluetooth_mesh_network_t));
+
+       BT_INFO("Mesh: Cancel Scan");
+       result = _bt_send_request(BT_BLUEZ_SERVICE, BT_MESH_NETWORK_CANCEL_SCAN,
+                       in_param1, in_param2, in_param3, in_param4, &out_param);
+       BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       return result;
+}
+
+BT_EXPORT_API int bluetooth_mesh_network_set_capabilities(
+       bluetooth_mesh_network_t *network,
+               bluetooth_mesh_provisioner_caps_t *caps)
+{
+       int result;
+
+       BT_CHECK_PARAMETER(network, return);
+       BT_CHECK_PARAMETER(caps, return);
+
+       BT_INIT_PARAMS();
+       BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       g_array_append_vals(in_param1, network,  sizeof(bluetooth_mesh_network_t));
+
+       g_array_append_vals(in_param2, caps, sizeof(bluetooth_mesh_provisioner_caps_t));
+
+       BT_INFO("Mesh: Set Provisioner capabilities");
+       result = _bt_send_request(BT_BLUEZ_SERVICE, BT_MESH_NETWORK_SET_CAPABILITIES,
+                       in_param1, in_param2, in_param3, in_param4, &out_param);
+       BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       return result;
+}
+
+BT_EXPORT_API int bluetooth_mesh_network_provision_device(
+               bluetooth_mesh_provisioning_request_t *req)
+{
+       int result;
+       bt_user_info_t *user_info;
+
+       BT_CHECK_PARAMETER(req, return);
+
+       user_info = _bt_get_user_data(BT_MESH);
+       retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
+
+       BT_INIT_PARAMS();
+       BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       g_array_append_vals(in_param1, req,
+                       sizeof(bluetooth_mesh_provisioning_request_t));
+
+       BT_INFO("Mesh: Set Provision Device");
+       result = _bt_send_request_async(BT_BLUEZ_SERVICE,
+                       BT_MESH_NETWORK_PROVISION_DEVICE,
+                       in_param1, in_param2, in_param3, in_param4,
+                       user_info->cb, user_info->user_data);
+
+       BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       return result;
+}
+
+BT_EXPORT_API int bluetooth_mesh_authentication_reply(int auth_type,
+               const char *auth_val, gboolean reply)
+{
+       int result;
+
+       char auth_string[BLUETOOTH_MESH_AUTH_VALUE_LENGTH_MAX];
+
+       BT_CHECK_PARAMETER(auth_val, return);
+
+       BT_INIT_PARAMS();
+       BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       g_strlcpy(auth_string, auth_val,
+                       sizeof(auth_string));
+       g_array_append_vals(in_param1,
+                       &auth_type, sizeof(int));
+       g_array_append_vals(in_param2, auth_string,
+                       BLUETOOTH_MESH_AUTH_VALUE_LENGTH_MAX);
+       g_array_append_vals(in_param3, &reply, sizeof(gboolean));
+
+       BT_INFO("Mesh: Set Provisioner Authentication Reply");
+       result = _bt_send_request(BT_BLUEZ_SERVICE, BT_MESH_AUTHENTICATION_REPLY,
+                       in_param1, in_param2, in_param3, in_param4, &out_param);
+
+       BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       return result;
+}
index f5b62e1..007a598 100644 (file)
@@ -28,6 +28,7 @@
 #include "bluetooth-api.h"
 #include "bluetooth-audio-api.h"
 #include "bluetooth-gatt-server-api.h"
+#include "bluetooth-mesh-api.h"
 #include "bt-request-handler.h"
 #include "bt-service-common.h"
 #include "bt-service-util.h"
@@ -40,6 +41,8 @@
 #include "bt-service-avrcp-tg.h"
 #include "bt-service-avrcp-ctrl.h"
 #include "bt-service-gatt.h"
+#include "bt-service-mesh-util.h"
+#include "bt-service-mesh-network.h"
 
 #ifdef TIZEN_FEATURE_BT_DPM
 #include "bt-service-dpm.h"
@@ -74,6 +77,7 @@ static gboolean is_le_intended = FALSE;
 
 static cynara *p_cynara;
 static cynara_configuration *conf;
+const char *requester_unique_creds = NULL;
 
 static const gchar bt_service_introspection_xml[] =
 "<node name='/org/projectx/bt_service'>"
@@ -107,6 +111,8 @@ static char *current_sender_playing = NULL;
 
 GDBusNodeInfo *node_info_g = NULL;
 
+static void __bt_fill_garray_from_variant(GVariant *var, GArray *param);
+
 static void __bt_service_method(GDBusConnection *connection,
                const gchar *sender,
                const gchar *object_path,
@@ -223,7 +229,10 @@ static gboolean __bt_is_sync_function(int service_function)
                        || service_function == BT_GATT_WATCH_CHARACTERISTIC
                        || service_function == BT_GATT_ACQUIRE_WRITE
 #endif
-                       || service_function == BT_AUDIO_SELECT_ROLE)
+                       || service_function == BT_AUDIO_SELECT_ROLE
+                       /* Mesh API's */
+                       || service_function == BT_MESH_NETWORK_CREATE
+                       || service_function == BT_MESH_NETWORK_SCAN)
                return TRUE;
        else
                return FALSE;
@@ -3347,6 +3356,172 @@ normal:
 
                break;
        }
+       case BT_MESH_NETWORK_CREATE: {
+               bluetooth_mesh_node_t node;
+               GSList *model_list = NULL;
+               int total_models = 0;
+               GArray *param3;
+               int i = 0;
+               const char *network_name = NULL;
+               bluetooth_mesh_network_t *network;
+
+               memset(&node, 0x00, sizeof(bluetooth_mesh_node_t));
+               sender = (char*)g_dbus_method_invocation_get_sender(context);
+
+               __bt_service_get_parameters(in_param1,
+                               &node, sizeof(bluetooth_mesh_node_t));
+               network_name = (const char *)g_variant_get_data(in_param2);
+               BT_INFO("MESH: Network name [%s]", network_name);
+
+               param3 = g_array_new(TRUE, TRUE, sizeof(gchar));
+               __bt_fill_garray_from_variant(in_param3, param3);
+
+               total_models = (param3->len) / sizeof(bluetooth_mesh_model_t);
+               for (i = 0; i < total_models; i++) {
+                       bluetooth_mesh_model_t *info = NULL;
+                       bluetooth_mesh_model_t *mod = NULL;
+
+                       info = &g_array_index(param3,
+                                       bluetooth_mesh_model_t, i);
+
+                       mod = g_memdup(info, sizeof(bluetooth_mesh_model_t));
+
+                       if (mod)
+                               model_list = g_slist_append(model_list,
+                                                       (gpointer)mod);
+               }
+               result = _bt_mesh_network_create(requester_unique_creds,
+                               sender, network_name,  &node, model_list);
+
+                /* Save invocation */
+               if (result == BLUETOOTH_ERROR_NONE) {
+                       BT_INFO("Mesh: Save Invoation");
+                       network =  g_malloc0(sizeof(bluetooth_mesh_network_t));
+
+                       /* Save Network name & UUID, Token will be received in event */
+                       _bt_mesh_util_convert_hex_to_string(
+                                       (uint8_t *) node.uuid, 16,
+                                       network->uuid,
+                                       BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
+                       BT_INFO("Mesh: Mesh Netwok UUID [%s]", network->uuid);
+                       g_strlcpy(network->name.name, network_name,
+                               sizeof(network->name.name));
+                       g_strlcpy(network->app_cred,
+                               requester_unique_creds,
+                               sizeof(network->app_cred));
+                       sender = (char*)g_dbus_method_invocation_get_sender(context);
+                       _bt_save_invocation_context(context,
+                                       result, sender,
+                                       function_name, (gpointer)network);
+               } else {
+                       BT_ERR("Mesh: Mesh Network creation schedule failed");
+                       g_slist_free_full(model_list, g_free);
+               }
+
+               /* Cleanup */
+               BT_INFO("Mesh: Cleanup");
+               g_free((gpointer)requester_unique_creds);
+               g_array_free(param3, TRUE);
+               BT_INFO("Mesh: Cleanup Done");
+               break;
+       }
+       case BT_MESH_NETWORK_SCAN: {
+               bluetooth_mesh_network_t network;
+               bluetooth_mesh_scan_param_t param;
+               memset(&network, 0x00, sizeof(bluetooth_mesh_network_t));
+               memset(&param, 0x00, sizeof(bluetooth_mesh_scan_param_t));
+
+               __bt_service_get_parameters(in_param1,
+                               &network, sizeof(bluetooth_mesh_network_t));
+
+               __bt_service_get_parameters(in_param2,
+                               &param, sizeof(bluetooth_mesh_scan_param_t));
+
+               result = _bt_mesh_network_scan(requester_unique_creds,
+                               sender, &network, &param);
+
+               if (result != BLUETOOTH_ERROR_NONE) {
+                       g_array_append_vals(*out_param1,
+                               &network, sizeof(bluetooth_mesh_network_t));
+               } else {
+                       bluetooth_mesh_network_t *net =  \
+                                       g_memdup(&network, sizeof(bluetooth_mesh_network_t));
+
+                       sender = (char*)g_dbus_method_invocation_get_sender(context);
+                       _bt_save_invocation_context(context, result, sender,
+                                       function_name, (gpointer)net);
+               }
+               break;
+       }
+       case BT_MESH_NETWORK_CANCEL_SCAN: {
+               bluetooth_mesh_network_t network;
+               memset(&network, 0x00, sizeof(bluetooth_mesh_network_t));
+
+               __bt_service_get_parameters(in_param1,
+                               &network, sizeof(bluetooth_mesh_network_t));
+
+               result = _bt_mesh_network_scan_cancel(requester_unique_creds,
+                       sender, &network);
+
+               if (result != BLUETOOTH_ERROR_NONE)
+                       g_array_append_vals(*out_param1,
+                               &network, sizeof(bluetooth_mesh_network_t));
+               break;
+       }
+       case BT_MESH_NETWORK_SET_CAPABILITIES: {
+               bluetooth_mesh_network_t network;
+               bluetooth_mesh_provisioner_caps_t caps;
+               memset(&network, 0x00, sizeof(bluetooth_mesh_network_t));
+               memset(&caps, 0x00, sizeof(bluetooth_mesh_provisioner_caps_t));
+
+               __bt_service_get_parameters(in_param1,
+                               &network, sizeof(bluetooth_mesh_network_t));
+
+               __bt_service_get_parameters(in_param2,
+                               &caps, sizeof(bluetooth_mesh_provisioner_caps_t));
+
+               result = _bt_mesh_network_set_provisioner_caps(
+                               requester_unique_creds, sender, &network, &caps);
+
+               break;
+       }
+       case BT_MESH_NETWORK_PROVISION_DEVICE: {
+               bluetooth_mesh_provisioning_request_t req;
+               memset(&req, 0x00, sizeof(bluetooth_mesh_provisioning_request_t));
+
+               __bt_service_get_parameters(in_param1,
+                               &req, sizeof(bluetooth_mesh_provisioning_request_t));
+
+               result = _bt_mesh_network_provision_device(
+                               requester_unique_creds, sender, &req);
+
+               /* Save invocation */
+               if (result != BLUETOOTH_ERROR_NONE) {
+                       g_array_append_vals(*out_param1, &req,
+                               sizeof(bluetooth_mesh_provisioning_request_t));
+               } else {
+                       bluetooth_mesh_provisioning_request_t *param =  \
+                               g_memdup(&req, sizeof(bluetooth_mesh_provisioning_request_t));
+
+                       sender = (char*)g_dbus_method_invocation_get_sender(context);
+                       _bt_save_invocation_context(context, result, sender,
+                                       function_name, (gpointer)param);
+               }
+               break;
+       }
+       case BT_MESH_AUTHENTICATION_REPLY: {
+               const char *auth_value = NULL;
+               gboolean authentication_reply = FALSE;
+               int auth_type;
+               auth_value = g_variant_get_data(in_param2);
+               __bt_service_get_parameters(in_param3,
+                               &authentication_reply, sizeof(gboolean));
+               __bt_service_get_parameters(in_param1,
+                               &auth_type, sizeof(int));
+               result = _bt_mesh_authentication_reply(auth_type,
+                               auth_value, authentication_reply);
+               break;
+       }
        default:
                BT_INFO("UnSupported function [%d]", function_name);
                result = BLUETOOTH_ERROR_NOT_SUPPORT;
@@ -4167,10 +4342,17 @@ gboolean __bt_service_check_privilege(int function_name,
        case BT_PBAP_PHONEBOOK_SEARCH:
 
        case BT_RFCOMM_LISTEN_AND_ACCEPT:
+       case BT_MESH_NETWORK_CREATE:
+       case BT_MESH_NETWORK_SCAN:
+       case BT_MESH_NETWORK_CANCEL_SCAN:
+       case BT_MESH_NETWORK_SET_CAPABILITIES:
+       case BT_MESH_NETWORK_PROVISION_DEVICE:
+       case BT_MESH_AUTHENTICATION_REPLY:
 
        ret_val = cynara_check(p_cynara, client_creds, client_session, user_creds,
                                                BT_PRIVILEGE_PUBLIC);
 
+       BT_INFO("Client Credentials [%s]", client_creds);
        if (ret_val != CYNARA_API_ACCESS_ALLOWED) {
                BT_ERR("Fail to access: %s", BT_PRIVILEGE_PUBLIC);
                result = FALSE;
@@ -4335,9 +4517,14 @@ gboolean __bt_service_check_privilege(int function_name,
                break;
        }
 
-       if (client_creds)
+       if (client_creds && function_name >= BT_FUNC_MESH_BASE) {
+               BT_INFO("MESH Function called creds [%s]", client_creds);
+               requester_unique_creds = g_strdup(client_creds);
                free(client_creds);
 
+       } else
+               BT_INFO("Non MESH Function called client creds [%s]", client_creds);
+
        if (user_creds)
                free(user_creds);