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