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