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