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