e9714b54546f1bfbd21167520d147fdf541cd120
[platform/core/connectivity/bluetooth-frwk.git] / bt-oal / bluez_hal / src / bt-hal-mesh-dbus-handler.c
1 /*
2  * Bluetooth HAL
3  *
4  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * @author: Anupam Roy <anupam.r@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *              http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stdbool.h>
25 #include <string.h>
26
27 #include <glib.h>
28 #include <gio/gio.h>
29 #include <dlog.h>
30 #include <vconf.h>
31 #include <ell/ell.h>
32
33 #include "bt-hal-mesh-dbus-handler.h"
34 #include "bt-hal-dbus-common-utils.h"
35 #include "bt-hal-internal.h"
36
37 #include <hardware/bt_mesh.h>
38
39 #define BT_HAL_MESH_DBUS_NAME "org.projectx.bt.mesh"
40
41 #define BT_HAL_UUID_LEN 16
42 #define BT_HAL_BLUEZ_MESH_NAME "org.bluez.mesh"
43
44 #define BT_HAL_MESH_NETWORK_INTERFACE "org.bluez.mesh.Network1"
45 #define BT_HAL_MESH_NODE_INTERFACE "org.bluez.mesh.Node1"
46 #define BT_HAL_MESH_MANAGEMENT_INTERFACE "org.bluez.mesh.Management1"
47 #define BT_HAL_MESH_ELEMENT_INTERFACE "org.bluez.mesh.Element1"
48 #define BT_HAL_MESH_APPLICATION_INTERFACE "org.bluez.mesh.Application1"
49 #define BT_HAL_MESH_PROVISION_AGENT_INTERFACE "org.bluez.mesh.ProvisionAgent1"
50 #define BT_HAL_MESH_PROVISIONER_INTERFACE "org.bluez.mesh.Provisioner1"
51 #define BT_HAL_MESH_ERROR_INTERFACE "org.bluez.mesh.Error"
52
53 #define BT_HAL_MESH_MAX_DEVKEY_BUF_SIZE 2048
54 #define BT_HAL_MESH_MAX_MSG_BUF_SIZE 2048
55
56 static const char *dbus_err_args = "org.freedesktop.DBus.Error.InvalidArgs";
57 static const char *dbus_err_fail = "org.freedesktop.DBus.Error.Failed";
58
59 static struct l_dbus *dbus = NULL;
60 static struct l_dbus_client *client = NULL;
61
62 static struct l_dbus_proxy *net_proxy = NULL;
63 static struct l_dbus_message *agent_msg;
64
65 static handle_stack_msg mesh_event_cb = NULL;
66
67
68 struct subnet_key_request {
69         uint16_t idx;
70         const char *str;
71 };
72
73 struct app_key_request {
74         uint16_t net_idx;
75         uint16_t app_idx;
76         const char *str;
77 };
78
79 struct configuration_request {
80         const char *ele_path;
81         bool rmt;
82         bool is_dev_key;
83         uint16_t dst;
84         uint16_t idx;
85         uint8_t *data;
86         uint16_t len;
87 };
88
89 struct key_config_request {
90         const char *ele_path;
91         uint16_t dst;
92         uint16_t key_req_idx;
93         uint16_t idx;
94         bool update_req;
95 };
96
97 struct mesh_provision_auth_action {
98         const char *action;
99         bt_hal_mesh_auth_variant_e auth_type;
100 };
101
102 struct mesh_remote_node_info {
103         uint16_t unicast;
104         uint8_t num_elements;
105 };
106
107 static struct mesh_provision_auth_action auth_table[] = {
108         { "blink", BT_HAL_MESH_AUTH_REQ_BLINK_COUNT_INPUT},
109         { "beep", BT_HAL_MESH_AUTH_REQ_BEEP_COUNT_INPUT},
110         { "vibrate", BT_HAL_MESH_AUTH_REQ_VIBRATE_COUNT_INPUT},
111         { "in-numeric", BT_HAL_MESH_AUTH_REQ_NUMERIC_INPUT},
112         { "in-alpha", BT_HAL_MESH_AUTH_REQ_ALPHANUMERIC_INPUT},
113         { "twist", BT_HAL_MESH_AUTH_TWIST_COUNT_DISPLAY},
114         { "push", BT_HAL_MESH_AUTH_PUSH_COUNT_DISPLAY},
115         { "out-numeric", BT_HAL_MESH_AUTH_NUMERIC_DISPLAY},
116         { "out-alpha", BT_HAL_MESH_AUTH_ALPHANUMERIC_DISPLAY},
117         { "static-oob", BT_HAL_MESH_AUTH_REQ_OOB_STATIC_KEY_INPUT},
118         { "unknown", BT_HAL_MESH_UNKNOWN_AUTH_METHOD},
119 };
120
121
122 static uint8_t __bt_mesh_util_get_prov_error_code(char *prov_err_str)
123 {
124         uint8_t ret = 0;
125
126         if (!g_strcmp0(prov_err_str, "success"))
127                 ret = BT_HAL_MESH_PROV_ERR_SUCCESS;
128         else if (!g_strcmp0(prov_err_str, "bad-pduread"))
129                 ret = BT_HAL_MESH_PROV_ERR_INVALID_PDU;
130         else if (!g_strcmp0(prov_err_str, "confirmation-failed"))
131                 ret = BT_HAL_MESH_PROV_ERR_CONFIRM_FAILED;
132         else if (!g_strcmp0(prov_err_str, "out-of-resources"))
133                 ret = BT_HAL_MESH_PROV_ERR_INSUF_RESOURCE;
134         else if (!g_strcmp0(prov_err_str, "decryption-error"))
135                 ret = BT_HAL_MESH_PROV_ERR_DECRYPT_FAILED;
136         else if (!g_strcmp0(prov_err_str, "cannot-assign-addresses"))
137                 ret = BT_HAL_MESH_PROV_ERR_CANT_ASSIGN_ADDR;
138         else if (!g_strcmp0(prov_err_str, "timeout"))
139                 ret = BT_HAL_MESH_PROV_ERR_TIMEOUT;
140         else if (!g_strcmp0(prov_err_str, "unexpected-error"))
141                 ret = BT_HAL_MESH_PROV_ERR_UNEXPECTED_ERR;
142
143         return ret;
144 }
145
146 static bt_hal_mesh_auth_variant_e  __mesh_get_authentication_type(char *str)
147 {
148         int len = strlen(str);
149         int sz = L_ARRAY_SIZE(auth_table);
150         int i;
151
152         for (i = 0; i < sz; ++i)
153                 if (len == strlen(auth_table[i].action) &&
154                                 !strcmp(str, auth_table[i].action))
155                         break;
156         if (i < sz) {
157                 return auth_table[i].auth_type;
158         } else {
159                 ERR("Mesh : Not A Proper Authentication Type!");
160                 return BT_HAL_MESH_UNKNOWN_AUTH_METHOD;
161         }
162 }
163
164 enum mesh_dbus_interface_e {
165         MESH_APP_IFACE,
166         MESH_PROV_IFACE,
167         MESH_AGENT_IFACE,
168         MESH_ELEMENT_IFACE,
169 };
170
171 typedef enum mesh_dbus_interface_e mesh_dbus_interface_e;
172
173 struct meshcfg_model {
174         uint16_t elem_index;
175         uint32_t model;
176 };
177
178 typedef struct meshcfg_model meshcfg_model;
179
180 struct meshcfg_el {
181         char *path;
182         uint16_t index;
183         GSList *models;
184 };
185
186 typedef struct meshcfg_el meshcfg_el;
187
188 struct meshcfg_app {
189         /* Remember Proxies & dbus paths */
190         char *path;
191         char *agent_path;
192         struct l_dbus_proxy *proxy;
193         struct l_dbus_proxy *mgmt_proxy;
194
195         /* Local node Info */
196         GSList *elements;
197         uint16_t cid;
198         uint16_t pid;
199         uint16_t vid;
200         uint16_t crpl;
201         uint8_t uuid[16];
202         union {
203                 uint64_t u64;
204                 uint8_t u8[8];
205         } token;
206         bool is_prov;
207         /* Caps */
208         bool static_oob;
209         bool public_oob;
210         uint16_t out_oob;
211         uint16_t in_oob;
212         struct l_dbus_message *msg;
213         guint scan_timer_id;
214 };
215
216 typedef struct meshcfg_app meshcfg_app;
217
218 /* Will contain critical data related to local Mesh Network */
219 static GSList *mesh_apps = NULL;
220
221
222 struct meshcfg_node {
223         const char *path;
224         struct l_dbus_proxy *proxy;
225         struct l_dbus_proxy *mgmt_proxy;
226         union {
227                 uint64_t u64;
228                 uint8_t u8[8];
229         } token;
230 };
231
232 typedef struct meshcfg_node meshcfg_node;
233
234 static void __mesh_append_byte_array(struct l_dbus_message_builder *builder,
235                 unsigned char *data, unsigned int len)
236 {
237         unsigned int i;
238
239         l_dbus_message_builder_enter_array(builder, "y");
240
241         for (i = 0; i < len; i++)
242                 l_dbus_message_builder_append_basic(builder, 'y', &(data[i]));
243
244         l_dbus_message_builder_leave_array(builder);
245 }
246
247 static gint __mesh_compare_network_uuid(gconstpointer data, gconstpointer user_data)
248 {
249         const meshcfg_app *app = (meshcfg_app*) data;
250         uint8_t uuid[16];
251         memcpy(uuid, (uint8_t*) user_data, 16);
252
253         return memcmp(uuid, app->uuid, sizeof(bt_uuid_t));
254 }
255
256 static unsigned char* __mesh_get_net_uuid_from_dbus_proxy_path(
257                 const char *dbus_path)
258 {
259         char uuid[33];
260         size_t sz;
261
262         memcpy(uuid, (void*)&dbus_path[20], sizeof(uuid));
263         uuid[32] = '\0';
264         INFO("Mesh: Net UUID string [%s]", uuid);
265         return l_util_from_hexstring(uuid, &sz);
266 }
267
268 static unsigned char* __mesh_get_net_uuid_from_path(
269                 const char *dbus_path, bool is_prov,
270                         mesh_dbus_interface_e iface)
271 {
272         char uuid[33];
273         size_t sz;
274
275         switch (iface) {
276         case MESH_APP_IFACE:
277         case MESH_PROV_IFACE:  {
278                 memcpy(uuid, is_prov ? (void*) &dbus_path[16] : (void*) &dbus_path[17], 32);
279                 uuid[32] = '\0';
280                 return l_util_from_hexstring(uuid, &sz);
281         }
282         case MESH_AGENT_IFACE: {
283                 memcpy(uuid, is_prov ? (void*) &dbus_path[16] : (void*) &dbus_path[23], 32);
284                 uuid[32] = '\0';
285                 return l_util_from_hexstring(uuid, &sz);
286         }
287         case MESH_ELEMENT_IFACE: {
288                 memcpy(uuid, is_prov ? (void*) &dbus_path[16] : (void*) &dbus_path[17], 32);
289                 uuid[32] = '\0';
290                 return l_util_from_hexstring(uuid, &sz);
291         }
292         default:
293                 return NULL;
294         }
295 }
296
297 static void __mesh_hal_free_elements(gpointer data)
298 {
299         meshcfg_el *element = (meshcfg_el*) data;
300         if (!element)
301                 return;
302         g_free(element->path);
303         if (element->models)
304                 g_slist_free_full(element->models, g_free);
305
306         element->models = NULL;
307         g_free(element);
308 }
309
310 static bool __bt_mesh_proxy_check(meshcfg_app *app)
311 {
312         /* Check meshd stack Vis up or not */
313         if (!dbus) {
314                 ERR("Mesh: DBUS is not UP!, possibly stack not Up!");
315                 return false;
316         }
317         /* Check Network Proxy is added or not */
318         if (!net_proxy) {
319                 ERR("Mesh: Network proxy is not attached yet!");
320                 return false;
321         }
322
323         if (app) {
324                 /* Check App management proxyis added or not */
325                 if (!app->mgmt_proxy) {
326                         ERR("Mesh: Network proxy is not attached yet!");
327                         return false;
328                 }
329                 /* Check App  Node Proxy is added or not */
330                 if (!app->proxy) {
331                         ERR("Mesh: Node proxy is not attached yet!");
332                         return false;
333                 }
334         }
335         return true;
336 }
337
338 static void __bt_hal_mesh_destroy_app_object(gpointer data)
339 {
340
341         meshcfg_app *app = (meshcfg_app*) data;
342         if (!app)
343                 return;
344
345         mesh_apps = g_slist_remove(mesh_apps, app);
346
347         if (app->path) {
348                 INFO("Mesh: App path [%s] ", app->path);
349                 g_free(app->path);
350         }
351         if (app->agent_path) {
352                 INFO("Mesh: Agent Path [%s]", app->agent_path);
353                 g_free(app->agent_path);
354         }
355
356         if (app->elements) {
357                 INFO("Mesh: Total elements present in app [%d]",
358                                 g_slist_length(app->elements));
359                 g_slist_free_full(app->elements, __mesh_hal_free_elements);
360         }
361
362         if (app->scan_timer_id > 0) {
363                 INFO("Mesh: Remove timer if already running");
364                 g_source_remove(app->scan_timer_id);
365                 app->scan_timer_id = 0;
366         }
367         g_free(app);
368 }
369
370 static void __mesh_client_connected(struct l_dbus *dbus_obj, void *user_data)
371 {
372         ERR("MESH: D-Bus client connected\n");
373         dbus = dbus_obj;
374         if (dbus)
375                 INFO("Mesh: MeshD connected: dbus [%p]", dbus);
376 }
377
378 static void __mesh_client_disconnected(struct l_dbus *dbus_obj, void *user_data)
379 {
380         ERR("MESH: D-Bus client disconnected, possibly meshd exited \n");
381         /* TODO: Send event to app about meshd termination  & then remove all mesh apps */
382         INFO("Mesh: Total number of networks present [%d]",
383                         g_slist_length(mesh_apps));
384
385         if (mesh_apps) {
386                 g_slist_free_full(mesh_apps, __bt_hal_mesh_destroy_app_object);
387                 mesh_apps = NULL;
388         }
389         /* Set DBUS to NULL */
390         if (dbus)
391                 INFO("Mesh: dbus [%p]", dbus);
392         if (net_proxy)
393                 INFO("Mesh: net proxy [%p]", net_proxy);
394
395         dbus = NULL;
396         net_proxy = NULL;
397         INFO("Mesh: All apps cleaned up after meshd exited");
398 }
399
400 static gint __compare_proxy_path(gconstpointer data, gconstpointer user_data)
401 {
402         int ret = 0;
403         char *app_uuid_path;
404         const meshcfg_app *app = (meshcfg_app*) data;
405         char *path = (char *) user_data;
406         if (!path)
407                 return -1;
408
409         app_uuid_path = l_util_hexstring(app->uuid, 16);
410         char **strings =  g_strsplit(path, "node", 2);
411
412         ret = g_strcmp0(strings[1], app_uuid_path);
413         g_free(strings[0]);
414         g_free(strings[1]);
415         l_free(app_uuid_path);
416         return ret;
417 }
418
419 static gint __compare_element_index(gconstpointer data, gconstpointer user_data)
420 {
421         const meshcfg_el *elem = data;
422         uint16_t elem_index = GPOINTER_TO_UINT(user_data);
423         if (!elem)
424                 return 1;
425
426         return (elem->index == elem_index ? 0 : -1);
427 }
428
429 static void __send_network_destroy_event(void *param, uint8_t status)
430 {
431         struct hal_ev_mesh_network_destroyed ev;
432         meshcfg_app *app = (meshcfg_app*)param;
433
434         memset(&ev, 0, sizeof(ev));
435         memcpy(ev.uuid, app->uuid, sizeof(app->uuid));
436         memcpy(ev.token, app->token.u8, 8);
437
438         ev.status = status;
439         if (mesh_event_cb)
440                 mesh_event_cb(HAL_EV_MESH_NETWORK_DESTROYED,
441                         (void*)&ev, sizeof(ev));
442 }
443
444 static void __mesh_proxy_added(struct l_dbus_proxy *proxy, void *user_data)
445 {
446         const char *interface = l_dbus_proxy_get_interface(proxy);
447         const char *path = l_dbus_proxy_get_path(proxy);
448
449         INFO("MESH: Proxy added: %s (%s)\n", interface, path);
450
451         if (!strcmp(interface, BT_HAL_MESH_NETWORK_INTERFACE)) {
452                 struct hal_ev_mesh_network_proxy_added ev;
453                 INFO("Mesh: Network Proxy added");
454
455                 /* Save Global proxy */
456                 net_proxy = proxy;
457                 if (net_proxy)
458                         INFO("Mesh: Net Proxy [%p]", net_proxy);
459
460                 memset(&ev, 0, sizeof(ev));
461                 ev.status = BT_STATUS_SUCCESS;
462
463                 /* Send event cb */
464                 if (mesh_event_cb)
465                         mesh_event_cb(HAL_EV_MESH_NETWORK_PROXY_ADDED,
466                                 (void*)&ev, sizeof(ev));
467
468                 return;
469         }
470
471         if (!strcmp(interface, BT_HAL_MESH_MANAGEMENT_INTERFACE)) {
472                 GSList *l;
473                 meshcfg_app *app;
474                 INFO("Mesh: Mgmt Proxy added");
475                 INFO("Mesh: Number of mesh app present in list [%d]",
476                         g_slist_length(mesh_apps));
477                 l = g_slist_find_custom(mesh_apps, path, __compare_proxy_path);
478                 if (l) {
479                         app = l->data;
480                         app->mgmt_proxy = proxy;
481                 } else {
482                         ERR("Mesh: app not found for Mgmt proxy");
483                 }
484                 return;
485         }
486
487         if (!strcmp(interface, BT_HAL_MESH_NODE_INTERFACE)) {
488                 INFO("Mesh: Node Proxy added");
489                 GSList *l;
490                 meshcfg_app *app;
491                 l = g_slist_find_custom(mesh_apps, path, __compare_proxy_path);
492                 if (l) {
493                         app = l->data;
494                         app->proxy = proxy;
495                 } else {
496                         ERR("Mesh: app not found for Node proxy");
497                 }
498                 return;
499         }
500 }
501
502 static void __mesh_proxy_removed(struct l_dbus_proxy *proxy, void *user_data)
503 {
504         const char *interface = l_dbus_proxy_get_interface(proxy);
505         const char *path = l_dbus_proxy_get_path(proxy);
506
507         INFO("Proxy removed: %s (%s)\n", interface, path);
508
509         if (!strcmp(interface, BT_HAL_MESH_NETWORK_INTERFACE)) {
510                 INFO("Mesh: Network Interface removed,, possibly meshd terminated.\n");
511                 /*TODO: Send event to app about stop of Mesh service  & then remove all apps */
512                 if (mesh_apps) {
513                         g_slist_free_full(mesh_apps, __bt_hal_mesh_destroy_app_object);
514                         mesh_apps = NULL;
515                         return;
516                 }
517         } else if (!strcmp(interface, BT_HAL_MESH_NODE_INTERFACE)) {
518                 INFO("Mesh: Node Interface removed,, possibly node has left network.\n");
519                 GSList *l;
520                 meshcfg_app *app;
521                 l = g_slist_find_custom(mesh_apps, path, __compare_proxy_path);
522                 if (l) {
523                         app = l->data;
524                         /* Send event to app about removal of a mesh local node */
525                         __send_network_destroy_event(app, BT_STATUS_SUCCESS);
526                         __bt_hal_mesh_destroy_app_object(app);
527                 } else {
528                         ERR("Mesh: app not found for Mgmt proxy");
529                 }
530                 return;
531         } else if (!strcmp(interface, BT_HAL_MESH_MANAGEMENT_INTERFACE)) {
532                 INFO("Mesh: Managament Interface removed,, possibly node has left network.\n");
533                 GSList *l;
534                 meshcfg_app *app;
535                 l = g_slist_find_custom(mesh_apps, path, __compare_proxy_path);
536                 if (l) {
537                         app = l->data;
538                         /* Send event to app about removal of a mesh local node */
539                         __send_network_destroy_event(app, BT_STATUS_SUCCESS);
540                         __bt_hal_mesh_destroy_app_object(app);
541                 } else {
542                         ERR("Mesh: app not found for Mgmt proxy");
543                 }
544                 return;
545         }
546 }
547
548 static void __mesh_dbus_client_ready(struct l_dbus_client *client_obj,
549                 void *user_data)
550 {
551         INFO("Mesh: D-Bus client ready: bluetooth-meshd connected \n");
552         client = client_obj;
553 }
554
555 static void __mesh_acquire_name_callback(struct l_dbus *dbus_obj, bool success,
556                                         bool queued, void *user_data)
557 {
558         if (success == false)
559                 ERR("Mesh: Fail to acquire dbus name\n");
560
561         if (!l_dbus_object_manager_enable(dbus_obj, "/"))
562                 ERR("Mesh: Failed to register the ObjectManager\n");
563 }
564
565 static void __mesh_ready_callback(void *user_data)
566 {
567         INFO("Mesh: Connected to D-Bus\n");
568
569         if (!l_dbus_name_acquire(dbus, BT_HAL_MESH_DBUS_NAME, false, false, false,
570                                 __mesh_acquire_name_callback, NULL))
571                 ERR("Mesh: Failed to own well-known name\n");
572 }
573
574 bool _bt_hal_mesh_stack_init(void)
575 {
576         INFO("Mesh: Connect with meshd");
577         /* Connect with meshd */
578         dbus = l_dbus_new_default(L_DBUS_SYSTEM_BUS);
579         if (!dbus)
580                 return false;
581
582         INFO("Mesh: Got dbus [%p]", dbus);
583
584         if (!l_dbus_set_ready_handler(dbus, __mesh_ready_callback, NULL, NULL))
585                 return false;
586
587         client = l_dbus_client_new(dbus,
588                         BT_HAL_BLUEZ_MESH_NAME, "/org/bluez/mesh");
589         if (!client)
590                 return false;
591
592         if (!l_dbus_client_set_connect_handler(client,
593                                 __mesh_client_connected, NULL, NULL))
594                 return false;
595
596         if (!l_dbus_client_set_disconnect_handler(client,
597                                 __mesh_client_disconnected, NULL,
598                                 NULL))
599                 return false;
600         if (!l_dbus_client_set_proxy_handlers(client,
601                                 __mesh_proxy_added, __mesh_proxy_removed,
602                                 NULL, NULL, NULL))
603                 return false;
604         if (!l_dbus_client_set_ready_handler(client,
605                                 __mesh_dbus_client_ready, NULL, NULL))
606                 return false;
607
608         INFO("Mesh: Stack Init watchers registered with  meshd");
609         return true;
610 }
611
612 void _bt_hal_mesh_stack_deinit(void)
613 {
614         INFO("Mesh: Stack Deinit");
615
616         if (client) {
617                 l_dbus_client_destroy(client);
618                 client = NULL;
619         }
620
621         if (dbus) {
622                 l_dbus_destroy(dbus);
623                 dbus = NULL;
624         }
625
626         /* Reset Globals */
627         net_proxy = NULL;
628         agent_msg = NULL;
629         INFO("Mesh: Number of meshapps present in memory [%d]",
630                         g_slist_length(mesh_apps));
631 }
632
633 /* To send stack event to hal-mesh handler */
634 void _bt_hal_mesh_register_dbus_handler_cb(handle_stack_msg cb)
635 {
636         mesh_event_cb = cb;
637 }
638
639 /* To send stack event to hal-mesh handler */
640 void _bt_hal_mesh_unregister_dbus_handler_cb()
641 {
642         mesh_event_cb = NULL;
643 }
644
645 static bool __mesh_get_companyid(struct l_dbus *dbus,
646                 struct l_dbus_message *message,
647                         struct l_dbus_message_builder *builder,
648                                 void *user_data)
649 {
650         meshcfg_app *app = (meshcfg_app*) user_data;
651         if (!app)
652                 return false;
653
654         l_dbus_message_builder_append_basic(builder, 'q', &app->cid);
655
656         return true;
657 }
658
659 static bool __mesh_get_productid(struct l_dbus *dbus,
660                 struct l_dbus_message *message,
661                         struct l_dbus_message_builder *builder,
662                                 void *user_data)
663 {
664         meshcfg_app *app = (meshcfg_app*) user_data;
665         if (!app)
666                 return false;
667         l_dbus_message_builder_append_basic(builder, 'q', &app->pid);
668
669         return true;
670 }
671
672 static bool __mesh_get_versionid(struct l_dbus *dbus,
673                 struct l_dbus_message *message,
674                         struct l_dbus_message_builder *builder,
675                                 void *user_data)
676 {
677         meshcfg_app *app = (meshcfg_app*) user_data;
678         if (!app)
679                 return false;
680         l_dbus_message_builder_append_basic(builder, 'q', &app->vid);
681
682         return true;
683 }
684
685 static bool __mesh_get_crpl(struct l_dbus *dbus,
686                 struct l_dbus_message *message,
687                         struct l_dbus_message_builder *builder,
688                                 void *user_data)
689 {
690         meshcfg_app *app = (meshcfg_app*) user_data;
691         if (!app)
692                 return false;
693         l_dbus_message_builder_append_basic(builder, 'q', &app->crpl);
694
695         return true;
696 }
697
698 static void __send_network_attach_event(void *param, uint8_t status)
699 {
700         struct hal_ev_mesh_network_attached ev;
701         meshcfg_app *app = (meshcfg_app*)param;
702
703         memset(&ev, 0, sizeof(ev));
704         memcpy(ev.uuid, app->uuid, sizeof(app->uuid));
705         memcpy(ev.token, app->token.u8, 8);
706
707         ev.status = status;
708         if (mesh_event_cb)
709                 mesh_event_cb(HAL_EV_MESH_NETWORK_ATTACHED,
710                         (void*)&ev, sizeof(ev));
711 }
712
713 static void __bt_hal_mesh_attach_node_reply(struct l_dbus_proxy *proxy,
714                 struct l_dbus_message *msg, void *user_data)
715 {
716         struct l_dbus_message_iter iter_cfg;
717         char *path;
718         meshcfg_app *app = (meshcfg_app*) user_data;
719         INFO("Mesh: Attach Node Reply: App path [%s] Agent Path [%s]",
720                 app->path, app->agent_path);
721
722         if (l_dbus_message_is_error(msg)) {
723                 const char *name;
724                 l_dbus_message_get_error(msg, &name, NULL);
725                 ERR("Mesh: Failed to attach node: %s", name);
726                 goto failed;
727
728         }
729
730         if (!l_dbus_message_get_arguments(msg, "oa(ya(qa{sv}))",
731                                 &path, &iter_cfg))
732                 goto failed;
733
734         INFO("Mesh: Attached with path %s\n", app->path);
735         __send_network_attach_event(app, BT_STATUS_SUCCESS);
736         return;
737 failed:
738         __send_network_attach_event(app, BT_STATUS_FAIL);
739         /* Destroy mesh app object */
740         __bt_hal_mesh_destroy_app_object(app);
741 }
742
743 static void __bt_hal_mesh_attach_node_setup(struct l_dbus_message *msg,
744                 void *user_data)
745 {
746         meshcfg_app *app = (meshcfg_app*) user_data;
747
748         l_dbus_message_set_arguments(msg, "ot", app->path,
749                         l_get_be64(app->token.u8));
750 }
751
752
753 static void __bt_hal_mesh_attach_node(void *user_data)
754 {
755         if (!l_dbus_proxy_method_call(net_proxy, "Attach",
756                                 __bt_hal_mesh_attach_node_setup,
757                                 __bt_hal_mesh_attach_node_reply,
758                                 user_data,
759                                 NULL)) {
760                 ERR("Mesh: Node attach failed!!");
761                 /* Node could not be attached */
762                 __send_network_attach_event(user_data, BT_STATUS_FAIL);
763                 /* Destroy mesh app object */
764                 __bt_hal_mesh_destroy_app_object((meshcfg_app*)user_data);
765         }
766 }
767
768 static struct l_dbus_message *__mesh_node_join_complete(struct l_dbus *dbus,
769                 struct l_dbus_message *message,
770                         void *user_data)
771 {
772         char *str;
773         uint64_t tmp;
774
775         meshcfg_app *app = (meshcfg_app*) user_data;
776         INFO("Mesh: Join Complete");
777
778         /* Return error */
779         if (!l_dbus_message_get_arguments(message, "t", &tmp)) {
780
781                 /* Send Network creation fail event */
782                 __send_network_attach_event(app, BT_STATUS_FAIL);
783
784                 /* Destroy mesh app object */
785                 __bt_hal_mesh_destroy_app_object(app);
786
787                 return l_dbus_message_new_error(message, dbus_err_args, NULL);
788         }
789
790         /* Save token */
791         app->token.u64 = l_get_be64(&tmp);
792         str = l_util_hexstring(&app->token.u8[0], 8);
793         INFO("Mesh: Created new node with token %s\n", str);
794         l_free(str);
795
796         /* Authenticate the node */
797         l_idle_oneshot(__bt_hal_mesh_attach_node, app, NULL);
798         return l_dbus_message_new_method_return(message);
799 }
800
801 static void __bt_hal_mesh_foreach_model_getter(gpointer data,
802                 gpointer user_data)
803 {
804         struct l_dbus_message_builder *builder = (struct l_dbus_message_builder *) user_data;
805         meshcfg_model *model_info = (meshcfg_model*) data;
806
807         l_dbus_message_builder_append_basic(builder, 'q', &model_info->model);
808 }
809
810 static bool __mesh_model_getter(struct l_dbus *dbus,
811                 struct l_dbus_message *message,
812                         struct l_dbus_message_builder *builder,
813                                 void *user_data)
814 {
815         meshcfg_el *element = (meshcfg_el*) user_data;
816
817         l_dbus_message_builder_enter_array(builder, "q");
818         g_slist_foreach(element->models,
819                 __bt_hal_mesh_foreach_model_getter, builder);
820
821         l_dbus_message_builder_leave_array(builder);
822
823         return true;
824 }
825
826 /*TODO: Vendor Model handling is currently not Handled */
827 static bool __mesh_vendor_model_getter(struct l_dbus *dbus,
828                 struct l_dbus_message *message,
829                         struct l_dbus_message_builder *builder,
830                                 void *user_data)
831 {
832         l_dbus_message_builder_enter_array(builder, "(qq)");
833         l_dbus_message_builder_leave_array(builder);
834
835         return true;
836 }
837
838 static bool __mesh_element_index_getter(struct l_dbus *dbus,
839                 struct l_dbus_message *message,
840                         struct l_dbus_message_builder *builder,
841                                 void *user_data)
842 {
843         meshcfg_el *element = (meshcfg_el*) user_data;
844         l_dbus_message_builder_append_basic(builder, 'y', &element->index);
845
846         return true;
847 }
848
849
850 static struct l_dbus_message *__mesh_device_message_received(struct l_dbus *dbus,
851                 struct l_dbus_message *msg, void *user_data)
852 {
853         struct l_dbus_message_iter iter;
854         uint16_t src, idx;
855         uint8_t *data;
856         uint32_t n;
857         bool rmt;
858         const char *dbus_path;
859         uint16_t size;
860         uint8_t *net_uuid;
861         dbus_path =  l_dbus_message_get_path(msg);
862         net_uuid = __mesh_get_net_uuid_from_path(dbus_path, true,  MESH_ELEMENT_IFACE);
863         uint8_t buf[BT_HAL_MESH_MAX_DEVKEY_BUF_SIZE];
864         struct hal_ev_mesh_devkey_message_event *ev = (void *)buf;
865
866         INFO("Mesh: app path [%s]", dbus_path);
867
868         memset(buf, 0, sizeof(buf));
869         size = (uint16_t) sizeof(*ev);
870         memcpy(ev->net_uuid, net_uuid, 16);
871         g_free(net_uuid);
872
873         if (!l_dbus_message_get_arguments(msg, "qbqay", &src, &rmt, &idx,
874                                 &iter)) {
875                 ERR("Mesh: Cannot parse received message");
876                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
877         }
878
879         if (!l_dbus_message_iter_get_fixed_array(&iter, &data, &n)) {
880                 ERR("Mesh: Cannot parse received message: data");
881                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
882         }
883
884         INFO("Mesh: Received dev key message (len %u):", n);
885         ev->source_addr = src;
886         ev->is_remote_devkey = rmt;
887         ev->netkey_idx = idx;
888         ev->data_len = n;
889         memcpy(ev->data, data, n);
890         size += n;
891
892         INFO("Mesh: Src [0x%2.2x]", src);
893         INFO("Mesh: Is Remote [%s]", rmt ? "YES" : "NO");
894         INFO("Mesh: NetKey Idx [0x%2.2x]", idx);
895         /* Send DevKeyMessage Received event */
896         if (mesh_event_cb)
897                 mesh_event_cb(HAL_EV_MESH_DEVKEY_MESSAGE_EVENT, (void*)buf, size);
898         return l_dbus_message_new_method_return(msg);
899 }
900
901 static struct l_dbus_message *__mesh_message_received(struct l_dbus *dbus,
902                 struct l_dbus_message *msg, void *user_data)
903 {
904         struct l_dbus_message_iter iter;
905         uint16_t src, idx, dst;
906         uint8_t *data;
907         uint32_t n;
908         const char *dbus_path;
909         uint16_t size;
910         uint8_t *net_uuid;
911         dbus_path =  l_dbus_message_get_path(msg);
912         net_uuid = __mesh_get_net_uuid_from_path(dbus_path, true,  MESH_ELEMENT_IFACE);
913         uint8_t buf[BT_HAL_MESH_MAX_MSG_BUF_SIZE];
914         struct hal_ev_mesh_message_event *ev = (void *)buf;
915
916         INFO("Mesh: app path [%s]", dbus_path);
917
918         memset(buf, 0, sizeof(buf));
919         size = (uint16_t) sizeof(*ev);
920         memcpy(ev->net_uuid, net_uuid, 16);
921         g_free(net_uuid);
922
923         if (!l_dbus_message_get_arguments(msg, "qqvay", &src, &idx, &dst,
924                                 &iter)) {
925                 ERR("Mesh: Cannot parse received message");
926                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
927         }
928
929         if (!l_dbus_message_iter_get_fixed_array(&iter, &data, &n)) {
930                 ERR("Mesh: Cannot parse received message: data");
931                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
932         }
933
934         INFO("Mesh: Received mesh message (len %u):", n);
935         ev->source_addr = src;
936         ev->dest_addr = dst;
937         ev->key_idx = idx;
938         ev->data_len = n;
939         memcpy(ev->data, data, n);
940         size += n;
941
942         INFO("Mesh: Src [0x%2.2x]", src);
943         INFO("Mesh: Dst [0x%2.2x]", dst);
944         INFO("Mesh: NetKey Idx [0x%2.2x]", idx);
945         /* Send Message Received event */
946         if (mesh_event_cb) {
947                 INFO("Mesh: Send message event");
948                 mesh_event_cb(HAL_EV_MESH_MESSAGE_EVENT, (void*)buf, size);
949         }
950         return l_dbus_message_new_method_return(msg);
951 }
952
953 static void __bt_hal_mesh_setup_ele_iface(struct l_dbus_interface *iface)
954 {
955         INFO("Mesh: Setup element interface properties & methods");
956         /* Properties */
957         l_dbus_interface_property(iface, "Index", 0, "y", __mesh_element_index_getter,
958                         NULL);
959         l_dbus_interface_property(iface, "VendorModels", 0, "a(qq)",
960                         __mesh_vendor_model_getter, NULL);
961         l_dbus_interface_property(iface, "Models", 0, "aq", __mesh_model_getter, NULL);
962
963         /* Methods */
964         l_dbus_interface_method(iface, "DevKeyMessageReceived", 0,
965                         __mesh_device_message_received, "", "qbqay", "source",
966                         "remote", "net_index", "data");
967         l_dbus_interface_method(iface, "MessageReceived", 0,
968                         __mesh_message_received, "", "qqvay", "source",
969                         "key_index", "destination", "data");
970         /* TODO: Other methods */
971 }
972
973 static struct l_dbus_message *__mesh_scan_result_received(struct l_dbus *dbus,
974                 struct l_dbus_message *msg,
975                         void *user_data)
976 {
977         struct l_dbus_message_iter iter, opts;
978         meshcfg_app *app = (meshcfg_app*) user_data;
979         int16_t rssi;
980         uint32_t n;
981         uint8_t *prov_data;
982         char *str;
983         const char *sig = "naya{sv}";
984
985         /* Find network uuid from dbus path */
986         struct hal_ev_mesh_scan_result ev;
987
988         if (!app->scan_timer_id) {
989                 /* Scan is not running */
990                 INFO("Got scan result, but scan is already stopped");
991                 return l_dbus_message_new_method_return(msg);
992         }
993         memset(&ev, 0, sizeof(ev));
994         memcpy(ev.net_uuid, app->uuid, 16);
995
996         if (!l_dbus_message_get_arguments(msg, sig, &rssi, &iter, &opts)) {
997                 ERR("Mesh: Cannot parse scan results");
998                 ev.status = BT_STATUS_FAIL;
999                 if (mesh_event_cb)
1000                         mesh_event_cb(HAL_EV_MESH_SCAN_RESULT, (void*)&ev, sizeof(ev));
1001                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
1002         }
1003
1004         if (!l_dbus_message_iter_get_fixed_array(&iter, &prov_data, &n) ||
1005                         n < 16) {
1006                 ERR("Mesh: Cannot parse scan result: data");
1007                 ev.status = BT_STATUS_FAIL;
1008                 if (mesh_event_cb)
1009                         mesh_event_cb(HAL_EV_MESH_SCAN_RESULT, (void*)&ev, sizeof(ev));
1010                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
1011         }
1012
1013         INFO("Mesh: Scan result:\n");
1014         INFO("Mesh: Scan rssi = [%d]\n", rssi);
1015         str = l_util_hexstring_upper(prov_data, 16);
1016         INFO("Mesh: Scan UUID = [%s]\n",  str);
1017         l_free(str);
1018
1019         if (n >= 18) {
1020                 str = l_util_hexstring_upper(prov_data + 16, 2);
1021                 INFO("Mesh: Scan OOB = [%s]\n", str);
1022                 l_free(str);
1023         }
1024
1025         if (n >= 22) {
1026                 str = l_util_hexstring_upper(prov_data + 18, 4);
1027                 INFO("Mesh: Scan URI hash = [%s]\n", str);
1028                 l_free(str);
1029         }
1030
1031         /* 16 octet Dev UUID */
1032         memcpy(ev.dev_uuid, prov_data, 16);
1033
1034         /* 2 octet Dev OOB Info */
1035         memcpy(ev.oob_info, prov_data + 16, 2);
1036
1037         /* 4 octet URI Hash */
1038         memcpy(ev.uri_hash, prov_data + 18, 4);
1039
1040         ev.rssi = rssi;
1041
1042         ev.status = BT_STATUS_SUCCESS;
1043         if (mesh_event_cb)
1044                 mesh_event_cb(HAL_EV_MESH_SCAN_RESULT,
1045                         (void*)&ev, sizeof(ev));
1046
1047         return l_dbus_message_new_method_return(msg);
1048 }
1049
1050 static struct l_dbus_message *__mesh_request_provisioner_call(
1051                 struct l_dbus *dbus,
1052                         struct l_dbus_message *msg,
1053                                 void *user_data)
1054 {
1055         uint8_t cnt;
1056         struct hal_ev_mesh_provision_finished ev;
1057         struct hal_ev_mesh_provision_data_request req;
1058         char *uuid_string;
1059         meshcfg_app *app = user_data;
1060
1061         INFO("Mesh: provisioning data requested app path [%s]",
1062                 app->path);
1063         uuid_string = l_util_hexstring(app->uuid, 16);
1064         INFO("Mesh: Network UUID [%s]", uuid_string);
1065
1066         memset(&ev, 0, sizeof(ev));
1067         memset(&req, 0, sizeof(req));
1068         memcpy(ev.net_uuid, app->uuid, 16);
1069         memcpy(req.net_uuid, app->uuid, 16);
1070         l_free(uuid_string);
1071
1072         if (!l_dbus_message_get_arguments(msg, "y", &cnt)) {
1073                 ERR("Mesh: Cannot parse request for prov data");
1074                 /* Send Event */
1075                 ev.status = BT_STATUS_FAIL;
1076                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1077                 if (mesh_event_cb)
1078                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1079                                 (void*)&ev, sizeof(ev));
1080                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
1081         }
1082
1083         app->msg = msg;
1084         req.count = cnt;
1085         if (mesh_event_cb)
1086                 mesh_event_cb(HAL_EV_MESH_PROVISIONING_DATA_REQUEST,
1087                         (void*)&req, sizeof(req));
1088
1089         l_dbus_message_ref(msg);
1090         return NULL;
1091 }
1092
1093 static struct l_dbus_message *__mesh_node_add_completed(
1094                 struct l_dbus *dbus,
1095                         struct l_dbus_message *msg,
1096                                 void *user_data)
1097 {
1098         struct l_dbus_message_iter iter;
1099         int16_t unicast;
1100         uint8_t cnt;
1101         uint32_t n;
1102         uint8_t *uuid;
1103         struct hal_ev_mesh_provision_finished ev;
1104         const char *dbus_path;
1105         uint8_t *net_uuid;
1106         dbus_path =  l_dbus_message_get_path(msg);
1107         net_uuid = __mesh_get_net_uuid_from_path(dbus_path,
1108                         true,  MESH_PROV_IFACE);
1109
1110         INFO("Mesh: app path [%s]", dbus_path);
1111
1112         memset(&ev, 0, sizeof(ev));
1113         memcpy(ev.net_uuid, net_uuid, 16);
1114
1115         g_free(net_uuid);
1116
1117         if (!l_dbus_message_get_arguments(msg, "ayqy", &iter, &unicast, &cnt)) {
1118                 ERR("Mesh: Cannot parse add node complete message");
1119                 /* Send Event */
1120                 ev.status = BT_STATUS_FAIL;
1121                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1122                 if (mesh_event_cb)
1123                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1124                                 (void*)&ev, sizeof(ev));
1125                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
1126         }
1127
1128         if (!l_dbus_message_iter_get_fixed_array(&iter, &uuid, &n) ||
1129                         n != 16) {
1130                 ERR("Mesh: Cannot parse add node complete message: uuid");
1131                 /* Send Event */
1132                 ev.status = BT_STATUS_FAIL;
1133                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1134                 if (mesh_event_cb)
1135                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1136                                 (void*)&ev, sizeof(ev));
1137                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
1138         }
1139
1140         /* Send Event */
1141         ev.status = BT_STATUS_SUCCESS;
1142         ev.reason = BT_HAL_MESH_PROV_ERR_SUCCESS;
1143         memcpy(ev.dev_uuid, uuid, 16);
1144         ev.unicast = unicast;
1145         ev.count = cnt;
1146
1147         if (mesh_event_cb)
1148                 mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1149                         (void*)&ev, sizeof(ev));
1150
1151         return l_dbus_message_new_method_return(msg);
1152 }
1153
1154 static struct l_dbus_message *__mesh_node_add_failed(
1155                 struct l_dbus *dbus,
1156                         struct l_dbus_message *msg,
1157                                 void *user_data)
1158 {
1159         struct l_dbus_message_iter iter;
1160         uint32_t n;
1161         uint8_t *uuid;
1162         char *str, *reason;
1163         struct hal_ev_mesh_provision_finished ev;
1164         const char *dbus_path;
1165
1166         uint8_t *net_uuid;
1167         dbus_path =  l_dbus_message_get_path(msg);
1168         net_uuid = __mesh_get_net_uuid_from_path(dbus_path,
1169                         true,  MESH_PROV_IFACE);
1170
1171         memset(&ev, 0, sizeof(ev));
1172         memcpy(ev.net_uuid, net_uuid, 16);
1173
1174         g_free(net_uuid);
1175         if (!l_dbus_message_get_arguments(msg, "ays", &iter, &reason)) {
1176                 ERR("Mesh: Cannot parse add node failed message");
1177                 /* Send Event */
1178                 ev.status = BT_STATUS_FAIL;
1179                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1180                 if (mesh_event_cb)
1181                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1182                                 (void*)&ev, sizeof(ev));
1183                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
1184         }
1185
1186         if (!l_dbus_message_iter_get_fixed_array(&iter, &uuid, &n) ||
1187                         n != 16) {
1188                 ERR("Mesh:Cannot parse add node failed message: uuid");
1189                 ev.status = BT_STATUS_FAIL;
1190                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1191                 if (mesh_event_cb)
1192                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1193                                 (void*)&ev, sizeof(ev));
1194                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
1195         }
1196
1197         INFO("Mesh: Provisioning failed:\n");
1198         str = l_util_hexstring_upper(uuid, 16);
1199         INFO("Mesh: UUID = [%s] Reason [%s]", str, reason);
1200         l_free(str);
1201
1202         ev.status = BT_STATUS_FAIL;
1203         ev.reason = __bt_mesh_util_get_prov_error_code(str);
1204         memcpy(ev.dev_uuid, uuid, 16);
1205
1206         if (mesh_event_cb)
1207                 mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1208                         (void*)&ev, sizeof(ev));
1209
1210         return l_dbus_message_new_method_return(msg);
1211 }
1212
1213 static void __bt_hal_mesh_setup_prov_iface(struct l_dbus_interface *interface)
1214 {
1215         INFO("Mesh: Setup provisioner interface properties & methods");
1216         l_dbus_interface_method(interface, "ScanResult", 0,
1217                         __mesh_scan_result_received, "",
1218                         "naya{sv}", "rssi", "data", "options");
1219
1220         l_dbus_interface_method(interface, "RequestProvData", 0,
1221                         __mesh_request_provisioner_call,
1222                         "qq", "y", "net_index", "unicast", "count");
1223
1224         l_dbus_interface_method(interface, "AddNodeComplete", 0,
1225                         __mesh_node_add_completed, "", "ayqy",
1226                         "uuid", "unicast", "count");
1227
1228         l_dbus_interface_method(interface, "AddNodeFailed", 0,
1229                         __mesh_node_add_failed,
1230                         "", "ays", "uuid", "reason");
1231 }
1232
1233 static void __bt_hal_mesh_setup_app_iface(struct l_dbus_interface *iface)
1234 {
1235         INFO("Mesh: Setup application interface properties & methods");
1236
1237         l_dbus_interface_property(iface, "CompanyID", 0, "q",
1238                         __mesh_get_companyid,
1239                         NULL);
1240         l_dbus_interface_property(iface, "VersionID", 0, "q",
1241                         __mesh_get_versionid,
1242                         NULL);
1243         l_dbus_interface_property(iface, "ProductID", 0, "q",
1244                         __mesh_get_productid,
1245                         NULL);
1246         l_dbus_interface_property(iface, "CRPL", 0, "q",
1247                         __mesh_get_crpl, NULL);
1248         l_dbus_interface_method(iface, "JoinComplete", 0,
1249                         __mesh_node_join_complete,
1250                         "", "t", "token");
1251
1252         /* TODO: Methods */
1253 }
1254
1255 static void __mesh_fill_in_capabilities(meshcfg_app *app,
1256                  struct l_dbus_message_builder *builder)
1257 {
1258         if (app->in_oob & 0x08)
1259                 l_dbus_message_builder_append_basic(builder, 's', "in-alpha");
1260         if (app->in_oob & 0x04)
1261                 l_dbus_message_builder_append_basic(builder, 's', "in-numeric");
1262         if (app->in_oob & 0x02)
1263                 l_dbus_message_builder_append_basic(builder, 's', "twist");
1264         if (app->in_oob & 0x01)
1265                 l_dbus_message_builder_append_basic(builder, 's', "push");
1266 }
1267
1268 static void __mesh_fill_out_capabilities(meshcfg_app *app,
1269                  struct l_dbus_message_builder *builder)
1270 {
1271         if (app->out_oob & 0x10)
1272                 l_dbus_message_builder_append_basic(builder, 's', "out-alpha");
1273         if (app->out_oob & 0x08)
1274                 l_dbus_message_builder_append_basic(builder, 's', "out-numeric");
1275         if (app->out_oob & 0x04)
1276                 l_dbus_message_builder_append_basic(builder, 's', "vibrate");
1277         if (app->out_oob & 0x02)
1278                 l_dbus_message_builder_append_basic(builder, 's', "beep");
1279         if (app->out_oob & 0x01)
1280                 l_dbus_message_builder_append_basic(builder, 's', "blink");
1281 }
1282
1283 static bool __mesh_agent_capability_getter(
1284                 struct l_dbus *dbus, struct l_dbus_message *message,
1285                         struct l_dbus_message_builder *builder,
1286                                 void *user_data)
1287 {
1288         meshcfg_app *app;
1289         app = user_data;
1290         INFO("Mesh: app path [%s]", app->path);
1291         INFO("Mesh: Agent path [%s]", app->agent_path);
1292
1293         if (!l_dbus_message_builder_enter_array(builder, "s"))
1294                 return false;
1295
1296         __mesh_fill_out_capabilities(app, builder);
1297         __mesh_fill_in_capabilities(app, builder);
1298
1299         if (app->static_oob)
1300                 l_dbus_message_builder_append_basic(builder,
1301                         's', "static-oob");
1302
1303
1304         l_dbus_message_builder_leave_array(builder);
1305         INFO("Mesh: __agent_capability_getter: Success");
1306         return true;
1307 }
1308
1309 static struct l_dbus_message *__mesh_agent_display_string_request(
1310                 struct l_dbus *dbus,
1311                         struct l_dbus_message *msg,
1312                                 void *user_data)
1313 {
1314         struct hal_ev_mesh_authentication_request ev;
1315         char *str;
1316         uint8_t *net_uuid;
1317         const char *dbus_path;
1318         meshcfg_app *app;
1319         app = user_data;
1320         INFO("Mesh: app path [%s]", app->path);
1321         INFO("Mesh: Agent path [%s]", app->agent_path);
1322
1323         dbus_path =  l_dbus_message_get_path(msg);
1324         net_uuid = __mesh_get_net_uuid_from_path(app->agent_path,
1325                         true,  MESH_AGENT_IFACE);
1326
1327         INFO("Mesh: app path [%s]", dbus_path);
1328
1329         memset(&ev, 0, sizeof(ev));
1330         memcpy(ev.net_uuid, net_uuid, 16);
1331
1332
1333         if (!l_dbus_message_get_arguments(msg, "s", &str)) {
1334                 ERR("Mesh: Cannot parse \"DisplayString\" arguments");
1335                 struct hal_ev_mesh_provision_finished ev;
1336                 memset(&ev, 0, sizeof(ev));
1337                 memcpy(ev.net_uuid, net_uuid, 16);
1338                 ev.status = BT_STATUS_FAIL;
1339                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1340                 if (mesh_event_cb)
1341                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1342                                 (void*)&ev, sizeof(ev));
1343
1344                 g_free(net_uuid);
1345
1346                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1347         }
1348
1349         INFO("Mesh:[OUT] AlphaNumeric Authentication: Value [%s]", str);
1350         ev.auth_type = __mesh_get_authentication_type(str);
1351         if (ev.auth_type == BT_HAL_MESH_UNKNOWN_AUTH_METHOD)
1352                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1353         g_strlcpy(ev.auth_value, str, sizeof(ev.auth_value));
1354
1355         if (mesh_event_cb)
1356                 mesh_event_cb(HAL_EV_MESH_AUTHENTICATION_REQUEST,
1357                         (void*)&ev, sizeof(ev));
1358
1359         g_free(net_uuid);
1360         return l_dbus_message_new_method_return(msg);
1361 }
1362
1363 static struct l_dbus_message *__mesh_agent_display_numeric_request(
1364                 struct l_dbus *dbus,
1365                         struct l_dbus_message *msg,
1366                                 void *user_data)
1367 {
1368         uint32_t n;
1369         struct hal_ev_mesh_authentication_request ev;
1370         char *str;
1371         char *auth_value;
1372         uint8_t *net_uuid;
1373         const char *dbus_path;
1374         meshcfg_app *app;
1375         app = user_data;
1376         INFO("Mesh: app path [%s]", app->path);
1377         INFO("Mesh: Agent path [%s]", app->agent_path);
1378
1379         dbus_path =  l_dbus_message_get_path(msg);
1380         net_uuid = __mesh_get_net_uuid_from_path(app->agent_path,
1381                                 true,  MESH_AGENT_IFACE);
1382
1383         INFO("Mesh: app path [%s]", dbus_path);
1384
1385         memset(&ev, 0, sizeof(ev));
1386         memcpy(ev.net_uuid, net_uuid, 16);
1387
1388
1389         if (!l_dbus_message_get_arguments(msg, "su", &str, &n)) {
1390                 ERR("Mesh: Cannot parse \"DisplayNumeric\" arguments");
1391                 struct hal_ev_mesh_provision_finished ev;
1392                 memset(&ev, 0, sizeof(ev));
1393                 memcpy(ev.net_uuid, net_uuid, 16);
1394                 ev.status = BT_STATUS_FAIL;
1395                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1396                 if (mesh_event_cb) {
1397                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1398                                 (void*)&ev, sizeof(ev));
1399                 }
1400                 g_free(net_uuid);
1401                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1402         }
1403
1404         INFO("Mesh:[OUT] Numeric Authentication type [%s] value [%u]", str, n);
1405         auth_value = l_strdup_printf("%u", n);
1406         ev.auth_type = __mesh_get_authentication_type(str);
1407         if (ev.auth_type == BT_HAL_MESH_UNKNOWN_AUTH_METHOD)
1408                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1409         g_strlcpy(ev.auth_value, auth_value, sizeof(ev.auth_value));
1410
1411         if (mesh_event_cb)
1412                 mesh_event_cb(HAL_EV_MESH_AUTHENTICATION_REQUEST,
1413                         (void*)&ev, sizeof(ev));
1414
1415         g_free(net_uuid);
1416
1417         return l_dbus_message_new_method_return(msg);
1418 }
1419
1420 static struct l_dbus_message *__mesh_agent_prompt_numeric_request(
1421                 struct l_dbus *dbus,
1422                         struct l_dbus_message *msg,
1423                                 void *user_data)
1424 {
1425         struct hal_ev_mesh_authentication_request ev;
1426         char *str;
1427         uint8_t *net_uuid;
1428         const char *dbus_path;
1429         GSList *l;
1430         meshcfg_app *app;
1431
1432         dbus_path =  l_dbus_message_get_path(msg);
1433         net_uuid = __mesh_get_net_uuid_from_path(dbus_path,
1434                         true,  MESH_AGENT_IFACE);
1435
1436         INFO("Mesh: app path [%s]", dbus_path);
1437
1438         l = g_slist_find_custom(mesh_apps, net_uuid,
1439                         __mesh_compare_network_uuid);
1440         if (!l) {
1441                 g_free(net_uuid);
1442                 return NULL;
1443         }
1444         app = l->data;
1445
1446         memset(&ev, 0, sizeof(ev));
1447         memcpy(ev.net_uuid, net_uuid, 16);
1448
1449         g_free(net_uuid);
1450         if (!l_dbus_message_get_arguments(msg, "s", &str)) {
1451                 ERR("Mesh: Cannot parse \"PromptNumeric\" arguments");
1452
1453                 struct hal_ev_mesh_provision_finished ev;
1454                 memset(&ev, 0, sizeof(ev));
1455                 memcpy(ev.net_uuid, app->uuid, 16);
1456                 ev.status = BT_STATUS_FAIL;
1457                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1458                 if (mesh_event_cb) {
1459                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1460                                 (void*)&ev, sizeof(ev));
1461                 }
1462                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1463         }
1464
1465         INFO("Mesh:[IN] Numeric Authentication type [%s]", str);
1466
1467         ev.auth_type = __mesh_get_authentication_type(str);
1468         if (ev.auth_type == BT_HAL_MESH_UNKNOWN_AUTH_METHOD)
1469                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1470         agent_msg = msg;
1471         l_dbus_message_ref(msg);
1472         if (mesh_event_cb)
1473                 mesh_event_cb(HAL_EV_MESH_AUTHENTICATION_REQUEST,
1474                         (void*)&ev, sizeof(ev));
1475
1476         return NULL;
1477 }
1478
1479 static struct l_dbus_message *__mesh_agent_prompt_static_request(
1480                 struct l_dbus *dbus,
1481                         struct l_dbus_message *msg,
1482                                 void *user_data)
1483 {
1484         struct hal_ev_mesh_authentication_request ev;
1485         char *str;
1486         uint8_t *net_uuid;
1487         const char *dbus_path;
1488         GSList *l;
1489         meshcfg_app *app = NULL;
1490
1491         dbus_path =  l_dbus_message_get_path(msg);
1492         net_uuid = __mesh_get_net_uuid_from_path(dbus_path, true,
1493                         MESH_AGENT_IFACE);
1494
1495         INFO("Mesh: app path [%s]", dbus_path);
1496
1497         l = g_slist_find_custom(mesh_apps, net_uuid,
1498                         __mesh_compare_network_uuid);
1499
1500         if (l)
1501                 app = l->data;
1502         else
1503                 ERR("Mesh: app not found");
1504
1505
1506         memset(&ev, 0, sizeof(ev));
1507         memcpy(ev.net_uuid, net_uuid, 16);
1508
1509         g_free(net_uuid);
1510         if (!l_dbus_message_get_arguments(msg, "s", &str)) {
1511                 ERR("Mesh: Cannot parse \"PromptNumeric\" arguments");
1512
1513                 struct hal_ev_mesh_provision_finished ev;
1514                 memset(&ev, 0, sizeof(ev));
1515
1516                 if (app)
1517                         memcpy(ev.net_uuid, app->uuid, 16);
1518
1519                 ev.status = BT_STATUS_FAIL;
1520                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1521                 if (mesh_event_cb)
1522                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1523                                         (void*)&ev, sizeof(ev));
1524                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1525         }
1526
1527         INFO("Mesh: [IN] AlphaNumeric Authentication type [%s]", str);
1528
1529         ev.auth_type = __mesh_get_authentication_type(str);
1530         if (ev.auth_type == BT_HAL_MESH_UNKNOWN_AUTH_METHOD)
1531                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1532         agent_msg = msg;
1533         l_dbus_message_ref(msg);
1534         if (mesh_event_cb)
1535                 mesh_event_cb(HAL_EV_MESH_AUTHENTICATION_REQUEST,
1536                                 (void*)&ev, sizeof(ev));
1537
1538         return NULL;
1539 }
1540
1541 static void __bt_hal_mesh_setup_agent_iface(struct l_dbus_interface *interface)
1542 {
1543         INFO("Mesh: Setup Agent interface properties & methods");
1544         l_dbus_interface_property(interface, "Capabilities", 0, "as",
1545                         __mesh_agent_capability_getter,
1546                         NULL);
1547         /* TODO: Other properties */
1548         l_dbus_interface_method(interface, "DisplayString", 0,
1549                         __mesh_agent_display_string_request,
1550                         "", "s", "value");
1551         l_dbus_interface_method(interface, "DisplayNumeric", 0,
1552                         __mesh_agent_display_numeric_request,
1553                         "", "su", "type", "number");
1554         l_dbus_interface_method(interface, "PromptNumeric", 0,
1555                         __mesh_agent_prompt_numeric_request,
1556                         "u", "s", "number", "type");
1557         l_dbus_interface_method(interface, "PromptStatic", 0,
1558                         __mesh_agent_prompt_static_request,
1559                         "ay", "s", "data", "type");
1560 }
1561
1562 static void __bt_hal_mesh_register_element_obj(gpointer data, gpointer user_data)
1563 {
1564         meshcfg_el *elem = (meshcfg_el*) data;
1565         INFO("Mesh: Register Element: Index [%d] elem path [%s]",
1566                 elem->index, elem->path);
1567         if (!l_dbus_register_object(dbus, elem->path, NULL, NULL,
1568                                 BT_HAL_MESH_ELEMENT_INTERFACE, elem, NULL)) {
1569                 ERR("Mesh: Failed to register object %s", elem->path);
1570         }
1571 }
1572
1573 bool __bt_hal_mesh_register_agent(meshcfg_app *ptr)
1574 {
1575         if (!ptr)
1576                 return false;
1577
1578         if (!l_dbus_register_interface(dbus, BT_HAL_MESH_PROVISION_AGENT_INTERFACE,
1579                                 __bt_hal_mesh_setup_agent_iface, NULL, false)) {
1580                 ERR("Mesh: Unable to register agent interface");
1581                 //return false;
1582         }
1583
1584         INFO("Mesh: Register Agent path [%s]",  ptr->agent_path);
1585         if (!l_dbus_register_object(dbus, ptr->agent_path, NULL, NULL,
1586                                 BT_HAL_MESH_PROVISION_AGENT_INTERFACE, ptr, NULL)) {
1587                 ERR("Mesh: Failed to register object %s", ptr->agent_path);
1588                 return false;
1589         }
1590
1591         if (!l_dbus_object_add_interface(dbus, ptr->agent_path,
1592                                 L_DBUS_INTERFACE_PROPERTIES, NULL)) {
1593                 ERR("Mesh: Failed to add interface %s",
1594                                 L_DBUS_INTERFACE_PROPERTIES);
1595                 return false;
1596         }
1597
1598         return true;
1599 }
1600
1601 bool __bt_hal_mesh_register_application(meshcfg_app *ptr)
1602 {
1603
1604         if (!ptr)
1605                 return false;
1606         if (!dbus)
1607                 return false;
1608
1609         if (!l_dbus_register_interface(dbus, BT_HAL_MESH_APPLICATION_INTERFACE,
1610                                 __bt_hal_mesh_setup_app_iface, NULL, false)) {
1611                 ERR("Mesh: Failed to register interface %s",
1612                                 BT_HAL_MESH_APPLICATION_INTERFACE);
1613                 //return false;
1614         }
1615
1616         if (!l_dbus_register_interface(dbus, BT_HAL_MESH_PROVISIONER_INTERFACE,
1617                                 __bt_hal_mesh_setup_prov_iface, NULL, false)) {
1618                 ERR("Mesh: Failed to register interface %s",
1619                                 BT_HAL_MESH_PROVISIONER_INTERFACE);
1620                 //return false;
1621         }
1622
1623         if (!l_dbus_register_object(dbus, ptr->path, NULL, NULL,
1624                                 BT_HAL_MESH_APPLICATION_INTERFACE, ptr,
1625                                 BT_HAL_MESH_PROVISIONER_INTERFACE, ptr,
1626                                 NULL)) {
1627                 ERR("Mesh: Failed to register object %s", ptr->path);
1628                 return false;
1629         }
1630
1631         if (!__bt_hal_mesh_register_agent(ptr))
1632                 return false;
1633
1634         if (!l_dbus_register_interface(dbus, BT_HAL_MESH_ELEMENT_INTERFACE,
1635                                 __bt_hal_mesh_setup_ele_iface, NULL, false)) {
1636                 ERR("Mesh: Failed to register interface %s",
1637                                 BT_HAL_MESH_ELEMENT_INTERFACE);
1638                 //return false;
1639         }
1640
1641         INFO("Mesh: Number of elements to be registsred [%d]",
1642                         g_slist_length(ptr->elements));
1643
1644         g_slist_foreach(ptr->elements, __bt_hal_mesh_register_element_obj, ptr);
1645
1646         INFO("Mesh: Add Object manager Interface: app path [%s]", ptr->path);
1647         if (!l_dbus_object_add_interface(dbus, ptr->path,
1648                                 L_DBUS_INTERFACE_OBJECT_MANAGER, NULL)) {
1649                 ERR("Mesh: Failed to add interface %s",
1650                                 L_DBUS_INTERFACE_OBJECT_MANAGER);
1651                 return false;
1652         }
1653         INFO("Mesh: Application Register completed");
1654
1655         return true;
1656 }
1657
1658 static void __bt_mesh_hal_create_element_object(gpointer data, gpointer user_data)
1659 {
1660         GSList *l;
1661         meshcfg_el *elem;
1662         meshcfg_model *model_info = (meshcfg_model*) data;
1663         meshcfg_app *app = (meshcfg_app*) user_data;
1664
1665         l = g_slist_find_custom(app->elements,
1666                 GUINT_TO_POINTER(model_info->elem_index), __compare_element_index);
1667         if (l) {
1668                 elem = l->data;
1669         } else {
1670                 elem = g_malloc0(sizeof(meshcfg_el));
1671                 elem->index = model_info->elem_index;
1672                 elem->path = g_strdup_printf("%s/elem%u", app->path, elem->index);
1673                 app->elements = g_slist_append(app->elements, elem);
1674                 INFO("Mesh: Created element index [%d] path [%s]",
1675                         elem->index, elem->path);
1676         }
1677         INFO("Mesh: This is model [0x%4.4x] for Element [0x%2.2x]",
1678                 model_info->model, elem->index);
1679         /* Add Model in the element */
1680         elem->models = g_slist_append(elem->models, model_info);
1681         INFO("Mesh: Model added in element: total Model count in elem [%d] is [%d]",
1682                         elem->index, g_slist_length(elem->models));
1683 }
1684
1685 meshcfg_app *__bt_hal_mesh_create_app(bt_hal_mesh_node_t *node,
1686                 GSList *models, bool is_prov)
1687 {
1688         uint8_t uuid[16];
1689         meshcfg_app *app = NULL;
1690         char *uuid_str = NULL;
1691
1692         uuid_str = l_util_hexstring(node->uuid.uu, sizeof(uuid));
1693         INFO("Mesh: Network UUID [%s]", uuid_str);
1694
1695         app = g_malloc0(sizeof(meshcfg_app));
1696         memcpy(app->uuid, node->uuid.uu, sizeof(uuid));
1697
1698         app->cid = node->vendor_info.companyid;
1699         app->pid = node->vendor_info.vendorid;
1700         app->vid =  node->vendor_info.versionid;
1701         app->crpl = node->vendor_info.crpl;
1702
1703         if (is_prov) {
1704                 app->path = g_strdup_printf("/tizen/mesh/cfg/%s", uuid_str);
1705                 app->agent_path = g_strdup_printf("%s/agent", app->path);
1706
1707         } else {
1708                 app->path = g_strdup_printf("/tizen/mesh/node/%s", uuid_str);
1709                 app->agent_path = g_strdup_printf("%s/agent", app->path);
1710         }
1711         g_slist_foreach(models, __bt_mesh_hal_create_element_object, app);
1712
1713         g_free(uuid_str);
1714         app->is_prov = is_prov;
1715         app->token.u64 = node->token.u64;
1716         INFO("Mesh: Token [%llu]", (unsigned long long int)app->token.u64);
1717         INFO("Mesh: app created");
1718         return app;
1719 }
1720
1721 static void __bt_hal_mesh_leave_net_reply(
1722                 struct l_dbus_proxy *proxy,
1723                         struct l_dbus_message *msg, void *user_data)
1724 {
1725         meshcfg_app *app;
1726         app = (meshcfg_app*) user_data;
1727
1728         INFO("Mesh: Leave Network Reply from Meshd: app path [%s]", app->path);
1729         if (l_dbus_message_is_error(msg)) {
1730                 const char *name;
1731
1732                 l_dbus_message_get_error(msg, &name, NULL);
1733                 ERR("Mesh: Failed to leave network: %s", name);
1734
1735                 /* Send Network Destroy fail event */
1736                 __send_network_destroy_event(app, BT_STATUS_FAIL);
1737         } else {
1738                 INFO("Mesh: Leave Network: Success, cleanup app after proxy removed");
1739         }
1740 }
1741
1742 static void __bt_hal_mesh_leave_net_setup(struct l_dbus_message *msg,
1743                 void *user_data)
1744 {
1745         meshcfg_app *app = (meshcfg_app*) user_data;
1746
1747         l_dbus_message_set_arguments(msg, "t", l_get_be64(app->token.u8));
1748         INFO("Mesh: Leave Network Setup app path [%s]", app->path);
1749 }
1750
1751 static void __bt_hal_mesh_release_net_reply(
1752                 struct l_dbus_proxy *proxy,
1753                         struct l_dbus_message *msg, void *user_data)
1754 {
1755         meshcfg_app *app;
1756         app = (meshcfg_app*) user_data;
1757
1758         INFO("Mesh:Release Network Reply from Meshd: app path [%s]", app->path);
1759         if (l_dbus_message_is_error(msg)) {
1760                 const char *name;
1761
1762                 l_dbus_message_get_error(msg, &name, NULL);
1763                 ERR("Mesh: Failed to Release network: %s", name);
1764
1765         } else {
1766                 INFO("Mesh: Release Network: Success, cleanup app after proxy removed");
1767         }
1768 }
1769
1770 static void __bt_hal_mesh_release_net_setup(struct l_dbus_message *msg,
1771                 void *user_data)
1772 {
1773         meshcfg_app *app = (meshcfg_app*) user_data;
1774
1775         l_dbus_message_set_arguments(msg, "t", l_get_be64(app->token.u8));
1776         INFO("Mesh: Release Network Setup app path [%s]", app->path);
1777 }
1778
1779 static void __bt_hal_mesh_create_net_reply(
1780                 struct l_dbus_proxy *proxy,
1781                         struct l_dbus_message *msg, void *user_data)
1782 {
1783         meshcfg_app *app;
1784         app = (meshcfg_app*) user_data;
1785
1786         INFO("Mesh: Create Network Reply from Meshd: app path [%s]", app->path);
1787         if (l_dbus_message_is_error(msg)) {
1788                 const char *name;
1789
1790                 l_dbus_message_get_error(msg, &name, NULL);
1791                 ERR("Mesh: Failed to create network: %s", name);
1792
1793                 /* Send Network creation fail event */
1794                 __send_network_attach_event(app, BT_STATUS_FAIL);
1795
1796                 /* Destroy mesh app object */
1797                 __bt_hal_mesh_destroy_app_object(app);
1798                 return;
1799         }
1800 }
1801
1802 static void __bt_hal_mesh_create_net_setup(struct l_dbus_message *msg,
1803                 void *user_data)
1804 {
1805         meshcfg_app *app;
1806         struct l_dbus_message_builder *builder;
1807         app = (meshcfg_app*) user_data;
1808
1809         builder = l_dbus_message_builder_new(msg);
1810
1811         INFO("Mesh: Create Network Setup app path [%s]", app->path);
1812         l_dbus_message_builder_append_basic(builder, 'o', app->path);
1813         __mesh_append_byte_array(builder, app->uuid, 16);
1814         l_dbus_message_builder_finalize(builder);
1815         l_dbus_message_builder_destroy(builder);
1816 }
1817
1818 static void __mesh_trigger_scan_finished_event(meshcfg_app *app)
1819 {
1820         struct hal_ev_mesh_scan_state_changed ev;
1821
1822         memset(&ev, 0, sizeof(ev));
1823         memcpy(ev.net_uuid, app->uuid, 16);
1824
1825         ev.status = BT_STATUS_SUCCESS;
1826
1827         ev.state = HAL_MESH_SCAN_STATE_STOPPED;
1828         if (mesh_event_cb)
1829                 mesh_event_cb(HAL_EV_MESH_SCAN_STATE_CHANGED,
1830                         (void*)&ev, sizeof(ev));
1831 }
1832
1833 static gboolean __bt_mesh_scan_timer_cb(gpointer user_data)
1834 {
1835         meshcfg_app *app = (meshcfg_app*) user_data;
1836         __mesh_trigger_scan_finished_event(app);
1837         return false;
1838 }
1839
1840 void __bt_mesh_enable_scanning_timer(uint8_t *net_uuid, uint16_t secs)
1841 {
1842         GSList *l;
1843         meshcfg_app *app;
1844         l = g_slist_find_custom(mesh_apps, net_uuid,
1845                         __mesh_compare_network_uuid);
1846         if (!l)
1847                 return;
1848         app = l->data;
1849
1850         if (app->scan_timer_id > 0) {
1851                 g_source_remove(app->scan_timer_id);
1852                 app->scan_timer_id = 0;
1853         }
1854
1855         app->scan_timer_id = g_timeout_add_seconds(secs,
1856                         __bt_mesh_scan_timer_cb, app);
1857
1858         return;
1859 }
1860
1861 static void __mesh_scan_reply(struct l_dbus_proxy *proxy,
1862                 struct l_dbus_message *msg, void *user_data)
1863 {
1864         struct hal_ev_mesh_scan_state_changed ev;
1865         const char *dbus_path;
1866         uint8_t *net_uuid;
1867         dbus_path =  l_dbus_proxy_get_path(proxy);
1868         INFO("Mesh: DBUS path [%s]", dbus_path);
1869         net_uuid = __mesh_get_net_uuid_from_dbus_proxy_path(dbus_path);
1870
1871         uint16_t secs = (uint16_t) L_PTR_TO_UINT(user_data);
1872         INFO("Mesh: Scan duration [%u]", secs);
1873
1874         memset(&ev, 0, sizeof(ev));
1875         memcpy(ev.net_uuid, net_uuid, 16);
1876
1877         if (l_dbus_message_is_error(msg)) {
1878                 const char *name;
1879                 l_dbus_message_get_error(msg, &name, NULL);
1880                 ERR("Mesh: Failed to start unprovisioned scan: [%s]", name);
1881                 ev.status = BT_STATUS_FAIL;
1882         } else {
1883                 INFO("Mesh: Unprovisioned scan started\n");
1884                 ev.status = BT_STATUS_SUCCESS;
1885                 __bt_mesh_enable_scanning_timer(net_uuid, secs);
1886         }
1887
1888         ev.state = HAL_MESH_SCAN_STATE_STARTED;
1889         if (mesh_event_cb)
1890                 mesh_event_cb(HAL_EV_MESH_SCAN_STATE_CHANGED,
1891                         (void*)&ev, sizeof(ev));
1892         l_free(net_uuid);
1893 }
1894
1895 static void append_dict_entry_basic(struct l_dbus_message_builder *builder,
1896                 const char *key, const char *signature,
1897                 const void *data)
1898 {
1899         if (!builder)
1900                 return;
1901
1902         l_dbus_message_builder_enter_dict(builder, "sv");
1903         l_dbus_message_builder_append_basic(builder, 's', key);
1904         l_dbus_message_builder_enter_variant(builder, signature);
1905         l_dbus_message_builder_append_basic(builder, signature[0], data);
1906         l_dbus_message_builder_leave_variant(builder);
1907         l_dbus_message_builder_leave_dict(builder);
1908 }
1909
1910 static void __mesh_scan_setup(struct l_dbus_message *msg, void *user_data)
1911 {
1912         struct l_dbus_message_builder *builder;
1913         uint16_t secs = (uint16_t) L_PTR_TO_UINT(user_data);
1914         INFO("Mesh: Scan duration [%u]", secs);
1915
1916         builder = l_dbus_message_builder_new(msg);
1917         l_dbus_message_builder_enter_array(builder, "{sv}");
1918         append_dict_entry_basic(builder, "Seconds", "q", &secs);
1919         l_dbus_message_builder_leave_array(builder);
1920         l_dbus_message_builder_finalize(builder);
1921         l_dbus_message_builder_destroy(builder);
1922 }
1923
1924
1925 bt_status_t _bt_hal_mesh_network_set_caps(
1926                 bt_uuid_t *net_uuid, bt_hal_mesh_prov_caps_t *caps)
1927 {
1928         GSList *l;
1929         meshcfg_app *app;
1930         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
1931         if (l) {
1932                 app = l->data;
1933                 /* Fill OOB data */
1934                 app->public_oob = caps->public_oob;
1935                 app->static_oob = caps->static_oob;
1936                 app->out_oob = caps->out_oob;
1937                 app->in_oob = caps->in_oob;
1938         } else {
1939                 ERR("Mesh: app not found!!");
1940                 return BT_STATUS_PARM_INVALID;
1941
1942         }
1943         return BT_STATUS_SUCCESS;
1944 }
1945
1946 static void __bt_hal_mesh_add_node_reply(
1947                 struct l_dbus_proxy *proxy,
1948                         struct l_dbus_message *msg,
1949                                 void *user_data)
1950 {
1951         struct hal_ev_mesh_provision_status ev;
1952         const char *dbus_path;
1953         uint8_t *net_uuid;
1954         dbus_path =  l_dbus_proxy_get_path(proxy);
1955         INFO("Mesh: DBUS path [%s]", dbus_path);
1956         net_uuid = __mesh_get_net_uuid_from_dbus_proxy_path(dbus_path);
1957
1958         bt_uuid_t *dev_uuid = (bt_uuid_t*) user_data;
1959
1960         INFO("Mesh: app path [%s]", dbus_path);
1961
1962         memset(&ev, 0, sizeof(ev));
1963         memcpy(ev.net_uuid, net_uuid, 16);
1964         memcpy(ev.dev_uuid, dev_uuid->uu, 16);
1965
1966         /* Free User data */
1967         g_free((void*)dev_uuid);
1968         l_free(net_uuid);
1969
1970         if (l_dbus_message_is_error(msg)) {
1971                 const char *name;
1972
1973                 l_dbus_message_get_error(msg, &name, NULL);
1974                 ERR("Mesh: Failed to start provisioning: %s", name);
1975                 ev.status = BT_STATUS_FAIL;
1976         } else {
1977                 INFO("Mesh: Provisioning started\n");
1978                 ev.status = BT_STATUS_SUCCESS;
1979         }
1980         if (mesh_event_cb)
1981                 mesh_event_cb(HAL_EV_MESH_PROVISIONING_STATUS,
1982                         (void*)&ev, sizeof(ev));
1983         INFO("Mesh: Provisioning status sent");
1984 }
1985
1986 static void __bt_hal_mesh_add_node_setup(struct l_dbus_message *msg,
1987                 void *user_data)
1988 {
1989         char *uuid;
1990         bt_uuid_t *dev = user_data;
1991         struct l_dbus_message_builder *builder;
1992         uuid =  l_util_hexstring(dev->uu, 16);
1993         INFO("Mesh: Add Node Setup UUID [%s]", uuid);
1994
1995         builder = l_dbus_message_builder_new(msg);
1996         __mesh_append_byte_array(builder, dev->uu, 16);
1997         l_dbus_message_builder_enter_array(builder, "{sv}");
1998         l_dbus_message_builder_leave_array(builder);
1999         l_dbus_message_builder_finalize(builder);
2000         l_dbus_message_builder_destroy(builder);
2001 }
2002
2003 bt_status_t _bt_hal_mesh_provision_device(
2004                 bt_uuid_t *net_uuid, bt_uuid_t *dev_uuid)
2005 {
2006         GSList *l;
2007         meshcfg_app *app;
2008         bt_uuid_t *dev;
2009         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
2010         if (l) {
2011                 app = l->data;
2012                 dev = g_memdup((gpointer)dev_uuid, 16);
2013                 INFO("Mesh: Schedule Add Node request to meshd");
2014                 if (!l_dbus_proxy_method_call(app->mgmt_proxy, "AddNode",
2015                                         __bt_hal_mesh_add_node_setup,
2016                                         __bt_hal_mesh_add_node_reply,
2017                                         (void*)dev, NULL))
2018                         return BT_STATUS_FAIL;
2019         } else {
2020                 ERR("Mesh: app not found!!");
2021                 return BT_STATUS_PARM_INVALID;
2022
2023         }
2024         return BT_STATUS_SUCCESS;
2025 }
2026
2027 static void __bt_hal_mesh_subnet_key_setup(
2028                 struct l_dbus_message *msg, void *user_data)
2029 {
2030         struct subnet_key_request *req = user_data;
2031         uint16_t idx = (uint16_t) req->idx;
2032
2033         l_dbus_message_set_arguments(msg, "q", idx);
2034 }
2035
2036 static void __bt_hal_mesh_subnet_key_reply(struct l_dbus_proxy *proxy,
2037                 struct l_dbus_message *msg, void *user_data)
2038 {
2039         struct hal_ev_mesh_netkey_execute_event ev;
2040         const char *dbus_path;
2041         uint8_t *net_uuid;
2042         struct subnet_key_request *req = user_data;
2043         const char *method = req->str;
2044
2045         dbus_path =  l_dbus_proxy_get_path(proxy);
2046         INFO("Mesh: DBUS path [%s]", dbus_path);
2047         net_uuid = __mesh_get_net_uuid_from_dbus_proxy_path(dbus_path);
2048
2049         memset(&ev, 0, sizeof(ev));
2050         memcpy(ev.net_uuid, net_uuid, 16);
2051         ev.key_idx = req->idx;
2052
2053         g_free(net_uuid);
2054
2055         if (l_dbus_message_is_error(msg)) {
2056                 const char *name;
2057
2058                 l_dbus_message_get_error(msg, &name, NULL);
2059                 ERR("Mesh: Subnet [%s] failed: error: [%s]", method, name);
2060                 ev.status = BT_STATUS_FAIL;
2061         }
2062
2063         ev.status = BT_STATUS_SUCCESS;
2064
2065         if (!strcmp("CreateSubnet", method)) {
2066                 INFO("Mesh: Reply for CreateSubnet");
2067                 ev.key_event = HAL_MESH_KEY_ADD;
2068         } else if (!strcmp("DeleteSubnet", method)) {
2069                 INFO("Mesh: Reply for DeleteSubnet");
2070                 ev.key_event = HAL_MESH_KEY_DELETE;
2071         } else if (!strcmp("UpdateSubnet", method)) {
2072                 INFO("Mesh: Reply for UpdateSubnet");
2073                 ev.key_event = HAL_MESH_KEY_UPDATE;
2074         }
2075
2076         if (mesh_event_cb)
2077                 mesh_event_cb(HAL_EV_MESH_NETKEY_EXECUTE_EVENT,
2078                         (void*)&ev, sizeof(ev));
2079 }
2080
2081 static bool  __mesh_subnet_netkey_command_execute(meshcfg_app *app,
2082                         uint16_t index, const char *key_execute_method)
2083 {
2084         struct subnet_key_request *req;
2085
2086         req = l_new(struct subnet_key_request, 1);
2087         req->str = key_execute_method;
2088         req->idx = index;
2089
2090         if (!l_dbus_proxy_method_call(app->mgmt_proxy, key_execute_method,
2091                                 __bt_hal_mesh_subnet_key_setup,
2092                                 __bt_hal_mesh_subnet_key_reply,
2093                                 req, l_free))
2094                 return false;
2095
2096         return true;
2097 }
2098
2099 static void __bt_hal_mesh_app_key_setup(struct l_dbus_message *msg,
2100         void *user_data)
2101 {
2102         struct app_key_request *req = user_data;
2103         uint16_t net_idx = (uint16_t) req->net_idx;
2104         uint16_t app_idx = (uint16_t) req->app_idx;
2105
2106         if (g_strcmp0(req->str, "CreateAppKey") == 0)
2107                 l_dbus_message_set_arguments(msg, "qq", net_idx, app_idx);
2108         else
2109                 l_dbus_message_set_arguments(msg, "q", app_idx);
2110 }
2111
2112 static void __bt_hal_mesh_app_key_reply(struct l_dbus_proxy *proxy,
2113                 struct l_dbus_message *msg, void *user_data)
2114 {
2115         struct hal_ev_mesh_appkey_execute_event ev;
2116         const char *dbus_path;
2117         uint8_t *net_uuid;
2118         struct app_key_request *req = user_data;
2119         const char *method = req->str;
2120
2121         dbus_path =  l_dbus_proxy_get_path(proxy);
2122         INFO("Mesh: DBUS path [%s]", dbus_path);
2123         net_uuid = __mesh_get_net_uuid_from_dbus_proxy_path(dbus_path);
2124
2125         memset(&ev, 0, sizeof(ev));
2126         memcpy(ev.net_uuid, net_uuid, 16);
2127         ev.net_idx = req->net_idx;
2128         ev.app_idx = req->app_idx;
2129
2130         g_free(net_uuid);
2131
2132         if (l_dbus_message_is_error(msg)) {
2133                 const char *name;
2134
2135                 l_dbus_message_get_error(msg, &name, NULL);
2136                 ERR("Mesh: AppKey execute [%s] failed: error: [%s]", method, name);
2137                 ev.status = BT_STATUS_FAIL;
2138         } else
2139                 ev.status = BT_STATUS_SUCCESS;
2140
2141         if (!strcmp("CreateAppKey", method)) {
2142                 INFO("Mesh: AppKey Create Reply");
2143                 ev.key_event = HAL_MESH_KEY_ADD;
2144         } else if (!strcmp("DeleteAppKey", method)) {
2145                 INFO("Mesh: AppKey Delete Reply");
2146                 ev.key_event = HAL_MESH_KEY_DELETE;
2147         } else if (!strcmp("UpdateAppKey", method)) {
2148                 INFO("Mesh: AppKey Update Reply");
2149                 ev.key_event = HAL_MESH_KEY_UPDATE;
2150         }
2151
2152         if (mesh_event_cb)
2153                 mesh_event_cb(HAL_EV_MESH_APPKEY_EXECUTE_EVENT, (void*)&ev, sizeof(ev));
2154 }
2155
2156 static bool  __mesh_subnet_appkey_command_execute(meshcfg_app *app,
2157                         uint16_t net_idx, uint16_t app_idx,
2158                                 const char *key_execute_method)
2159 {
2160         struct app_key_request *req;
2161
2162         req = l_new(struct app_key_request, 1);
2163         req->str = key_execute_method;
2164         req->net_idx = net_idx;
2165         req->app_idx = app_idx;
2166
2167         if (!l_dbus_proxy_method_call(app->mgmt_proxy, key_execute_method,
2168                                 __bt_hal_mesh_app_key_setup,
2169                                 __bt_hal_mesh_app_key_reply,
2170                                 req, l_free))
2171                 return false;
2172
2173         return true;
2174 }
2175
2176 bt_status_t _bt_hal_mesh_network_subnet_execute(bt_uuid_t *net_uuid,
2177                         bt_mesh_key_op_e op, uint16_t netkey_idx)
2178 {
2179         GSList *l;
2180         meshcfg_app *app;
2181         bool status = true;
2182         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
2183         if (l) {
2184                 app = l->data;
2185
2186                 if (op == BT_MESH_KEY_CREATE)
2187                         status = __mesh_subnet_netkey_command_execute(app,
2188                                         netkey_idx, "CreateSubnet");
2189                 else if (op == BT_MESH_KEY_DELETE)
2190                         status = __mesh_subnet_netkey_command_execute(app,
2191                                         netkey_idx, "DeleteSubnet");
2192                 else if (op == BT_MESH_KEY_UPDATE)
2193                         status = __mesh_subnet_netkey_command_execute(app,
2194                                         netkey_idx, "UpdateSubnet");
2195                 if (!status)
2196                         return BT_STATUS_FAIL;
2197
2198         } else {
2199                 ERR("Mesh: app not found!!");
2200                 return BT_STATUS_PARM_INVALID;
2201
2202         }
2203         return BT_STATUS_SUCCESS;
2204 }
2205
2206 bt_status_t _bt_hal_mesh_network_appkey_execute(bt_uuid_t *net_uuid,
2207                         bt_mesh_key_op_e op, uint16_t netkey_idx, uint16_t appkey_idx)
2208 {
2209         GSList *l;
2210         meshcfg_app *app;
2211         bool status = true;
2212         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
2213         if (l) {
2214                 app = l->data;
2215
2216                 if (op == BT_MESH_KEY_CREATE)
2217                         status = __mesh_subnet_appkey_command_execute(app,
2218                                 netkey_idx, appkey_idx, "CreateAppKey");
2219                 else if (op == BT_MESH_KEY_DELETE)
2220                         status = __mesh_subnet_appkey_command_execute(app,
2221                                 netkey_idx, appkey_idx, "DeleteAppKey");
2222                 else if (op == BT_MESH_KEY_UPDATE) {
2223                         INFO("Mesh: Update ApKey command NK Idx [0x%2.2x] AK Idx [0x%2.2x]",
2224                                         netkey_idx, appkey_idx);
2225                         status = __mesh_subnet_appkey_command_execute(app,
2226                                 netkey_idx, appkey_idx, "UpdateAppKey");
2227                 }
2228                 if (!status)
2229                         return BT_STATUS_FAIL;
2230
2231         } else {
2232                 ERR("Mesh: app not found!!");
2233                 return BT_STATUS_PARM_INVALID;
2234
2235         }
2236         return BT_STATUS_SUCCESS;
2237 }
2238
2239 bt_status_t _bt_hal_mesh_send_provision_data(
2240                 bt_uuid_t *net_uuid, uint16_t netkey_idx, uint16_t unicast)
2241 {
2242         GSList *l;
2243         meshcfg_app *app;
2244         struct l_dbus_message *msg;
2245         struct l_dbus_message *reply;
2246
2247         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
2248         if (l) {
2249                 app = l->data;
2250                 msg = app->msg;
2251
2252                 reply = l_dbus_message_new_method_return(msg);
2253                 l_dbus_message_set_arguments(reply, "qq", netkey_idx,  unicast);
2254                 l_dbus_send(dbus, reply);
2255         } else {
2256                 ERR("Mesh: app not found!!");
2257                 return BT_STATUS_PARM_INVALID;
2258         }
2259         return BT_STATUS_SUCCESS;
2260 }
2261
2262 bt_status_t _bt_hal_mesh_network_scan_cancel(bt_uuid_t *net_uuid)
2263 {
2264         GSList *l;
2265         meshcfg_app *app;
2266         l = g_slist_find_custom(mesh_apps,
2267                 net_uuid->uu, __mesh_compare_network_uuid);
2268         if (l) {
2269                 app = l->data;
2270                 if (!__bt_mesh_proxy_check(app)) {
2271                         ERR("Mesh: Proxy check failed!!");
2272                         return BT_STATUS_FAIL;
2273                 }
2274                 if (!l_dbus_proxy_method_call(app->mgmt_proxy,
2275                                 "UnprovisionedScanCancel",
2276                                         NULL, NULL, NULL, NULL))
2277                         return BT_STATUS_FAIL;
2278         } else {
2279                 ERR("Mesh: app not found!!");
2280                 return BT_STATUS_PARM_INVALID;
2281         }
2282
2283         /* Stop Scan timer */
2284         if (app->scan_timer_id > 0) {
2285                 g_source_remove(app->scan_timer_id);
2286                 app->scan_timer_id = 0;
2287         }
2288
2289         /* Trigger Scan finished event */
2290         __mesh_trigger_scan_finished_event(app);
2291
2292         return BT_STATUS_SUCCESS;
2293 }
2294
2295 bt_status_t _bt_hal_mesh_auth_reply(bt_hal_mesh_auth_variant_e auth_type,
2296                         const char *auth_value)
2297 {
2298         uint32_t val_u32;
2299         struct l_dbus_message *reply = NULL;
2300         struct l_dbus_message_builder *builder;
2301         uint8_t *alpha;
2302         bt_status_t ret = BT_STATUS_SUCCESS;
2303         size_t sz = 0;
2304
2305         /* Proxy Check */
2306         if (!__bt_mesh_proxy_check(0)) {
2307                 ERR("Mesh: Proxy check failed!!");
2308                 return BT_STATUS_FAIL;
2309         }
2310         INFO("Mesh: Authentication Reply: auth type [%d]", auth_type);
2311         INFO("Mesh: Authentication Reply: auth value [%s]", auth_value);
2312         /* For Numeric Type Inputs: Numeric, Blink, Beep & Vibrate */
2313         if (auth_type >= BT_HAL_MESH_AUTH_REQ_NUMERIC_INPUT &&
2314                         auth_type <= BT_HAL_MESH_AUTH_REQ_VIBRATE_COUNT_INPUT) {
2315                 INFO("Mesh: Authentication reply: Numeric Type");
2316                 val_u32 = atoi(auth_value);
2317                 reply = l_dbus_message_new_method_return(agent_msg);
2318                 l_dbus_message_set_arguments(reply, "u", val_u32);
2319                 if (!reply)
2320                         reply = l_dbus_message_new_error(agent_msg, dbus_err_fail, NULL);
2321                 l_dbus_send(dbus, reply);
2322                 ret = BT_STATUS_SUCCESS;
2323         /* For Alpha-Numeric */
2324         } else if (auth_type == BT_HAL_MESH_AUTH_REQ_ALPHANUMERIC_INPUT ||
2325                         auth_type == BT_HAL_MESH_AUTH_REQ_OOB_STATIC_KEY_INPUT ||
2326                         auth_type == BT_HAL_MESH_AUTH_REQ_OOB_PUBLIC_KEY_INPUT) {
2327                 INFO("Mesh: Authentication reply: Alpha-Numeric Type");
2328                 alpha = l_util_from_hexstring(auth_value, &sz);
2329                 reply = l_dbus_message_new_method_return(agent_msg);
2330                 builder = l_dbus_message_builder_new(reply);
2331                 __mesh_append_byte_array(builder, alpha, 16);
2332                 l_dbus_message_builder_finalize(builder);
2333                 l_dbus_message_builder_destroy(builder);
2334                 l_free(alpha);
2335                 if (!reply)
2336                         reply = l_dbus_message_new_error(agent_msg, dbus_err_fail, NULL);
2337                 l_dbus_send(dbus, reply);
2338                 ret = BT_STATUS_SUCCESS;
2339         }
2340         return ret;
2341 }
2342
2343 bt_status_t _bt_hal_mesh_network_scan(bt_uuid_t *net_uuid,
2344                 bt_hal_mesh_scan_param_t *param)
2345 {
2346         GSList *l;
2347         meshcfg_app *app;
2348         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
2349         if (l) {
2350                 app = l->data;
2351                 if (!__bt_mesh_proxy_check(app)) {
2352                         ERR("Mesh: Proxy check failed!!");
2353                         return BT_STATUS_FAIL;
2354                 }
2355                 if (!l_dbus_proxy_method_call(app->mgmt_proxy, "UnprovisionedScan",
2356                                         __mesh_scan_setup, __mesh_scan_reply,
2357                                         L_UINT_TO_PTR(param->scan_time), NULL))
2358                         return BT_STATUS_FAIL;
2359         } else {
2360                 ERR("Mesh: app not found!!");
2361                 return BT_STATUS_PARM_INVALID;
2362         }
2363         return BT_STATUS_SUCCESS;
2364 }
2365
2366 static void __bt_hal_mesh_delete_node_setup(struct l_dbus_message *msg,
2367                 void *user_data)
2368 {
2369         struct mesh_remote_node_info *node_info = \
2370                 (struct mesh_remote_node_info*) user_data;
2371
2372         l_dbus_message_set_arguments(msg, "qy",
2373                 node_info->unicast, node_info->num_elements);
2374         INFO("Mesh: Delete Remote Node Setup params passed");
2375 }
2376
2377 static void __bt_hal_mesh_delete_node_reply(
2378                 struct l_dbus_proxy *proxy,
2379                         struct l_dbus_message *msg, void *user_data)
2380 {
2381         INFO("Mesh: Delete Remote Node Reply from DBUS");
2382 }
2383
2384 bt_status_t _bt_hal_mesh_node_delete(bt_uuid_t *network,
2385                 uint16_t unicast, uint16_t num_elements)
2386 {
2387         GSList *l;
2388         meshcfg_app *app;
2389         struct mesh_remote_node_info *node_info;
2390         INFO("Mesh: Delete Remote Node");
2391         l = g_slist_find_custom(mesh_apps, network->uu, __mesh_compare_network_uuid);
2392         if (l) {
2393                 app = l->data;
2394                 if (!__bt_mesh_proxy_check(app)) {
2395                         ERR("Mesh: Proxy check failed!!");
2396                         return BT_STATUS_FAIL;
2397                 }
2398                 INFO("Mesh: Delete Remote Node Unicast [0x%2.2x] Num els [%u]",
2399                         unicast, num_elements);
2400
2401                 /* Delete Remote Node Request */
2402                 node_info = g_malloc0(sizeof(struct mesh_remote_node_info));
2403                 node_info->unicast = unicast;
2404                 node_info->num_elements = num_elements;
2405
2406                 if (!l_dbus_proxy_method_call(app->mgmt_proxy, "DeleteRemoteNode",
2407                                         __bt_hal_mesh_delete_node_setup,
2408                                         __bt_hal_mesh_delete_node_reply, node_info,
2409                                         l_free)) {
2410                         ERR("Mesh: Delete Remote Node Request failed!!");
2411                         g_free(node_info);
2412                         return BT_STATUS_FAIL;
2413                 }
2414         } else {
2415                 ERR("Mesh: App not found!!");
2416                 return BT_STATUS_PARM_INVALID;
2417         }
2418         INFO("Mesh: Delete Remote Node Call issued successfully!!");
2419         return BT_STATUS_SUCCESS;
2420 }
2421
2422 bt_status_t _bt_hal_mesh_network_release(bt_uuid_t *net_uuid)
2423 {
2424         GSList *l;
2425         meshcfg_app *app;
2426         INFO("Mesh: Release Network");
2427         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
2428         if (l) {
2429                 app = l->data;
2430                 if (!__bt_mesh_proxy_check(app)) {
2431                         ERR("Mesh: Proxy check failed!!");
2432                         return BT_STATUS_FAIL;
2433                 }
2434                 INFO("Mesh: Release Network");
2435                 /* Create CFG Network */
2436                 if (!l_dbus_proxy_method_call(net_proxy, "Release",
2437                                         __bt_hal_mesh_release_net_setup,
2438                                         __bt_hal_mesh_release_net_reply, app,
2439                                         NULL)) {
2440                         ERR("Mesh: Network Release failed!!");
2441                         return BT_STATUS_FAIL;
2442                 }
2443         } else {
2444                 ERR("Mesh: App not found!!");
2445                 return BT_STATUS_PARM_INVALID;
2446         }
2447         INFO("Mesh: Network Release Call issued successfully!!");
2448         return BT_STATUS_SUCCESS;
2449 }
2450
2451 bt_status_t _bt_hal_mesh_network_destroy(bt_uuid_t *net_uuid)
2452 {
2453         GSList *l;
2454         meshcfg_app *app;
2455         INFO("Mesh: Destroy network");
2456         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
2457         if (l) {
2458                 app = l->data;
2459                 if (!__bt_mesh_proxy_check(app)) {
2460                         ERR("Mesh: Proxy check failed!!");
2461                         return BT_STATUS_FAIL;
2462                 }
2463                 INFO("Mesh: Destroy Network");
2464                 /* Create CFG Network */
2465                 if (!l_dbus_proxy_method_call(net_proxy, "Leave",
2466                                         __bt_hal_mesh_leave_net_setup,
2467                                         __bt_hal_mesh_leave_net_reply, app,
2468                                         NULL)) {
2469                         ERR("Mesh: Network Leave failed!!");
2470                         return BT_STATUS_FAIL;
2471                 }
2472         } else {
2473                 ERR("Mesh: App not found!!");
2474                 return BT_STATUS_PARM_INVALID;
2475         }
2476         INFO("Mesh: Network Leave Call issued successfully!!");
2477         return BT_STATUS_SUCCESS;
2478 }
2479
2480 bt_status_t _bt_hal_mesh_create_network(
2481                 bt_hal_mesh_node_t *node, GSList *models, bool is_prov)
2482 {
2483         meshcfg_app *app;
2484
2485         INFO("Mesh: Create Network Request");
2486
2487         if (!__bt_mesh_proxy_check(0)) {
2488                 ERR("Mesh: Proxy check failed!!");
2489                 return BT_STATUS_FAIL;
2490         }
2491
2492         INFO("Mesh: Node Element count [%d]", node->num_elements);
2493         INFO("Mesh: Node Primary Unicast[0x%2.2x]", node->primary_unicast);
2494         INFO("Mesh: Node Vendor Info: CID[0x%2.2x]", node->vendor_info.companyid);
2495         INFO("Mesh: Node Vendor Info: VID[0x%2.2x]", node->vendor_info.vendorid);
2496         INFO("Mesh: Node Vendor Info: VSID[0x%2.2x]", node->vendor_info.versionid);
2497         INFO("Mesh: Node Vendor Info: CRPL[0x%2.2x]", node->vendor_info.crpl);
2498         INFO("Mesh: Node Total Number of Models in the node[%d]", g_slist_length(models));
2499         INFO("Mesh: Token [%llu]", (unsigned long long int)node->token.u64);
2500         /* Create DBUS APP */
2501         app = __bt_hal_mesh_create_app(node, models, is_prov);
2502         if (!app)
2503                 return BT_STATUS_FAIL;
2504
2505         /* Register DBUS APP */
2506         if (!__bt_hal_mesh_register_application(app))
2507                 goto failed;
2508
2509         if (app->token.u64 == 0) {
2510                 INFO("Mesh: Create New Network");
2511                 /* Create CFG Network */
2512                 if (!l_dbus_proxy_method_call(net_proxy, "CreateNetwork",
2513                                         __bt_hal_mesh_create_net_setup,
2514                                         __bt_hal_mesh_create_net_reply, app,
2515                                         NULL)) {
2516                         ERR("Mesh: Network Create failed!!");
2517                         goto failed;
2518                 }
2519         } else {
2520                 INFO("Mesh: Attach Node to Network: Token [%llu]", (unsigned long long int)app->token.u64);
2521                 /* Attach to Network */
2522                 if (!l_dbus_proxy_method_call(net_proxy, "Attach",
2523                                         __bt_hal_mesh_attach_node_setup,
2524                                         __bt_hal_mesh_attach_node_reply,
2525                                         app,
2526                                 NULL)) {
2527                         ERR("Mesh: Node attach failed!!");
2528                         goto failed;
2529                 }
2530         }
2531
2532         INFO("Mesh: Node registration request scheudled");
2533         mesh_apps = g_slist_append(mesh_apps, app);
2534         INFO("Mesh: Total number of apps in list  [%d]",
2535                 g_slist_length(mesh_apps));
2536         return BT_STATUS_SUCCESS;
2537 failed:
2538         ERR("Mesh: network can not be created!!");
2539         __bt_hal_mesh_destroy_app_object(app);
2540         return BT_STATUS_FAIL;
2541 }
2542
2543 static void __bt_hal_mesh_config_send(
2544                 struct l_dbus_message *msg, void *user_data)
2545 {
2546         struct configuration_request *req = user_data;
2547         struct l_dbus_message_builder *builder;
2548
2549         builder = l_dbus_message_builder_new(msg);
2550
2551         l_dbus_message_builder_append_basic(builder, 'o', req->ele_path);
2552         l_dbus_message_builder_append_basic(builder, 'q', &req->dst);
2553         if (req->is_dev_key)
2554                 l_dbus_message_builder_append_basic(builder, 'b', &req->rmt);
2555
2556         l_dbus_message_builder_append_basic(builder, 'q', &req->idx);
2557         __mesh_append_byte_array(builder, req->data, req->len);
2558         l_dbus_message_builder_finalize(builder);
2559         l_dbus_message_builder_destroy(builder);
2560 }
2561
2562 static void __bt_hal_mesh_key_config_send(
2563                 struct l_dbus_message *msg, void *user_data)
2564 {
2565         struct key_config_request *req = user_data;
2566         struct l_dbus_message_builder *builder;
2567
2568         builder = l_dbus_message_builder_new(msg);
2569
2570         l_dbus_message_builder_append_basic(builder, 'o', req->ele_path);
2571         l_dbus_message_builder_append_basic(builder, 'q', &req->dst);
2572         l_dbus_message_builder_append_basic(builder, 'q', &req->key_req_idx);
2573         l_dbus_message_builder_append_basic(builder, 'q', &req->idx);
2574         l_dbus_message_builder_append_basic(builder, 'b', &req->update_req);
2575         l_dbus_message_builder_finalize(builder);
2576         l_dbus_message_builder_destroy(builder);
2577 }
2578
2579 static void __bt_hal_mesh_model_execute_message(
2580                 struct l_dbus_message *msg, void *user_data)
2581 {
2582         struct configuration_request *req = user_data;
2583         struct l_dbus_message_builder *builder;
2584
2585         builder = l_dbus_message_builder_new(msg);
2586
2587         l_dbus_message_builder_append_basic(builder, 'o', req->ele_path);
2588         l_dbus_message_builder_append_basic(builder, 'q', &req->dst);
2589         l_dbus_message_builder_append_basic(builder, 'q', &req->idx);
2590         __mesh_append_byte_array(builder, req->data, req->len);
2591         l_dbus_message_builder_finalize(builder);
2592         l_dbus_message_builder_destroy(builder);
2593 }
2594
2595 bt_status_t _bt_hal_mesh_send_key_config_message(
2596                 bt_uuid_t *network, uint16_t dest,
2597                         bool is_netkey, bool is_update,
2598                                 uint16_t key_idx, uint16_t netkey_idx)
2599 {
2600         GSList *l;
2601         GSList *l1;
2602         struct key_config_request *req;
2603         meshcfg_app *app;
2604         meshcfg_el *elem;
2605         const char *key_method = (!is_netkey) ? "AddAppKey" : "AddNetKey";
2606         /* Source is Config Client Local Node */
2607         int src_elem_idx = 0;
2608         l = g_slist_find_custom(mesh_apps, network->uu, __mesh_compare_network_uuid);
2609         if (l) {
2610                 app = l->data;
2611                 if (!__bt_mesh_proxy_check(app)) {
2612                         ERR("Mesh: Proxy check failed!!");
2613                         return BT_STATUS_FAIL;
2614                 }
2615                 l1 = g_slist_find_custom(app->elements,
2616                         GUINT_TO_POINTER(src_elem_idx), __compare_element_index);
2617                 if (!l1)
2618                         return BT_STATUS_FAIL;
2619                 elem = l1->data;
2620
2621                 req = l_new(struct key_config_request, 1);
2622                 req->ele_path = elem->path;
2623                 req->dst = dest;
2624                 req->key_req_idx = key_idx;
2625                 req->idx = netkey_idx; /* Encryption Key index */
2626                 req->update_req = is_update;
2627
2628                 if (!l_dbus_proxy_method_call(app->proxy, key_method,
2629                                         __bt_hal_mesh_key_config_send, NULL,
2630                                         (void*)req, l_free))
2631                         return BT_STATUS_FAIL;
2632         } else {
2633                 ERR("Mesh: app not found!!");
2634                 return BT_STATUS_PARM_INVALID;
2635
2636         }
2637         return BT_STATUS_SUCCESS;
2638 }
2639
2640 bt_status_t _bt_hal_mesh_send_configuration_message(
2641         bt_uuid_t *network, uint16_t dest,
2642                 bool is_dev_key, uint16_t netkey_idx,
2643                         uint8_t *buf, int len)
2644 {
2645         GSList *l;
2646         GSList *l1;
2647         struct configuration_request *req;
2648         meshcfg_app *app;
2649         meshcfg_el *elem;
2650         int src_elem_idx = 0;
2651         l = g_slist_find_custom(mesh_apps, network->uu,
2652                         __mesh_compare_network_uuid);
2653         if (l) {
2654                 app = l->data;
2655                 if (!__bt_mesh_proxy_check(app)) {
2656                         ERR("Mesh: Proxy check failed!!");
2657                         return BT_STATUS_FAIL;
2658                 }
2659                 l1 = g_slist_find_custom(app->elements,
2660                                 GUINT_TO_POINTER(src_elem_idx),
2661                                 __compare_element_index);
2662                 if (!l1)
2663                         return BT_STATUS_FAIL;
2664                 elem = l1->data;
2665
2666                 req = l_new(struct configuration_request, 1);
2667                 req->ele_path = elem->path;
2668                 req->dst = dest;
2669                 req->idx = netkey_idx;
2670                 req->data = buf;
2671                 req->len = len;
2672                 req->rmt = true;
2673                 req->is_dev_key = is_dev_key;
2674
2675                 if (!l_dbus_proxy_method_call(app->proxy, "DevKeySend",
2676                                         __bt_hal_mesh_config_send, NULL,
2677                                         (void*)req, l_free))
2678                         return BT_STATUS_FAIL;
2679         } else {
2680                 ERR("Mesh: app not found!!");
2681                 return BT_STATUS_PARM_INVALID;
2682
2683         }
2684         return BT_STATUS_SUCCESS;
2685 }
2686
2687 bt_status_t _bt_hal_mesh_model_execute_message(
2688         bt_uuid_t *network, uint16_t dest,
2689         uint16_t appkey_idx, uint8_t *buf, int len)
2690 {
2691         GSList *l;
2692         GSList *l1;
2693         struct configuration_request *req;
2694         meshcfg_app *app;
2695         meshcfg_el *elem;
2696         int src_elem_idx = 0;
2697         l = g_slist_find_custom(mesh_apps, network->uu,
2698                         __mesh_compare_network_uuid);
2699         if (l) {
2700                 app = l->data;
2701                 if (!__bt_mesh_proxy_check(app)) {
2702                         ERR("Mesh: Proxy check failed!!");
2703                         return BT_STATUS_FAIL;
2704                 }
2705                 l1 = g_slist_find_custom(app->elements,
2706                                 GUINT_TO_POINTER(src_elem_idx),
2707                                 __compare_element_index);
2708                 if (!l1)
2709                         return BT_STATUS_FAIL;
2710                 elem = l1->data;
2711
2712                 req = l_new(struct configuration_request, 1);
2713                 req->ele_path = elem->path;
2714                 req->dst = dest;
2715                 req->idx = appkey_idx;
2716                 req->data = buf;
2717                 req->len = len;
2718                 req->rmt = false;
2719                 req->is_dev_key = false;
2720
2721                 if (!l_dbus_proxy_method_call(app->proxy, "Send",
2722                                         __bt_hal_mesh_model_execute_message,
2723                                         NULL, (void*)req, l_free))
2724                         return BT_STATUS_FAIL;
2725         } else {
2726                 ERR("Mesh: app not found!!");
2727                 return BT_STATUS_PARM_INVALID;
2728
2729         }
2730         return BT_STATUS_SUCCESS;
2731 }