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