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