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