Fix Svace Issues
[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 static uint32_t iv_index;
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_dbus_path(gconstpointer data, gconstpointer user_data)
421 {
422         int ret = 0;
423         const meshcfg_app *app = (meshcfg_app*) data;
424         char *path = (char *) user_data;
425         if (!path) {
426                 INFO("Mesh: NULL dbus path");
427                 return -1;
428         }
429         char **strings =  g_strsplit(path, "/elem", 2);
430         ret = g_strcmp0(strings[0], app->path);
431         g_strfreev(strings);
432         return ret;
433 }
434
435 static gint __compare_element_index(gconstpointer data, gconstpointer user_data)
436 {
437         const meshcfg_el *elem = data;
438         uint16_t elem_index = GPOINTER_TO_UINT(user_data);
439         if (!elem)
440                 return 1;
441
442         return (elem->index == elem_index ? 0 : -1);
443 }
444
445 static void __send_network_destroy_event(void *param, uint8_t status)
446 {
447         struct hal_ev_mesh_network_destroyed ev;
448         meshcfg_app *app = (meshcfg_app*)param;
449
450         memset(&ev, 0, sizeof(ev));
451         memcpy(ev.uuid, app->uuid, sizeof(app->uuid));
452         memcpy(ev.token, app->token.u8, 8);
453
454         ev.status = status;
455         if (mesh_event_cb)
456                 mesh_event_cb(HAL_EV_MESH_NETWORK_DESTROYED,
457                         (void*)&ev, sizeof(ev));
458 }
459
460 static void __mesh_proxy_added(struct l_dbus_proxy *proxy, void *user_data)
461 {
462         const char *interface = l_dbus_proxy_get_interface(proxy);
463         const char *path = l_dbus_proxy_get_path(proxy);
464
465         INFO("MESH: Proxy added: %s (%s)\n", interface, path);
466
467         if (!strcmp(interface, BT_HAL_MESH_NETWORK_INTERFACE)) {
468                 struct hal_ev_mesh_network_proxy_added ev;
469                 INFO("Mesh: Network Proxy added");
470
471                 /* Save Global proxy */
472                 net_proxy = proxy;
473                 if (net_proxy)
474                         INFO("Mesh: Net Proxy [%p]", net_proxy);
475
476                 memset(&ev, 0, sizeof(ev));
477                 ev.status = BT_STATUS_SUCCESS;
478
479                 /* Send event cb */
480                 if (mesh_event_cb)
481                         mesh_event_cb(HAL_EV_MESH_NETWORK_PROXY_ADDED,
482                                 (void*)&ev, sizeof(ev));
483
484                 return;
485         }
486
487         if (!strcmp(interface, BT_HAL_MESH_MANAGEMENT_INTERFACE)) {
488                 GSList *l;
489                 meshcfg_app *app;
490                 INFO("Mesh: Mgmt Proxy added");
491                 INFO("Mesh: Number of mesh app present in list [%d]",
492                         g_slist_length(mesh_apps));
493                 l = g_slist_find_custom(mesh_apps, path, __compare_proxy_path);
494                 if (l) {
495                         app = l->data;
496                         app->mgmt_proxy = proxy;
497                 } else {
498                         ERR("Mesh: app not found for Mgmt proxy");
499                 }
500                 return;
501         }
502
503         if (!strcmp(interface, BT_HAL_MESH_NODE_INTERFACE)) {
504                 INFO("Mesh: Node Proxy added");
505                 GSList *l;
506                 meshcfg_app *app;
507                 l = g_slist_find_custom(mesh_apps, path, __compare_proxy_path);
508                 if (l) {
509                         app = l->data;
510                         app->proxy = proxy;
511                 } else {
512                         ERR("Mesh: app not found for Node proxy");
513                 }
514                 return;
515         }
516 }
517
518 static void __mesh_proxy_removed(struct l_dbus_proxy *proxy, void *user_data)
519 {
520         const char *interface = l_dbus_proxy_get_interface(proxy);
521         const char *path = l_dbus_proxy_get_path(proxy);
522
523         INFO("Proxy removed: %s (%s)\n", interface, path);
524
525         if (!strcmp(interface, BT_HAL_MESH_NETWORK_INTERFACE)) {
526                 INFO("Mesh: Network Interface removed,, possibly meshd terminated.\n");
527                 /*TODO: Send event to app about stop of Mesh service  & then remove all apps */
528                 if (mesh_apps) {
529                         g_slist_free_full(mesh_apps, __bt_hal_mesh_destroy_app_object);
530                         mesh_apps = NULL;
531                         return;
532                 }
533         } else if (!strcmp(interface, BT_HAL_MESH_NODE_INTERFACE)) {
534                 INFO("Mesh: Node Interface removed,, possibly node has left network.\n");
535                 GSList *l;
536                 meshcfg_app *app;
537                 l = g_slist_find_custom(mesh_apps, path, __compare_proxy_path);
538                 if (l) {
539                         app = l->data;
540                         /* Send event to app about removal of a mesh local node */
541                         __send_network_destroy_event(app, BT_STATUS_SUCCESS);
542                         __bt_hal_mesh_destroy_app_object(app);
543                 } else {
544                         ERR("Mesh: app not found for Mgmt proxy");
545                 }
546                 return;
547         } else if (!strcmp(interface, BT_HAL_MESH_MANAGEMENT_INTERFACE)) {
548                 INFO("Mesh: Managament Interface removed,, possibly node has left network.\n");
549                 GSList *l;
550                 meshcfg_app *app;
551                 l = g_slist_find_custom(mesh_apps, path, __compare_proxy_path);
552                 if (l) {
553                         app = l->data;
554                         /* Send event to app about removal of a mesh local node */
555                         __send_network_destroy_event(app, BT_STATUS_SUCCESS);
556                         __bt_hal_mesh_destroy_app_object(app);
557                 } else {
558                         ERR("Mesh: app not found for Mgmt proxy");
559                 }
560                 return;
561         }
562 }
563
564 static void __mesh_property_changed(struct l_dbus_proxy *proxy, const char *name,
565                                 struct l_dbus_message *msg, void *user_data)
566 {
567         const char *interface = l_dbus_proxy_get_interface(proxy);
568         const char *path = l_dbus_proxy_get_path(proxy);
569         GSList *l;
570         meshcfg_app *app = NULL;
571
572         l = g_slist_find_custom(mesh_apps, path, __compare_proxy_path);
573         if (l) {
574                 app = l->data;
575         } else {
576                 ERR("Mesh: app not found for Mgmt proxy");
577         }
578
579         INFO("Property changed: %s %s %s\n", name, path, interface);
580
581         if (!app)
582                 return;
583
584         if (!strcmp(interface, BT_HAL_MESH_NODE_INTERFACE)) {
585
586                 if (!strcmp(name, "IvIndex")) {
587                         uint32_t ivi;
588
589                         if (!l_dbus_message_get_arguments(msg, "u", &ivi))
590                                 return;
591
592                         INFO("New IV Index: %u\n", ivi);
593
594                         iv_index = ivi;
595                         /*TODO: save iv index */
596                 }
597         }
598 }
599
600
601 static void __mesh_dbus_client_ready(struct l_dbus_client *client_obj,
602                 void *user_data)
603 {
604         INFO("Mesh: D-Bus client ready: bluetooth-meshd connected \n");
605         client = client_obj;
606 }
607
608 static void __mesh_acquire_name_callback(struct l_dbus *dbus_obj, bool success,
609                                         bool queued, void *user_data)
610 {
611         if (success == false)
612                 ERR("Mesh: Fail to acquire dbus name\n");
613
614         if (!l_dbus_object_manager_enable(dbus_obj, "/"))
615                 ERR("Mesh: Failed to register the ObjectManager\n");
616 }
617
618 static void __mesh_ready_callback(void *user_data)
619 {
620         INFO("Mesh: Connected to D-Bus\n");
621
622         if (!l_dbus_name_acquire(dbus, BT_HAL_MESH_DBUS_NAME, false, false, false,
623                                 __mesh_acquire_name_callback, NULL))
624                 ERR("Mesh: Failed to own well-known name\n");
625 }
626
627 bool _bt_hal_mesh_stack_init(void)
628 {
629         INFO("Mesh: Connect with meshd");
630         /* Connect with meshd */
631         dbus = l_dbus_new_default(L_DBUS_SYSTEM_BUS);
632         if (!dbus)
633                 return false;
634
635         INFO("Mesh: Got dbus [%p]", dbus);
636
637         if (!l_dbus_set_ready_handler(dbus, __mesh_ready_callback, NULL, NULL))
638                 return false;
639
640         client = l_dbus_client_new(dbus,
641                         BT_HAL_BLUEZ_MESH_NAME, "/org/bluez/mesh");
642         if (!client)
643                 return false;
644
645         if (!l_dbus_client_set_connect_handler(client,
646                                 __mesh_client_connected, NULL, NULL))
647                 return false;
648
649         if (!l_dbus_client_set_disconnect_handler(client,
650                                 __mesh_client_disconnected, NULL,
651                                 NULL))
652                 return false;
653         if (!l_dbus_client_set_proxy_handlers(client,
654                                 __mesh_proxy_added, __mesh_proxy_removed,
655                                 __mesh_property_changed, NULL, NULL))
656                 return false;
657         if (!l_dbus_client_set_ready_handler(client,
658                                 __mesh_dbus_client_ready, NULL, NULL))
659                 return false;
660
661         INFO("Mesh: Stack Init watchers registered with  meshd");
662         return true;
663 }
664
665 void _bt_hal_mesh_stack_deinit(void)
666 {
667         INFO("Mesh: Stack Deinit");
668
669         if (client) {
670                 l_dbus_client_destroy(client);
671                 client = NULL;
672         }
673
674         if (dbus) {
675                 l_dbus_destroy(dbus);
676                 dbus = NULL;
677         }
678
679         /* Reset Globals */
680         net_proxy = NULL;
681         agent_msg = NULL;
682         INFO("Mesh: Number of meshapps present in memory [%d]",
683                         g_slist_length(mesh_apps));
684 }
685
686 /* To send stack event to hal-mesh handler */
687 void _bt_hal_mesh_register_dbus_handler_cb(handle_stack_msg cb)
688 {
689         mesh_event_cb = cb;
690 }
691
692 /* To send stack event to hal-mesh handler */
693 void _bt_hal_mesh_unregister_dbus_handler_cb()
694 {
695         mesh_event_cb = NULL;
696 }
697
698 static bool __mesh_get_companyid(struct l_dbus *dbus,
699                 struct l_dbus_message *message,
700                         struct l_dbus_message_builder *builder,
701                                 void *user_data)
702 {
703         meshcfg_app *app = (meshcfg_app*) user_data;
704         if (!app)
705                 return false;
706
707         l_dbus_message_builder_append_basic(builder, 'q', &app->cid);
708
709         return true;
710 }
711
712 static bool __mesh_get_productid(struct l_dbus *dbus,
713                 struct l_dbus_message *message,
714                         struct l_dbus_message_builder *builder,
715                                 void *user_data)
716 {
717         meshcfg_app *app = (meshcfg_app*) user_data;
718         if (!app)
719                 return false;
720         l_dbus_message_builder_append_basic(builder, 'q', &app->pid);
721
722         return true;
723 }
724
725 static bool __mesh_get_versionid(struct l_dbus *dbus,
726                 struct l_dbus_message *message,
727                         struct l_dbus_message_builder *builder,
728                                 void *user_data)
729 {
730         meshcfg_app *app = (meshcfg_app*) user_data;
731         if (!app)
732                 return false;
733         l_dbus_message_builder_append_basic(builder, 'q', &app->vid);
734
735         return true;
736 }
737
738 static bool __mesh_get_crpl(struct l_dbus *dbus,
739                 struct l_dbus_message *message,
740                         struct l_dbus_message_builder *builder,
741                                 void *user_data)
742 {
743         meshcfg_app *app = (meshcfg_app*) user_data;
744         if (!app)
745                 return false;
746         l_dbus_message_builder_append_basic(builder, 'q', &app->crpl);
747
748         return true;
749 }
750
751 static void __send_network_attach_event(void *param, uint8_t status)
752 {
753         struct hal_ev_mesh_network_attached ev;
754         meshcfg_app *app = (meshcfg_app*)param;
755
756         memset(&ev, 0, sizeof(ev));
757         memcpy(ev.uuid, app->uuid, sizeof(app->uuid));
758         memcpy(ev.token, app->token.u8, 8);
759         ev.is_prov = app->is_prov;
760
761         ev.status = status;
762         if (mesh_event_cb)
763                 mesh_event_cb(HAL_EV_MESH_NETWORK_ATTACHED,
764                         (void*)&ev, sizeof(ev));
765 }
766
767 static void __bt_hal_mesh_attach_node_reply(struct l_dbus_proxy *proxy,
768                 struct l_dbus_message *msg, void *user_data)
769 {
770         struct l_dbus_message_iter iter_cfg;
771         char *path;
772         meshcfg_app *app = (meshcfg_app*) user_data;
773         uint32_t ivi;
774
775         INFO("Mesh: Attach Node Reply: App path [%s] Agent Path [%s]",
776                 app->path, app->agent_path);
777
778         if (l_dbus_message_is_error(msg)) {
779                 const char *name;
780                 l_dbus_message_get_error(msg, &name, NULL);
781                 ERR("Mesh: Failed to attach node: %s", name);
782                 goto failed;
783
784         }
785
786         if (!l_dbus_message_get_arguments(msg, "oa(ya(qa{sv}))",
787                                 &path, &iter_cfg))
788                 goto failed;
789
790         INFO("Mesh: Attached with path %s\n", app->path);
791         __send_network_attach_event(app, BT_STATUS_SUCCESS);
792
793         if (l_dbus_proxy_get_property(app->proxy, "IvIndex", "u", &ivi) &&
794                                                         ivi != iv_index) {
795                 iv_index = ivi;
796                 /* TODO: Save IV index */
797         }
798
799         return;
800 failed:
801         __send_network_attach_event(app, BT_STATUS_FAIL);
802         /* Destroy mesh app object */
803         __bt_hal_mesh_destroy_app_object(app);
804 }
805
806 static void __bt_hal_mesh_attach_node_setup(struct l_dbus_message *msg,
807                 void *user_data)
808 {
809         meshcfg_app *app = (meshcfg_app*) user_data;
810
811         l_dbus_message_set_arguments(msg, "ot", app->path,
812                         l_get_be64(app->token.u8));
813 }
814
815
816 static void __bt_hal_mesh_attach_node(void *user_data)
817 {
818         if (!l_dbus_proxy_method_call(net_proxy, "Attach",
819                                 __bt_hal_mesh_attach_node_setup,
820                                 __bt_hal_mesh_attach_node_reply,
821                                 user_data,
822                                 NULL)) {
823                 ERR("Mesh: Node attach failed!!");
824                 /* Node could not be attached */
825                 __send_network_attach_event(user_data, BT_STATUS_FAIL);
826                 /* Destroy mesh app object */
827                 __bt_hal_mesh_destroy_app_object((meshcfg_app*)user_data);
828         }
829 }
830
831 static struct l_dbus_message *__mesh_node_join_complete(struct l_dbus *dbus,
832                 struct l_dbus_message *message,
833                         void *user_data)
834 {
835         char *str;
836         uint64_t tmp;
837
838         meshcfg_app *app = (meshcfg_app*) user_data;
839         INFO("Mesh: Join Complete");
840
841         /* Return error */
842         if (!l_dbus_message_get_arguments(message, "t", &tmp)) {
843
844                 /* Send Network creation fail event */
845                 __send_network_attach_event(app, BT_STATUS_FAIL);
846
847                 /* Destroy mesh app object */
848                 __bt_hal_mesh_destroy_app_object(app);
849
850                 return l_dbus_message_new_error(message, dbus_err_args, NULL);
851         }
852
853         /* Save token */
854         app->token.u64 = l_get_be64(&tmp);
855         str = l_util_hexstring(&app->token.u8[0], 8);
856         INFO("Mesh: Created new node with token %s\n", str);
857         l_free(str);
858
859         /* Authenticate the node */
860         l_idle_oneshot(__bt_hal_mesh_attach_node, app, NULL);
861         return l_dbus_message_new_method_return(message);
862 }
863
864 static void append_dict_entry_basic(struct l_dbus_message_builder *builder,
865                 const char *key, const char *signature,
866                 const void *data)
867 {
868         if (!builder)
869                 return;
870
871         l_dbus_message_builder_enter_dict(builder, "sv");
872         l_dbus_message_builder_append_basic(builder, 's', key);
873         l_dbus_message_builder_enter_variant(builder, signature);
874         l_dbus_message_builder_append_basic(builder, signature[0], data);
875         l_dbus_message_builder_leave_variant(builder);
876         l_dbus_message_builder_leave_dict(builder);
877 }
878
879 static void __bt_hal_mesh_foreach_model_getter(gpointer data,
880                 gpointer user_data)
881 {
882         struct l_dbus_message_builder *builder = (struct l_dbus_message_builder *) user_data;
883         meshcfg_model *model_info = (meshcfg_model*) data;
884         bool pub_enable = true;
885         bool sub_enable = true;
886
887         l_dbus_message_builder_enter_struct(builder, "qa{sv}");
888         l_dbus_message_builder_append_basic(builder, 'q', &model_info->model);
889         l_dbus_message_builder_enter_array(builder, "{sv}");
890         append_dict_entry_basic(builder, "Subscribe", "b", &sub_enable);
891         append_dict_entry_basic(builder, "Publish", "b", &pub_enable);
892         l_dbus_message_builder_leave_array(builder);
893         l_dbus_message_builder_leave_struct(builder);
894 }
895
896 static bool __mesh_model_getter(struct l_dbus *dbus,
897                 struct l_dbus_message *message,
898                         struct l_dbus_message_builder *builder,
899                                 void *user_data)
900 {
901         meshcfg_el *element = (meshcfg_el*) user_data;
902
903         l_dbus_message_builder_enter_array(builder, "(qa{sv})");
904         g_slist_foreach(element->models,
905                 __bt_hal_mesh_foreach_model_getter, builder);
906
907         l_dbus_message_builder_leave_array(builder);
908
909         return true;
910 }
911
912 /*TODO: Vendor Model handling is currently not Handled */
913 static bool __mesh_vendor_model_getter(struct l_dbus *dbus,
914                 struct l_dbus_message *message,
915                         struct l_dbus_message_builder *builder,
916                                 void *user_data)
917 {
918         l_dbus_message_builder_enter_array(builder, "(qqa{sv})");
919         l_dbus_message_builder_leave_array(builder);
920
921         return true;
922 }
923
924 static bool __mesh_element_index_getter(struct l_dbus *dbus,
925                 struct l_dbus_message *message,
926                         struct l_dbus_message_builder *builder,
927                                 void *user_data)
928 {
929         meshcfg_el *element = (meshcfg_el*) user_data;
930         l_dbus_message_builder_append_basic(builder, 'y', &element->index);
931
932         return true;
933 }
934
935
936 static struct l_dbus_message *__mesh_device_message_received(struct l_dbus *dbus,
937                 struct l_dbus_message *msg, void *user_data)
938 {
939         struct l_dbus_message_iter iter;
940         uint16_t src, idx;
941         uint8_t *data;
942         uint32_t n;
943         bool rmt;
944         const char *dbus_path;
945         uint16_t size;
946         uint8_t *net_uuid;
947         dbus_path =  l_dbus_message_get_path(msg);
948         net_uuid = __mesh_get_net_uuid_from_path(dbus_path, true,  MESH_ELEMENT_IFACE);
949         uint8_t buf[BT_HAL_MESH_MAX_DEVKEY_BUF_SIZE];
950         struct hal_ev_mesh_devkey_message_event *ev = (void *)buf;
951
952         INFO("Mesh: app path [%s]", dbus_path);
953
954         memset(buf, 0, sizeof(buf));
955         size = (uint16_t) sizeof(*ev);
956         memcpy(ev->net_uuid, net_uuid, 16);
957         g_free(net_uuid);
958
959         if (!l_dbus_message_get_arguments(msg, "qbqay", &src, &rmt, &idx,
960                                 &iter)) {
961                 ERR("Mesh: Cannot parse received message");
962                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
963         }
964
965         if (!l_dbus_message_iter_get_fixed_array(&iter, &data, &n)) {
966                 ERR("Mesh: Cannot parse received message: data");
967                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
968         }
969
970         INFO("Mesh: Received dev key message (len %u):", n);
971         ev->source_addr = src;
972         ev->is_remote_devkey = rmt;
973         ev->netkey_idx = idx;
974         ev->data_len = n;
975         memcpy(ev->data, data, n);
976         size += n;
977
978         INFO("Mesh: Src [0x%2.2x]", src);
979         INFO("Mesh: Is Remote [%s]", rmt ? "YES" : "NO");
980         INFO("Mesh: NetKey Idx [0x%2.2x]", idx);
981         /* Send DevKeyMessage Received event */
982         if (mesh_event_cb)
983                 mesh_event_cb(HAL_EV_MESH_DEVKEY_MESSAGE_EVENT, (void*)buf, size);
984         return l_dbus_message_new_method_return(msg);
985 }
986
987 static struct l_dbus_message *__mesh_message_received(struct l_dbus *dbus,
988                 struct l_dbus_message *msg, void *user_data)
989 {
990         struct l_dbus_message_iter iter;
991         uint16_t src, idx, dst;
992         uint8_t *data;
993         uint32_t n;
994         const char *dbus_path;
995         uint16_t size;
996         bool is_provisioner = true;
997         uint8_t *net_uuid;
998         dbus_path =  l_dbus_message_get_path(msg);
999         GSList *l = g_slist_find_custom(mesh_apps, dbus_path, __compare_dbus_path);
1000         if (l) {
1001                 meshcfg_app *app = NULL;
1002                 app = l->data;
1003                 INFO("Mesh: is Provisioner [%d]", app->is_prov);
1004                 is_provisioner = app->is_prov;
1005         } else {
1006                 ERR("Mesh: app is NULL");
1007         }
1008         net_uuid = __mesh_get_net_uuid_from_path(dbus_path, is_provisioner,  MESH_ELEMENT_IFACE);
1009         uint8_t buf[BT_HAL_MESH_MAX_MSG_BUF_SIZE];
1010         struct hal_ev_mesh_message_event *ev = (void *)buf;
1011
1012         INFO("Mesh: app path [%s]", dbus_path);
1013
1014         memset(buf, 0, sizeof(buf));
1015         size = (uint16_t) sizeof(*ev);
1016         memcpy(ev->net_uuid, net_uuid, 16);
1017         g_free(net_uuid);
1018         ev->is_prov = is_provisioner;
1019
1020         if (!l_dbus_message_get_arguments(msg, "qqvay", &src, &idx, &dst,
1021                                 &iter)) {
1022                 ERR("Mesh: Cannot parse received message");
1023                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
1024         }
1025
1026         if (!l_dbus_message_iter_get_fixed_array(&iter, &data, &n)) {
1027                 ERR("Mesh: Cannot parse received message: data");
1028                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
1029         }
1030
1031         INFO("Mesh: Received mesh message (len %u):", n);
1032         ev->source_addr = src;
1033         ev->dest_addr = dst;
1034         ev->key_idx = idx;
1035         ev->data_len = n;
1036         memcpy(ev->data, data, n);
1037         size += n;
1038
1039         INFO("Mesh: Src [0x%2.2x]", src);
1040         INFO("Mesh: Dst [0x%2.2x]", dst);
1041         INFO("Mesh: NetKey Idx [0x%2.2x]", idx);
1042         /* Send Message Received event */
1043         if (mesh_event_cb) {
1044                 INFO("Mesh: Send message event");
1045                 mesh_event_cb(HAL_EV_MESH_MESSAGE_EVENT, (void*)buf, size);
1046         }
1047         return l_dbus_message_new_method_return(msg);
1048 }
1049
1050 static void __bt_hal_mesh_setup_ele_iface(struct l_dbus_interface *iface)
1051 {
1052         INFO("Mesh: Setup element interface properties & methods");
1053         /* Properties */
1054         l_dbus_interface_property(iface, "Index", 0, "y", __mesh_element_index_getter,
1055                         NULL);
1056         l_dbus_interface_property(iface, "VendorModels", 0, "a(qqa{sv})",
1057                         __mesh_vendor_model_getter, NULL);
1058         l_dbus_interface_property(iface, "Models", 0, "a(qa{sv})", __mesh_model_getter,
1059                                                                         NULL);
1060
1061         /* Methods */
1062         l_dbus_interface_method(iface, "DevKeyMessageReceived", 0,
1063                         __mesh_device_message_received, "", "qbqay", "source",
1064                         "remote", "net_index", "data");
1065         l_dbus_interface_method(iface, "MessageReceived", 0,
1066                         __mesh_message_received, "", "qqvay", "source",
1067                         "key_index", "destination", "data");
1068         /* TODO: Other methods */
1069 }
1070
1071 static struct l_dbus_message *__mesh_scan_result_received(struct l_dbus *dbus,
1072                 struct l_dbus_message *msg,
1073                         void *user_data)
1074 {
1075         struct l_dbus_message_iter iter, opts;
1076         meshcfg_app *app = (meshcfg_app*) user_data;
1077         int16_t rssi;
1078         uint32_t n;
1079         uint8_t *prov_data;
1080         char *str;
1081         const char *sig = "naya{sv}";
1082
1083         /* Find network uuid from dbus path */
1084         struct hal_ev_mesh_scan_result ev;
1085
1086         if (!app->scan_timer_id) {
1087                 /* Scan is not running */
1088                 INFO("Got scan result, but scan is already stopped");
1089                 return l_dbus_message_new_method_return(msg);
1090         }
1091         memset(&ev, 0, sizeof(ev));
1092         memcpy(ev.net_uuid, app->uuid, 16);
1093
1094         if (!l_dbus_message_get_arguments(msg, sig, &rssi, &iter, &opts)) {
1095                 ERR("Mesh: Cannot parse scan results");
1096                 ev.status = BT_STATUS_FAIL;
1097                 if (mesh_event_cb)
1098                         mesh_event_cb(HAL_EV_MESH_SCAN_RESULT, (void*)&ev, sizeof(ev));
1099                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
1100         }
1101
1102         if (!l_dbus_message_iter_get_fixed_array(&iter, &prov_data, &n) ||
1103                         n < 16) {
1104                 ERR("Mesh: Cannot parse scan result: data");
1105                 ev.status = BT_STATUS_FAIL;
1106                 if (mesh_event_cb)
1107                         mesh_event_cb(HAL_EV_MESH_SCAN_RESULT, (void*)&ev, sizeof(ev));
1108                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
1109         }
1110
1111         INFO("Mesh: Scan result:\n");
1112         INFO("Mesh: Scan rssi = [%d]\n", rssi);
1113         str = l_util_hexstring_upper(prov_data, 16);
1114         INFO("Mesh: Scan UUID = [%s]\n",  str);
1115         l_free(str);
1116
1117         if (n >= 18) {
1118                 str = l_util_hexstring_upper(prov_data + 16, 2);
1119                 INFO("Mesh: Scan OOB = [%s]\n", str);
1120                 l_free(str);
1121         }
1122
1123         if (n >= 22) {
1124                 str = l_util_hexstring_upper(prov_data + 18, 4);
1125                 INFO("Mesh: Scan URI hash = [%s]\n", str);
1126                 l_free(str);
1127         }
1128
1129         /* 16 octet Dev UUID */
1130         memcpy(ev.dev_uuid, prov_data, 16);
1131
1132         /* 2 octet Dev OOB Info */
1133         memcpy(ev.oob_info, prov_data + 16, 2);
1134
1135         /* 4 octet URI Hash */
1136         memcpy(ev.uri_hash, prov_data + 18, 4);
1137
1138         ev.rssi = rssi;
1139
1140         ev.status = BT_STATUS_SUCCESS;
1141         if (mesh_event_cb)
1142                 mesh_event_cb(HAL_EV_MESH_SCAN_RESULT,
1143                         (void*)&ev, sizeof(ev));
1144
1145         return l_dbus_message_new_method_return(msg);
1146 }
1147
1148 static struct l_dbus_message *__mesh_request_provisioner_call(
1149                 struct l_dbus *dbus,
1150                         struct l_dbus_message *msg,
1151                                 void *user_data)
1152 {
1153         uint8_t cnt;
1154         struct hal_ev_mesh_provision_finished ev;
1155         struct hal_ev_mesh_provision_data_request req;
1156         char *uuid_string;
1157         meshcfg_app *app = user_data;
1158
1159         INFO("Mesh: provisioning data requested app path [%s]",
1160                 app->path);
1161         uuid_string = l_util_hexstring(app->uuid, 16);
1162         INFO("Mesh: Network UUID [%s]", uuid_string);
1163
1164         memset(&ev, 0, sizeof(ev));
1165         memset(&req, 0, sizeof(req));
1166         memcpy(ev.net_uuid, app->uuid, 16);
1167         memcpy(req.net_uuid, app->uuid, 16);
1168         l_free(uuid_string);
1169
1170         if (!l_dbus_message_get_arguments(msg, "y", &cnt)) {
1171                 ERR("Mesh: Cannot parse request for prov data");
1172                 /* Send Event */
1173                 ev.status = BT_STATUS_FAIL;
1174                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1175                 if (mesh_event_cb)
1176                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1177                                 (void*)&ev, sizeof(ev));
1178                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
1179         }
1180
1181         app->msg = msg;
1182         req.count = cnt;
1183         if (mesh_event_cb)
1184                 mesh_event_cb(HAL_EV_MESH_PROVISIONING_DATA_REQUEST,
1185                         (void*)&req, sizeof(req));
1186
1187         l_dbus_message_ref(msg);
1188         return NULL;
1189 }
1190
1191 static struct l_dbus_message *__mesh_node_add_completed(
1192                 struct l_dbus *dbus,
1193                         struct l_dbus_message *msg,
1194                                 void *user_data)
1195 {
1196         struct l_dbus_message_iter iter;
1197         int16_t unicast;
1198         uint8_t cnt;
1199         uint32_t n;
1200         uint8_t *uuid;
1201         struct hal_ev_mesh_provision_finished ev;
1202         const char *dbus_path;
1203         uint8_t *net_uuid;
1204         dbus_path =  l_dbus_message_get_path(msg);
1205         net_uuid = __mesh_get_net_uuid_from_path(dbus_path,
1206                         true,  MESH_PROV_IFACE);
1207
1208         INFO("Mesh: app path [%s]", dbus_path);
1209
1210         memset(&ev, 0, sizeof(ev));
1211         memcpy(ev.net_uuid, net_uuid, 16);
1212
1213         g_free(net_uuid);
1214
1215         if (!l_dbus_message_get_arguments(msg, "ayqy", &iter, &unicast, &cnt)) {
1216                 ERR("Mesh: Cannot parse add node complete message");
1217                 /* Send Event */
1218                 ev.status = BT_STATUS_FAIL;
1219                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1220                 if (mesh_event_cb)
1221                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1222                                 (void*)&ev, sizeof(ev));
1223                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
1224         }
1225
1226         if (!l_dbus_message_iter_get_fixed_array(&iter, &uuid, &n) ||
1227                         n != 16) {
1228                 ERR("Mesh: Cannot parse add node complete message: uuid");
1229                 /* Send Event */
1230                 ev.status = BT_STATUS_FAIL;
1231                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1232                 if (mesh_event_cb)
1233                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1234                                 (void*)&ev, sizeof(ev));
1235                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
1236         }
1237
1238         /* Send Event */
1239         ev.status = BT_STATUS_SUCCESS;
1240         ev.reason = BT_HAL_MESH_PROV_ERR_SUCCESS;
1241         memcpy(ev.dev_uuid, uuid, 16);
1242         ev.unicast = unicast;
1243         ev.count = cnt;
1244
1245         if (mesh_event_cb)
1246                 mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1247                         (void*)&ev, sizeof(ev));
1248
1249         return l_dbus_message_new_method_return(msg);
1250 }
1251
1252 static struct l_dbus_message *__mesh_node_add_failed(
1253                 struct l_dbus *dbus,
1254                         struct l_dbus_message *msg,
1255                                 void *user_data)
1256 {
1257         struct l_dbus_message_iter iter;
1258         uint32_t n;
1259         uint8_t *uuid;
1260         char *str, *reason;
1261         struct hal_ev_mesh_provision_finished ev;
1262         const char *dbus_path;
1263
1264         uint8_t *net_uuid;
1265         dbus_path =  l_dbus_message_get_path(msg);
1266         net_uuid = __mesh_get_net_uuid_from_path(dbus_path,
1267                         true,  MESH_PROV_IFACE);
1268
1269         memset(&ev, 0, sizeof(ev));
1270         memcpy(ev.net_uuid, net_uuid, 16);
1271
1272         g_free(net_uuid);
1273         if (!l_dbus_message_get_arguments(msg, "ays", &iter, &reason)) {
1274                 ERR("Mesh: Cannot parse add node failed message");
1275                 /* Send Event */
1276                 ev.status = BT_STATUS_FAIL;
1277                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1278                 if (mesh_event_cb)
1279                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1280                                 (void*)&ev, sizeof(ev));
1281                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
1282         }
1283
1284         if (!l_dbus_message_iter_get_fixed_array(&iter, &uuid, &n) ||
1285                         n != 16) {
1286                 ERR("Mesh:Cannot parse add node failed message: uuid");
1287                 ev.status = BT_STATUS_FAIL;
1288                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1289                 if (mesh_event_cb)
1290                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1291                                 (void*)&ev, sizeof(ev));
1292                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
1293         }
1294
1295         INFO("Mesh: Provisioning failed:\n");
1296         str = l_util_hexstring_upper(uuid, 16);
1297         INFO("Mesh: UUID = [%s] Reason [%s]", str, reason);
1298
1299         ev.status = BT_STATUS_FAIL;
1300         ev.reason = __bt_mesh_util_get_prov_error_code(str);
1301         memcpy(ev.dev_uuid, uuid, 16);
1302
1303         l_free(str);
1304
1305         if (mesh_event_cb)
1306                 mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1307                         (void*)&ev, sizeof(ev));
1308
1309         return l_dbus_message_new_method_return(msg);
1310 }
1311
1312 static void __bt_hal_mesh_setup_prov_iface(struct l_dbus_interface *interface)
1313 {
1314         INFO("Mesh: Setup provisioner interface properties & methods");
1315         l_dbus_interface_method(interface, "ScanResult", 0,
1316                         __mesh_scan_result_received, "",
1317                         "naya{sv}", "rssi", "data", "options");
1318
1319         l_dbus_interface_method(interface, "RequestProvData", 0,
1320                         __mesh_request_provisioner_call,
1321                         "qq", "y", "net_index", "unicast", "count");
1322
1323         l_dbus_interface_method(interface, "AddNodeComplete", 0,
1324                         __mesh_node_add_completed, "", "ayqy",
1325                         "uuid", "unicast", "count");
1326
1327         l_dbus_interface_method(interface, "AddNodeFailed", 0,
1328                         __mesh_node_add_failed,
1329                         "", "ays", "uuid", "reason");
1330 }
1331
1332 static void __bt_hal_mesh_setup_app_iface(struct l_dbus_interface *iface)
1333 {
1334         INFO("Mesh: Setup application interface properties & methods");
1335
1336         l_dbus_interface_property(iface, "CompanyID", 0, "q",
1337                         __mesh_get_companyid,
1338                         NULL);
1339         l_dbus_interface_property(iface, "VersionID", 0, "q",
1340                         __mesh_get_versionid,
1341                         NULL);
1342         l_dbus_interface_property(iface, "ProductID", 0, "q",
1343                         __mesh_get_productid,
1344                         NULL);
1345         l_dbus_interface_property(iface, "CRPL", 0, "q",
1346                         __mesh_get_crpl, NULL);
1347         l_dbus_interface_method(iface, "JoinComplete", 0,
1348                         __mesh_node_join_complete,
1349                         "", "t", "token");
1350
1351         /* TODO: Methods */
1352 }
1353
1354 static void __mesh_fill_in_capabilities(meshcfg_app *app,
1355                  struct l_dbus_message_builder *builder)
1356 {
1357         if (app->in_oob & 0x08)
1358                 l_dbus_message_builder_append_basic(builder, 's', "in-alpha");
1359         if (app->in_oob & 0x04)
1360                 l_dbus_message_builder_append_basic(builder, 's', "in-numeric");
1361         if (app->in_oob & 0x02)
1362                 l_dbus_message_builder_append_basic(builder, 's', "twist");
1363         if (app->in_oob & 0x01)
1364                 l_dbus_message_builder_append_basic(builder, 's', "push");
1365 }
1366
1367 static void __mesh_fill_out_capabilities(meshcfg_app *app,
1368                  struct l_dbus_message_builder *builder)
1369 {
1370         if (app->out_oob & 0x10)
1371                 l_dbus_message_builder_append_basic(builder, 's', "out-alpha");
1372         if (app->out_oob & 0x08)
1373                 l_dbus_message_builder_append_basic(builder, 's', "out-numeric");
1374         if (app->out_oob & 0x04)
1375                 l_dbus_message_builder_append_basic(builder, 's', "vibrate");
1376         if (app->out_oob & 0x02)
1377                 l_dbus_message_builder_append_basic(builder, 's', "beep");
1378         if (app->out_oob & 0x01)
1379                 l_dbus_message_builder_append_basic(builder, 's', "blink");
1380 }
1381
1382 static bool __mesh_agent_capability_getter(
1383                 struct l_dbus *dbus, struct l_dbus_message *message,
1384                         struct l_dbus_message_builder *builder,
1385                                 void *user_data)
1386 {
1387         meshcfg_app *app;
1388         app = user_data;
1389         INFO("Mesh: app path [%s]", app->path);
1390         INFO("Mesh: Agent path [%s]", app->agent_path);
1391
1392         if (!l_dbus_message_builder_enter_array(builder, "s"))
1393                 return false;
1394
1395         __mesh_fill_out_capabilities(app, builder);
1396         __mesh_fill_in_capabilities(app, builder);
1397
1398         if (app->static_oob)
1399                 l_dbus_message_builder_append_basic(builder,
1400                         's', "static-oob");
1401
1402
1403         l_dbus_message_builder_leave_array(builder);
1404         INFO("Mesh: __agent_capability_getter: Success");
1405         return true;
1406 }
1407
1408 static struct l_dbus_message *__mesh_agent_display_string_request(
1409                 struct l_dbus *dbus,
1410                         struct l_dbus_message *msg,
1411                                 void *user_data)
1412 {
1413         struct hal_ev_mesh_authentication_request ev;
1414         char *str;
1415         uint8_t *net_uuid;
1416         const char *dbus_path;
1417         meshcfg_app *app;
1418         app = user_data;
1419         INFO("Mesh: app path [%s]", app->path);
1420         INFO("Mesh: Agent path [%s]", app->agent_path);
1421
1422         dbus_path =  l_dbus_message_get_path(msg);
1423         net_uuid = __mesh_get_net_uuid_from_path(app->agent_path,
1424                         true,  MESH_AGENT_IFACE);
1425
1426         INFO("Mesh: app path [%s]", dbus_path);
1427
1428         memset(&ev, 0, sizeof(ev));
1429         memcpy(ev.net_uuid, net_uuid, 16);
1430
1431
1432         if (!l_dbus_message_get_arguments(msg, "s", &str)) {
1433                 ERR("Mesh: Cannot parse \"DisplayString\" arguments");
1434                 struct hal_ev_mesh_provision_finished ev;
1435                 memset(&ev, 0, sizeof(ev));
1436                 memcpy(ev.net_uuid, net_uuid, 16);
1437                 ev.status = BT_STATUS_FAIL;
1438                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1439                 if (mesh_event_cb)
1440                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1441                                 (void*)&ev, sizeof(ev));
1442
1443                 g_free(net_uuid);
1444
1445                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1446         }
1447
1448         INFO("Mesh:[OUT] AlphaNumeric Authentication: Value [%s]", str);
1449         ev.auth_type = __mesh_get_authentication_type(str);
1450         if (ev.auth_type == BT_HAL_MESH_UNKNOWN_AUTH_METHOD)
1451                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1452         g_strlcpy(ev.auth_value, str, sizeof(ev.auth_value));
1453
1454         if (mesh_event_cb)
1455                 mesh_event_cb(HAL_EV_MESH_AUTHENTICATION_REQUEST,
1456                         (void*)&ev, sizeof(ev));
1457
1458         g_free(net_uuid);
1459         return l_dbus_message_new_method_return(msg);
1460 }
1461
1462 static struct l_dbus_message *__mesh_agent_display_numeric_request(
1463                 struct l_dbus *dbus,
1464                         struct l_dbus_message *msg,
1465                                 void *user_data)
1466 {
1467         uint32_t n;
1468         struct hal_ev_mesh_authentication_request ev;
1469         char *str;
1470         char *auth_value;
1471         uint8_t *net_uuid;
1472         const char *dbus_path;
1473         meshcfg_app *app;
1474         app = user_data;
1475         INFO("Mesh: app path [%s]", app->path);
1476         INFO("Mesh: Agent path [%s]", app->agent_path);
1477
1478         dbus_path =  l_dbus_message_get_path(msg);
1479         net_uuid = __mesh_get_net_uuid_from_path(app->agent_path,
1480                                 true,  MESH_AGENT_IFACE);
1481
1482         INFO("Mesh: app path [%s]", dbus_path);
1483
1484         memset(&ev, 0, sizeof(ev));
1485         memcpy(ev.net_uuid, net_uuid, 16);
1486
1487
1488         if (!l_dbus_message_get_arguments(msg, "su", &str, &n)) {
1489                 ERR("Mesh: Cannot parse \"DisplayNumeric\" arguments");
1490                 struct hal_ev_mesh_provision_finished ev;
1491                 memset(&ev, 0, sizeof(ev));
1492                 memcpy(ev.net_uuid, net_uuid, 16);
1493                 ev.status = BT_STATUS_FAIL;
1494                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1495                 if (mesh_event_cb) {
1496                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1497                                 (void*)&ev, sizeof(ev));
1498                 }
1499                 g_free(net_uuid);
1500                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1501         }
1502
1503         INFO("Mesh:[OUT] Numeric Authentication type [%s] value [%u]", str, n);
1504         auth_value = l_strdup_printf("%u", n);
1505         ev.auth_type = __mesh_get_authentication_type(str);
1506         if (ev.auth_type == BT_HAL_MESH_UNKNOWN_AUTH_METHOD) {
1507                 l_free(auth_value);
1508                 g_free(net_uuid);
1509                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1510         }
1511         g_strlcpy(ev.auth_value, auth_value, sizeof(ev.auth_value));
1512
1513         if (mesh_event_cb)
1514                 mesh_event_cb(HAL_EV_MESH_AUTHENTICATION_REQUEST,
1515                         (void*)&ev, sizeof(ev));
1516
1517         l_free(auth_value);
1518         g_free(net_uuid);
1519
1520         return l_dbus_message_new_method_return(msg);
1521 }
1522
1523 static struct l_dbus_message *__mesh_agent_prompt_numeric_request(
1524                 struct l_dbus *dbus,
1525                         struct l_dbus_message *msg,
1526                                 void *user_data)
1527 {
1528         struct hal_ev_mesh_authentication_request ev;
1529         char *str;
1530         uint8_t *net_uuid;
1531         const char *dbus_path;
1532         GSList *l;
1533         meshcfg_app *app;
1534
1535         dbus_path =  l_dbus_message_get_path(msg);
1536         net_uuid = __mesh_get_net_uuid_from_path(dbus_path,
1537                         true,  MESH_AGENT_IFACE);
1538
1539         INFO("Mesh: app path [%s]", dbus_path);
1540
1541         l = g_slist_find_custom(mesh_apps, net_uuid,
1542                         __mesh_compare_network_uuid);
1543         if (!l) {
1544                 g_free(net_uuid);
1545                 return NULL;
1546         }
1547         app = l->data;
1548
1549         memset(&ev, 0, sizeof(ev));
1550         memcpy(ev.net_uuid, net_uuid, 16);
1551
1552         g_free(net_uuid);
1553         if (!l_dbus_message_get_arguments(msg, "s", &str)) {
1554                 ERR("Mesh: Cannot parse \"PromptNumeric\" arguments");
1555
1556                 struct hal_ev_mesh_provision_finished ev;
1557                 memset(&ev, 0, sizeof(ev));
1558                 memcpy(ev.net_uuid, app->uuid, 16);
1559                 ev.status = BT_STATUS_FAIL;
1560                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1561                 if (mesh_event_cb) {
1562                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1563                                 (void*)&ev, sizeof(ev));
1564                 }
1565                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1566         }
1567
1568         INFO("Mesh:[IN] Numeric Authentication type [%s]", str);
1569
1570         ev.auth_type = __mesh_get_authentication_type(str);
1571         if (ev.auth_type == BT_HAL_MESH_UNKNOWN_AUTH_METHOD)
1572                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1573         agent_msg = msg;
1574         l_dbus_message_ref(msg);
1575         if (mesh_event_cb)
1576                 mesh_event_cb(HAL_EV_MESH_AUTHENTICATION_REQUEST,
1577                         (void*)&ev, sizeof(ev));
1578
1579         return NULL;
1580 }
1581
1582 static struct l_dbus_message *__mesh_agent_prompt_static_request(
1583                 struct l_dbus *dbus,
1584                         struct l_dbus_message *msg,
1585                                 void *user_data)
1586 {
1587         struct hal_ev_mesh_authentication_request ev;
1588         char *str;
1589         uint8_t *net_uuid;
1590         const char *dbus_path;
1591         GSList *l;
1592         meshcfg_app *app = NULL;
1593
1594         dbus_path =  l_dbus_message_get_path(msg);
1595         net_uuid = __mesh_get_net_uuid_from_path(dbus_path, true,
1596                         MESH_AGENT_IFACE);
1597
1598         INFO("Mesh: app path [%s]", dbus_path);
1599
1600         l = g_slist_find_custom(mesh_apps, net_uuid,
1601                         __mesh_compare_network_uuid);
1602
1603         if (l)
1604                 app = l->data;
1605         else
1606                 ERR("Mesh: app not found");
1607
1608
1609         memset(&ev, 0, sizeof(ev));
1610         memcpy(ev.net_uuid, net_uuid, 16);
1611
1612         g_free(net_uuid);
1613         if (!l_dbus_message_get_arguments(msg, "s", &str)) {
1614                 ERR("Mesh: Cannot parse \"PromptNumeric\" arguments");
1615
1616                 struct hal_ev_mesh_provision_finished ev;
1617                 memset(&ev, 0, sizeof(ev));
1618
1619                 if (app)
1620                         memcpy(ev.net_uuid, app->uuid, 16);
1621
1622                 ev.status = BT_STATUS_FAIL;
1623                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1624                 if (mesh_event_cb)
1625                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1626                                         (void*)&ev, sizeof(ev));
1627                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1628         }
1629
1630         INFO("Mesh: [IN] AlphaNumeric Authentication type [%s]", str);
1631
1632         ev.auth_type = __mesh_get_authentication_type(str);
1633         if (ev.auth_type == BT_HAL_MESH_UNKNOWN_AUTH_METHOD)
1634                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1635         agent_msg = msg;
1636         l_dbus_message_ref(msg);
1637         if (mesh_event_cb)
1638                 mesh_event_cb(HAL_EV_MESH_AUTHENTICATION_REQUEST,
1639                                 (void*)&ev, sizeof(ev));
1640
1641         return NULL;
1642 }
1643
1644 static void __bt_hal_mesh_setup_agent_iface(struct l_dbus_interface *interface)
1645 {
1646         INFO("Mesh: Setup Agent interface properties & methods");
1647         l_dbus_interface_property(interface, "Capabilities", 0, "as",
1648                         __mesh_agent_capability_getter,
1649                         NULL);
1650         /* TODO: Other properties */
1651         l_dbus_interface_method(interface, "DisplayString", 0,
1652                         __mesh_agent_display_string_request,
1653                         "", "s", "value");
1654         l_dbus_interface_method(interface, "DisplayNumeric", 0,
1655                         __mesh_agent_display_numeric_request,
1656                         "", "su", "type", "number");
1657         l_dbus_interface_method(interface, "PromptNumeric", 0,
1658                         __mesh_agent_prompt_numeric_request,
1659                         "u", "s", "number", "type");
1660         l_dbus_interface_method(interface, "PromptStatic", 0,
1661                         __mesh_agent_prompt_static_request,
1662                         "ay", "s", "data", "type");
1663 }
1664
1665 static void __bt_hal_mesh_register_element_obj(gpointer data, gpointer user_data)
1666 {
1667         meshcfg_el *elem = (meshcfg_el*) data;
1668         INFO("Mesh: Register Element: Index [%d] elem path [%s]",
1669                 elem->index, elem->path);
1670         if (!l_dbus_register_object(dbus, elem->path, NULL, NULL,
1671                                 BT_HAL_MESH_ELEMENT_INTERFACE, elem, NULL)) {
1672                 ERR("Mesh: Failed to register object %s", elem->path);
1673         }
1674 }
1675
1676 bool __bt_hal_mesh_register_agent(meshcfg_app *ptr)
1677 {
1678         if (!ptr)
1679                 return false;
1680
1681         if (!l_dbus_register_interface(dbus, BT_HAL_MESH_PROVISION_AGENT_INTERFACE,
1682                                 __bt_hal_mesh_setup_agent_iface, NULL, false)) {
1683                 ERR("Mesh: Unable to register agent interface");
1684                 //return false;
1685         }
1686
1687         INFO("Mesh: Register Agent path [%s]",  ptr->agent_path);
1688         if (!l_dbus_register_object(dbus, ptr->agent_path, NULL, NULL,
1689                                 BT_HAL_MESH_PROVISION_AGENT_INTERFACE, ptr, NULL)) {
1690                 ERR("Mesh: Failed to register object %s", ptr->agent_path);
1691                 return false;
1692         }
1693
1694         if (!l_dbus_object_add_interface(dbus, ptr->agent_path,
1695                                 L_DBUS_INTERFACE_PROPERTIES, NULL)) {
1696                 ERR("Mesh: Failed to add interface %s",
1697                                 L_DBUS_INTERFACE_PROPERTIES);
1698                 return false;
1699         }
1700
1701         return true;
1702 }
1703
1704 bool __bt_hal_mesh_register_application(meshcfg_app *ptr)
1705 {
1706
1707         if (!ptr)
1708                 return false;
1709         if (!dbus)
1710                 return false;
1711
1712         if (!l_dbus_register_interface(dbus, BT_HAL_MESH_APPLICATION_INTERFACE,
1713                                 __bt_hal_mesh_setup_app_iface, NULL, false)) {
1714                 ERR("Mesh: Failed to register interface %s",
1715                                 BT_HAL_MESH_APPLICATION_INTERFACE);
1716                 return false;
1717         }
1718
1719         if (!l_dbus_register_interface(dbus, BT_HAL_MESH_PROVISIONER_INTERFACE,
1720                                 __bt_hal_mesh_setup_prov_iface, NULL, false)) {
1721                 ERR("Mesh: Failed to register interface %s",
1722                                 BT_HAL_MESH_PROVISIONER_INTERFACE);
1723                 return false;
1724         }
1725
1726         if (!l_dbus_register_object(dbus, ptr->path, NULL, NULL,
1727                                 BT_HAL_MESH_APPLICATION_INTERFACE, ptr,
1728                                 BT_HAL_MESH_PROVISIONER_INTERFACE, ptr,
1729                                 NULL)) {
1730                 ERR("Mesh: Failed to register object %s", ptr->path);
1731                 return false;
1732         }
1733
1734         if (!__bt_hal_mesh_register_agent(ptr))
1735                 return false;
1736
1737         if (!l_dbus_register_interface(dbus, BT_HAL_MESH_ELEMENT_INTERFACE,
1738                                 __bt_hal_mesh_setup_ele_iface, NULL, false)) {
1739                 ERR("Mesh: Failed to register interface %s",
1740                                 BT_HAL_MESH_ELEMENT_INTERFACE);
1741                 return false;
1742         }
1743
1744         INFO("Mesh: Number of elements to be registsred [%d]",
1745                         g_slist_length(ptr->elements));
1746
1747         g_slist_foreach(ptr->elements, __bt_hal_mesh_register_element_obj, ptr);
1748
1749         INFO("Mesh: Add Object manager Interface: app path [%s]", ptr->path);
1750         if (!l_dbus_object_add_interface(dbus, ptr->path,
1751                                 L_DBUS_INTERFACE_OBJECT_MANAGER, NULL)) {
1752                 ERR("Mesh: Failed to add interface %s",
1753                                 L_DBUS_INTERFACE_OBJECT_MANAGER);
1754                 return false;
1755         }
1756         INFO("Mesh: Application Register completed");
1757
1758         return true;
1759 }
1760
1761 static void __bt_mesh_hal_create_element_object(gpointer data, gpointer user_data)
1762 {
1763         GSList *l;
1764         meshcfg_el *elem;
1765         meshcfg_model *model_info = (meshcfg_model*) data;
1766         meshcfg_app *app = (meshcfg_app*) user_data;
1767
1768         l = g_slist_find_custom(app->elements,
1769                 GUINT_TO_POINTER(model_info->elem_index), __compare_element_index);
1770         if (l) {
1771                 elem = l->data;
1772         } else {
1773                 elem = g_malloc0(sizeof(meshcfg_el));
1774                 elem->index = model_info->elem_index;
1775                 elem->path = g_strdup_printf("%s/elem%u", app->path, elem->index);
1776                 app->elements = g_slist_append(app->elements, elem);
1777                 INFO("Mesh: Created element index [%d] path [%s]",
1778                         elem->index, elem->path);
1779         }
1780         INFO("Mesh: This is model [0x%4.4x] for Element [0x%2.2x]",
1781                 model_info->model, elem->index);
1782         /* Add Model in the element */
1783         elem->models = g_slist_append(elem->models, model_info);
1784         INFO("Mesh: Model added in element: total Model count in elem [%d] is [%d]",
1785                         elem->index, g_slist_length(elem->models));
1786 }
1787
1788 meshcfg_app *__bt_hal_mesh_create_app(bt_hal_mesh_node_t *node,
1789                 GSList *models, bool is_prov)
1790 {
1791         uint8_t uuid[16];
1792         meshcfg_app *app = NULL;
1793         char *uuid_str = NULL;
1794
1795         uuid_str = l_util_hexstring(node->uuid.uu, sizeof(uuid));
1796         INFO("Mesh: Network UUID [%s]", uuid_str);
1797
1798         app = g_malloc0(sizeof(meshcfg_app));
1799         memcpy(app->uuid, node->uuid.uu, sizeof(uuid));
1800
1801         app->cid = node->vendor_info.companyid;
1802         app->pid = node->vendor_info.vendorid;
1803         app->vid =  node->vendor_info.versionid;
1804         app->crpl = node->vendor_info.crpl;
1805         INFO("Mesh: is_prov [%d]", is_prov);
1806
1807         if (is_prov) {
1808                 app->path = g_strdup_printf("/tizen/mesh/cfg/%s", uuid_str);
1809                 app->agent_path = g_strdup_printf("%s/agent", app->path);
1810
1811         } else {
1812                 app->path = g_strdup_printf("/tizen/mesh/node/%s", uuid_str);
1813                 app->agent_path = g_strdup_printf("%s/agent", app->path);
1814         }
1815         g_slist_foreach(models, __bt_mesh_hal_create_element_object, app);
1816
1817         g_free(uuid_str);
1818         app->is_prov = is_prov;
1819         app->token.u64 = node->token.u64;
1820         INFO("Mesh: Token [%llu]", (unsigned long long int)app->token.u64);
1821         INFO("Mesh: app created");
1822         return app;
1823 }
1824
1825 static void __bt_hal_mesh_leave_net_reply(
1826                 struct l_dbus_proxy *proxy,
1827                         struct l_dbus_message *msg, void *user_data)
1828 {
1829         meshcfg_app *app;
1830         app = (meshcfg_app*) user_data;
1831
1832         INFO("Mesh: Leave Network Reply from Meshd: app path [%s]", app->path);
1833         if (l_dbus_message_is_error(msg)) {
1834                 const char *name;
1835
1836                 l_dbus_message_get_error(msg, &name, NULL);
1837                 ERR("Mesh: Failed to leave network: %s", name);
1838
1839                 /* Send Network Destroy fail event */
1840                 __send_network_destroy_event(app, BT_STATUS_FAIL);
1841         } else {
1842                 INFO("Mesh: Leave Network: Success, cleanup app after proxy removed");
1843         }
1844 }
1845
1846 static void __bt_hal_mesh_leave_net_setup(struct l_dbus_message *msg,
1847                 void *user_data)
1848 {
1849         meshcfg_app *app = (meshcfg_app*) user_data;
1850
1851         l_dbus_message_set_arguments(msg, "t", l_get_be64(app->token.u8));
1852         INFO("Mesh: Leave Network Setup app path [%s]", app->path);
1853 }
1854
1855 static void __bt_hal_mesh_release_net_reply(
1856                 struct l_dbus_proxy *proxy,
1857                         struct l_dbus_message *msg, void *user_data)
1858 {
1859         meshcfg_app *app;
1860         app = (meshcfg_app*) user_data;
1861
1862         INFO("Mesh:Release Network Reply from Meshd: app path [%s]", app->path);
1863         if (l_dbus_message_is_error(msg)) {
1864                 const char *name;
1865
1866                 l_dbus_message_get_error(msg, &name, NULL);
1867                 ERR("Mesh: Failed to Release network: %s", name);
1868
1869         } else {
1870                 INFO("Mesh: Release Network: Success, cleanup app after proxy removed");
1871         }
1872 }
1873
1874 static void __bt_hal_mesh_release_net_setup(struct l_dbus_message *msg,
1875                 void *user_data)
1876 {
1877         meshcfg_app *app = (meshcfg_app*) user_data;
1878
1879         l_dbus_message_set_arguments(msg, "t", l_get_be64(app->token.u8));
1880         INFO("Mesh: Release Network Setup app path [%s]", app->path);
1881 }
1882
1883 static void __bt_hal_mesh_create_net_reply(
1884                 struct l_dbus_proxy *proxy,
1885                         struct l_dbus_message *msg, void *user_data)
1886 {
1887         meshcfg_app *app;
1888         app = (meshcfg_app*) user_data;
1889
1890         INFO("Mesh: Create Network Reply from Meshd: app path [%s]", app->path);
1891         if (l_dbus_message_is_error(msg)) {
1892                 const char *name;
1893
1894                 l_dbus_message_get_error(msg, &name, NULL);
1895                 ERR("Mesh: Failed to create network: %s", name);
1896
1897                 /* Send Network creation fail event */
1898                 __send_network_attach_event(app, BT_STATUS_FAIL);
1899
1900                 /* Destroy mesh app object */
1901                 __bt_hal_mesh_destroy_app_object(app);
1902                 return;
1903         }
1904 }
1905
1906 static void __bt_hal_mesh_create_net_setup(struct l_dbus_message *msg,
1907                 void *user_data)
1908 {
1909         meshcfg_app *app;
1910         struct l_dbus_message_builder *builder;
1911         app = (meshcfg_app*) user_data;
1912
1913         builder = l_dbus_message_builder_new(msg);
1914
1915         INFO("Mesh: Create Network Setup app path [%s]", app->path);
1916         l_dbus_message_builder_append_basic(builder, 'o', app->path);
1917         __mesh_append_byte_array(builder, app->uuid, 16);
1918         l_dbus_message_builder_finalize(builder);
1919         l_dbus_message_builder_destroy(builder);
1920 }
1921
1922 static void __mesh_trigger_scan_finished_event(meshcfg_app *app)
1923 {
1924         struct hal_ev_mesh_scan_state_changed ev;
1925
1926         memset(&ev, 0, sizeof(ev));
1927         memcpy(ev.net_uuid, app->uuid, 16);
1928
1929         ev.status = BT_STATUS_SUCCESS;
1930
1931         ev.state = HAL_MESH_SCAN_STATE_STOPPED;
1932         if (mesh_event_cb)
1933                 mesh_event_cb(HAL_EV_MESH_SCAN_STATE_CHANGED,
1934                         (void*)&ev, sizeof(ev));
1935 }
1936
1937 static gboolean __bt_mesh_scan_timer_cb(gpointer user_data)
1938 {
1939         meshcfg_app *app = (meshcfg_app*) user_data;
1940         __mesh_trigger_scan_finished_event(app);
1941         return false;
1942 }
1943
1944 void __bt_mesh_enable_scanning_timer(uint8_t *net_uuid, uint16_t secs)
1945 {
1946         GSList *l;
1947         meshcfg_app *app;
1948         l = g_slist_find_custom(mesh_apps, net_uuid,
1949                         __mesh_compare_network_uuid);
1950         if (!l)
1951                 return;
1952         app = l->data;
1953
1954         if (app->scan_timer_id > 0) {
1955                 g_source_remove(app->scan_timer_id);
1956                 app->scan_timer_id = 0;
1957         }
1958
1959         app->scan_timer_id = g_timeout_add_seconds(secs,
1960                         __bt_mesh_scan_timer_cb, app);
1961
1962         return;
1963 }
1964
1965 static void __mesh_scan_reply(struct l_dbus_proxy *proxy,
1966                 struct l_dbus_message *msg, void *user_data)
1967 {
1968         struct hal_ev_mesh_scan_state_changed ev;
1969         const char *dbus_path;
1970         uint8_t *net_uuid;
1971         dbus_path =  l_dbus_proxy_get_path(proxy);
1972         INFO("Mesh: DBUS path [%s]", dbus_path);
1973         net_uuid = __mesh_get_net_uuid_from_dbus_proxy_path(dbus_path);
1974
1975         uint16_t secs = (uint16_t) L_PTR_TO_UINT(user_data);
1976         INFO("Mesh: Scan duration [%u]", secs);
1977
1978         memset(&ev, 0, sizeof(ev));
1979         memcpy(ev.net_uuid, net_uuid, 16);
1980
1981         if (l_dbus_message_is_error(msg)) {
1982                 const char *name;
1983                 l_dbus_message_get_error(msg, &name, NULL);
1984                 ERR("Mesh: Failed to start unprovisioned scan: [%s]", name);
1985                 ev.status = BT_STATUS_FAIL;
1986         } else {
1987                 INFO("Mesh: Unprovisioned scan started\n");
1988                 ev.status = BT_STATUS_SUCCESS;
1989                 __bt_mesh_enable_scanning_timer(net_uuid, secs);
1990         }
1991
1992         ev.state = HAL_MESH_SCAN_STATE_STARTED;
1993         if (mesh_event_cb)
1994                 mesh_event_cb(HAL_EV_MESH_SCAN_STATE_CHANGED,
1995                         (void*)&ev, sizeof(ev));
1996         l_free(net_uuid);
1997 }
1998
1999 static void __mesh_scan_setup(struct l_dbus_message *msg, void *user_data)
2000 {
2001         struct l_dbus_message_builder *builder;
2002         uint16_t secs = (uint16_t) L_PTR_TO_UINT(user_data);
2003         INFO("Mesh: Scan duration [%u]", secs);
2004
2005         builder = l_dbus_message_builder_new(msg);
2006         l_dbus_message_builder_enter_array(builder, "{sv}");
2007         append_dict_entry_basic(builder, "Seconds", "q", &secs);
2008         l_dbus_message_builder_leave_array(builder);
2009         l_dbus_message_builder_finalize(builder);
2010         l_dbus_message_builder_destroy(builder);
2011 }
2012
2013
2014 bt_status_t _bt_hal_mesh_network_set_caps(
2015                 bt_uuid_t *net_uuid, bt_hal_mesh_prov_caps_t *caps)
2016 {
2017         GSList *l;
2018         meshcfg_app *app;
2019         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
2020         if (l) {
2021                 app = l->data;
2022                 /* Fill OOB data */
2023                 app->public_oob = caps->public_oob;
2024                 app->static_oob = caps->static_oob;
2025                 app->out_oob = caps->out_oob;
2026                 app->in_oob = caps->in_oob;
2027         } else {
2028                 ERR("Mesh: app not found!!");
2029                 return BT_STATUS_PARM_INVALID;
2030
2031         }
2032         return BT_STATUS_SUCCESS;
2033 }
2034
2035 static void __bt_hal_mesh_add_node_reply(
2036                 struct l_dbus_proxy *proxy,
2037                         struct l_dbus_message *msg,
2038                                 void *user_data)
2039 {
2040         struct hal_ev_mesh_provision_status ev;
2041         const char *dbus_path;
2042         uint8_t *net_uuid;
2043         dbus_path =  l_dbus_proxy_get_path(proxy);
2044         INFO("Mesh: DBUS path [%s]", dbus_path);
2045         net_uuid = __mesh_get_net_uuid_from_dbus_proxy_path(dbus_path);
2046
2047         bt_uuid_t *dev_uuid = (bt_uuid_t*) user_data;
2048
2049         INFO("Mesh: app path [%s]", dbus_path);
2050
2051         memset(&ev, 0, sizeof(ev));
2052         memcpy(ev.net_uuid, net_uuid, 16);
2053         memcpy(ev.dev_uuid, dev_uuid->uu, 16);
2054
2055         /* Free User data */
2056         g_free((void*)dev_uuid);
2057         l_free(net_uuid);
2058
2059         if (l_dbus_message_is_error(msg)) {
2060                 const char *name;
2061
2062                 l_dbus_message_get_error(msg, &name, NULL);
2063                 ERR("Mesh: Failed to start provisioning: %s", name);
2064                 ev.status = BT_STATUS_FAIL;
2065         } else {
2066                 INFO("Mesh: Provisioning started\n");
2067                 ev.status = BT_STATUS_SUCCESS;
2068         }
2069         if (mesh_event_cb)
2070                 mesh_event_cb(HAL_EV_MESH_PROVISIONING_STATUS,
2071                         (void*)&ev, sizeof(ev));
2072         INFO("Mesh: Provisioning status sent");
2073 }
2074
2075 static void __bt_hal_mesh_add_node_setup(struct l_dbus_message *msg,
2076                 void *user_data)
2077 {
2078         char *uuid = NULL;
2079         bt_uuid_t *dev = user_data;
2080         struct l_dbus_message_builder *builder;
2081
2082         uuid =  l_util_hexstring(dev->uu, 16);
2083         if (uuid == NULL)
2084                 return;
2085
2086         INFO("Mesh: Add Node Setup UUID [%s]", uuid);
2087
2088         builder = l_dbus_message_builder_new(msg);
2089         __mesh_append_byte_array(builder, dev->uu, 16);
2090         l_dbus_message_builder_enter_array(builder, "{sv}");
2091         l_dbus_message_builder_leave_array(builder);
2092         l_dbus_message_builder_finalize(builder);
2093         l_dbus_message_builder_destroy(builder);
2094
2095         l_free(uuid);
2096 }
2097
2098 bt_status_t _bt_hal_mesh_provision_device(
2099                 bt_uuid_t *net_uuid, bt_uuid_t *dev_uuid)
2100 {
2101         GSList *l;
2102         meshcfg_app *app;
2103         bt_uuid_t *dev;
2104         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
2105         if (l) {
2106                 app = l->data;
2107                 dev = g_memdup2((gpointer)dev_uuid, 16);
2108                 INFO("Mesh: Schedule Add Node request to meshd");
2109                 if (!l_dbus_proxy_method_call(app->mgmt_proxy, "AddNode",
2110                                         __bt_hal_mesh_add_node_setup,
2111                                         __bt_hal_mesh_add_node_reply,
2112                                         (void*)dev, NULL))
2113                         return BT_STATUS_FAIL;
2114         } else {
2115                 ERR("Mesh: app not found!!");
2116                 return BT_STATUS_PARM_INVALID;
2117
2118         }
2119         return BT_STATUS_SUCCESS;
2120 }
2121
2122 static void __bt_hal_mesh_subnet_key_setup(
2123                 struct l_dbus_message *msg, void *user_data)
2124 {
2125         struct subnet_key_request *req = user_data;
2126         uint16_t idx = (uint16_t) req->idx;
2127
2128         l_dbus_message_set_arguments(msg, "q", idx);
2129 }
2130
2131 static void __bt_hal_mesh_subnet_key_reply(struct l_dbus_proxy *proxy,
2132                 struct l_dbus_message *msg, void *user_data)
2133 {
2134         struct hal_ev_mesh_netkey_execute_event ev;
2135         const char *dbus_path;
2136         uint8_t *net_uuid;
2137         struct subnet_key_request *req = user_data;
2138         const char *method = req->str;
2139
2140         dbus_path =  l_dbus_proxy_get_path(proxy);
2141         INFO("Mesh: DBUS path [%s]", dbus_path);
2142         net_uuid = __mesh_get_net_uuid_from_dbus_proxy_path(dbus_path);
2143
2144         memset(&ev, 0, sizeof(ev));
2145         memcpy(ev.net_uuid, net_uuid, 16);
2146         ev.key_idx = req->idx;
2147
2148         g_free(net_uuid);
2149
2150         if (l_dbus_message_is_error(msg)) {
2151                 const char *name;
2152
2153                 l_dbus_message_get_error(msg, &name, NULL);
2154                 ERR("Mesh: Subnet [%s] failed: error: [%s]", method, name);
2155                 ev.status = BT_STATUS_FAIL;
2156         }
2157
2158         ev.status = BT_STATUS_SUCCESS;
2159
2160         if (!strcmp("CreateSubnet", method)) {
2161                 INFO("Mesh: Reply for CreateSubnet");
2162                 ev.key_event = HAL_MESH_KEY_ADD;
2163         } else if (!strcmp("DeleteSubnet", method)) {
2164                 INFO("Mesh: Reply for DeleteSubnet");
2165                 ev.key_event = HAL_MESH_KEY_DELETE;
2166         } else if (!strcmp("UpdateSubnet", method)) {
2167                 INFO("Mesh: Reply for UpdateSubnet");
2168                 ev.key_event = HAL_MESH_KEY_UPDATE;
2169         }
2170
2171         if (mesh_event_cb)
2172                 mesh_event_cb(HAL_EV_MESH_NETKEY_EXECUTE_EVENT,
2173                         (void*)&ev, sizeof(ev));
2174 }
2175
2176 static bool  __mesh_subnet_netkey_command_execute(meshcfg_app *app,
2177                         uint16_t index, const char *key_execute_method)
2178 {
2179         struct subnet_key_request *req;
2180
2181         req = l_new(struct subnet_key_request, 1);
2182         req->str = key_execute_method;
2183         req->idx = index;
2184
2185         if (!l_dbus_proxy_method_call(app->mgmt_proxy, key_execute_method,
2186                                 __bt_hal_mesh_subnet_key_setup,
2187                                 __bt_hal_mesh_subnet_key_reply,
2188                                 req, l_free))
2189                 return false;
2190
2191         return true;
2192 }
2193
2194 static void __bt_hal_mesh_app_key_setup(struct l_dbus_message *msg,
2195         void *user_data)
2196 {
2197         struct app_key_request *req = user_data;
2198         uint16_t net_idx = (uint16_t) req->net_idx;
2199         uint16_t app_idx = (uint16_t) req->app_idx;
2200
2201         if (g_strcmp0(req->str, "CreateAppKey") == 0)
2202                 l_dbus_message_set_arguments(msg, "qq", net_idx, app_idx);
2203         else
2204                 l_dbus_message_set_arguments(msg, "q", app_idx);
2205 }
2206
2207 static void __bt_hal_mesh_app_key_reply(struct l_dbus_proxy *proxy,
2208                 struct l_dbus_message *msg, void *user_data)
2209 {
2210         struct hal_ev_mesh_appkey_execute_event ev;
2211         const char *dbus_path;
2212         uint8_t *net_uuid;
2213         struct app_key_request *req = user_data;
2214         const char *method = req->str;
2215
2216         dbus_path =  l_dbus_proxy_get_path(proxy);
2217         INFO("Mesh: DBUS path [%s]", dbus_path);
2218         net_uuid = __mesh_get_net_uuid_from_dbus_proxy_path(dbus_path);
2219
2220         memset(&ev, 0, sizeof(ev));
2221         memcpy(ev.net_uuid, net_uuid, 16);
2222         ev.net_idx = req->net_idx;
2223         ev.app_idx = req->app_idx;
2224
2225         g_free(net_uuid);
2226
2227         if (l_dbus_message_is_error(msg)) {
2228                 const char *name;
2229
2230                 l_dbus_message_get_error(msg, &name, NULL);
2231                 ERR("Mesh: AppKey execute [%s] failed: error: [%s]", method, name);
2232                 ev.status = BT_STATUS_FAIL;
2233         } else
2234                 ev.status = BT_STATUS_SUCCESS;
2235
2236         if (!strcmp("CreateAppKey", method)) {
2237                 INFO("Mesh: AppKey Create Reply");
2238                 ev.key_event = HAL_MESH_KEY_ADD;
2239         } else if (!strcmp("DeleteAppKey", method)) {
2240                 INFO("Mesh: AppKey Delete Reply");
2241                 ev.key_event = HAL_MESH_KEY_DELETE;
2242         } else if (!strcmp("UpdateAppKey", method)) {
2243                 INFO("Mesh: AppKey Update Reply");
2244                 ev.key_event = HAL_MESH_KEY_UPDATE;
2245         }
2246
2247         if (mesh_event_cb)
2248                 mesh_event_cb(HAL_EV_MESH_APPKEY_EXECUTE_EVENT, (void*)&ev, sizeof(ev));
2249 }
2250
2251 static bool  __mesh_subnet_appkey_command_execute(meshcfg_app *app,
2252                         uint16_t net_idx, uint16_t app_idx,
2253                                 const char *key_execute_method)
2254 {
2255         struct app_key_request *req;
2256
2257         req = l_new(struct app_key_request, 1);
2258         req->str = key_execute_method;
2259         req->net_idx = net_idx;
2260         req->app_idx = app_idx;
2261
2262         if (!l_dbus_proxy_method_call(app->mgmt_proxy, key_execute_method,
2263                                 __bt_hal_mesh_app_key_setup,
2264                                 __bt_hal_mesh_app_key_reply,
2265                                 req, l_free))
2266                 return false;
2267
2268         return true;
2269 }
2270
2271 bt_status_t _bt_hal_mesh_network_subnet_execute(bt_uuid_t *net_uuid,
2272                         bt_mesh_key_op_e op, uint16_t netkey_idx)
2273 {
2274         GSList *l;
2275         meshcfg_app *app;
2276         bool status = true;
2277         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
2278         if (l) {
2279                 app = l->data;
2280
2281                 if (op == BT_MESH_KEY_CREATE)
2282                         status = __mesh_subnet_netkey_command_execute(app,
2283                                         netkey_idx, "CreateSubnet");
2284                 else if (op == BT_MESH_KEY_DELETE)
2285                         status = __mesh_subnet_netkey_command_execute(app,
2286                                         netkey_idx, "DeleteSubnet");
2287                 else if (op == BT_MESH_KEY_UPDATE)
2288                         status = __mesh_subnet_netkey_command_execute(app,
2289                                         netkey_idx, "UpdateSubnet");
2290                 if (!status)
2291                         return BT_STATUS_FAIL;
2292
2293         } else {
2294                 ERR("Mesh: app not found!!");
2295                 return BT_STATUS_PARM_INVALID;
2296
2297         }
2298         return BT_STATUS_SUCCESS;
2299 }
2300
2301 bt_status_t _bt_hal_mesh_network_appkey_execute(bt_uuid_t *net_uuid,
2302                         bt_mesh_key_op_e op, uint16_t netkey_idx, uint16_t appkey_idx)
2303 {
2304         GSList *l;
2305         meshcfg_app *app;
2306         bool status = true;
2307         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
2308         if (l) {
2309                 app = l->data;
2310
2311                 if (op == BT_MESH_KEY_CREATE)
2312                         status = __mesh_subnet_appkey_command_execute(app,
2313                                 netkey_idx, appkey_idx, "CreateAppKey");
2314                 else if (op == BT_MESH_KEY_DELETE)
2315                         status = __mesh_subnet_appkey_command_execute(app,
2316                                 netkey_idx, appkey_idx, "DeleteAppKey");
2317                 else if (op == BT_MESH_KEY_UPDATE) {
2318                         INFO("Mesh: Update ApKey command NK Idx [0x%2.2x] AK Idx [0x%2.2x]",
2319                                         netkey_idx, appkey_idx);
2320                         status = __mesh_subnet_appkey_command_execute(app,
2321                                 netkey_idx, appkey_idx, "UpdateAppKey");
2322                 }
2323                 if (!status)
2324                         return BT_STATUS_FAIL;
2325
2326         } else {
2327                 ERR("Mesh: app not found!!");
2328                 return BT_STATUS_PARM_INVALID;
2329
2330         }
2331         return BT_STATUS_SUCCESS;
2332 }
2333
2334 bt_status_t _bt_hal_mesh_send_provision_data(
2335                 bt_uuid_t *net_uuid, uint16_t netkey_idx, uint16_t unicast)
2336 {
2337         GSList *l;
2338         meshcfg_app *app;
2339         struct l_dbus_message *msg;
2340         struct l_dbus_message *reply;
2341
2342         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
2343         if (l) {
2344                 app = l->data;
2345                 msg = app->msg;
2346
2347                 reply = l_dbus_message_new_method_return(msg);
2348                 l_dbus_message_set_arguments(reply, "qq", netkey_idx,  unicast);
2349                 l_dbus_send(dbus, reply);
2350         } else {
2351                 ERR("Mesh: app not found!!");
2352                 return BT_STATUS_PARM_INVALID;
2353         }
2354         return BT_STATUS_SUCCESS;
2355 }
2356
2357 bt_status_t _bt_hal_mesh_network_scan_cancel(bt_uuid_t *net_uuid)
2358 {
2359         GSList *l;
2360         meshcfg_app *app;
2361         l = g_slist_find_custom(mesh_apps,
2362                 net_uuid->uu, __mesh_compare_network_uuid);
2363         if (l) {
2364                 app = l->data;
2365                 if (!__bt_mesh_proxy_check(app)) {
2366                         ERR("Mesh: Proxy check failed!!");
2367                         return BT_STATUS_FAIL;
2368                 }
2369                 if (!l_dbus_proxy_method_call(app->mgmt_proxy,
2370                                 "UnprovisionedScanCancel",
2371                                         NULL, NULL, NULL, NULL))
2372                         return BT_STATUS_FAIL;
2373         } else {
2374                 ERR("Mesh: app not found!!");
2375                 return BT_STATUS_PARM_INVALID;
2376         }
2377
2378         /* Stop Scan timer */
2379         if (app->scan_timer_id > 0) {
2380                 g_source_remove(app->scan_timer_id);
2381                 app->scan_timer_id = 0;
2382         }
2383
2384         /* Trigger Scan finished event */
2385         __mesh_trigger_scan_finished_event(app);
2386
2387         return BT_STATUS_SUCCESS;
2388 }
2389
2390 bt_status_t _bt_hal_mesh_auth_reply(bt_hal_mesh_auth_variant_e auth_type,
2391                         const char *auth_value)
2392 {
2393         uint32_t val_u32;
2394         struct l_dbus_message *reply = NULL;
2395         struct l_dbus_message_builder *builder;
2396         uint8_t *alpha;
2397         bt_status_t ret = BT_STATUS_SUCCESS;
2398         size_t sz = 0;
2399
2400         /* Proxy Check */
2401         if (!__bt_mesh_proxy_check(0)) {
2402                 ERR("Mesh: Proxy check failed!!");
2403                 return BT_STATUS_FAIL;
2404         }
2405         INFO("Mesh: Authentication Reply: auth type [%d]", auth_type);
2406         INFO("Mesh: Authentication Reply: auth value [%s]", auth_value);
2407         /* For Numeric Type Inputs: Numeric, Blink, Beep & Vibrate */
2408         if (auth_type >= BT_HAL_MESH_AUTH_REQ_NUMERIC_INPUT &&
2409                         auth_type <= BT_HAL_MESH_AUTH_REQ_VIBRATE_COUNT_INPUT) {
2410                 INFO("Mesh: Authentication reply: Numeric Type");
2411                 val_u32 = atoi(auth_value);
2412                 reply = l_dbus_message_new_method_return(agent_msg);
2413                 l_dbus_message_set_arguments(reply, "u", val_u32);
2414                 if (!reply)
2415                         reply = l_dbus_message_new_error(agent_msg, dbus_err_fail, NULL);
2416                 l_dbus_send(dbus, reply);
2417                 ret = BT_STATUS_SUCCESS;
2418         /* For Alpha-Numeric */
2419         } else if (auth_type == BT_HAL_MESH_AUTH_REQ_ALPHANUMERIC_INPUT ||
2420                         auth_type == BT_HAL_MESH_AUTH_REQ_OOB_STATIC_KEY_INPUT ||
2421                         auth_type == BT_HAL_MESH_AUTH_REQ_OOB_PUBLIC_KEY_INPUT) {
2422                 INFO("Mesh: Authentication reply: Alpha-Numeric Type");
2423                 alpha = l_util_from_hexstring(auth_value, &sz);
2424                 reply = l_dbus_message_new_method_return(agent_msg);
2425                 builder = l_dbus_message_builder_new(reply);
2426                 __mesh_append_byte_array(builder, alpha, 16);
2427                 l_dbus_message_builder_finalize(builder);
2428                 l_dbus_message_builder_destroy(builder);
2429                 l_free(alpha);
2430                 if (!reply)
2431                         reply = l_dbus_message_new_error(agent_msg, dbus_err_fail, NULL);
2432                 l_dbus_send(dbus, reply);
2433                 ret = BT_STATUS_SUCCESS;
2434         }
2435         return ret;
2436 }
2437
2438 bt_status_t _bt_hal_mesh_network_scan(bt_uuid_t *net_uuid,
2439                 bt_hal_mesh_scan_param_t *param)
2440 {
2441         GSList *l;
2442         meshcfg_app *app;
2443         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
2444         if (l) {
2445                 app = l->data;
2446                 if (!__bt_mesh_proxy_check(app)) {
2447                         ERR("Mesh: Proxy check failed!!");
2448                         return BT_STATUS_FAIL;
2449                 }
2450                 if (!l_dbus_proxy_method_call(app->mgmt_proxy, "UnprovisionedScan",
2451                                         __mesh_scan_setup, __mesh_scan_reply,
2452                                         L_UINT_TO_PTR(param->scan_time), NULL))
2453                         return BT_STATUS_FAIL;
2454         } else {
2455                 ERR("Mesh: app not found!!");
2456                 return BT_STATUS_PARM_INVALID;
2457         }
2458         return BT_STATUS_SUCCESS;
2459 }
2460
2461 static void __bt_hal_mesh_delete_node_setup(struct l_dbus_message *msg,
2462                 void *user_data)
2463 {
2464         struct mesh_remote_node_info *node_info = \
2465                 (struct mesh_remote_node_info*) user_data;
2466
2467         l_dbus_message_set_arguments(msg, "qy",
2468                 node_info->unicast, node_info->num_elements);
2469         INFO("Mesh: Delete Remote Node Setup params passed");
2470 }
2471
2472 static void __bt_hal_mesh_delete_node_reply(
2473                 struct l_dbus_proxy *proxy,
2474                         struct l_dbus_message *msg, void *user_data)
2475 {
2476         INFO("Mesh: Delete Remote Node Reply from DBUS");
2477 }
2478
2479 bt_status_t _bt_hal_mesh_node_delete(bt_uuid_t *network,
2480                 uint16_t unicast, uint16_t num_elements)
2481 {
2482         GSList *l;
2483         meshcfg_app *app;
2484         struct mesh_remote_node_info *node_info;
2485         INFO("Mesh: Delete Remote Node");
2486         l = g_slist_find_custom(mesh_apps, network->uu, __mesh_compare_network_uuid);
2487         if (l) {
2488                 app = l->data;
2489                 if (!__bt_mesh_proxy_check(app)) {
2490                         ERR("Mesh: Proxy check failed!!");
2491                         return BT_STATUS_FAIL;
2492                 }
2493                 INFO("Mesh: Delete Remote Node Unicast [0x%2.2x] Num els [%u]",
2494                         unicast, num_elements);
2495
2496                 /* Delete Remote Node Request */
2497                 node_info = g_malloc0(sizeof(struct mesh_remote_node_info));
2498                 node_info->unicast = unicast;
2499                 node_info->num_elements = num_elements;
2500
2501                 if (!l_dbus_proxy_method_call(app->mgmt_proxy, "DeleteRemoteNode",
2502                                         __bt_hal_mesh_delete_node_setup,
2503                                         __bt_hal_mesh_delete_node_reply, node_info,
2504                                         l_free)) {
2505                         ERR("Mesh: Delete Remote Node Request failed!!");
2506                         g_free(node_info);
2507                         return BT_STATUS_FAIL;
2508                 }
2509         } else {
2510                 ERR("Mesh: App not found!!");
2511                 return BT_STATUS_PARM_INVALID;
2512         }
2513         INFO("Mesh: Delete Remote Node Call issued successfully!!");
2514         return BT_STATUS_SUCCESS;
2515 }
2516
2517 bt_status_t _bt_hal_mesh_network_release(bt_uuid_t *net_uuid)
2518 {
2519         GSList *l;
2520         meshcfg_app *app;
2521         INFO("Mesh: Release Network");
2522         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
2523         if (l) {
2524                 app = l->data;
2525                 if (!__bt_mesh_proxy_check(app)) {
2526                         ERR("Mesh: Proxy check failed!!");
2527                         return BT_STATUS_FAIL;
2528                 }
2529                 INFO("Mesh: Release Network");
2530                 /* Create CFG Network */
2531                 if (!l_dbus_proxy_method_call(net_proxy, "Release",
2532                                         __bt_hal_mesh_release_net_setup,
2533                                         __bt_hal_mesh_release_net_reply, app,
2534                                         NULL)) {
2535                         ERR("Mesh: Network Release failed!!");
2536                         return BT_STATUS_FAIL;
2537                 }
2538         } else {
2539                 ERR("Mesh: App not found!!");
2540                 return BT_STATUS_PARM_INVALID;
2541         }
2542         INFO("Mesh: Network Release Call issued successfully!!");
2543         return BT_STATUS_SUCCESS;
2544 }
2545
2546 bt_status_t _bt_hal_mesh_network_destroy(bt_uuid_t *net_uuid)
2547 {
2548         GSList *l;
2549         meshcfg_app *app;
2550         INFO("Mesh: Destroy network");
2551         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
2552         if (l) {
2553                 app = l->data;
2554                 if (!__bt_mesh_proxy_check(app)) {
2555                         ERR("Mesh: Proxy check failed!!");
2556                         return BT_STATUS_FAIL;
2557                 }
2558                 INFO("Mesh: Destroy Network");
2559                 /* Create CFG Network */
2560                 if (!l_dbus_proxy_method_call(net_proxy, "Leave",
2561                                         __bt_hal_mesh_leave_net_setup,
2562                                         __bt_hal_mesh_leave_net_reply, app,
2563                                         NULL)) {
2564                         ERR("Mesh: Network Leave failed!!");
2565                         return BT_STATUS_FAIL;
2566                 }
2567         } else {
2568                 ERR("Mesh: App not found!!");
2569                 return BT_STATUS_PARM_INVALID;
2570         }
2571         INFO("Mesh: Network Leave Call issued successfully!!");
2572         return BT_STATUS_SUCCESS;
2573 }
2574
2575 bt_status_t _bt_hal_mesh_create_network(
2576                 bt_hal_mesh_node_t *node, GSList *models, bool is_prov)
2577 {
2578         meshcfg_app *app;
2579
2580         INFO("Mesh: Create Network Request");
2581
2582         if (!__bt_mesh_proxy_check(0)) {
2583                 ERR("Mesh: Proxy check failed!!");
2584                 return BT_STATUS_FAIL;
2585         }
2586
2587         INFO("Mesh: Node Element count [%d]", node->num_elements);
2588         INFO("Mesh: Node Primary Unicast[0x%2.2x]", node->primary_unicast);
2589         INFO("Mesh: Node Vendor Info: CID[0x%2.2x]", node->vendor_info.companyid);
2590         INFO("Mesh: Node Vendor Info: VID[0x%2.2x]", node->vendor_info.vendorid);
2591         INFO("Mesh: Node Vendor Info: VSID[0x%2.2x]", node->vendor_info.versionid);
2592         INFO("Mesh: Node Vendor Info: CRPL[0x%2.2x]", node->vendor_info.crpl);
2593         INFO("Mesh: Node Total Number of Models in the node[%d]", g_slist_length(models));
2594         INFO("Mesh: Token [%llu]", (unsigned long long int)node->token.u64);
2595         /* Create DBUS APP */
2596         app = __bt_hal_mesh_create_app(node, models, is_prov);
2597         if (!app)
2598                 return BT_STATUS_FAIL;
2599
2600         /* Register DBUS APP */
2601         if (!__bt_hal_mesh_register_application(app))
2602                 goto failed;
2603
2604         if (app->token.u64 == 0) {
2605                 INFO("Mesh: Create New Network");
2606                 /* Create CFG Network */
2607                 if (!l_dbus_proxy_method_call(net_proxy, "CreateNetwork",
2608                                         __bt_hal_mesh_create_net_setup,
2609                                         __bt_hal_mesh_create_net_reply, app,
2610                                         NULL)) {
2611                         ERR("Mesh: Network Create failed!!");
2612                         goto failed;
2613                 }
2614         } else {
2615                 INFO("Mesh: Attach Node to Network: Token [%llu]", (unsigned long long int)app->token.u64);
2616                 /* Attach to Network */
2617                 if (!l_dbus_proxy_method_call(net_proxy, "Attach",
2618                                         __bt_hal_mesh_attach_node_setup,
2619                                         __bt_hal_mesh_attach_node_reply,
2620                                         app,
2621                                 NULL)) {
2622                         ERR("Mesh: Node attach failed!!");
2623                         goto failed;
2624                 }
2625         }
2626
2627         INFO("Mesh: Node registration request scheudled");
2628         mesh_apps = g_slist_append(mesh_apps, app);
2629         INFO("Mesh: Total number of apps in list  [%d]",
2630                 g_slist_length(mesh_apps));
2631         return BT_STATUS_SUCCESS;
2632 failed:
2633         ERR("Mesh: network can not be created!!");
2634         __bt_hal_mesh_destroy_app_object(app);
2635         return BT_STATUS_FAIL;
2636 }
2637
2638 bt_status_t _bt_hal_mesh_join_network(
2639                 bt_hal_mesh_node_t *node, GSList *models)
2640 {
2641         meshcfg_app *app;
2642
2643         INFO("Mesh: Join Network Request");
2644
2645         if (!__bt_mesh_proxy_check(0)) {
2646                 ERR("Mesh: Proxy check failed!!");
2647                 return BT_STATUS_FAIL;
2648         }
2649
2650         INFO("Mesh: Node Element count [%d]", node->num_elements);
2651         INFO("Mesh: Node Primary Unicast[0x%2.2x]", node->primary_unicast);
2652         INFO("Mesh: Node Vendor Info: CID[0x%2.2x]", node->vendor_info.companyid);
2653         INFO("Mesh: Node Vendor Info: VID[0x%2.2x]", node->vendor_info.vendorid);
2654         INFO("Mesh: Node Vendor Info: VSID[0x%2.2x]", node->vendor_info.versionid);
2655         INFO("Mesh: Node Vendor Info: CRPL[0x%2.2x]", node->vendor_info.crpl);
2656         INFO("Mesh: Node Total Number of Models in the node[%d]", g_slist_length(models));
2657         INFO("Mesh: Token [%llu]", (unsigned long long int)node->token.u64);
2658         /* Create DBUS APP */
2659         app = __bt_hal_mesh_create_app(node, models, false);
2660         if (!app)
2661                 return BT_STATUS_FAIL;
2662         /* Register DBUS APP */
2663         if (!__bt_hal_mesh_register_application(app))
2664                 goto failed;
2665
2666         INFO("Mesh: Create New Network");
2667         INFO("Mesh: app is_prov [%d]", app->is_prov);
2668         if (!l_dbus_proxy_method_call(net_proxy, "Join",
2669                                 __bt_hal_mesh_create_net_setup,
2670                                 __bt_hal_mesh_create_net_reply, app,
2671                                 NULL)) {
2672                  ERR("Mesh: Join Network failed!!");
2673                  goto failed;
2674         }
2675
2676         INFO("Mesh: Node registration request scheudled");
2677         INFO("Mesh: Total number of apps in list Before [%d]",
2678                         g_slist_length(mesh_apps));
2679         mesh_apps = g_slist_append(mesh_apps, app);
2680         INFO("Mesh: Total number of apps in list  [%d]",
2681                         g_slist_length(mesh_apps));
2682         return BT_STATUS_SUCCESS;
2683 failed:
2684         ERR("Mesh: network can not be joined!!");
2685         __bt_hal_mesh_destroy_app_object(app);
2686         return BT_STATUS_FAIL;
2687 }
2688
2689 bt_status_t _bt_hal_mesh_join_cancel(bt_uuid_t *node_uuid)
2690 {
2691         GSList *l;
2692         meshcfg_app *app;
2693         INFO("Mesh: Call cancel join");
2694         l = g_slist_last(mesh_apps);
2695         if (l) {
2696                 app = l->data;
2697                 if (!l_dbus_proxy_method_call(net_proxy, "Cancel",
2698                                         NULL,
2699                                         NULL, NULL,
2700                                         NULL)) {
2701                         ERR("Mesh: Cancel Join failed!!");
2702                         return BT_STATUS_FAIL;
2703                 }
2704         } else {
2705                 ERR("Mesh: App not found!!");
2706                 return BT_STATUS_PARM_INVALID;
2707         }
2708         INFO("Mesh: Cancel Join request Call issued successfully!!");
2709         __bt_hal_mesh_destroy_app_object(app);
2710         return BT_STATUS_SUCCESS;
2711 }
2712
2713 static void __bt_hal_mesh_config_send(
2714                 struct l_dbus_message *msg, void *user_data)
2715 {
2716         struct configuration_request *req = user_data;
2717         struct l_dbus_message_builder *builder;
2718
2719         builder = l_dbus_message_builder_new(msg);
2720
2721         l_dbus_message_builder_append_basic(builder, 'o', req->ele_path);
2722         l_dbus_message_builder_append_basic(builder, 'q', &req->dst);
2723         if (req->is_dev_key)
2724                 l_dbus_message_builder_append_basic(builder, 'b', &req->rmt);
2725
2726         l_dbus_message_builder_append_basic(builder, 'q', &req->idx);
2727
2728         /* Options */
2729         l_dbus_message_builder_enter_array(builder, "{sv}");
2730         l_dbus_message_builder_enter_dict(builder, "sv");
2731         l_dbus_message_builder_leave_dict(builder);
2732         l_dbus_message_builder_leave_array(builder);
2733
2734         __mesh_append_byte_array(builder, req->data, req->len);
2735         l_dbus_message_builder_finalize(builder);
2736         l_dbus_message_builder_destroy(builder);
2737 }
2738
2739 static void __bt_hal_mesh_key_config_send(
2740                 struct l_dbus_message *msg, void *user_data)
2741 {
2742         struct key_config_request *req = user_data;
2743         struct l_dbus_message_builder *builder;
2744
2745         builder = l_dbus_message_builder_new(msg);
2746
2747         l_dbus_message_builder_append_basic(builder, 'o', req->ele_path);
2748         l_dbus_message_builder_append_basic(builder, 'q', &req->dst);
2749         l_dbus_message_builder_append_basic(builder, 'q', &req->key_req_idx);
2750         l_dbus_message_builder_append_basic(builder, 'q', &req->idx);
2751         l_dbus_message_builder_append_basic(builder, 'b', &req->update_req);
2752         l_dbus_message_builder_finalize(builder);
2753         l_dbus_message_builder_destroy(builder);
2754 }
2755
2756 static void __bt_hal_mesh_model_execute_message(
2757                 struct l_dbus_message *msg, void *user_data)
2758 {
2759         struct configuration_request *req = user_data;
2760         struct l_dbus_message_builder *builder;
2761
2762         builder = l_dbus_message_builder_new(msg);
2763
2764         l_dbus_message_builder_append_basic(builder, 'o', req->ele_path);
2765         l_dbus_message_builder_append_basic(builder, 'q', &req->dst);
2766         l_dbus_message_builder_append_basic(builder, 'q', &req->idx);
2767
2768         /* Options */
2769         l_dbus_message_builder_enter_array(builder, "{sv}");
2770         l_dbus_message_builder_enter_dict(builder, "sv");
2771         l_dbus_message_builder_leave_dict(builder);
2772         l_dbus_message_builder_leave_array(builder);
2773
2774         __mesh_append_byte_array(builder, req->data, req->len);
2775         l_dbus_message_builder_finalize(builder);
2776         l_dbus_message_builder_destroy(builder);
2777 }
2778
2779 bt_status_t _bt_hal_mesh_send_key_config_message(
2780                 bt_uuid_t *network, uint16_t dest,
2781                         bool is_netkey, bool is_update,
2782                                 uint16_t key_idx, uint16_t netkey_idx)
2783 {
2784         GSList *l;
2785         GSList *l1;
2786         struct key_config_request *req;
2787         meshcfg_app *app;
2788         meshcfg_el *elem;
2789         const char *key_method = (!is_netkey) ? "AddAppKey" : "AddNetKey";
2790         /* Source is Config Client Local Node */
2791         int src_elem_idx = 0;
2792         l = g_slist_find_custom(mesh_apps, network->uu, __mesh_compare_network_uuid);
2793         if (l) {
2794                 app = l->data;
2795                 if (!__bt_mesh_proxy_check(app)) {
2796                         ERR("Mesh: Proxy check failed!!");
2797                         return BT_STATUS_FAIL;
2798                 }
2799                 l1 = g_slist_find_custom(app->elements,
2800                         GUINT_TO_POINTER(src_elem_idx), __compare_element_index);
2801                 if (!l1)
2802                         return BT_STATUS_FAIL;
2803                 elem = l1->data;
2804
2805                 req = l_new(struct key_config_request, 1);
2806                 req->ele_path = elem->path;
2807                 req->dst = dest;
2808                 req->key_req_idx = key_idx;
2809                 req->idx = netkey_idx; /* Encryption Key index */
2810                 req->update_req = is_update;
2811
2812                 if (!l_dbus_proxy_method_call(app->proxy, key_method,
2813                                         __bt_hal_mesh_key_config_send, NULL,
2814                                         (void*)req, l_free))
2815                         return BT_STATUS_FAIL;
2816         } else {
2817                 ERR("Mesh: app not found!!");
2818                 return BT_STATUS_PARM_INVALID;
2819
2820         }
2821         return BT_STATUS_SUCCESS;
2822 }
2823
2824 bt_status_t _bt_hal_mesh_send_configuration_message(
2825         bt_uuid_t *network, uint16_t dest,
2826                 bool is_dev_key, uint16_t netkey_idx,
2827                         uint8_t *buf, int len)
2828 {
2829         GSList *l;
2830         GSList *l1;
2831         struct configuration_request *req;
2832         meshcfg_app *app;
2833         meshcfg_el *elem;
2834         int src_elem_idx = 0;
2835         l = g_slist_find_custom(mesh_apps, network->uu,
2836                         __mesh_compare_network_uuid);
2837         if (l) {
2838                 app = l->data;
2839                 if (!__bt_mesh_proxy_check(app)) {
2840                         ERR("Mesh: Proxy check failed!!");
2841                         return BT_STATUS_FAIL;
2842                 }
2843                 l1 = g_slist_find_custom(app->elements,
2844                                 GUINT_TO_POINTER(src_elem_idx),
2845                                 __compare_element_index);
2846                 if (!l1)
2847                         return BT_STATUS_FAIL;
2848                 elem = l1->data;
2849
2850                 req = l_new(struct configuration_request, 1);
2851                 req->ele_path = elem->path;
2852                 req->dst = dest;
2853                 req->idx = netkey_idx;
2854                 req->data = buf;
2855                 req->len = len;
2856                 req->rmt = true;
2857                 req->is_dev_key = is_dev_key;
2858
2859                 if (!l_dbus_proxy_method_call(app->proxy, "DevKeySend",
2860                                         __bt_hal_mesh_config_send, NULL,
2861                                         (void*)req, l_free))
2862                         return BT_STATUS_FAIL;
2863         } else {
2864                 ERR("Mesh: app not found!!");
2865                 return BT_STATUS_PARM_INVALID;
2866
2867         }
2868         return BT_STATUS_SUCCESS;
2869 }
2870
2871 bt_status_t _bt_hal_mesh_model_execute_message(
2872         bt_uuid_t *network, uint16_t dest,
2873         uint16_t appkey_idx, uint8_t *buf, int len)
2874 {
2875         GSList *l;
2876         GSList *l1;
2877         struct configuration_request *req;
2878         meshcfg_app *app;
2879         meshcfg_el *elem;
2880         int src_elem_idx = 0;
2881         l = g_slist_find_custom(mesh_apps, network->uu,
2882                         __mesh_compare_network_uuid);
2883         if (l) {
2884                 app = l->data;
2885                 if (!__bt_mesh_proxy_check(app)) {
2886                         ERR("Mesh: Proxy check failed!!");
2887                         return BT_STATUS_FAIL;
2888                 }
2889                 l1 = g_slist_find_custom(app->elements,
2890                                 GUINT_TO_POINTER(src_elem_idx),
2891                                 __compare_element_index);
2892                 if (!l1)
2893                         return BT_STATUS_FAIL;
2894                 elem = l1->data;
2895
2896                 req = l_new(struct configuration_request, 1);
2897                 req->ele_path = elem->path;
2898                 req->dst = dest;
2899                 req->idx = appkey_idx;
2900                 req->data = buf;
2901                 req->len = len;
2902                 req->rmt = false;
2903                 req->is_dev_key = false;
2904
2905                 if (!l_dbus_proxy_method_call(app->proxy, "Send",
2906                                         __bt_hal_mesh_model_execute_message,
2907                                         NULL, (void*)req, l_free))
2908                         return BT_STATUS_FAIL;
2909         } else {
2910                 ERR("Mesh: app not found!!");
2911                 return BT_STATUS_PARM_INVALID;
2912
2913         }
2914         return BT_STATUS_SUCCESS;
2915 }