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