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