Mesh: Add HAL implementation
authorAnupam Roy <anupam.r@samsung.com>
Thu, 25 Jun 2020 15:00:54 +0000 (20:30 +0530)
committerAnupam Roy <anupam.r@samsung.com>
Fri, 17 Jul 2020 09:18:52 +0000 (14:48 +0530)
This patch adds following
- Implements the HAL interface for
  Mesh Network & Node configurations.
- Implements HAL DBUS handler interfaces
  for communicating with Mesh daemon

Change-Id: I4bcf3e3e7d18911ed676c09ffa6d3fae421937da
Signed-off-by: Anupam Roy <anupam.r@samsung.com>
bt-oal/bluez_hal/CMakeLists.txt
bt-oal/bluez_hal/src/bt-hal-mesh-dbus-handler.c [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-mesh.c [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-mesh.h [new file with mode: 0644]

index 08fad30..2ac18ae 100644 (file)
@@ -35,6 +35,8 @@ SET(SRCS
 ./src/bt-hal-gatt-client.c
 ./src/bt-hal-hf-client.c
 ./src/bt-hal-hf-client-dbus-handler.c
+./src/bt-hal-mesh.c
+./src/bt-hal-mesh-dbus-handler.c
 )
 
 SET(PREFIX ${CMAKE_INSTALL_PREFIX})
diff --git a/bt-oal/bluez_hal/src/bt-hal-mesh-dbus-handler.c b/bt-oal/bluez_hal/src/bt-hal-mesh-dbus-handler.c
new file mode 100644 (file)
index 0000000..db099aa
--- /dev/null
@@ -0,0 +1,2205 @@
+/*
+ * Bluetooth HAL
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+#include <dlog.h>
+#include <vconf.h>
+#include <ell/ell.h>
+
+#include "bt-hal-mesh-dbus-handler.h"
+#include "bt-hal-dbus-common-utils.h"
+#include "bt-hal-internal.h"
+
+#include <hardware/bt_mesh.h>
+
+#define BT_HAL_UUID_LEN 16
+#define BT_HAL_BLUEZ_MESH_NAME "org.bluez.mesh"
+
+#define BT_HAL_MESH_NETWORK_INTERFACE "org.bluez.mesh.Network1"
+#define BT_HAL_MESH_NODE_INTERFACE "org.bluez.mesh.Node1"
+#define BT_HAL_MESH_MANAGEMENT_INTERFACE "org.bluez.mesh.Management1"
+#define BT_HAL_MESH_ELEMENT_INTERFACE "org.bluez.mesh.Element1"
+#define BT_HAL_MESH_APPLICATION_INTERFACE "org.bluez.mesh.Application1"
+#define BT_HAL_MESH_PROVISION_AGENT_INTERFACE "org.bluez.mesh.ProvisionAgent1"
+#define BT_HAL_MESH_PROVISIONER_INTERFACE "org.bluez.mesh.Provisioner1"
+#define BT_HAL_MESH_ERROR_INTERFACE "org.bluez.mesh.Error"
+
+#define BT_HAL_MESH_MAX_DEVKEY_BUF_SIZE 2048
+
+static const char *dbus_err_args = "org.freedesktop.DBus.Error.InvalidArgs";
+static const char *dbus_err_fail = "org.freedesktop.DBus.Error.Failed";
+
+static struct l_dbus *dbus = NULL;
+static struct l_dbus_client *client = NULL;
+
+static struct l_dbus_proxy *net_proxy;
+static struct l_dbus_message *agent_msg;
+
+static handle_stack_msg mesh_event_cb = NULL;
+
+
+struct subnet_key_request {
+       uint16_t idx;
+       const char *str;
+};
+
+struct app_key_request {
+       uint16_t net_idx;
+       uint16_t app_idx;
+       const char *str;
+};
+
+struct configuration_request {
+       const char *ele_path;
+       bool rmt;
+       bool is_dev_key;
+       uint16_t dst;
+       uint16_t idx;
+       uint8_t *data;
+       uint16_t len;
+};
+
+struct key_config_request {
+       const char *ele_path;
+       uint16_t dst;
+       uint16_t key_req_idx;
+       uint16_t idx;
+       bool update_req;
+};
+
+struct mesh_provision_auth_action {
+       const char *action;
+       bt_hal_mesh_auth_variant_e auth_type;
+};
+
+static struct mesh_provision_auth_action auth_table[] = {
+       { "blink", BT_HAL_MESH_AUTH_REQ_BLINK_COUNT_INPUT},
+       { "beep", BT_HAL_MESH_AUTH_REQ_BEEP_COUNT_INPUT},
+       { "vibrate", BT_HAL_MESH_AUTH_REQ_VIBRATE_COUNT_INPUT},
+       { "in-numeric", BT_HAL_MESH_AUTH_REQ_NUMERIC_INPUT},
+       { "in-alpha", BT_HAL_MESH_AUTH_REQ_ALPHANUMERIC_INPUT},
+       { "twist", BT_HAL_MESH_AUTH_TWIST_COUNT_DISPLAY},
+       { "push", BT_HAL_MESH_AUTH_PUSH_COUNT_DISPLAY},
+       { "out-numeric", BT_HAL_MESH_AUTH_NUMERIC_DISPLAY},
+       { "out-alpha", BT_HAL_MESH_AUTH_ALPHANUMERIC_DISPLAY},
+       { "static-oob", BT_HAL_MESH_AUTH_REQ_OOB_STATIC_KEY_INPUT},
+};
+
+
+static uint8_t __bt_mesh_util_get_prov_error_code(char *prov_err_str)
+{
+       uint8_t ret = 0;
+
+       if (!g_strcmp0(prov_err_str, "success"))
+               ret = BT_HAL_MESH_PROV_ERR_SUCCESS;
+       else if (!g_strcmp0(prov_err_str, "bad-pduread"))
+               ret = BT_HAL_MESH_PROV_ERR_INVALID_PDU;
+       else if (!g_strcmp0(prov_err_str, "confirmation-failed"))
+               ret = BT_HAL_MESH_PROV_ERR_CONFIRM_FAILED;
+       else if (!g_strcmp0(prov_err_str, "out-of-resources"))
+               ret = BT_HAL_MESH_PROV_ERR_INSUF_RESOURCE;
+       else if (!g_strcmp0(prov_err_str, "decryption-error"))
+               ret = BT_HAL_MESH_PROV_ERR_DECRYPT_FAILED;
+       else if (!g_strcmp0(prov_err_str, "cannot-assign-addresses"))
+               ret = BT_HAL_MESH_PROV_ERR_CANT_ASSIGN_ADDR;
+       else if (!g_strcmp0(prov_err_str, "timeout"))
+               ret = BT_HAL_MESH_PROV_ERR_TIMEOUT;
+       else if (!g_strcmp0(prov_err_str, "unexpected-error"))
+               ret = BT_HAL_MESH_PROV_ERR_UNEXPECTED_ERR;
+
+       return ret;
+}
+
+static bt_hal_mesh_auth_variant_e  __mesh_get_authentication_type(char *str)
+{
+       int len = strlen(str);
+       int sz = L_ARRAY_SIZE(auth_table);
+       int i;
+
+       for (i = 0; i < sz; ++i)
+               if (len == strlen(auth_table[i].action) &&
+                               !strcmp(str, auth_table[i].action))
+                       break;
+
+       return auth_table[i].auth_type;
+}
+
+enum mesh_dbus_interface_e {
+       MESH_APP_IFACE,
+       MESH_PROV_IFACE,
+       MESH_AGENT_IFACE,
+       MESH_ELEMENT_IFACE,
+};
+
+typedef enum mesh_dbus_interface_e mesh_dbus_interface_e;
+
+struct meshcfg_model {
+       uint16_t elem_index;
+       uint32_t model;
+};
+
+typedef struct meshcfg_model meshcfg_model;
+
+struct meshcfg_el {
+       char *path;
+       uint16_t index;
+       GSList *models;
+};
+
+typedef struct meshcfg_el meshcfg_el;
+
+struct meshcfg_app {
+       /* Remember Proxies & dbus paths */
+       char *path;
+       char *agent_path;
+       struct l_dbus_proxy *proxy;
+       struct l_dbus_proxy *mgmt_proxy;
+
+       /* Local node Info */
+       GSList *elements;
+       uint16_t cid;
+       uint16_t pid;
+       uint16_t vid;
+       uint16_t crpl;
+       uint8_t uuid[16];
+       union {
+               uint64_t u64;
+               uint8_t u8[8];
+       } token;
+       bool is_prov;
+       /* Caps */
+       bool static_oob;
+       bool public_oob;
+       uint16_t out_oob;
+       uint16_t in_oob;
+       struct l_dbus_message *msg;
+       guint scan_timer_id;
+};
+
+typedef struct meshcfg_app meshcfg_app;
+
+/* Will contain critical data related to local Mesh Network */
+GSList *mesh_apps;
+
+
+struct meshcfg_node {
+       const char *path;
+       struct l_dbus_proxy *proxy;
+       struct l_dbus_proxy *mgmt_proxy;
+       union {
+               uint64_t u64;
+               uint8_t u8[8];
+       } token;
+};
+
+typedef struct meshcfg_node meshcfg_node;
+
+static void __mesh_append_byte_array(struct l_dbus_message_builder *builder,
+               unsigned char *data, unsigned int len)
+{
+       unsigned int i;
+
+       l_dbus_message_builder_enter_array(builder, "y");
+
+       for (i = 0; i < len; i++)
+               l_dbus_message_builder_append_basic(builder, 'y', &(data[i]));
+
+       l_dbus_message_builder_leave_array(builder);
+}
+
+static gint __mesh_compare_network_uuid(gconstpointer data, gconstpointer user_data)
+{
+       const meshcfg_app *app = (meshcfg_app*) data;
+       uint8_t uuid[16];
+       memcpy(uuid, (uint8_t*) user_data, 16);
+
+       return memcmp(uuid, app->uuid, sizeof(bt_uuid_t));
+}
+
+static unsigned char* __mesh_get_net_uuid_from_dbus_proxy_path(
+               const char *dbus_path)
+{
+       char uuid[33];
+       size_t sz;
+
+       memcpy(uuid, (void*)&dbus_path[20], sizeof(uuid));
+       uuid[32] = '\0';
+       INFO("Mesh: Net UUID string [%s]", uuid);
+       return l_util_from_hexstring(uuid, &sz);
+}
+
+static unsigned char* __mesh_get_net_uuid_from_path(
+               const char *dbus_path, bool is_prov,
+                       mesh_dbus_interface_e iface)
+{
+       char uuid[33];
+       size_t sz;
+
+       switch(iface) {
+       case MESH_APP_IFACE:
+       case MESH_PROV_IFACE:  {
+               memcpy(uuid, is_prov ? (void*) &dbus_path[16] : (void*) &dbus_path[17], 32);
+               uuid[32] = '\0';
+               return l_util_from_hexstring(uuid, &sz);
+       }
+       case MESH_AGENT_IFACE: {
+               memcpy(uuid, is_prov ? (void*) &dbus_path[22] : (void*) &dbus_path[23], 32);
+               uuid[32] = '\0';
+               return l_util_from_hexstring(uuid, &sz);
+       }
+       case MESH_ELEMENT_IFACE: {
+               memcpy(uuid, is_prov ? (void*) &dbus_path[16] : (void*) &dbus_path[17], 32);
+               uuid[32] = '\0';
+               return l_util_from_hexstring(uuid, &sz);
+       }
+       default:
+               return NULL;
+       }
+}
+
+static void __mesh_hal_free_elements(gpointer data)
+{
+       meshcfg_el *element = (meshcfg_el*) data;
+       g_free(element->path);
+       if (element->models)
+               g_slist_free_full(element->models, g_free);
+       g_free(element);
+}
+
+static void __bt_hal_mesh_destroy_app_object(gpointer data)
+{
+
+       meshcfg_app *app = (meshcfg_app*) data;
+       if (!app)
+               return;
+
+       mesh_apps = g_slist_remove(mesh_apps, app);
+       g_free(app->path);
+       g_free(app->agent_path);
+
+       if (app->elements)
+               g_slist_free_full(app->elements, __mesh_hal_free_elements);
+       g_free(app);
+}
+
+static void __mesh_client_connected(struct l_dbus *dbus, void *user_data)
+{
+       ERR("MESH: D-Bus client connected\n");
+}
+
+static void __mesh_client_disconnected(struct l_dbus *dbus, void *user_data)
+{
+       ERR("MESH: D-Bus client disconnected, possibly meshd exited \n");
+       /* TODO: Send event to app about meshd termination  & then remove all mesh apps */
+       if (mesh_apps) {
+               g_slist_free_full(mesh_apps, __bt_hal_mesh_destroy_app_object);
+               mesh_apps = NULL;
+       }
+}
+
+static gint __compare_proxy_path(gconstpointer data, gconstpointer user_data)
+{
+       int ret = 0;
+       char *app_uuid_path;
+       const meshcfg_app *app = (meshcfg_app*) data;
+       char *path = (char *) user_data;
+       INFO("Mesh: proxy path compare: path [%s]", path);
+       INFO("Mesh: App Path  path [%s]", app->path);
+       if (!path)
+               return -1;
+
+       app_uuid_path = l_util_hexstring(app->uuid, 16);
+       INFO("Mesh:App UUID string [%s]", app_uuid_path);
+       char **strings =  g_strsplit(path, "node", 2);
+
+       INFO("Mesh:String 0 [%s]", strings[0]);
+       INFO("Mesh:String 1 [%s]", strings[1]);
+       ret = g_strcmp0(strings[1], app_uuid_path);
+       g_free(strings[0]);
+       g_free(strings[1]);
+       l_free(app_uuid_path);
+       return ret;
+}
+
+static gint __compare_element_index(gconstpointer data, gconstpointer user_data)
+{
+       const meshcfg_el *elem = data;
+       uint16_t elem_index = GPOINTER_TO_UINT(user_data);
+       if (!elem)
+               return 1;
+
+       return (elem->index == elem_index ? 0: -1);
+}
+
+static void __mesh_proxy_added(struct l_dbus_proxy *proxy, void *user_data)
+{
+       const char *interface = l_dbus_proxy_get_interface(proxy);
+       const char *path = l_dbus_proxy_get_path(proxy);
+
+       INFO("MESH: Proxy added: %s (%s)\n", interface, path);
+
+       if (!strcmp(interface, BT_HAL_MESH_NETWORK_INTERFACE)) {
+
+               /* Save Global proxy */
+               net_proxy = proxy;
+               return;
+       }
+
+       if (!strcmp(interface, BT_HAL_MESH_MANAGEMENT_INTERFACE)) {
+               GSList *l;
+               meshcfg_app *app;
+               INFO("Mesh: Number of mesh app present in list [%d]",
+                       g_slist_length(mesh_apps));
+               l = g_slist_find_custom(mesh_apps, path, __compare_proxy_path);
+               if (l) {
+                       app = l->data;
+                       app->mgmt_proxy = proxy;
+               } else {
+                       ERR("Mesh: app not found for Mgmt proxy");
+               }
+               return;
+       }
+
+       if (!strcmp(interface, BT_HAL_MESH_NODE_INTERFACE)) {
+
+               GSList *l;
+               meshcfg_app *app;
+               l = g_slist_find_custom(mesh_apps, path, __compare_proxy_path);
+               if (l) {
+                       app = l->data;
+                       app->mgmt_proxy = proxy;
+               } else {
+                       ERR("Mesh: app not found for Node proxy");
+               }
+               return;
+       }
+}
+
+static void __mesh_proxy_removed(struct l_dbus_proxy *proxy, void *user_data)
+{
+       const char *interface = l_dbus_proxy_get_interface(proxy);
+       const char *path = l_dbus_proxy_get_path(proxy);
+
+       INFO("Proxy removed: %s (%s)\n", interface, path);
+
+       if (!strcmp(interface, BT_HAL_MESH_NETWORK_INTERFACE)) {
+               INFO("Mesh: Network Interface removed,, possibly meshd terminated.\n");
+               /*TODO: Send event to app about stop of Mesh service  & then remove all apps */
+               if (mesh_apps) {
+                       g_slist_free_full(mesh_apps, __bt_hal_mesh_destroy_app_object);
+                       mesh_apps = NULL;
+                       return;
+               }
+       } else if (!strcmp(interface, BT_HAL_MESH_NODE_INTERFACE)) {
+               INFO("Mesh: Node Interface removed,, possibly node has left network.\n");
+               GSList *l;
+               meshcfg_app *app;
+               l = g_slist_find_custom(mesh_apps, path, __compare_proxy_path);
+               if (l) {
+                       app = l->data;
+                       /*TODO: Send event to app about removal of a mesh local node */
+                       __bt_hal_mesh_destroy_app_object(app);
+               } else {
+                       ERR("Mesh: app not found for Mgmt proxy");
+               }
+               return;
+       } else if (!strcmp(interface, BT_HAL_MESH_MANAGEMENT_INTERFACE)) {
+               INFO("Mesh: Managament Interface removed,, possibly node has left network.\n");
+               GSList *l;
+               meshcfg_app *app;
+               l = g_slist_find_custom(mesh_apps, path, __compare_proxy_path);
+               if (l) {
+                       app = l->data;
+                       /*TODO: Send event to app about removal of
+                       a mesh local node: first send event, then destroy mesh object */
+                       __bt_hal_mesh_destroy_app_object(app);
+               } else {
+                       ERR("Mesh: app not found for Mgmt proxy");
+               }
+               return;
+       }
+}
+
+static void __mesh_dbus_client_ready(struct l_dbus_client *client,
+               void *user_data)
+{
+       INFO("Mesh: D-Bus client ready: bluetooth-meshd connected \n");
+       /* TODO: Book keeping */
+}
+
+static void __mesh_ready_callback(void *user_data)
+{
+       INFO("Mesh: Connected to D-Bus\n");
+       if (!l_dbus_object_manager_enable(dbus, "/"))
+               ERR("Mesh: Failed to register the ObjectManager\n");
+}
+
+bool _bt_hal_mesh_stack_init(void)
+{
+       INFO("Mesh: Connect with meshd");
+       /* Connect with meshd */
+       dbus = l_dbus_new_default(L_DBUS_SYSTEM_BUS);
+       if (!dbus)
+               return false;
+
+       if (!l_dbus_set_ready_handler(dbus, __mesh_ready_callback, NULL, NULL))
+               return false;
+
+       client = l_dbus_client_new(dbus,
+                       BT_HAL_BLUEZ_MESH_NAME, "/org/bluez/mesh");
+       if (!client)
+               return false;
+
+       if (!l_dbus_client_set_connect_handler(client,
+                               __mesh_client_connected, NULL, NULL))
+               return false;
+
+       if (!l_dbus_client_set_disconnect_handler(client,
+                               __mesh_client_disconnected, NULL,
+                               NULL))
+               return false;
+       if (!l_dbus_client_set_proxy_handlers(client,
+                               __mesh_proxy_added, __mesh_proxy_removed,
+                               NULL, NULL, NULL))
+               return false;
+       if (!l_dbus_client_set_ready_handler(client,
+                               __mesh_dbus_client_ready, NULL, NULL))
+               return false;
+
+       INFO("Mesh: Stack Init watchers registered with  meshd");
+       return true;
+}
+
+/* To send stack event to hal-mesh handler */
+void _bt_hal_mesh_register_dbus_handler_cb(handle_stack_msg cb)
+{
+       mesh_event_cb = cb;
+}
+
+/* To send stack event to hal-mesh handler */
+void _bt_hal_mesh_unregister_dbus_handler_cb()
+{
+       mesh_event_cb = NULL;
+}
+
+static bool __mesh_get_companyid(struct l_dbus *dbus,
+               struct l_dbus_message *message,
+                       struct l_dbus_message_builder *builder,
+                               void *user_data)
+{
+       meshcfg_app *app = (meshcfg_app*) user_data;
+       if (!app)
+               return false;
+
+       l_dbus_message_builder_append_basic(builder, 'q', &app->cid);
+
+       return true;
+}
+
+static bool __mesh_get_productid(struct l_dbus *dbus,
+               struct l_dbus_message *message,
+                       struct l_dbus_message_builder *builder,
+                               void *user_data)
+{
+       meshcfg_app *app = (meshcfg_app*) user_data;
+       if (!app)
+               return false;
+       l_dbus_message_builder_append_basic(builder, 'q', &app->pid);
+
+       return true;
+}
+
+static bool __mesh_get_versionid(struct l_dbus *dbus,
+               struct l_dbus_message *message,
+                       struct l_dbus_message_builder *builder,
+                               void *user_data)
+{
+       meshcfg_app *app = (meshcfg_app*) user_data;
+       if (!app)
+               return false;
+       l_dbus_message_builder_append_basic(builder, 'q', &app->vid);
+
+       return true;
+}
+
+static bool __mesh_get_crpl(struct l_dbus *dbus,
+               struct l_dbus_message *message,
+                       struct l_dbus_message_builder *builder,
+                               void *user_data)
+{
+       meshcfg_app *app = (meshcfg_app*) user_data;
+       if (!app)
+               return false;
+       l_dbus_message_builder_append_basic(builder, 'q', &app->crpl);
+
+       return true;
+}
+
+static void __send_network_attach_event(void *param, uint8_t status)
+{
+       struct hal_ev_mesh_network_attached ev;
+       meshcfg_app *app = (meshcfg_app*)param;
+
+       memset(&ev, 0, sizeof(ev));
+       memcpy(ev.uuid, app->uuid, sizeof(app->uuid));
+       memcpy(ev.token, app->token.u8, 8);
+
+       ev.status = status;
+       if (mesh_event_cb)
+               mesh_event_cb(HAL_EV_MESH_NETWORK_ATTACHED,
+                       (void*)&ev, sizeof(ev));
+}
+
+static void __bt_hal_mesh_attach_node_reply(struct l_dbus_proxy *proxy,
+               struct l_dbus_message *msg, void *user_data)
+{
+       struct l_dbus_message_iter iter_cfg;
+       meshcfg_app *app = (meshcfg_app*) user_data;
+       INFO("Mesh: Attach Node Reply: App path [%s] Agent Path [%s]",
+               app->path, app->agent_path);
+
+       if (l_dbus_message_is_error(msg)) {
+               const char *name;
+               l_dbus_message_get_error(msg, &name, NULL);
+               ERR("Mesh: Failed to attach node: %s", name);
+               goto failed;
+
+       }
+
+       if (!l_dbus_message_get_arguments(msg, "oa(ya(qa{sv}))",
+                               &app->path, &iter_cfg))
+               goto failed;
+
+       INFO("Mesh: Attached with path %s\n", app->path);
+       __send_network_attach_event(app, BT_STATUS_SUCCESS);
+       return;
+failed:
+       __send_network_attach_event(app, BT_STATUS_FAIL);
+       /* Destroy mesh app object */
+       __bt_hal_mesh_destroy_app_object(app);
+}
+
+static void __bt_hal_mesh_attach_node_setup(struct l_dbus_message *msg,
+               void *user_data)
+{
+       meshcfg_app *app = (meshcfg_app*) user_data;
+
+       l_dbus_message_set_arguments(msg, "ot", app->path,
+                       l_get_be64(app->token.u8));
+}
+
+
+static void __bt_hal_mesh_attach_node(void *user_data)
+{
+       if (!l_dbus_proxy_method_call(net_proxy, "Attach",
+                               __bt_hal_mesh_attach_node_setup,
+                               __bt_hal_mesh_attach_node_reply,
+                               user_data,
+                               NULL)) {
+               ERR("Mesh: Node attach failed!!");
+               /* Node could not be attached */
+               __send_network_attach_event(user_data, BT_STATUS_FAIL);
+               /* Destroy mesh app object */
+               __bt_hal_mesh_destroy_app_object((meshcfg_app*)user_data);
+       }
+}
+
+static struct l_dbus_message *__mesh_node_join_complete(struct l_dbus *dbus,
+               struct l_dbus_message *message,
+                       void *user_data)
+{
+       char *str;
+       uint64_t tmp;
+
+       meshcfg_app *app = (meshcfg_app*) user_data;
+       INFO("Mesh: Join Complete");
+
+       /* Return error */
+       if (!l_dbus_message_get_arguments(message, "t", &tmp)) {
+
+               /* Send Network creation fail event */
+               __send_network_attach_event(app, BT_STATUS_FAIL);
+
+               /* Destroy mesh app object */
+               __bt_hal_mesh_destroy_app_object(app);
+
+               return l_dbus_message_new_error(message, dbus_err_args, NULL);
+       }
+
+       /* Save token */
+       app->token.u64 = l_get_be64(&tmp);
+       str = l_util_hexstring(&app->token.u8[0], 8);
+       INFO("Mesh: Created new node with token %s\n", str);
+       l_free(str);
+
+       /* Athenticate the node */
+       l_idle_oneshot(__bt_hal_mesh_attach_node, app, NULL);
+       return l_dbus_message_new_method_return(message);
+}
+
+static void __bt_hal_mesh_foreach_model_getter(gpointer data,
+               gpointer user_data)
+{
+       struct l_dbus_message_builder *builder = (struct l_dbus_message_builder *) user_data;
+       meshcfg_model *model_info = (meshcfg_model*) data;
+
+       l_dbus_message_builder_append_basic(builder, 'q', &model_info->model);
+}
+
+static bool __mesh_model_getter(struct l_dbus *dbus,
+               struct l_dbus_message *message,
+                       struct l_dbus_message_builder *builder,
+                               void *user_data)
+{
+       meshcfg_el *element = (meshcfg_el*) user_data;
+
+       l_dbus_message_builder_enter_array(builder, "q");
+       g_slist_foreach(element->models,
+               __bt_hal_mesh_foreach_model_getter, builder);
+
+       l_dbus_message_builder_leave_array(builder);
+
+       return true;
+}
+
+/*TODO: Vendor Model handling is currently not Handled */
+static bool __mesh_vendor_model_getter(struct l_dbus *dbus,
+               struct l_dbus_message *message,
+                       struct l_dbus_message_builder *builder,
+                               void *user_data)
+{
+       l_dbus_message_builder_enter_array(builder, "(qq)");
+       l_dbus_message_builder_leave_array(builder);
+
+       return true;
+}
+
+static bool __mesh_element_index_getter(struct l_dbus *dbus,
+               struct l_dbus_message *message,
+                       struct l_dbus_message_builder *builder,
+                               void *user_data)
+{
+       meshcfg_el *element = (meshcfg_el*) user_data;
+       l_dbus_message_builder_append_basic(builder, 'y', &element->index);
+
+       return true;
+}
+
+
+static struct l_dbus_message *__mesh_device_message_received(struct l_dbus *dbus,
+               struct l_dbus_message *msg, void *user_data)
+{
+       struct l_dbus_message_iter iter;
+       uint16_t src, idx;
+       uint8_t *data;
+       uint32_t n;
+       bool rmt;
+       const char *dbus_path;
+       uint16_t size;
+       uint8_t *net_uuid;
+       dbus_path =  l_dbus_message_get_path(msg);
+       net_uuid = __mesh_get_net_uuid_from_path(dbus_path, true,  MESH_ELEMENT_IFACE);
+       uint8_t buf[BT_HAL_MESH_MAX_DEVKEY_BUF_SIZE];
+       struct hal_ev_mesh_devkey_message_event *ev = (void *)buf;
+
+       INFO("Mesh: app path [%s]", dbus_path);
+
+       memset(buf, 0, sizeof(buf));
+       size = (uint16_t) sizeof(*ev);
+       memcpy(ev->net_uuid, net_uuid, 16);
+       g_free(net_uuid);
+
+       if (!l_dbus_message_get_arguments(msg, "qbqay", &src, &rmt, &idx,
+                               &iter)) {
+               ERR("Mesh: Cannot parse received message");
+               return l_dbus_message_new_error(msg, dbus_err_args, NULL);
+       }
+
+       if (!l_dbus_message_iter_get_fixed_array(&iter, &data, &n)) {
+               ERR("Mesh: Cannot parse received message: data");
+               return l_dbus_message_new_error(msg, dbus_err_args, NULL);
+       }
+
+       INFO("Mesh: Received dev key message (len %u):", n);
+       ev->source_addr = src;
+       ev->is_remote_devkey = rmt;
+       ev->netkey_idx = idx;
+       ev->data_len = n;
+       memcpy(ev->data, buf, n);
+       size += n;
+
+       /* Send DevKeyMessage Received event */
+       if (mesh_event_cb) {
+               mesh_event_cb(HAL_EV_MESH_DEVKEY_MESSAGE_EVENT, (void*)buf, size);
+       }
+       return l_dbus_message_new_method_return(msg);
+}
+
+static void __bt_hal_mesh_setup_ele_iface(struct l_dbus_interface *iface)
+{
+       INFO("Mesh: Setup element interface properties & methods");
+       /* Properties */
+       l_dbus_interface_property(iface, "Index", 0, "y", __mesh_element_index_getter,
+                       NULL);
+       l_dbus_interface_property(iface, "VendorModels", 0, "a(qq)",
+                       __mesh_vendor_model_getter, NULL);
+       l_dbus_interface_property(iface, "Models", 0, "aq", __mesh_model_getter, NULL);
+
+       /* Methods */
+       l_dbus_interface_method(iface, "DevKeyMessageReceived", 0,
+                       __mesh_device_message_received, "", "qbqay", "source",
+                       "remote", "net_index", "data");
+       /* TODO: Other methods */
+}
+
+static struct l_dbus_message *__mesh_scan_result_received(struct l_dbus *dbus,
+               struct l_dbus_message *msg,
+                       void *user_data)
+{
+       struct l_dbus_message_iter iter, opts;
+       meshcfg_app *app = (meshcfg_app*) user_data;
+       int16_t rssi;
+       uint32_t n;
+       uint8_t *prov_data;
+       char *str;
+       const char *sig = "naya{sv}";
+
+       /* Find network uuid from dbus path */
+       struct hal_ev_mesh_scan_result ev;
+
+       if (!app->scan_timer_id) {
+               /* Scan is not running */
+               INFO("Got scan result, but scan is already stopped");
+               return l_dbus_message_new_method_return(msg);
+       }
+       memset(&ev, 0, sizeof(ev));
+       memcpy(ev.net_uuid, app->uuid, 16);
+
+       if (!l_dbus_message_get_arguments(msg, sig, &rssi, &iter, &opts)) {
+               ERR("Mesh: Cannot parse scan results");
+               ev.status = BT_STATUS_FAIL;
+               if (mesh_event_cb) {
+                       mesh_event_cb(HAL_EV_MESH_SCAN_RESULT, (void*)&ev, sizeof(ev));
+               }
+               return l_dbus_message_new_error(msg, dbus_err_args, NULL);
+       }
+
+       if (!l_dbus_message_iter_get_fixed_array(&iter, &prov_data, &n) ||
+                       n < 16) {
+               ERR("Mesh: Cannot parse scan result: data");
+               ev.status = BT_STATUS_FAIL;
+               if (mesh_event_cb) {
+                       mesh_event_cb(HAL_EV_MESH_SCAN_RESULT, (void*)&ev, sizeof(ev));
+               }
+               return l_dbus_message_new_error(msg, dbus_err_args, NULL);
+       }
+
+       INFO("Mesh: Scan result:\n");
+       INFO("Mesh: Scan rssi = [%d]\n", rssi);
+       str = l_util_hexstring_upper(prov_data, 16);
+       INFO("Mesh: Scan UUID = [%s]\n",  str);
+       l_free(str);
+
+       if (n >= 18) {
+               str = l_util_hexstring_upper(prov_data + 16, 2);
+               INFO("Mesh: Scan OOB = [%s]\n", str);
+               l_free(str);
+       }
+
+       if (n >= 22) {
+               str = l_util_hexstring_upper(prov_data + 18, 4);
+               INFO("Mesh: Scan URI hash = [%s]\n", str);
+               l_free(str);
+       }
+
+       /* 16 octet Dev UUID */
+       memcpy(ev.dev_uuid, prov_data, 16);
+
+       /* 2 octet Dev OOB Info */
+       memcpy(ev.oob_info, prov_data + 16, 2);
+
+       /* 4 octet URI Hash */
+       memcpy(ev.uri_hash, prov_data + 18, 4);
+
+       ev.rssi = rssi;
+
+       ev.status = BT_STATUS_SUCCESS;
+       if (mesh_event_cb)
+               mesh_event_cb(HAL_EV_MESH_SCAN_RESULT,
+                       (void*)&ev, sizeof(ev));
+
+       return l_dbus_message_new_method_return(msg);
+}
+
+static struct l_dbus_message *__mesh_request_provisioner_call(
+               struct l_dbus *dbus,
+                       struct l_dbus_message *msg,
+                               void *user_data)
+{
+       uint8_t cnt;
+       struct hal_ev_mesh_provision_finished ev;
+       struct hal_ev_mesh_provision_data_request req;
+       meshcfg_app *app = user_data;
+
+       memset(&ev, 0, sizeof(ev));
+       memset(&req, 0, sizeof(req));
+       memcpy(ev.net_uuid, app->uuid, 16);
+       memcpy(req.net_uuid, app->uuid, 16);
+
+       if (!l_dbus_message_get_arguments(msg, "y", &cnt)) {
+               ERR("Mesh: Cannot parse request for prov data");
+               /* Send Event */
+               ev.status = BT_STATUS_FAIL;
+               ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
+               if (mesh_event_cb)
+                       mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
+                               (void*)&ev, sizeof(ev));
+               return l_dbus_message_new_error(msg, dbus_err_args, NULL);
+       }
+
+       app->msg = msg;
+       req.count = cnt;
+       if (mesh_event_cb)
+               mesh_event_cb(HAL_EV_MESH_PROVISIONING_DATA_REQUEST,
+                       (void*)&ev, sizeof(ev));
+
+       l_dbus_message_ref(msg);
+       return NULL;
+}
+
+static struct l_dbus_message *__mesh_node_add_completed(
+               struct l_dbus *dbus,
+                       struct l_dbus_message *msg,
+                               void *user_data)
+{
+       struct l_dbus_message_iter iter;
+       int16_t unicast;
+       uint8_t cnt;
+       uint32_t n;
+       uint8_t *uuid;
+       struct hal_ev_mesh_provision_finished ev;
+       const char *dbus_path;
+       uint8_t *net_uuid;
+       dbus_path =  l_dbus_message_get_path(msg);
+       net_uuid = __mesh_get_net_uuid_from_path(dbus_path,
+                       true,  MESH_PROV_IFACE);
+
+       INFO("Mesh: app path [%s]", dbus_path);
+
+       memset(&ev, 0, sizeof(ev));
+       memcpy(ev.net_uuid, net_uuid, 16);
+
+       g_free(net_uuid);
+
+       if (!l_dbus_message_get_arguments(msg, "ayqy", &iter, &unicast, &cnt)) {
+               ERR("Mesh: Cannot parse add node complete message");
+               /* Send Event */
+               ev.status = BT_STATUS_FAIL;
+               ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
+               if (mesh_event_cb)
+                       mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
+                               (void*)&ev, sizeof(ev));
+               return l_dbus_message_new_error(msg, dbus_err_args, NULL);
+       }
+
+       if (!l_dbus_message_iter_get_fixed_array(&iter, &uuid, &n) ||
+                       n != 16) {
+               ERR("Mesh: Cannot parse add node complete message: uuid");
+               /* Send Event */
+               ev.status = BT_STATUS_FAIL;
+               ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
+               if (mesh_event_cb)
+                       mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
+                               (void*)&ev, sizeof(ev));
+               return l_dbus_message_new_error(msg, dbus_err_args, NULL);
+       }
+
+       /* Send Event */
+       ev.status = BT_STATUS_SUCCESS;
+       ev.reason = BT_HAL_MESH_PROV_ERR_SUCCESS;
+       memcpy(ev.dev_uuid, uuid, 16);
+       ev.unicast = unicast;
+       ev.count = cnt;
+
+       if (mesh_event_cb)
+               mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
+                       (void*)&ev, sizeof(ev));
+
+       return l_dbus_message_new_method_return(msg);
+}
+
+static struct l_dbus_message *__mesh_node_add_failed(
+               struct l_dbus *dbus,
+                       struct l_dbus_message *msg,
+                               void *user_data)
+{
+       struct l_dbus_message_iter iter;
+       uint32_t n;
+       uint8_t *uuid;
+       char *str, *reason;
+       struct hal_ev_mesh_provision_finished ev;
+       const char *dbus_path;
+
+       uint8_t *net_uuid;
+       dbus_path =  l_dbus_message_get_path(msg);
+       net_uuid = __mesh_get_net_uuid_from_path(dbus_path,
+                       true,  MESH_PROV_IFACE);
+
+       memset(&ev, 0, sizeof(ev));
+       memcpy(ev.net_uuid, net_uuid, 16);
+
+       g_free(net_uuid);
+       if (!l_dbus_message_get_arguments(msg, "ays", &iter, &reason)) {
+               ERR("Mesh: Cannot parse add node failed message");
+               /* Send Event */
+               ev.status = BT_STATUS_FAIL;
+               ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
+               if (mesh_event_cb)
+                       mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
+                               (void*)&ev, sizeof(ev));
+               return l_dbus_message_new_error(msg, dbus_err_args, NULL);
+       }
+
+       if (!l_dbus_message_iter_get_fixed_array(&iter, &uuid, &n) ||
+                       n != 16) {
+               ERR("Mesh:Cannot parse add node failed message: uuid");
+               ev.status = BT_STATUS_FAIL;
+               ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
+               if (mesh_event_cb)
+                       mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
+                               (void*)&ev, sizeof(ev));
+               return l_dbus_message_new_error(msg, dbus_err_args, NULL);
+       }
+
+       INFO("Mesh: Provisioning failed:\n");
+       str = l_util_hexstring_upper(uuid, 16);
+       INFO("Mesh: UUID = [%s] Reason [%s]", str, reason);
+       l_free(str);
+
+       ev.status = BT_STATUS_FAIL;
+       ev.reason = __bt_mesh_util_get_prov_error_code(str);
+       memcpy(ev.dev_uuid, uuid, 16);
+
+       if (mesh_event_cb)
+               mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
+                       (void*)&ev, sizeof(ev));
+
+       return l_dbus_message_new_method_return(msg);
+}
+
+static void __bt_hal_mesh_setup_prov_iface(struct l_dbus_interface *interface)
+{
+       INFO("Mesh: Setup provisioner interface properties & methods");
+       l_dbus_interface_method(interface, "ScanResult", 0,
+                       __mesh_scan_result_received, "",
+                       "naya{sv}", "rssi", "data", "options");
+
+       l_dbus_interface_method(interface, "RequestProvData", 0,
+                       __mesh_request_provisioner_call,
+                       "qq", "y", "net_index", "unicast", "count");
+
+       l_dbus_interface_method(interface, "AddNodeComplete", 0,
+                       __mesh_node_add_completed, "", "ayqy",
+                       "uuid", "unicast", "count");
+
+       l_dbus_interface_method(interface, "AddNodeFailed", 0,
+                       __mesh_node_add_failed,
+                       "", "ays", "uuid", "reason");
+}
+
+static void __bt_hal_mesh_setup_app_iface(struct l_dbus_interface *iface)
+{
+       INFO("Mesh: Setup application interface properties & methods");
+
+       l_dbus_interface_property(iface, "CompanyID", 0, "q",
+                       __mesh_get_companyid,
+                       NULL);
+       l_dbus_interface_property(iface, "VersionID", 0, "q",
+                       __mesh_get_versionid,
+                       NULL);
+       l_dbus_interface_property(iface, "ProductID", 0, "q",
+                       __mesh_get_productid,
+                       NULL);
+       l_dbus_interface_property(iface, "CRPL", 0, "q",
+                       __mesh_get_crpl, NULL);
+       l_dbus_interface_method(iface, "JoinComplete", 0,
+                       __mesh_node_join_complete,
+                       "", "t", "token");
+
+       /* TODO: Methods */
+}
+
+static void __mesh_fill_in_capabilities(meshcfg_app *app,
+                struct l_dbus_message_builder *builder)
+{
+       if (app->in_oob & 0x08)
+               l_dbus_message_builder_append_basic(builder, 's', "in-alpha");
+       if (app->in_oob & 0x04)
+               l_dbus_message_builder_append_basic(builder, 's', "in-numeric");
+       if (app->in_oob & 0x02)
+               l_dbus_message_builder_append_basic(builder, 's', "twist");
+       if (app->in_oob & 0x01)
+               l_dbus_message_builder_append_basic(builder, 's', "push");
+}
+
+static void __mesh_fill_out_capabilities(meshcfg_app *app,
+                struct l_dbus_message_builder *builder)
+{
+       if (app->out_oob & 0x10)
+               l_dbus_message_builder_append_basic(builder, 's', "out-alpha");
+       if (app->out_oob & 0x08)
+               l_dbus_message_builder_append_basic(builder, 's', "out-numeric");
+       if (app->out_oob & 0x04)
+               l_dbus_message_builder_append_basic(builder, 's', "vibrate");
+       if (app->out_oob & 0x02)
+               l_dbus_message_builder_append_basic(builder, 's', "beep");
+       if (app->out_oob & 0x01)
+               l_dbus_message_builder_append_basic(builder, 's', "blink");
+}
+
+static bool __mesh_agent_capability_getter(
+               struct l_dbus *dbus,struct l_dbus_message *message,
+                       struct l_dbus_message_builder *builder,
+                               void *user_data)
+{
+       meshcfg_app *app;
+       app = user_data;
+       INFO("Mesh: app path [%s]", app->path);
+       INFO("Mesh: Agent path [%s]", app->agent_path);
+
+       if (!l_dbus_message_builder_enter_array(builder, "s")) {
+               return false;
+       }
+
+       __mesh_fill_out_capabilities(app, builder);
+       __mesh_fill_in_capabilities(app, builder);
+
+       if (app->static_oob)
+               l_dbus_message_builder_append_basic(builder,
+                       's', "static-oob");
+
+
+       l_dbus_message_builder_leave_array(builder);
+       INFO("Mesh: __agent_capability_getter: Success");
+       return true;
+}
+
+static struct l_dbus_message *__mesh_agent_display_string_request(
+               struct l_dbus *dbus,
+                       struct l_dbus_message *msg,
+                               void *user_data)
+{
+       struct hal_ev_mesh_authentication_request ev;
+       char *str;
+       uint8_t *net_uuid;
+       const char *dbus_path;
+       meshcfg_app *app;
+       app = user_data;
+       INFO("Mesh: app path [%s]", app->path);
+       INFO("Mesh: Agent path [%s]", app->agent_path);
+
+       dbus_path =  l_dbus_message_get_path(msg);
+       net_uuid = __mesh_get_net_uuid_from_path(app->agent_path,
+                       true,  MESH_AGENT_IFACE);
+
+       INFO("Mesh: app path [%s]", dbus_path);
+
+       memset(&ev, 0, sizeof(ev));
+       memcpy(ev.net_uuid, net_uuid, 16);
+
+
+       if (!l_dbus_message_get_arguments(msg, "s", &str)) {
+               ERR("Mesh: Cannot parse \"DisplayString\" arguments");
+               struct hal_ev_mesh_provision_finished ev;
+               memset(&ev, 0, sizeof(ev));
+               memcpy(ev.net_uuid, net_uuid, 16);
+               ev.status = BT_STATUS_FAIL;
+               ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
+               if (mesh_event_cb)
+                       mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
+                               (void*)&ev, sizeof(ev));
+
+               g_free(net_uuid);
+
+               return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
+       }
+
+       INFO("Mesh:[OUT] AlphaNumeric Authentication: Value [%s]", str);
+       ev.auth_type = BT_HAL_MESH_AUTH_ALPHANUMERIC_DISPLAY;
+       g_strlcpy(ev.auth_value, str, sizeof(ev.auth_value));
+
+       if (mesh_event_cb)
+               mesh_event_cb(HAL_EV_MESH_AUTHENTICATION_REQUEST,
+                       (void*)&ev, sizeof(ev));
+
+       g_free(net_uuid);
+       return l_dbus_message_new_method_return(msg);
+}
+
+static struct l_dbus_message *__mesh_agent_display_numeric_request(
+               struct l_dbus *dbus,
+                       struct l_dbus_message *msg,
+                               void *user_data)
+{
+       uint32_t n;
+       struct hal_ev_mesh_authentication_request ev;
+       char *str;
+       char *auth_value;
+       uint8_t *net_uuid;
+       const char *dbus_path;
+       meshcfg_app *app;
+       app = user_data;
+       INFO("Mesh: app path [%s]", app->path);
+       INFO("Mesh: Agent path [%s]", app->agent_path);
+
+       dbus_path =  l_dbus_message_get_path(msg);
+       net_uuid = __mesh_get_net_uuid_from_path(app->agent_path,
+                               true,  MESH_AGENT_IFACE);
+
+       INFO("Mesh: app path [%s]", dbus_path);
+
+       memset(&ev, 0, sizeof(ev));
+       memcpy(ev.net_uuid, net_uuid, 16);
+
+
+       if (!l_dbus_message_get_arguments(msg, "su", &str, &n)) {
+               ERR("Mesh: Cannot parse \"DisplayNumeric\" arguments");
+               struct hal_ev_mesh_provision_finished ev;
+               memset(&ev, 0, sizeof(ev));
+               memcpy(ev.net_uuid, net_uuid, 16);
+               ev.status = BT_STATUS_FAIL;
+               ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
+               if (mesh_event_cb) {
+                       mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
+                               (void*)&ev, sizeof(ev));
+               }
+               g_free(net_uuid);
+               return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
+       }
+
+       INFO("Mesh:[OUT] Numeric Authentication type [%s] value [%u]", str, n);
+       auth_value = l_strdup_printf("%u",n);
+       ev.auth_type = __mesh_get_authentication_type(str);
+       g_strlcpy(ev.auth_value, auth_value, sizeof(ev.auth_value));
+
+       if (mesh_event_cb)
+               mesh_event_cb(HAL_EV_MESH_AUTHENTICATION_REQUEST,
+                       (void*)&ev, sizeof(ev));
+
+       g_free(net_uuid);
+
+       return l_dbus_message_new_method_return(msg);
+}
+
+static struct l_dbus_message *__mesh_agent_prompt_numeric_request(
+               struct l_dbus *dbus,
+                       struct l_dbus_message *msg,
+                               void *user_data)
+{
+       struct hal_ev_mesh_authentication_request ev;
+       char *str;
+       uint8_t *net_uuid;
+       const char *dbus_path;
+       GSList *l;
+       meshcfg_app *app;
+
+       dbus_path =  l_dbus_message_get_path(msg);
+       net_uuid = __mesh_get_net_uuid_from_path(dbus_path,
+                       true,  MESH_AGENT_IFACE);
+
+       INFO("Mesh: app path [%s]", dbus_path);
+
+       l = g_slist_find_custom(mesh_apps, net_uuid,
+                       __mesh_compare_network_uuid);
+       app = l->data;
+
+       memset(&ev, 0, sizeof(ev));
+       memcpy(ev.net_uuid, net_uuid, 16);
+
+       g_free(net_uuid);
+       if (!l_dbus_message_get_arguments(msg, "s", &str)) {
+               ERR("Mesh: Cannot parse \"PromptNumeric\" arguments");
+
+               struct hal_ev_mesh_provision_finished ev;
+               memset(&ev, 0, sizeof(ev));
+               memcpy(ev.net_uuid, app->uuid, 16);
+               ev.status = BT_STATUS_FAIL;
+               ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
+               if (mesh_event_cb) {
+                       mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
+                               (void*)&ev, sizeof(ev));
+               }
+               return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
+       }
+
+       INFO("Mesh:[IN] Numeric Authentication type [%s]", str);
+
+       ev.auth_type = __mesh_get_authentication_type(str);
+       agent_msg = msg;
+       l_dbus_message_ref(msg);
+       if (mesh_event_cb)
+               mesh_event_cb(HAL_EV_MESH_AUTHENTICATION_REQUEST,
+                       (void*)&ev, sizeof(ev));
+
+       return NULL;
+}
+
+static struct l_dbus_message *__mesh_agent_prompt_static_request(
+               struct l_dbus *dbus,
+                       struct l_dbus_message *msg,
+                               void *user_data)
+{
+       struct hal_ev_mesh_authentication_request ev;
+       char *str;
+       uint8_t *net_uuid;
+       const char *dbus_path;
+       GSList *l;
+       meshcfg_app *app;
+
+       dbus_path =  l_dbus_message_get_path(msg);
+       net_uuid = __mesh_get_net_uuid_from_path(dbus_path, true,
+                       MESH_AGENT_IFACE);
+
+       INFO("Mesh: app path [%s]", dbus_path);
+
+       l = g_slist_find_custom(mesh_apps, net_uuid,
+                       __mesh_compare_network_uuid);
+       app = l->data;
+
+       memset(&ev, 0, sizeof(ev));
+       memcpy(ev.net_uuid, net_uuid, 16);
+
+       g_free(net_uuid);
+       if (!l_dbus_message_get_arguments(msg, "s", &str)) {
+               ERR("Mesh: Cannot parse \"PromptNumeric\" arguments");
+
+               struct hal_ev_mesh_provision_finished ev;
+               memset(&ev, 0, sizeof(ev));
+               memcpy(ev.net_uuid, app->uuid, 16);
+               ev.status = BT_STATUS_FAIL;
+               ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
+               if (mesh_event_cb)
+                       mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
+                                       (void*)&ev, sizeof(ev));
+               return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
+       }
+
+       INFO("Mesh: [IN] AlphaNumeric Authentication type [%s]", str);
+
+       ev.auth_type = __mesh_get_authentication_type(str);
+       agent_msg = msg;
+       l_dbus_message_ref(msg);
+       if (mesh_event_cb)
+               mesh_event_cb(HAL_EV_MESH_AUTHENTICATION_REQUEST,
+                               (void*)&ev, sizeof(ev));
+
+       return NULL;
+}
+
+static void __bt_hal_mesh_setup_agent_iface(struct l_dbus_interface *interface)
+{
+       INFO("Mesh: Setup Agent interface properties & methods");
+       l_dbus_interface_property(interface, "Capabilities", 0, "as",
+                       __mesh_agent_capability_getter,
+                       NULL);
+       /* TODO: Other properties */
+       l_dbus_interface_method(interface, "DisplayString", 0,
+                       __mesh_agent_display_string_request,
+                       "", "s", "value");
+       l_dbus_interface_method(interface, "DisplayNumeric", 0,
+                       __mesh_agent_display_numeric_request,
+                       "", "su", "type", "number");
+       l_dbus_interface_method(interface, "PromptNumeric", 0,
+                       __mesh_agent_prompt_numeric_request,
+                       "u", "s", "number", "type");
+       l_dbus_interface_method(interface, "PromptStatic", 0,
+                       __mesh_agent_prompt_static_request,
+                       "ay", "s", "data", "type");
+}
+
+static void __bt_hal_mesh_register_element_obj(gpointer data, gpointer user_data)
+{
+       meshcfg_el *elem = (meshcfg_el*) data;
+       INFO("Mesh: Register Element: Index [%d] elem path [%s]",
+               elem->index, elem->path);
+       if (!l_dbus_register_object(dbus, elem->path, NULL, NULL,
+                               BT_HAL_MESH_ELEMENT_INTERFACE, elem, NULL)) {
+               ERR("Mesh: Failed to register object %s", elem->path);
+       }
+}
+
+bool __bt_hal_mesh_register_agent(meshcfg_app *ptr)
+{
+       if (!ptr)
+               return false;
+
+       if (!l_dbus_register_interface(dbus, BT_HAL_MESH_PROVISION_AGENT_INTERFACE,
+                               __bt_hal_mesh_setup_agent_iface, NULL, false)) {
+               ERR("Mesh: Unable to register agent interface");
+               return false;
+       }
+
+       INFO("Mesh: Register Agent path [%s]",  ptr->agent_path);
+       if (!l_dbus_register_object(dbus, ptr->agent_path, NULL, NULL,
+                               BT_HAL_MESH_PROVISION_AGENT_INTERFACE, ptr, NULL)) {
+               ERR("Mesh: Failed to register object %s", ptr->agent_path);
+               return false;
+       }
+
+       if (!l_dbus_object_add_interface(dbus, ptr->agent_path,
+                               L_DBUS_INTERFACE_PROPERTIES, NULL)) {
+               ERR("Mesh: Failed to add interface %s",
+                               L_DBUS_INTERFACE_PROPERTIES);
+               return false;
+       }
+
+       return true;
+}
+
+bool __bt_hal_mesh_register_application(meshcfg_app *ptr)
+{
+
+       if (!ptr)
+               return false;
+
+       if (!l_dbus_register_interface(dbus, BT_HAL_MESH_APPLICATION_INTERFACE,
+                               __bt_hal_mesh_setup_app_iface, NULL, false)) {
+               ERR("Mesh: Failed to register interface %s",
+                               BT_HAL_MESH_APPLICATION_INTERFACE);
+               return false;
+       }
+
+       if (!l_dbus_register_interface(dbus, BT_HAL_MESH_PROVISIONER_INTERFACE,
+                               __bt_hal_mesh_setup_prov_iface, NULL, false)) {
+               ERR("Mesh: Failed to register interface %s",
+                               BT_HAL_MESH_PROVISIONER_INTERFACE);
+               return false;
+       }
+
+       if (!l_dbus_register_object(dbus, ptr->path, NULL, NULL,
+                               BT_HAL_MESH_APPLICATION_INTERFACE, ptr,
+                               BT_HAL_MESH_PROVISIONER_INTERFACE, ptr,
+                               NULL)) {
+               ERR("Mesh: Failed to register object %s", ptr->path);
+               return false;
+       }
+
+       if (!__bt_hal_mesh_register_agent(ptr))
+               return false;
+
+       if (!l_dbus_register_interface(dbus, BT_HAL_MESH_ELEMENT_INTERFACE,
+                               __bt_hal_mesh_setup_ele_iface, NULL, false)) {
+               ERR("Mesh: Failed to register interface %s",
+                               BT_HAL_MESH_ELEMENT_INTERFACE);
+               return false;
+       }
+
+       INFO("Mesh: Number of elements to be registsred [%d]",
+               g_slist_length(ptr->elements));
+
+       g_slist_foreach(ptr->elements, __bt_hal_mesh_register_element_obj, ptr);
+
+       INFO("Mesh: Add Object manager Interface: app path [%s]", ptr->path);
+       if (!l_dbus_object_add_interface(dbus, ptr->path,
+                               L_DBUS_INTERFACE_OBJECT_MANAGER, NULL)) {
+                       ERR("Mesh: Failed to add interface %s",
+                                       L_DBUS_INTERFACE_OBJECT_MANAGER);
+                       return false;
+               }
+       INFO("Mesh: Application Register completed");
+
+       return true;
+}
+
+static void __bt_mesh_hal_create_element_object(gpointer data, gpointer user_data)
+{
+       GSList *l;
+       meshcfg_el *elem;
+       meshcfg_model *model_info = (meshcfg_model*) data;
+       meshcfg_app *app = (meshcfg_app*) user_data;
+
+       l = g_slist_find_custom(app->elements,
+               GUINT_TO_POINTER(model_info->elem_index), __compare_element_index);
+       if (l) {
+               elem = l->data;
+       } else {
+               elem = g_malloc0(sizeof(meshcfg_el));
+               elem->index = model_info->elem_index;
+               elem->path = g_strdup_printf("%s/elem%u",app->path, elem->index);
+               app->elements = g_slist_append(app->elements, elem);
+               INFO("Mesh: Created element index [%d] path [%s]",
+                       elem->index, elem->path);
+       }
+       /* Add Model in the element */
+       elem->models = g_slist_append(elem->models, model_info);
+       INFO("Mesh: total models of the element with index [%d] is [%d]",
+                       elem->index, g_slist_length(elem->models));
+}
+
+meshcfg_app *__bt_hal_mesh_create_app(bt_hal_mesh_node_t *node,
+               GSList *models, bool is_prov)
+{
+       uint8_t uuid[16];
+       meshcfg_app *app = NULL;
+       char *uuid_str = NULL;
+
+       uuid_str = l_util_hexstring(node->uuid.uu, sizeof(uuid));
+
+       app = g_malloc0(sizeof(meshcfg_app));
+       memcpy(app->uuid, node->uuid.uu, sizeof(uuid));
+
+       app->cid = node->vendor_info.companyid;
+       app->pid = node->vendor_info.vendorid;
+       app->vid =  node->vendor_info.versionid;
+       app->crpl = node->vendor_info.crpl;
+
+       if (is_prov) {
+               app->path = g_strdup_printf("/tizen/mesh/cfg/%s", uuid_str);
+               app->agent_path = g_strdup_printf("/tizen/mesh/cfg/agent/%s", uuid_str);
+
+       } else {
+               app->path = g_strdup_printf("/tizen/mesh/node/%s", uuid_str);
+               app->agent_path = g_strdup_printf("/tizen/mesh/node/agent/%s", uuid_str);
+       }
+       g_slist_foreach(models, __bt_mesh_hal_create_element_object, app);
+
+       g_free(uuid_str);
+       app->is_prov = is_prov;
+       INFO("Mesh: app created");
+       return app;
+}
+
+static void __bt_hal_mesh_create_net_reply(
+               struct l_dbus_proxy *proxy,
+                       struct l_dbus_message *msg, void *user_data)
+{
+       meshcfg_app *app;
+       app = (meshcfg_app*) user_data;
+
+       INFO("Mesh: Create Network Reply from Meshd: app path [%s]", app->path);
+       if (l_dbus_message_is_error(msg)) {
+               const char *name;
+
+               l_dbus_message_get_error(msg, &name, NULL);
+               ERR("Mesh: Failed to create network: %s", name);
+
+               /* Send Network creation fail event */
+               __send_network_attach_event(app, BT_STATUS_FAIL);
+
+               /* Destroy mesh app object */
+               __bt_hal_mesh_destroy_app_object(app);
+               return;
+       }
+}
+
+static void __bt_hal_mesh_create_net_setup(struct l_dbus_message *msg,
+               void *user_data)
+{
+       meshcfg_app *app;
+       struct l_dbus_message_builder *builder;
+       app = (meshcfg_app*) user_data;
+
+       builder = l_dbus_message_builder_new(msg);
+
+       INFO("Mesh: Create Network Setup app path [%s]", app->path);
+       l_dbus_message_builder_append_basic(builder, 'o', app->path);
+       __mesh_append_byte_array(builder, app->uuid, 16);
+       l_dbus_message_builder_finalize(builder);
+       l_dbus_message_builder_destroy(builder);
+}
+
+static void __mesh_trigger_scan_finished_event(meshcfg_app *app)
+{
+       struct hal_ev_mesh_scan_state_changed ev;
+
+       memset(&ev, 0, sizeof(ev));
+       memcpy(ev.net_uuid, app->uuid, 16);
+
+       ev.status = BT_STATUS_SUCCESS;
+
+       ev.state = HAL_MESH_SCAN_STATE_STOPPED;
+       if (mesh_event_cb)
+               mesh_event_cb(HAL_EV_MESH_SCAN_STATE_CHANGED,
+                       (void*)&ev, sizeof(ev));
+}
+
+static gboolean __bt_mesh_scan_timer_cb(gpointer user_data)
+{
+       meshcfg_app *app = (meshcfg_app*) user_data;
+       __mesh_trigger_scan_finished_event(app);
+       return false;
+}
+
+void __bt_mesh_enable_scanning_timer(uint8_t *net_uuid, uint16_t secs)
+{
+       GSList *l;
+       meshcfg_app *app;
+       l = g_slist_find_custom(mesh_apps, net_uuid,
+                       __mesh_compare_network_uuid);
+       app = l->data;
+
+       if (app->scan_timer_id > 0) {
+               g_source_remove(app->scan_timer_id);
+               app->scan_timer_id = 0;
+       }
+
+       app->scan_timer_id = g_timeout_add_seconds(secs,
+                       __bt_mesh_scan_timer_cb, app);
+
+       return;
+}
+
+static void __mesh_scan_reply(struct l_dbus_proxy *proxy,
+               struct l_dbus_message *msg, void *user_data)
+{
+       struct hal_ev_mesh_scan_state_changed ev;
+       const char *dbus_path;
+       uint8_t *net_uuid;
+       dbus_path =  l_dbus_proxy_get_path(proxy);
+       INFO("Mesh: DBUS path [%s]", dbus_path);
+       net_uuid = __mesh_get_net_uuid_from_dbus_proxy_path(dbus_path);
+
+       uint16_t secs = (uint16_t) L_PTR_TO_UINT(user_data);
+       INFO("Mesh: Scan duration [%u]", secs);
+
+       memset(&ev, 0, sizeof(ev));
+       memcpy(ev.net_uuid, net_uuid, 16);
+
+       if (l_dbus_message_is_error(msg)) {
+               const char *name;
+               l_dbus_message_get_error(msg, &name, NULL);
+               ERR("Mesh: Failed to start unprovisioned scan: [%s]", name);
+               ev.status = BT_STATUS_FAIL;
+       } else {
+               INFO("Mesh: Unprovisioned scan started\n");
+               ev.status = BT_STATUS_SUCCESS;
+               __bt_mesh_enable_scanning_timer(net_uuid, secs);
+       }
+
+       ev.state = HAL_MESH_SCAN_STATE_STARTED;
+       if (mesh_event_cb)
+               mesh_event_cb(HAL_EV_MESH_SCAN_STATE_CHANGED,
+                       (void*)&ev, sizeof(ev));
+       l_free(net_uuid);
+}
+
+static void append_dict_entry_basic(struct l_dbus_message_builder *builder,
+               const char *key, const char *signature,
+               const void *data)
+{
+       if (!builder)
+               return;
+
+       l_dbus_message_builder_enter_dict(builder, "sv");
+       l_dbus_message_builder_append_basic(builder, 's', key);
+       l_dbus_message_builder_enter_variant(builder, signature);
+       l_dbus_message_builder_append_basic(builder, signature[0], data);
+       l_dbus_message_builder_leave_variant(builder);
+       l_dbus_message_builder_leave_dict(builder);
+}
+
+static void __mesh_scan_setup(struct l_dbus_message *msg, void *user_data)
+{
+       struct l_dbus_message_builder *builder;
+       uint16_t secs = (uint16_t) L_PTR_TO_UINT(user_data);
+       INFO("Mesh: Scan duration [%u]", secs);
+
+       builder = l_dbus_message_builder_new(msg);
+       l_dbus_message_builder_enter_array(builder, "{sv}");
+       append_dict_entry_basic(builder, "Seconds", "q", &secs);
+       l_dbus_message_builder_leave_array(builder);
+       l_dbus_message_builder_finalize(builder);
+       l_dbus_message_builder_destroy(builder);
+}
+
+
+bt_status_t _bt_hal_mesh_network_set_caps(
+               bt_uuid_t *net_uuid, bt_hal_mesh_prov_caps_t *caps)
+{
+       GSList *l;
+       meshcfg_app *app;
+       l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
+       if (l) {
+               app = l->data;
+               /* Fill OOB data */
+               app->public_oob = caps->public_oob;
+               app->static_oob = caps->static_oob;
+               app->out_oob = caps->out_oob;
+               app->in_oob = caps->in_oob;
+       } else {
+               ERR("Mesh: app not found!!");
+               return BT_STATUS_PARM_INVALID;
+
+       }
+       return BT_STATUS_SUCCESS;
+}
+
+static void __bt_hal_mesh_add_node_reply(
+               struct l_dbus_proxy *proxy,
+                       struct l_dbus_message *msg,
+                               void *user_data)
+{
+       struct hal_ev_mesh_provision_status ev;
+       const char *dbus_path;
+       uint8_t *net_uuid;
+       dbus_path =  l_dbus_proxy_get_path(proxy);
+       INFO("Mesh: DBUS path [%s]", dbus_path);
+       net_uuid = __mesh_get_net_uuid_from_dbus_proxy_path(dbus_path);
+
+       bt_uuid_t *dev_uuid = (bt_uuid_t*) user_data;
+
+       INFO("Mesh: app path [%s]", dbus_path);
+
+       memset(&ev, 0, sizeof(ev));
+       memcpy(ev.net_uuid, net_uuid, 16);
+       memcpy(ev.dev_uuid, dev_uuid->uu, 16);
+
+       /* Free User data */
+       g_free((void*)dev_uuid);
+       l_free(net_uuid);
+
+       if (l_dbus_message_is_error(msg)) {
+               const char *name;
+
+               l_dbus_message_get_error(msg, &name, NULL);
+               ERR("Mesh: Failed to start provisioning: %s", name);
+               ev.status = BT_STATUS_FAIL;
+       } else {
+               INFO("Mesh: Provisioning started\n");
+               ev.status = BT_STATUS_SUCCESS;
+       }
+       if (mesh_event_cb)
+               mesh_event_cb(HAL_EV_MESH_PROVISIONING_STATUS,
+                       (void*)&ev, sizeof(ev));
+}
+
+static void __bt_hal_mesh_add_node_setup(struct l_dbus_message *msg,
+               void *user_data)
+{
+       bt_uuid_t *dev = user_data;
+       struct l_dbus_message_builder *builder;
+
+       builder = l_dbus_message_builder_new(msg);
+       __mesh_append_byte_array(builder, dev->uu, 16);
+       l_dbus_message_builder_enter_array(builder, "{sv}");
+       l_dbus_message_builder_leave_array(builder);
+       l_dbus_message_builder_finalize(builder);
+       l_dbus_message_builder_destroy(builder);
+
+       l_free(dev);
+}
+
+bt_status_t _bt_hal_mesh_provision_device(
+               bt_uuid_t *net_uuid, bt_uuid_t *dev_uuid)
+{
+       GSList *l;
+       meshcfg_app *app;
+       bt_uuid_t *dev;
+       l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
+       if (l) {
+               app = l->data;
+               dev = g_memdup((gpointer)dev_uuid, 16);
+
+               if (!l_dbus_proxy_method_call(app->mgmt_proxy, "AddNode",
+                                       __bt_hal_mesh_add_node_setup,
+                                       __bt_hal_mesh_add_node_reply,
+                                       (void*)dev, NULL))
+                       return BT_STATUS_FAIL;
+       } else {
+               ERR("Mesh: app not found!!");
+               return BT_STATUS_PARM_INVALID;
+
+       }
+       return BT_STATUS_SUCCESS;
+}
+
+static void __bt_hal_mesh_subnet_key_setup(
+               struct l_dbus_message *msg, void *user_data)
+{
+       struct subnet_key_request *req = user_data;
+       uint16_t idx = (uint16_t) req->idx;
+
+       l_dbus_message_set_arguments(msg, "q", idx);
+}
+
+static void __bt_hal_mesh_subnet_key_reply(struct l_dbus_proxy *proxy,
+               struct l_dbus_message *msg, void *user_data)
+{
+       struct hal_ev_mesh_netkey_execute_event ev;
+       const char *dbus_path;
+       uint8_t *net_uuid;
+       struct subnet_key_request *req = user_data;
+       const char *method = req->str;
+
+       dbus_path =  l_dbus_proxy_get_path(proxy);
+       INFO("Mesh: DBUS path [%s]", dbus_path);
+       net_uuid = __mesh_get_net_uuid_from_dbus_proxy_path(dbus_path);
+
+       memset(&ev, 0, sizeof(ev));
+       memcpy(ev.net_uuid, net_uuid, 16);
+       ev.key_idx = req->idx;
+
+       g_free(net_uuid);
+
+       if (l_dbus_message_is_error(msg)) {
+               const char *name;
+
+               l_dbus_message_get_error(msg, &name, NULL);
+               ERR("Mesh: Subnet [%s] failed: error: [%s]", method, name);
+               ev.status = BT_STATUS_FAIL;
+       }
+
+       ev.status = BT_STATUS_SUCCESS;
+
+       if (!strcmp("CreateSubnet", method)) {
+               ev.key_event = HAL_MESH_KEY_ADD;
+       } else if (!strcmp("DeleteSubnet", method)) {
+               ev.key_event = HAL_MESH_KEY_DELETE;
+       } else if (!strcmp("UpdateSubnet", method)) {
+               ev.key_event = HAL_MESH_KEY_UPDATE;
+       }
+
+       if (mesh_event_cb)
+               mesh_event_cb(HAL_EV_MESH_NETKEY_EXECUTE_EVENT,
+                       (void*)&ev, sizeof(ev));
+}
+
+static bool  __mesh_subnet_netkey_command_execute(meshcfg_app *app,
+                       uint16_t index, const char *key_execute_method)
+{
+       struct subnet_key_request *req;
+
+       req = l_new(struct subnet_key_request, 1);
+       req->str = key_execute_method;
+       req->idx = index;
+
+       if (!l_dbus_proxy_method_call(app->mgmt_proxy, key_execute_method,
+                               __bt_hal_mesh_subnet_key_setup,
+                               __bt_hal_mesh_subnet_key_reply,
+                               req, l_free))
+               return false;
+
+       return true;
+}
+
+static void __bt_hal_mesh_app_key_setup(struct l_dbus_message *msg,
+       void *user_data)
+{
+       struct app_key_request *req = user_data;
+       uint16_t net_idx = (uint16_t) req->net_idx;
+       uint16_t app_idx = (uint16_t) req->app_idx;
+
+        l_dbus_message_set_arguments(msg, "qq", net_idx, app_idx);
+}
+
+static void __bt_hal_mesh_app_key_reply(struct l_dbus_proxy *proxy,
+               struct l_dbus_message *msg, void *user_data)
+{
+       struct hal_ev_mesh_appkey_execute_event ev;
+       const char *dbus_path;
+       uint8_t *net_uuid;
+       struct app_key_request *req = user_data;
+       const char *method = req->str;
+
+       dbus_path =  l_dbus_proxy_get_path(proxy);
+       INFO("Mesh: DBUS path [%s]", dbus_path);
+       net_uuid = __mesh_get_net_uuid_from_dbus_proxy_path(dbus_path);
+
+       memset(&ev, 0, sizeof(ev));
+       memcpy(ev.net_uuid, net_uuid, 16);
+       ev.net_idx = req->net_idx;
+       ev.app_idx = req->app_idx;
+
+       g_free(net_uuid);
+
+       if (l_dbus_message_is_error(msg)) {
+               const char *name;
+
+               l_dbus_message_get_error(msg, &name, NULL);
+               ERR("Mesh: AppKey execute [%s] failed: error: [%s]", method, name);
+               ev.status = BT_STATUS_FAIL;
+       }
+
+       ev.status = BT_STATUS_SUCCESS;
+
+       if (!strcmp("CreateAppKey", method)) {
+               ev.key_event = HAL_MESH_KEY_ADD;
+       } else if (!strcmp("DeleteAppKey", method)) {
+               ev.key_event = HAL_MESH_KEY_DELETE;
+       } else if (!strcmp("UpdateAppKey", method)) {
+               ev.key_event = HAL_MESH_KEY_UPDATE;
+       }
+
+       if (mesh_event_cb)
+               mesh_event_cb(HAL_EV_MESH_APPKEY_EXECUTE_EVENT, (void*)&ev, sizeof(ev));
+}
+
+static bool  __mesh_subnet_appkey_command_execute(meshcfg_app *app,
+                       uint16_t net_idx, uint16_t app_idx,
+                               const char *key_execute_method)
+{
+       struct app_key_request *req;
+
+       req = l_new(struct app_key_request, 1);
+       req->str = key_execute_method;
+       req->net_idx = net_idx;
+       req->app_idx = app_idx;
+
+       if (!l_dbus_proxy_method_call(app->mgmt_proxy, key_execute_method,
+                               __bt_hal_mesh_app_key_setup,
+                               __bt_hal_mesh_app_key_reply,
+                               req, l_free))
+               return false;
+
+       return true;
+}
+
+bt_status_t _bt_hal_mesh_network_subnet_execute(bt_uuid_t *net_uuid,
+                       bt_mesh_key_op_e op, uint16_t netkey_idx)
+{
+       GSList *l;
+       meshcfg_app *app;
+       bool status = true;
+       l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
+       if (l) {
+               app = l->data;
+
+               if (op == BT_MESH_KEY_CREATE)
+                       status = __mesh_subnet_netkey_command_execute(app,
+                                       netkey_idx, "CreateSubnet");
+               else if (op == BT_MESH_KEY_DELETE)
+                       status = __mesh_subnet_netkey_command_execute(app,
+                                       netkey_idx, "DeleteSubnet");
+               else if (op == BT_MESH_KEY_UPDATE)
+                       status = __mesh_subnet_netkey_command_execute(app,
+                                       netkey_idx, "UpdateSubnet");
+               if (!status)
+                       return BT_STATUS_FAIL;
+
+       } else {
+               ERR("Mesh: app not found!!");
+               return BT_STATUS_PARM_INVALID;
+
+       }
+       return BT_STATUS_SUCCESS;
+}
+
+bt_status_t _bt_hal_mesh_network_appkey_execute(bt_uuid_t *net_uuid,
+                       bt_mesh_key_op_e op, uint16_t netkey_idx, uint16_t appkey_idx)
+{
+       GSList *l;
+       meshcfg_app *app;
+       bool status = true;
+       l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
+       if (l) {
+               app = l->data;
+
+               if (op == BT_MESH_KEY_CREATE)
+                       status = __mesh_subnet_appkey_command_execute(app,
+                               netkey_idx, appkey_idx, "CreateAppKey");
+               else if (op == BT_MESH_KEY_DELETE)
+                       status = __mesh_subnet_appkey_command_execute(app,
+                               netkey_idx, appkey_idx, "DeleteAppKey");
+               else if (op == BT_MESH_KEY_UPDATE)
+                       status = __mesh_subnet_appkey_command_execute(app,
+                               netkey_idx, appkey_idx, "UpdateAppKey");
+               if (!status)
+                       return BT_STATUS_FAIL;
+
+       } else {
+               ERR("Mesh: app not found!!");
+               return BT_STATUS_PARM_INVALID;
+
+       }
+       return BT_STATUS_SUCCESS;
+}
+
+bt_status_t _bt_hal_mesh_send_provision_data(
+               bt_uuid_t *net_uuid, uint16_t netkey_idx, uint16_t unicast)
+{
+       GSList *l;
+       meshcfg_app *app;
+       struct l_dbus_message *msg;
+       struct l_dbus_message *reply;
+
+       l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
+       if (l) {
+               app = l->data;
+               msg = app->msg;
+
+               reply = l_dbus_message_new_method_return(msg);
+               l_dbus_message_set_arguments(reply, "qq", netkey_idx,  unicast);
+               l_dbus_send(dbus, reply);
+       } else {
+               ERR("Mesh: app not found!!");
+               return BT_STATUS_PARM_INVALID;
+       }
+       return BT_STATUS_SUCCESS;
+}
+
+bt_status_t _bt_hal_mesh_network_scan_cancel(bt_uuid_t *net_uuid)
+{
+       GSList *l;
+       meshcfg_app *app;
+       l = g_slist_find_custom(mesh_apps,
+               net_uuid->uu, __mesh_compare_network_uuid);
+       if (l) {
+               app = l->data;
+               if (!l_dbus_proxy_method_call(app->mgmt_proxy,
+                               "UnprovisionedScanCancel",
+                                       NULL, NULL, NULL, NULL))
+                       return BT_STATUS_FAIL;
+       } else {
+               ERR("Mesh: app not found!!");
+               return BT_STATUS_PARM_INVALID;
+       }
+
+       /* Stop Scan timer */
+       if (app->scan_timer_id > 0) {
+               g_source_remove(app->scan_timer_id);
+               app->scan_timer_id = 0;
+       }
+
+       /* Trigger Scan finished event */
+       __mesh_trigger_scan_finished_event(app);
+
+       return BT_STATUS_SUCCESS;
+}
+
+bt_status_t _bt_hal_mesh_auth_reply(bt_hal_mesh_auth_variant_e auth_type,
+                       const char *auth_value)
+{
+       uint32_t val_u32;
+       struct l_dbus_message *reply = NULL;
+       struct l_dbus_message_builder *builder;
+       uint8_t alpha[16];
+
+       /* For Numeric Type Inputs: Numeric, Blink, Beep & Vibrate */
+       if (auth_type >= BT_HAL_MESH_AUTH_REQ_NUMERIC_INPUT &&
+                       auth_type <= BT_HAL_MESH_AUTH_REQ_VIBRATE_COUNT_INPUT) {
+               INFO("Mesh: Authentication reply: Numeric ype");
+               val_u32 = atoi(auth_value);
+               reply = l_dbus_message_new_method_return(agent_msg);
+               l_dbus_message_set_arguments(reply, "u", val_u32);
+               /* For Alpha-Numeric */
+       } else if (auth_type == BT_HAL_MESH_AUTH_REQ_ALPHANUMERIC_INPUT) {
+               INFO("Mesh: Authentication reply: Alpha-Numeric ype");
+               memset(alpha, 0x00, 16);
+               memcpy(alpha, auth_value, strlen(auth_value));
+               reply = l_dbus_message_new_method_return(agent_msg);
+               builder = l_dbus_message_builder_new(reply);
+               __mesh_append_byte_array(builder, alpha, 16);
+               l_dbus_message_builder_finalize(builder);
+               l_dbus_message_builder_destroy(builder);
+       }
+       return BT_STATUS_SUCCESS;
+}
+
+bt_status_t _bt_hal_mesh_network_scan(bt_uuid_t *net_uuid,
+               bt_hal_mesh_scan_param_t *param)
+{
+       GSList *l;
+       meshcfg_app *app;
+       l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
+       if (l) {
+               app = l->data;
+               if (!l_dbus_proxy_method_call(app->mgmt_proxy, "UnprovisionedScan",
+                                       __mesh_scan_setup, __mesh_scan_reply,
+                                       L_UINT_TO_PTR(param->scan_time), NULL))
+                       return BT_STATUS_FAIL;
+       } else {
+               ERR("Mesh: app not found!!");
+               return BT_STATUS_PARM_INVALID;
+       }
+       return BT_STATUS_SUCCESS;
+}
+
+bt_status_t _bt_hal_mesh_create_network(
+               bt_hal_mesh_node_t *node, GSList *models, bool is_prov)
+{
+       meshcfg_app *app;
+
+       INFO("Mesh: Create Network Request");
+       /* Create DBUS APP */
+       app = __bt_hal_mesh_create_app(node, models, is_prov);
+       if (!app)
+               return BT_STATUS_FAIL;
+
+       /* Register DBUS APP */
+       if (!__bt_hal_mesh_register_application(app)) {
+               goto failed;
+       }
+
+       if (app->token.u64 == 0) {
+               INFO("Mesh: Create New Network");
+               /* Create CFG Network */
+               if (!l_dbus_proxy_method_call(net_proxy, "CreateNetwork",
+                                       __bt_hal_mesh_create_net_setup,
+                                       __bt_hal_mesh_create_net_reply, app,
+                                       NULL)) {
+                       ERR("Mesh: Network Create failed!!");
+                       goto failed;
+               }
+       } else {
+               INFO("Mesh: Attach Node to Network");
+               /* Attach to Network */
+               if (!l_dbus_proxy_method_call(net_proxy, "Attach",
+                                       __bt_hal_mesh_attach_node_setup,
+                                       __bt_hal_mesh_attach_node_reply,
+                                       app,
+                               NULL)) {
+                       ERR("Mesh: Node attach failed!!");
+                       goto failed;
+               }
+       }
+
+       INFO("Mesh: Node registration request scheudled");
+       mesh_apps = g_slist_append(mesh_apps, app);
+       INFO("Mesh: Total number of apps in list  [%d]",
+               g_slist_length(mesh_apps));
+       return BT_STATUS_SUCCESS;
+failed:
+       ERR("Mesh: network can not be created!!");
+       __bt_hal_mesh_destroy_app_object(app);
+       return BT_STATUS_FAIL;
+}
+
+static void __bt_hal_mesh_config_send(
+               struct l_dbus_message *msg, void *user_data)
+{
+       struct configuration_request *req = user_data;
+       struct l_dbus_message_builder *builder;
+
+       builder = l_dbus_message_builder_new(msg);
+
+       l_dbus_message_builder_append_basic(builder, 'o', req->ele_path);
+       l_dbus_message_builder_append_basic(builder, 'q', &req->dst);
+       if (req->is_dev_key)
+               l_dbus_message_builder_append_basic(builder, 'b', &req->rmt);
+
+       l_dbus_message_builder_append_basic(builder, 'q', &req->idx);
+       __mesh_append_byte_array(builder, req->data, req->len);
+       l_dbus_message_builder_finalize(builder);
+       l_dbus_message_builder_destroy(builder);
+}
+
+static void __bt_hal_mesh_key_config_send(
+               struct l_dbus_message *msg, void *user_data)
+{
+       struct key_config_request *req = user_data;
+       struct l_dbus_message_builder *builder;
+
+       builder = l_dbus_message_builder_new(msg);
+
+       l_dbus_message_builder_append_basic(builder, 'o', req->ele_path);
+       l_dbus_message_builder_append_basic(builder, 'q', &req->dst);
+       l_dbus_message_builder_append_basic(builder, 'q', &req->key_req_idx);
+       l_dbus_message_builder_append_basic(builder, 'q', &req->idx);
+       l_dbus_message_builder_append_basic(builder, 'b', &req->update_req);
+       l_dbus_message_builder_finalize(builder);
+       l_dbus_message_builder_destroy(builder);
+}
+
+bt_status_t _bt_hal_mesh_send_key_config_message(
+               bt_uuid_t *network, uint16_t dest,
+                       bool is_netkey, bool is_update,
+                               uint16_t key_idx, uint16_t netkey_idx)
+{
+       GSList *l;
+       GSList *l1;
+       struct key_config_request *req;
+       meshcfg_app *app;
+       meshcfg_el *elem;
+       const char *key_method = (!is_netkey) ? "AddAppKey" : "AddNetKey";
+       /* Source is Config Client Local Node */
+       int src_elem_idx = 0;
+       l = g_slist_find_custom(mesh_apps, network->uu, __mesh_compare_network_uuid);
+       if (l) {
+               app = l->data;
+               l1 = g_slist_find_custom(app->elements,
+                       GUINT_TO_POINTER(src_elem_idx), __compare_element_index);
+               elem = l1->data;
+
+               req = l_new(struct key_config_request, 1);
+               req->ele_path = elem->path;
+               req->dst = dest;
+               req->key_req_idx = key_idx;
+               req->idx = netkey_idx; /* Encryption Key index */
+               req->update_req = is_update;
+
+               if (!l_dbus_proxy_method_call(app->mgmt_proxy, key_method,
+                                       __bt_hal_mesh_key_config_send, NULL,
+                                       (void*)req, l_free))
+                       return BT_STATUS_FAIL;
+       } else {
+               ERR("Mesh: app not found!!");
+               return BT_STATUS_PARM_INVALID;
+
+       }
+       return BT_STATUS_SUCCESS;
+}
+
+bt_status_t _bt_hal_mesh_send_configuration_message(
+       bt_uuid_t *network, uint16_t dest,
+               bool is_dev_key, uint16_t netkey_idx,
+                       uint8_t *buf, int len)
+{
+       GSList *l;
+       GSList *l1;
+       struct configuration_request *req;
+       meshcfg_app *app;
+       meshcfg_el *elem;
+       int src_elem_idx = 0;
+       l = g_slist_find_custom(mesh_apps, network->uu,
+                       __mesh_compare_network_uuid);
+       if (l) {
+               app = l->data;
+               l1 = g_slist_find_custom(app->elements,
+                               GUINT_TO_POINTER(src_elem_idx),
+                               __compare_element_index);
+               elem = l1->data;
+
+               req = l_new(struct configuration_request, 1);
+               req->ele_path = elem->path;
+               req->dst = dest;
+               req->idx = netkey_idx;
+               req->data = buf;
+               req->len = len;
+               req->rmt = true;
+               req->is_dev_key = is_dev_key;
+
+               if (!l_dbus_proxy_method_call(app->mgmt_proxy, "DevKeySend",
+                                       __bt_hal_mesh_config_send, NULL,
+                                       (void*)req, l_free))
+                       return BT_STATUS_FAIL;
+       } else {
+               ERR("Mesh: app not found!!");
+               return BT_STATUS_PARM_INVALID;
+
+       }
+       return BT_STATUS_SUCCESS;
+}
diff --git a/bt-oal/bluez_hal/src/bt-hal-mesh.c b/bt-oal/bluez_hal/src/bt-hal-mesh.c
new file mode 100644 (file)
index 0000000..8711b15
--- /dev/null
@@ -0,0 +1,344 @@
+/*
+ * Bluetooth-frwk
+ *
+ * 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 <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ell/ell.h>
+#include <dlog.h>
+#include <glib.h>
+
+#include "bt-hal.h"
+#include "bt-hal-log.h"
+#include "bt-hal-msg.h"
+#include "bt-hal-utils.h"
+
+#include "bt-hal-mesh-dbus-handler.h"
+#include "bt-hal-event-receiver.h"
+
+static const btmesh_callbacks_t *bt_hal_mesh_cbacks = NULL;
+
+static bool interface_ready(void)
+{
+       return bt_hal_mesh_cbacks != NULL;
+}
+
+static void __bt_hal_mesh_network_attached(void *buf, uint16_t len)
+{
+       struct hal_ev_mesh_network_attached *ev = buf;
+       if (bt_hal_mesh_cbacks->network_attached_cb)
+               bt_hal_mesh_cbacks->network_attached_cb(ev->status,
+                       (bt_mesh_token_t*)&ev->token,
+                               (bt_uuid_t*)&ev->uuid);
+}
+
+static void __bt_hal_handle_network_scan_result(void *buf, uint16_t len)
+{
+       struct hal_ev_mesh_scan_result *ev = buf;
+       bt_mesh_scan_result_t result;
+       memset(&result, 0x00, sizeof(bt_mesh_scan_result_t));
+
+       memcpy(result.dev_uuid.uu, ev->dev_uuid, 16);
+       memcpy(&result.oob_info, ev->oob_info, 2);
+       memcpy(&result.uri_hash, ev->uri_hash, 4);
+       result.rssi = ev->rssi;
+
+       if (bt_hal_mesh_cbacks->scan_result_cb)
+               bt_hal_mesh_cbacks->scan_result_cb(ev->status,
+                       (bt_uuid_t*)&ev->net_uuid,
+                               (bt_mesh_scan_result_t*)&result);
+}
+
+static void __bt_hal_handle_network_scan_status(void *buf, uint16_t len)
+{
+       struct hal_ev_mesh_scan_state_changed *ev = buf;
+
+       if (bt_hal_mesh_cbacks->scan_status_cb)
+               bt_hal_mesh_cbacks->scan_status_cb(ev->state, ev->status,
+                       (bt_uuid_t*)&ev->net_uuid);
+}
+
+static void __bt_hal_handle_network_provisioning_status(void *buf, uint16_t len)
+{
+       struct hal_ev_mesh_provision_status *ev = buf;
+
+       if (bt_hal_mesh_cbacks->provisioning_status_cb)
+               bt_hal_mesh_cbacks->provisioning_status_cb(ev->status,
+                               (bt_uuid_t*)&ev->net_uuid,
+                                       (bt_uuid_t*)&ev->dev_uuid);
+}
+
+static void __bt_hal_handle_network_provisioning_finished(void *buf, uint16_t len)
+{
+       struct hal_ev_mesh_provision_finished *ev = buf;
+
+       if (bt_hal_mesh_cbacks->provisioning_finished_cb)
+               bt_hal_mesh_cbacks->provisioning_finished_cb(ev->status, ev->reason,
+                               (bt_uuid_t*)&ev->net_uuid, (bt_uuid_t*)&ev->dev_uuid,
+                                       ev->unicast, ev->count);
+}
+
+static void __bt_hal_handle_network_provisioning_data_requested(void *buf,
+               uint16_t len)
+{
+       struct hal_ev_mesh_provision_data_request *ev = buf;
+
+       if (bt_hal_mesh_cbacks->provisioning_data_requested_cb)
+               bt_hal_mesh_cbacks->provisioning_data_requested_cb(
+                       (bt_uuid_t*)&ev->net_uuid, ev->count);
+}
+
+static void __bt_hal_handle_authentication_requested(void *buf, uint16_t len)
+{
+       struct hal_ev_mesh_authentication_request *ev = buf;
+
+       if (bt_hal_mesh_cbacks->authentication_requested_cb)
+               bt_hal_mesh_cbacks->authentication_requested_cb(
+                       (bt_uuid_t*)&ev->net_uuid, ev->auth_type, ev->auth_value);
+}
+
+static void __bt_hal_handle_netkey_execute_event(void *buf, uint16_t len)
+{
+       struct hal_ev_mesh_netkey_execute_event *ev = buf;
+
+       if (bt_hal_mesh_cbacks->netkey_execute_cb)
+               bt_hal_mesh_cbacks->netkey_execute_cb(ev->status,
+                       (bt_uuid_t*)&ev->net_uuid,
+                               ev->key_event, ev->key_idx);
+}
+
+static void __bt_hal_handle_appkey_execute_event(void *buf, uint16_t len)
+{
+       struct hal_ev_mesh_appkey_execute_event *ev = buf;
+
+       if (bt_hal_mesh_cbacks->appkey_execute_cb)
+               bt_hal_mesh_cbacks->appkey_execute_cb(ev->status,
+                       (bt_uuid_t*)&ev->net_uuid, ev->key_event,
+                               ev->net_idx, ev->app_idx);
+}
+
+static void __bt_hal_handle_devkey_message_received_event(void *buf, uint16_t len)
+{
+       struct hal_ev_mesh_devkey_message_event *ev = buf;
+
+       if (bt_hal_mesh_cbacks->devkey_msg_cb)
+               bt_hal_mesh_cbacks->devkey_msg_cb((bt_uuid_t*)&ev->net_uuid,
+                       ev->source_addr,
+                               ev->is_remote_devkey, ev->netkey_idx,
+                                       ev->data_len, ev->data);
+}
+
+static void __bt_hal_handle_mesh_events(int message, void *buf, uint16_t len)
+{
+       DBG("+");
+
+       if (!interface_ready())
+               return;
+
+       switch (message) {
+       case HAL_EV_MESH_NETWORK_ATTACHED:
+               DBG("Mesh Event: HAL_EV_MESH_NETWORK_ATTACHED");
+               __bt_hal_mesh_network_attached(buf, len);
+               break;
+       case HAL_EV_MESH_SCAN_STATE_CHANGED:
+               DBG("Mesh Event: HAL_EV_MESH_SCAN_STATE_CHANGED");
+               __bt_hal_handle_network_scan_status(buf, len);
+               break;
+       case HAL_EV_MESH_SCAN_RESULT:
+               DBG("Mesh Event: HAL_EV_MESH_SCAN_RESULT");
+               __bt_hal_handle_network_scan_result(buf, len);
+               break;
+       case HAL_EV_MESH_PROVISIONING_STATUS:
+               DBG("Mesh Event: HAL_EV_MESH_SCAN_RESULT");
+               __bt_hal_handle_network_provisioning_status(buf, len);
+               break;
+       case HAL_EV_MESH_PROVISIONING_FINISHED:
+               DBG("Mesh Event: HAL_EV_MESH_PROVISIONING_FINISHED");
+               __bt_hal_handle_network_provisioning_finished(buf, len);
+               break;
+       case HAL_EV_MESH_PROVISIONING_DATA_REQUEST:
+               DBG("Mesh Event: HAL_EV_MESH_PROVISIONING_DATA_REQUEST");
+               __bt_hal_handle_network_provisioning_data_requested(buf, len);
+               break;
+       case HAL_EV_MESH_AUTHENTICATION_REQUEST:
+               DBG("Mesh Event: HAL_EV_MESH_AUTHENTICATION_REQUEST");
+               __bt_hal_handle_authentication_requested(buf, len);
+               break;
+       case HAL_EV_MESH_NETKEY_EXECUTE_EVENT:
+               DBG("Mesh Event: HAL_EV_MESH_NETKEY_EXECUTE_EVENT");
+               __bt_hal_handle_netkey_execute_event(buf, len);
+               break;
+       case HAL_EV_MESH_APPKEY_EXECUTE_EVENT:
+               DBG("Mesh Event: HAL_EV_MESH_APPKEY_EXECUTE_EVENT");
+               __bt_hal_handle_appkey_execute_event(buf, len);
+               break;
+       case HAL_EV_MESH_DEVKEY_MESSAGE_EVENT:
+               DBG("Mesh Event: HAL_EV_MESH_DEVKEY_MESSAGE_EVENT");
+               __bt_hal_handle_devkey_message_received_event(buf, len);
+               break;
+       default:
+               DBG("Mesh Event Currently not handled!!");
+               break;
+       }
+
+       DBG("-");
+}
+
+static bt_status_t mesh_create_network(bt_hal_mesh_node_t *node,
+               GSList *models, bool is_prov)
+{
+       DBG("");
+       return _bt_hal_mesh_create_network(node, models, is_prov);
+}
+
+static bt_status_t mesh_scan(bt_uuid_t *network, bt_hal_mesh_scan_param_t *param)
+{
+       DBG("");
+       return _bt_hal_mesh_network_scan(network, param);
+}
+
+static bt_status_t mesh_scan_cancel(bt_uuid_t *network)
+{
+       DBG("");
+       return _bt_hal_mesh_network_scan_cancel(network);
+}
+
+static bt_status_t mesh_set_prov_caps(bt_uuid_t *network,
+               bt_hal_mesh_prov_caps_t *caps)
+{
+       DBG("");
+       return _bt_hal_mesh_network_set_caps(network, caps);
+}
+
+static bt_status_t mesh_provision_device(bt_uuid_t *network,
+               bt_uuid_t *dev_uuid)
+{
+       DBG("");
+       return _bt_hal_mesh_provision_device(network, dev_uuid);
+}
+
+static bt_status_t mesh_send_provision_data(bt_uuid_t* network_uuid,
+               uint16_t netkey_idx, uint16_t unicast)
+{
+       DBG("");
+       return _bt_hal_mesh_send_provision_data(network_uuid,
+                       netkey_idx, unicast);
+}
+
+static bt_status_t mesh_network_subnet_operation(bt_uuid_t* network_uuid,
+                       bt_mesh_key_op_e op, uint16_t netkey_idx)
+{
+       DBG("");
+       return _bt_hal_mesh_network_subnet_execute(network_uuid,
+                       op, netkey_idx);
+}
+
+static bt_status_t mesh_network_appkey_operation(bt_uuid_t* network_uuid,
+                       bt_mesh_key_op_e op, uint16_t netkey_idx,
+                               uint16_t appkey_idx)
+{
+       DBG("");
+       return _bt_hal_mesh_network_appkey_execute(network_uuid,
+                       op, netkey_idx, appkey_idx);
+}
+
+static bt_status_t mesh_auth_reply(bt_hal_mesh_auth_variant_e auth_type,
+               const char *auth_value)
+{
+       DBG("");
+       return _bt_hal_mesh_auth_reply(auth_type, auth_value);
+}
+
+/* Remote Node operations */
+static bt_status_t mesh_send_configuration_message(bt_uuid_t *network,
+               uint16_t dest, bool is_dev_key, uint16_t netkey_idx,
+                       uint8_t *buf, int len)
+{
+       DBG("");
+       return _bt_hal_mesh_send_configuration_message(network, dest,
+                       is_dev_key, netkey_idx, buf, len);
+}
+
+static bt_status_t mesh_key_configuration_message(bt_uuid_t *network,
+               uint16_t dest, bool is_netkey,
+                       bool is_update, uint16_t key_idx,
+                               uint16_t netkey_idx)
+{
+       DBG("");
+       return _bt_hal_mesh_send_key_config_message(network, dest,
+               is_netkey, is_update,
+                       key_idx, netkey_idx);
+}
+
+static bt_status_t init(btmesh_callbacks_t *callbacks)
+{
+       DBG("");
+
+       if (interface_ready())
+               return BT_STATUS_SUCCESS;
+
+       bt_hal_mesh_cbacks = callbacks;
+       INFO("Register Mesh events callback function");
+
+       _bt_hal_mesh_register_dbus_handler_cb(__bt_hal_handle_mesh_events);
+       _bt_hal_register_event_handler_cb(HAL_MESH, __bt_hal_handle_mesh_events);
+
+       if (!_bt_hal_mesh_stack_init())
+               return BT_STATUS_FAIL;
+
+       return BT_STATUS_SUCCESS;
+}
+
+static void cleanup(void)
+{
+       DBG("");
+
+       if (!interface_ready())
+               return;
+
+       _bt_hal_mesh_unregister_dbus_handler_cb();
+       _bt_hal_unregister_event_handler_cb(HAL_MESH);
+
+       bt_hal_mesh_cbacks = NULL;
+}
+
+static btmesh_interface_t mesh_if = {
+       .size = sizeof(mesh_if),
+       .init = init,
+       .create = mesh_create_network,
+       .scan = mesh_scan,
+       .scan_cancel = mesh_scan_cancel,
+       .capability = mesh_set_prov_caps,
+       .provision = mesh_provision_device,
+       .provision_data = mesh_send_provision_data,
+       .auth_reply = mesh_auth_reply,
+       .subnet_execute = mesh_network_subnet_operation,
+       .appkey_execute = mesh_network_appkey_operation,
+       .config_send = mesh_send_configuration_message,
+       .key_send = mesh_key_configuration_message,
+       .cleanup = cleanup
+};
+
+btmesh_interface_t *bt_get_mesh_interface(void)
+{
+       return &mesh_if;
+}
diff --git a/bt-oal/bluez_hal/src/bt-hal-mesh.h b/bt-oal/bluez_hal/src/bt-hal-mesh.h
new file mode 100644 (file)
index 0000000..2aa7a68
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Bluetooth-frwk
+ *
+ * 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.
+ *
+ */
+
+#ifndef __BT_HAL_MESH_H__
+#define __BT_HAL_MESH_H__
+
+#include <stdint.h>
+#include <glib.h>
+#include <unistd.h>
+#include <dlog.h>
+#include <stdio.h>
+
+btmesh_interface_t *bt_get_mesh_interface(void);
+
+#endif //__BT_HAL_MESH_H__