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